13887d241SBalamuruhan S /*
23887d241SBalamuruhan S * QEMU PowerPC PowerNV Emulation of a few HOMER related registers
33887d241SBalamuruhan S *
43887d241SBalamuruhan S * Copyright (c) 2019, IBM Corporation.
53887d241SBalamuruhan S *
63887d241SBalamuruhan S * This program is free software; you can redistribute it and/or modify
73887d241SBalamuruhan S * it under the terms of the GNU General Public License, version 2, as
83887d241SBalamuruhan S * published by the Free Software Foundation.
93887d241SBalamuruhan S *
103887d241SBalamuruhan S * This program is distributed in the hope that it will be useful,
113887d241SBalamuruhan S * but WITHOUT ANY WARRANTY; without even the implied warranty of
123887d241SBalamuruhan S * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
133887d241SBalamuruhan S * GNU General Public License for more details.
143887d241SBalamuruhan S *
153887d241SBalamuruhan S * You should have received a copy of the GNU General Public License
163887d241SBalamuruhan S * along with this program; if not, see <http://www.gnu.org/licenses/>.
173887d241SBalamuruhan S */
183887d241SBalamuruhan S
193887d241SBalamuruhan S #include "qemu/osdep.h"
208f092316SCédric Le Goater #include "qemu/log.h"
213887d241SBalamuruhan S #include "qapi/error.h"
223887d241SBalamuruhan S #include "exec/hwaddr.h"
238be545baSRichard Henderson #include "system/memory.h"
2432cad1ffSPhilippe Mathieu-Daudé #include "system/cpus.h"
253887d241SBalamuruhan S #include "hw/qdev-core.h"
26f2582acfSGreg Kurz #include "hw/qdev-properties.h"
273887d241SBalamuruhan S #include "hw/ppc/pnv.h"
282c6fe2e2SMarkus Armbruster #include "hw/ppc/pnv_chip.h"
293887d241SBalamuruhan S #include "hw/ppc/pnv_homer.h"
308f092316SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
313887d241SBalamuruhan S
328f092316SCédric Le Goater /* P8 PBA BARs */
338f092316SCédric Le Goater #define PBA_BAR0 0x00
348f092316SCédric Le Goater #define PBA_BAR1 0x01
358f092316SCédric Le Goater #define PBA_BAR2 0x02
368f092316SCédric Le Goater #define PBA_BAR3 0x03
378f092316SCédric Le Goater #define PBA_BARMASK0 0x04
388f092316SCédric Le Goater #define PBA_BARMASK1 0x05
398f092316SCédric Le Goater #define PBA_BARMASK2 0x06
408f092316SCédric Le Goater #define PBA_BARMASK3 0x07
418f092316SCédric Le Goater
pnv_homer_power8_pba_read(void * opaque,hwaddr addr,unsigned size)428f092316SCédric Le Goater static uint64_t pnv_homer_power8_pba_read(void *opaque, hwaddr addr,
438f092316SCédric Le Goater unsigned size)
448f092316SCédric Le Goater {
458f092316SCédric Le Goater PnvHomer *homer = PNV_HOMER(opaque);
462935a3fbSNicholas Piggin PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
478f092316SCédric Le Goater uint32_t reg = addr >> 3;
488f092316SCédric Le Goater uint64_t val = 0;
498f092316SCédric Le Goater
508f092316SCédric Le Goater switch (reg) {
518f092316SCédric Le Goater case PBA_BAR0:
522935a3fbSNicholas Piggin val = homer->base;
538f092316SCédric Le Goater break;
548f092316SCédric Le Goater case PBA_BARMASK0: /* P8 homer region mask */
552935a3fbSNicholas Piggin val = (hmrc->size - 1) & 0x300000;
568f092316SCédric Le Goater break;
578f092316SCédric Le Goater case PBA_BAR3: /* P8 occ common area */
588f092316SCédric Le Goater val = PNV_OCC_COMMON_AREA_BASE;
598f092316SCédric Le Goater break;
608f092316SCédric Le Goater case PBA_BARMASK3: /* P8 occ common area mask */
618f092316SCédric Le Goater val = (PNV_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
628f092316SCédric Le Goater break;
638f092316SCédric Le Goater default:
648f092316SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
658f092316SCédric Le Goater HWADDR_PRIx "\n", addr >> 3);
668f092316SCédric Le Goater }
678f092316SCédric Le Goater return val;
688f092316SCédric Le Goater }
698f092316SCédric Le Goater
pnv_homer_power8_pba_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)708f092316SCédric Le Goater static void pnv_homer_power8_pba_write(void *opaque, hwaddr addr,
718f092316SCédric Le Goater uint64_t val, unsigned size)
728f092316SCédric Le Goater {
738f092316SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
748f092316SCédric Le Goater HWADDR_PRIx "\n", addr >> 3);
758f092316SCédric Le Goater }
768f092316SCédric Le Goater
778f092316SCédric Le Goater static const MemoryRegionOps pnv_homer_power8_pba_ops = {
788f092316SCédric Le Goater .read = pnv_homer_power8_pba_read,
798f092316SCédric Le Goater .write = pnv_homer_power8_pba_write,
808f092316SCédric Le Goater .valid.min_access_size = 8,
818f092316SCédric Le Goater .valid.max_access_size = 8,
828f092316SCédric Le Goater .impl.min_access_size = 8,
838f092316SCédric Le Goater .impl.max_access_size = 8,
848f092316SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN,
858f092316SCédric Le Goater };
868f092316SCédric Le Goater
pnv_homer_power8_get_base(PnvChip * chip)872935a3fbSNicholas Piggin static hwaddr pnv_homer_power8_get_base(PnvChip *chip)
882935a3fbSNicholas Piggin {
892935a3fbSNicholas Piggin return PNV_HOMER_BASE(chip);
902935a3fbSNicholas Piggin }
912935a3fbSNicholas Piggin
pnv_homer_power8_class_init(ObjectClass * klass,const void * data)92*12d1a768SPhilippe Mathieu-Daudé static void pnv_homer_power8_class_init(ObjectClass *klass, const void *data)
933887d241SBalamuruhan S {
943887d241SBalamuruhan S PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
953887d241SBalamuruhan S
962935a3fbSNicholas Piggin homer->get_base = pnv_homer_power8_get_base;
972935a3fbSNicholas Piggin homer->size = PNV_HOMER_SIZE;
988f092316SCédric Le Goater homer->pba_size = PNV_XSCOM_PBA_SIZE;
998f092316SCédric Le Goater homer->pba_ops = &pnv_homer_power8_pba_ops;
1003887d241SBalamuruhan S }
1013887d241SBalamuruhan S
1023887d241SBalamuruhan S static const TypeInfo pnv_homer_power8_type_info = {
1033887d241SBalamuruhan S .name = TYPE_PNV8_HOMER,
1043887d241SBalamuruhan S .parent = TYPE_PNV_HOMER,
1053887d241SBalamuruhan S .instance_size = sizeof(PnvHomer),
1063887d241SBalamuruhan S .class_init = pnv_homer_power8_class_init,
1073887d241SBalamuruhan S };
1083887d241SBalamuruhan S
pnv_homer_power9_pba_read(void * opaque,hwaddr addr,unsigned size)1098f092316SCédric Le Goater static uint64_t pnv_homer_power9_pba_read(void *opaque, hwaddr addr,
1108f092316SCédric Le Goater unsigned size)
1118f092316SCédric Le Goater {
1128f092316SCédric Le Goater PnvHomer *homer = PNV_HOMER(opaque);
1132935a3fbSNicholas Piggin PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
1148f092316SCédric Le Goater uint32_t reg = addr >> 3;
1158f092316SCédric Le Goater uint64_t val = 0;
1168f092316SCédric Le Goater
1178f092316SCédric Le Goater switch (reg) {
1188f092316SCédric Le Goater case PBA_BAR0:
1192935a3fbSNicholas Piggin val = homer->base;
1208f092316SCédric Le Goater break;
1218f092316SCédric Le Goater case PBA_BARMASK0: /* P9 homer region mask */
1222935a3fbSNicholas Piggin val = (hmrc->size - 1) & 0x300000;
1238f092316SCédric Le Goater break;
1248f092316SCédric Le Goater case PBA_BAR2: /* P9 occ common area */
1258f092316SCédric Le Goater val = PNV9_OCC_COMMON_AREA_BASE;
1268f092316SCédric Le Goater break;
1278f092316SCédric Le Goater case PBA_BARMASK2: /* P9 occ common area size */
1288f092316SCédric Le Goater val = (PNV9_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
1298f092316SCédric Le Goater break;
1308f092316SCédric Le Goater default:
1318f092316SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
1328f092316SCédric Le Goater HWADDR_PRIx "\n", addr >> 3);
1338f092316SCédric Le Goater }
1348f092316SCédric Le Goater return val;
1358f092316SCédric Le Goater }
1368f092316SCédric Le Goater
pnv_homer_power9_pba_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)1378f092316SCédric Le Goater static void pnv_homer_power9_pba_write(void *opaque, hwaddr addr,
1388f092316SCédric Le Goater uint64_t val, unsigned size)
1398f092316SCédric Le Goater {
1408f092316SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
1418f092316SCédric Le Goater HWADDR_PRIx "\n", addr >> 3);
1428f092316SCédric Le Goater }
1438f092316SCédric Le Goater
1448f092316SCédric Le Goater static const MemoryRegionOps pnv_homer_power9_pba_ops = {
1458f092316SCédric Le Goater .read = pnv_homer_power9_pba_read,
1468f092316SCédric Le Goater .write = pnv_homer_power9_pba_write,
1478f092316SCédric Le Goater .valid.min_access_size = 8,
1488f092316SCédric Le Goater .valid.max_access_size = 8,
1498f092316SCédric Le Goater .impl.min_access_size = 8,
1508f092316SCédric Le Goater .impl.max_access_size = 8,
1518f092316SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN,
1528f092316SCédric Le Goater };
1538f092316SCédric Le Goater
pnv_homer_power9_get_base(PnvChip * chip)1542935a3fbSNicholas Piggin static hwaddr pnv_homer_power9_get_base(PnvChip *chip)
1552935a3fbSNicholas Piggin {
1562935a3fbSNicholas Piggin return PNV9_HOMER_BASE(chip);
1572935a3fbSNicholas Piggin }
1582935a3fbSNicholas Piggin
pnv_homer_power9_class_init(ObjectClass * klass,const void * data)159*12d1a768SPhilippe Mathieu-Daudé static void pnv_homer_power9_class_init(ObjectClass *klass, const void *data)
1603887d241SBalamuruhan S {
1613887d241SBalamuruhan S PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
1623887d241SBalamuruhan S
1632935a3fbSNicholas Piggin homer->get_base = pnv_homer_power9_get_base;
1642935a3fbSNicholas Piggin homer->size = PNV_HOMER_SIZE;
1658f092316SCédric Le Goater homer->pba_size = PNV9_XSCOM_PBA_SIZE;
1668f092316SCédric Le Goater homer->pba_ops = &pnv_homer_power9_pba_ops;
1673887d241SBalamuruhan S }
1683887d241SBalamuruhan S
1693887d241SBalamuruhan S static const TypeInfo pnv_homer_power9_type_info = {
1703887d241SBalamuruhan S .name = TYPE_PNV9_HOMER,
1713887d241SBalamuruhan S .parent = TYPE_PNV_HOMER,
1723887d241SBalamuruhan S .instance_size = sizeof(PnvHomer),
1733887d241SBalamuruhan S .class_init = pnv_homer_power9_class_init,
1743887d241SBalamuruhan S };
1753887d241SBalamuruhan S
pnv_homer_power10_pba_read(void * opaque,hwaddr addr,unsigned size)17692499676SCédric Le Goater static uint64_t pnv_homer_power10_pba_read(void *opaque, hwaddr addr,
17792499676SCédric Le Goater unsigned size)
17892499676SCédric Le Goater {
17992499676SCédric Le Goater PnvHomer *homer = PNV_HOMER(opaque);
1802935a3fbSNicholas Piggin PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
18192499676SCédric Le Goater uint32_t reg = addr >> 3;
18292499676SCédric Le Goater uint64_t val = 0;
18392499676SCédric Le Goater
18492499676SCédric Le Goater switch (reg) {
18592499676SCédric Le Goater case PBA_BAR0:
1862935a3fbSNicholas Piggin val = homer->base;
18792499676SCédric Le Goater break;
18892499676SCédric Le Goater case PBA_BARMASK0: /* P10 homer region mask */
1892935a3fbSNicholas Piggin val = (hmrc->size - 1) & 0x300000;
19092499676SCédric Le Goater break;
19192499676SCédric Le Goater case PBA_BAR2: /* P10 occ common area */
19292499676SCédric Le Goater val = PNV10_OCC_COMMON_AREA_BASE;
19392499676SCédric Le Goater break;
19492499676SCédric Le Goater case PBA_BARMASK2: /* P10 occ common area size */
19592499676SCédric Le Goater val = (PNV10_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
19692499676SCédric Le Goater break;
19792499676SCédric Le Goater default:
19892499676SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
19992499676SCédric Le Goater HWADDR_PRIx "\n", addr >> 3);
20092499676SCédric Le Goater }
20192499676SCédric Le Goater return val;
20292499676SCédric Le Goater }
20392499676SCédric Le Goater
pnv_homer_power10_pba_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)20492499676SCédric Le Goater static void pnv_homer_power10_pba_write(void *opaque, hwaddr addr,
20592499676SCédric Le Goater uint64_t val, unsigned size)
20692499676SCédric Le Goater {
20792499676SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
20892499676SCédric Le Goater HWADDR_PRIx "\n", addr >> 3);
20992499676SCédric Le Goater }
21092499676SCédric Le Goater
21192499676SCédric Le Goater static const MemoryRegionOps pnv_homer_power10_pba_ops = {
21292499676SCédric Le Goater .read = pnv_homer_power10_pba_read,
21392499676SCédric Le Goater .write = pnv_homer_power10_pba_write,
21492499676SCédric Le Goater .valid.min_access_size = 8,
21592499676SCédric Le Goater .valid.max_access_size = 8,
21692499676SCédric Le Goater .impl.min_access_size = 8,
21792499676SCédric Le Goater .impl.max_access_size = 8,
21892499676SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN,
21992499676SCédric Le Goater };
22092499676SCédric Le Goater
pnv_homer_power10_get_base(PnvChip * chip)2212935a3fbSNicholas Piggin static hwaddr pnv_homer_power10_get_base(PnvChip *chip)
2222935a3fbSNicholas Piggin {
2232935a3fbSNicholas Piggin return PNV10_HOMER_BASE(chip);
2242935a3fbSNicholas Piggin }
2252935a3fbSNicholas Piggin
pnv_homer_power10_class_init(ObjectClass * klass,const void * data)226*12d1a768SPhilippe Mathieu-Daudé static void pnv_homer_power10_class_init(ObjectClass *klass, const void *data)
22792499676SCédric Le Goater {
22892499676SCédric Le Goater PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
22992499676SCédric Le Goater
2302935a3fbSNicholas Piggin homer->get_base = pnv_homer_power10_get_base;
2312935a3fbSNicholas Piggin homer->size = PNV_HOMER_SIZE;
23292499676SCédric Le Goater homer->pba_size = PNV10_XSCOM_PBA_SIZE;
23392499676SCédric Le Goater homer->pba_ops = &pnv_homer_power10_pba_ops;
23492499676SCédric Le Goater }
23592499676SCédric Le Goater
23692499676SCédric Le Goater static const TypeInfo pnv_homer_power10_type_info = {
23792499676SCédric Le Goater .name = TYPE_PNV10_HOMER,
23892499676SCédric Le Goater .parent = TYPE_PNV_HOMER,
23992499676SCédric Le Goater .instance_size = sizeof(PnvHomer),
24092499676SCédric Le Goater .class_init = pnv_homer_power10_class_init,
24192499676SCédric Le Goater };
24292499676SCédric Le Goater
pnv_homer_realize(DeviceState * dev,Error ** errp)2433887d241SBalamuruhan S static void pnv_homer_realize(DeviceState *dev, Error **errp)
2443887d241SBalamuruhan S {
2453887d241SBalamuruhan S PnvHomer *homer = PNV_HOMER(dev);
2463887d241SBalamuruhan S PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
24770bc5c24SNicholas Piggin char homer_str[32];
2483887d241SBalamuruhan S
249f2582acfSGreg Kurz assert(homer->chip);
250f2582acfSGreg Kurz
2518f092316SCédric Le Goater pnv_xscom_region_init(&homer->pba_regs, OBJECT(dev), hmrc->pba_ops,
2528f092316SCédric Le Goater homer, "xscom-pba", hmrc->pba_size);
2538f092316SCédric Le Goater
25470bc5c24SNicholas Piggin /* Homer RAM region */
2552935a3fbSNicholas Piggin homer->base = hmrc->get_base(homer->chip);
2562935a3fbSNicholas Piggin
25770bc5c24SNicholas Piggin snprintf(homer_str, sizeof(homer_str), "homer-chip%d-memory",
25870bc5c24SNicholas Piggin homer->chip->chip_id);
25970bc5c24SNicholas Piggin if (!memory_region_init_ram(&homer->mem, OBJECT(homer),
26070bc5c24SNicholas Piggin homer_str, hmrc->size, errp)) {
26170bc5c24SNicholas Piggin return;
26270bc5c24SNicholas Piggin }
2633887d241SBalamuruhan S }
2643887d241SBalamuruhan S
26590f5755eSRichard Henderson static const Property pnv_homer_properties[] = {
266f2582acfSGreg Kurz DEFINE_PROP_LINK("chip", PnvHomer, chip, TYPE_PNV_CHIP, PnvChip *),
267f2582acfSGreg Kurz };
268f2582acfSGreg Kurz
pnv_homer_class_init(ObjectClass * klass,const void * data)269*12d1a768SPhilippe Mathieu-Daudé static void pnv_homer_class_init(ObjectClass *klass, const void *data)
2703887d241SBalamuruhan S {
2713887d241SBalamuruhan S DeviceClass *dc = DEVICE_CLASS(klass);
2723887d241SBalamuruhan S
2733887d241SBalamuruhan S dc->realize = pnv_homer_realize;
2743887d241SBalamuruhan S dc->desc = "PowerNV HOMER Memory";
2754f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_homer_properties);
27623a782ebSCédric Le Goater dc->user_creatable = false;
2773887d241SBalamuruhan S }
2783887d241SBalamuruhan S
2793887d241SBalamuruhan S static const TypeInfo pnv_homer_type_info = {
2803887d241SBalamuruhan S .name = TYPE_PNV_HOMER,
2813887d241SBalamuruhan S .parent = TYPE_DEVICE,
2823887d241SBalamuruhan S .instance_size = sizeof(PnvHomer),
2833887d241SBalamuruhan S .class_init = pnv_homer_class_init,
2843887d241SBalamuruhan S .class_size = sizeof(PnvHomerClass),
2853887d241SBalamuruhan S .abstract = true,
2863887d241SBalamuruhan S };
2873887d241SBalamuruhan S
pnv_homer_register_types(void)2883887d241SBalamuruhan S static void pnv_homer_register_types(void)
2893887d241SBalamuruhan S {
2903887d241SBalamuruhan S type_register_static(&pnv_homer_type_info);
2913887d241SBalamuruhan S type_register_static(&pnv_homer_power8_type_info);
2923887d241SBalamuruhan S type_register_static(&pnv_homer_power9_type_info);
29392499676SCédric Le Goater type_register_static(&pnv_homer_power10_type_info);
2943887d241SBalamuruhan S }
2953887d241SBalamuruhan S
2963887d241SBalamuruhan S type_init(pnv_homer_register_types);
297