xref: /qemu/hw/ppc/pnv_homer.c (revision 4f67d30b5e74e060b8dbe10528829b47345cd6e8)
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"
233887d241SBalamuruhan S #include "exec/memory.h"
243887d241SBalamuruhan S #include "sysemu/cpus.h"
253887d241SBalamuruhan S #include "hw/qdev-core.h"
26f2582acfSGreg Kurz #include "hw/qdev-properties.h"
273887d241SBalamuruhan S #include "hw/ppc/pnv.h"
283887d241SBalamuruhan S #include "hw/ppc/pnv_homer.h"
298f092316SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
303887d241SBalamuruhan S 
313887d241SBalamuruhan S 
323887d241SBalamuruhan S static bool core_max_array(PnvHomer *homer, hwaddr addr)
333887d241SBalamuruhan S {
343887d241SBalamuruhan S     int i;
353887d241SBalamuruhan S     PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
363887d241SBalamuruhan S 
373887d241SBalamuruhan S     for (i = 0; i <= homer->chip->nr_cores; i++) {
383887d241SBalamuruhan S         if (addr == (hmrc->core_max_base + i)) {
393887d241SBalamuruhan S             return true;
403887d241SBalamuruhan S        }
413887d241SBalamuruhan S     }
423887d241SBalamuruhan S     return false;
433887d241SBalamuruhan S }
443887d241SBalamuruhan S 
453887d241SBalamuruhan S /* P8 Pstate table */
463887d241SBalamuruhan S 
473887d241SBalamuruhan S #define PNV8_OCC_PSTATE_VERSION          0x1f8001
483887d241SBalamuruhan S #define PNV8_OCC_PSTATE_MIN              0x1f8003
493887d241SBalamuruhan S #define PNV8_OCC_PSTATE_VALID            0x1f8000
503887d241SBalamuruhan S #define PNV8_OCC_PSTATE_THROTTLE         0x1f8002
513887d241SBalamuruhan S #define PNV8_OCC_PSTATE_NOM              0x1f8004
523887d241SBalamuruhan S #define PNV8_OCC_PSTATE_TURBO            0x1f8005
533887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ULTRA_TURBO      0x1f8006
543887d241SBalamuruhan S #define PNV8_OCC_PSTATE_DATA             0x1f8008
553887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ID_ZERO          0x1f8010
563887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ID_ONE           0x1f8018
573887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ID_TWO           0x1f8020
583887d241SBalamuruhan S #define PNV8_OCC_VDD_VOLTAGE_IDENTIFIER  0x1f8012
593887d241SBalamuruhan S #define PNV8_OCC_VCS_VOLTAGE_IDENTIFIER  0x1f8013
603887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ZERO_FREQUENCY   0x1f8014
613887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ONE_FREQUENCY    0x1f801c
623887d241SBalamuruhan S #define PNV8_OCC_PSTATE_TWO_FREQUENCY    0x1f8024
633887d241SBalamuruhan S #define PNV8_CORE_MAX_BASE               0x1f8810
643887d241SBalamuruhan S 
653887d241SBalamuruhan S 
663887d241SBalamuruhan S static uint64_t pnv_power8_homer_read(void *opaque, hwaddr addr,
673887d241SBalamuruhan S                                       unsigned size)
683887d241SBalamuruhan S {
693887d241SBalamuruhan S     PnvHomer *homer = PNV_HOMER(opaque);
703887d241SBalamuruhan S 
713887d241SBalamuruhan S     switch (addr) {
723887d241SBalamuruhan S     case PNV8_OCC_PSTATE_VERSION:
733887d241SBalamuruhan S     case PNV8_OCC_PSTATE_MIN:
743887d241SBalamuruhan S     case PNV8_OCC_PSTATE_ID_ZERO:
753887d241SBalamuruhan S         return 0;
763887d241SBalamuruhan S     case PNV8_OCC_PSTATE_VALID:
773887d241SBalamuruhan S     case PNV8_OCC_PSTATE_THROTTLE:
783887d241SBalamuruhan S     case PNV8_OCC_PSTATE_NOM:
793887d241SBalamuruhan S     case PNV8_OCC_PSTATE_TURBO:
803887d241SBalamuruhan S     case PNV8_OCC_PSTATE_ID_ONE:
813887d241SBalamuruhan S     case PNV8_OCC_VDD_VOLTAGE_IDENTIFIER:
823887d241SBalamuruhan S     case PNV8_OCC_VCS_VOLTAGE_IDENTIFIER:
833887d241SBalamuruhan S         return 1;
843887d241SBalamuruhan S     case PNV8_OCC_PSTATE_ULTRA_TURBO:
853887d241SBalamuruhan S     case PNV8_OCC_PSTATE_ID_TWO:
863887d241SBalamuruhan S         return 2;
873887d241SBalamuruhan S     case PNV8_OCC_PSTATE_DATA:
883887d241SBalamuruhan S         return 0x1000000000000000;
893887d241SBalamuruhan S     /* P8 frequency for 0, 1, and 2 pstates */
903887d241SBalamuruhan S     case PNV8_OCC_PSTATE_ZERO_FREQUENCY:
913887d241SBalamuruhan S     case PNV8_OCC_PSTATE_ONE_FREQUENCY:
923887d241SBalamuruhan S     case PNV8_OCC_PSTATE_TWO_FREQUENCY:
933887d241SBalamuruhan S         return 3000;
943887d241SBalamuruhan S     }
953887d241SBalamuruhan S     /* pstate table core max array */
963887d241SBalamuruhan S     if (core_max_array(homer, addr)) {
973887d241SBalamuruhan S         return 1;
983887d241SBalamuruhan S     }
993887d241SBalamuruhan S     return 0;
1003887d241SBalamuruhan S }
1013887d241SBalamuruhan S 
1023887d241SBalamuruhan S static void pnv_power8_homer_write(void *opaque, hwaddr addr,
1033887d241SBalamuruhan S                                    uint64_t val, unsigned size)
1043887d241SBalamuruhan S {
1053887d241SBalamuruhan S     /* callback function defined to homer write */
1063887d241SBalamuruhan S     return;
1073887d241SBalamuruhan S }
1083887d241SBalamuruhan S 
1093887d241SBalamuruhan S static const MemoryRegionOps pnv_power8_homer_ops = {
1103887d241SBalamuruhan S     .read = pnv_power8_homer_read,
1113887d241SBalamuruhan S     .write = pnv_power8_homer_write,
1123887d241SBalamuruhan S     .valid.min_access_size = 1,
1133887d241SBalamuruhan S     .valid.max_access_size = 8,
1143887d241SBalamuruhan S     .impl.min_access_size = 1,
1153887d241SBalamuruhan S     .impl.max_access_size = 8,
1163887d241SBalamuruhan S     .endianness = DEVICE_BIG_ENDIAN,
1173887d241SBalamuruhan S };
1183887d241SBalamuruhan S 
1198f092316SCédric Le Goater /* P8 PBA BARs */
1208f092316SCédric Le Goater #define PBA_BAR0                     0x00
1218f092316SCédric Le Goater #define PBA_BAR1                     0x01
1228f092316SCédric Le Goater #define PBA_BAR2                     0x02
1238f092316SCédric Le Goater #define PBA_BAR3                     0x03
1248f092316SCédric Le Goater #define PBA_BARMASK0                 0x04
1258f092316SCédric Le Goater #define PBA_BARMASK1                 0x05
1268f092316SCédric Le Goater #define PBA_BARMASK2                 0x06
1278f092316SCédric Le Goater #define PBA_BARMASK3                 0x07
1288f092316SCédric Le Goater 
1298f092316SCédric Le Goater static uint64_t pnv_homer_power8_pba_read(void *opaque, hwaddr addr,
1308f092316SCédric Le Goater                                           unsigned size)
1318f092316SCédric Le Goater {
1328f092316SCédric Le Goater     PnvHomer *homer = PNV_HOMER(opaque);
1338f092316SCédric Le Goater     PnvChip *chip = homer->chip;
1348f092316SCédric Le Goater     uint32_t reg = addr >> 3;
1358f092316SCédric Le Goater     uint64_t val = 0;
1368f092316SCédric Le Goater 
1378f092316SCédric Le Goater     switch (reg) {
1388f092316SCédric Le Goater     case PBA_BAR0:
1398f092316SCédric Le Goater         val = PNV_HOMER_BASE(chip);
1408f092316SCédric Le Goater         break;
1418f092316SCédric Le Goater     case PBA_BARMASK0: /* P8 homer region mask */
1428f092316SCédric Le Goater         val = (PNV_HOMER_SIZE - 1) & 0x300000;
1438f092316SCédric Le Goater         break;
1448f092316SCédric Le Goater     case PBA_BAR3: /* P8 occ common area */
1458f092316SCédric Le Goater         val = PNV_OCC_COMMON_AREA_BASE;
1468f092316SCédric Le Goater         break;
1478f092316SCédric Le Goater     case PBA_BARMASK3: /* P8 occ common area mask */
1488f092316SCédric Le Goater         val = (PNV_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
1498f092316SCédric Le Goater         break;
1508f092316SCédric Le Goater     default:
1518f092316SCédric Le Goater         qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
1528f092316SCédric Le Goater                       HWADDR_PRIx "\n", addr >> 3);
1538f092316SCédric Le Goater     }
1548f092316SCédric Le Goater     return val;
1558f092316SCédric Le Goater }
1568f092316SCédric Le Goater 
1578f092316SCédric Le Goater static void pnv_homer_power8_pba_write(void *opaque, hwaddr addr,
1588f092316SCédric Le Goater                                          uint64_t val, unsigned size)
1598f092316SCédric Le Goater {
1608f092316SCédric Le Goater     qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
1618f092316SCédric Le Goater                   HWADDR_PRIx "\n", addr >> 3);
1628f092316SCédric Le Goater }
1638f092316SCédric Le Goater 
1648f092316SCédric Le Goater static const MemoryRegionOps pnv_homer_power8_pba_ops = {
1658f092316SCédric Le Goater     .read = pnv_homer_power8_pba_read,
1668f092316SCédric Le Goater     .write = pnv_homer_power8_pba_write,
1678f092316SCédric Le Goater     .valid.min_access_size = 8,
1688f092316SCédric Le Goater     .valid.max_access_size = 8,
1698f092316SCédric Le Goater     .impl.min_access_size = 8,
1708f092316SCédric Le Goater     .impl.max_access_size = 8,
1718f092316SCédric Le Goater     .endianness = DEVICE_BIG_ENDIAN,
1728f092316SCédric Le Goater };
1738f092316SCédric Le Goater 
1743887d241SBalamuruhan S static void pnv_homer_power8_class_init(ObjectClass *klass, void *data)
1753887d241SBalamuruhan S {
1763887d241SBalamuruhan S     PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
1773887d241SBalamuruhan S 
1788f092316SCédric Le Goater     homer->pba_size = PNV_XSCOM_PBA_SIZE;
1798f092316SCédric Le Goater     homer->pba_ops = &pnv_homer_power8_pba_ops;
1803887d241SBalamuruhan S     homer->homer_size = PNV_HOMER_SIZE;
1813887d241SBalamuruhan S     homer->homer_ops = &pnv_power8_homer_ops;
1823887d241SBalamuruhan S     homer->core_max_base = PNV8_CORE_MAX_BASE;
1833887d241SBalamuruhan S }
1843887d241SBalamuruhan S 
1853887d241SBalamuruhan S static const TypeInfo pnv_homer_power8_type_info = {
1863887d241SBalamuruhan S     .name          = TYPE_PNV8_HOMER,
1873887d241SBalamuruhan S     .parent        = TYPE_PNV_HOMER,
1883887d241SBalamuruhan S     .instance_size = sizeof(PnvHomer),
1893887d241SBalamuruhan S     .class_init    = pnv_homer_power8_class_init,
1903887d241SBalamuruhan S };
1913887d241SBalamuruhan S 
1923887d241SBalamuruhan S /* P9 Pstate table */
1933887d241SBalamuruhan S 
1943887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ID_ZERO          0xe2018
1953887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ID_ONE           0xe2020
1963887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ID_TWO           0xe2028
1973887d241SBalamuruhan S #define PNV9_OCC_PSTATE_DATA             0xe2000
1983887d241SBalamuruhan S #define PNV9_OCC_PSTATE_DATA_AREA        0xe2008
1993887d241SBalamuruhan S #define PNV9_OCC_PSTATE_MIN              0xe2003
2003887d241SBalamuruhan S #define PNV9_OCC_PSTATE_NOM              0xe2004
2013887d241SBalamuruhan S #define PNV9_OCC_PSTATE_TURBO            0xe2005
2023887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ULTRA_TURBO      0xe2818
2033887d241SBalamuruhan S #define PNV9_OCC_MAX_PSTATE_ULTRA_TURBO  0xe2006
2043887d241SBalamuruhan S #define PNV9_OCC_PSTATE_MAJOR_VERSION    0xe2001
2053887d241SBalamuruhan S #define PNV9_OCC_OPAL_RUNTIME_DATA       0xe2b85
2063887d241SBalamuruhan S #define PNV9_CHIP_HOMER_IMAGE_POINTER    0x200008
2073887d241SBalamuruhan S #define PNV9_CHIP_HOMER_BASE             0x0
2083887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ZERO_FREQUENCY   0xe201c
2093887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ONE_FREQUENCY    0xe2024
2103887d241SBalamuruhan S #define PNV9_OCC_PSTATE_TWO_FREQUENCY    0xe202c
2113887d241SBalamuruhan S #define PNV9_OCC_ROLE_MASTER_OR_SLAVE    0xe2002
2123887d241SBalamuruhan S #define PNV9_CORE_MAX_BASE               0xe2819
2133887d241SBalamuruhan S 
2143887d241SBalamuruhan S 
2153887d241SBalamuruhan S static uint64_t pnv_power9_homer_read(void *opaque, hwaddr addr,
2163887d241SBalamuruhan S                                       unsigned size)
2173887d241SBalamuruhan S {
2183887d241SBalamuruhan S     PnvHomer *homer = PNV_HOMER(opaque);
2193887d241SBalamuruhan S 
2203887d241SBalamuruhan S     switch (addr) {
2213887d241SBalamuruhan S     case PNV9_OCC_MAX_PSTATE_ULTRA_TURBO:
2223887d241SBalamuruhan S     case PNV9_OCC_PSTATE_ID_ZERO:
2233887d241SBalamuruhan S         return 0;
2243887d241SBalamuruhan S     case PNV9_OCC_PSTATE_DATA:
2253887d241SBalamuruhan S     case PNV9_OCC_ROLE_MASTER_OR_SLAVE:
2263887d241SBalamuruhan S     case PNV9_OCC_PSTATE_NOM:
2273887d241SBalamuruhan S     case PNV9_OCC_PSTATE_TURBO:
2283887d241SBalamuruhan S     case PNV9_OCC_PSTATE_ID_ONE:
2293887d241SBalamuruhan S     case PNV9_OCC_PSTATE_ULTRA_TURBO:
2303887d241SBalamuruhan S     case PNV9_OCC_OPAL_RUNTIME_DATA:
2313887d241SBalamuruhan S         return 1;
2323887d241SBalamuruhan S     case PNV9_OCC_PSTATE_MIN:
2333887d241SBalamuruhan S     case PNV9_OCC_PSTATE_ID_TWO:
2343887d241SBalamuruhan S         return 2;
2353887d241SBalamuruhan S 
2363887d241SBalamuruhan S     /* 3000 khz frequency for 0, 1, and 2 pstates */
2373887d241SBalamuruhan S     case PNV9_OCC_PSTATE_ZERO_FREQUENCY:
2383887d241SBalamuruhan S     case PNV9_OCC_PSTATE_ONE_FREQUENCY:
2393887d241SBalamuruhan S     case PNV9_OCC_PSTATE_TWO_FREQUENCY:
2403887d241SBalamuruhan S         return 3000;
2413887d241SBalamuruhan S     case PNV9_OCC_PSTATE_MAJOR_VERSION:
2423887d241SBalamuruhan S         return 0x90;
2433887d241SBalamuruhan S     case PNV9_CHIP_HOMER_BASE:
2443887d241SBalamuruhan S     case PNV9_OCC_PSTATE_DATA_AREA:
2453887d241SBalamuruhan S     case PNV9_CHIP_HOMER_IMAGE_POINTER:
2463887d241SBalamuruhan S         return 0x1000000000000000;
2473887d241SBalamuruhan S     }
2483887d241SBalamuruhan S     /* pstate table core max array */
2493887d241SBalamuruhan S     if (core_max_array(homer, addr)) {
2503887d241SBalamuruhan S         return 1;
2513887d241SBalamuruhan S     }
2523887d241SBalamuruhan S     return 0;
2533887d241SBalamuruhan S }
2543887d241SBalamuruhan S 
2553887d241SBalamuruhan S static void pnv_power9_homer_write(void *opaque, hwaddr addr,
2563887d241SBalamuruhan S                                    uint64_t val, unsigned size)
2573887d241SBalamuruhan S {
2583887d241SBalamuruhan S     /* callback function defined to homer write */
2593887d241SBalamuruhan S     return;
2603887d241SBalamuruhan S }
2613887d241SBalamuruhan S 
2623887d241SBalamuruhan S static const MemoryRegionOps pnv_power9_homer_ops = {
2633887d241SBalamuruhan S     .read = pnv_power9_homer_read,
2643887d241SBalamuruhan S     .write = pnv_power9_homer_write,
2653887d241SBalamuruhan S     .valid.min_access_size = 1,
2663887d241SBalamuruhan S     .valid.max_access_size = 8,
2673887d241SBalamuruhan S     .impl.min_access_size = 1,
2683887d241SBalamuruhan S     .impl.max_access_size = 8,
2693887d241SBalamuruhan S     .endianness = DEVICE_BIG_ENDIAN,
2703887d241SBalamuruhan S };
2713887d241SBalamuruhan S 
2728f092316SCédric Le Goater static uint64_t pnv_homer_power9_pba_read(void *opaque, hwaddr addr,
2738f092316SCédric Le Goater                                           unsigned size)
2748f092316SCédric Le Goater {
2758f092316SCédric Le Goater     PnvHomer *homer = PNV_HOMER(opaque);
2768f092316SCédric Le Goater     PnvChip *chip = homer->chip;
2778f092316SCédric Le Goater     uint32_t reg = addr >> 3;
2788f092316SCédric Le Goater     uint64_t val = 0;
2798f092316SCédric Le Goater 
2808f092316SCédric Le Goater     switch (reg) {
2818f092316SCédric Le Goater     case PBA_BAR0:
2828f092316SCédric Le Goater         val = PNV9_HOMER_BASE(chip);
2838f092316SCédric Le Goater         break;
2848f092316SCédric Le Goater     case PBA_BARMASK0: /* P9 homer region mask */
2858f092316SCédric Le Goater         val = (PNV9_HOMER_SIZE - 1) & 0x300000;
2868f092316SCédric Le Goater         break;
2878f092316SCédric Le Goater     case PBA_BAR2: /* P9 occ common area */
2888f092316SCédric Le Goater         val = PNV9_OCC_COMMON_AREA_BASE;
2898f092316SCédric Le Goater         break;
2908f092316SCédric Le Goater     case PBA_BARMASK2: /* P9 occ common area size */
2918f092316SCédric Le Goater         val = (PNV9_OCC_COMMON_AREA_SIZE - 1) & 0x700000;
2928f092316SCédric Le Goater         break;
2938f092316SCédric Le Goater     default:
2948f092316SCédric Le Goater         qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%"
2958f092316SCédric Le Goater                       HWADDR_PRIx "\n", addr >> 3);
2968f092316SCédric Le Goater     }
2978f092316SCédric Le Goater     return val;
2988f092316SCédric Le Goater }
2998f092316SCédric Le Goater 
3008f092316SCédric Le Goater static void pnv_homer_power9_pba_write(void *opaque, hwaddr addr,
3018f092316SCédric Le Goater                                          uint64_t val, unsigned size)
3028f092316SCédric Le Goater {
3038f092316SCédric Le Goater     qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%"
3048f092316SCédric Le Goater                   HWADDR_PRIx "\n", addr >> 3);
3058f092316SCédric Le Goater }
3068f092316SCédric Le Goater 
3078f092316SCédric Le Goater static const MemoryRegionOps pnv_homer_power9_pba_ops = {
3088f092316SCédric Le Goater     .read = pnv_homer_power9_pba_read,
3098f092316SCédric Le Goater     .write = pnv_homer_power9_pba_write,
3108f092316SCédric Le Goater     .valid.min_access_size = 8,
3118f092316SCédric Le Goater     .valid.max_access_size = 8,
3128f092316SCédric Le Goater     .impl.min_access_size = 8,
3138f092316SCédric Le Goater     .impl.max_access_size = 8,
3148f092316SCédric Le Goater     .endianness = DEVICE_BIG_ENDIAN,
3158f092316SCédric Le Goater };
3168f092316SCédric Le Goater 
3173887d241SBalamuruhan S static void pnv_homer_power9_class_init(ObjectClass *klass, void *data)
3183887d241SBalamuruhan S {
3193887d241SBalamuruhan S     PnvHomerClass *homer = PNV_HOMER_CLASS(klass);
3203887d241SBalamuruhan S 
3218f092316SCédric Le Goater     homer->pba_size = PNV9_XSCOM_PBA_SIZE;
3228f092316SCédric Le Goater     homer->pba_ops = &pnv_homer_power9_pba_ops;
3233887d241SBalamuruhan S     homer->homer_size = PNV9_HOMER_SIZE;
3243887d241SBalamuruhan S     homer->homer_ops = &pnv_power9_homer_ops;
3253887d241SBalamuruhan S     homer->core_max_base = PNV9_CORE_MAX_BASE;
3263887d241SBalamuruhan S }
3273887d241SBalamuruhan S 
3283887d241SBalamuruhan S static const TypeInfo pnv_homer_power9_type_info = {
3293887d241SBalamuruhan S     .name          = TYPE_PNV9_HOMER,
3303887d241SBalamuruhan S     .parent        = TYPE_PNV_HOMER,
3313887d241SBalamuruhan S     .instance_size = sizeof(PnvHomer),
3323887d241SBalamuruhan S     .class_init    = pnv_homer_power9_class_init,
3333887d241SBalamuruhan S };
3343887d241SBalamuruhan S 
3353887d241SBalamuruhan S static void pnv_homer_realize(DeviceState *dev, Error **errp)
3363887d241SBalamuruhan S {
3373887d241SBalamuruhan S     PnvHomer *homer = PNV_HOMER(dev);
3383887d241SBalamuruhan S     PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer);
3393887d241SBalamuruhan S 
340f2582acfSGreg Kurz     assert(homer->chip);
341f2582acfSGreg Kurz 
3428f092316SCédric Le Goater     pnv_xscom_region_init(&homer->pba_regs, OBJECT(dev), hmrc->pba_ops,
3438f092316SCédric Le Goater                           homer, "xscom-pba", hmrc->pba_size);
3448f092316SCédric Le Goater 
3453887d241SBalamuruhan S     /* homer region */
3463887d241SBalamuruhan S     memory_region_init_io(&homer->regs, OBJECT(dev),
3473887d241SBalamuruhan S                           hmrc->homer_ops, homer, "homer-main-memory",
3483887d241SBalamuruhan S                           hmrc->homer_size);
3493887d241SBalamuruhan S }
3503887d241SBalamuruhan S 
351f2582acfSGreg Kurz static Property pnv_homer_properties[] = {
352f2582acfSGreg Kurz     DEFINE_PROP_LINK("chip", PnvHomer, chip, TYPE_PNV_CHIP, PnvChip *),
353f2582acfSGreg Kurz     DEFINE_PROP_END_OF_LIST(),
354f2582acfSGreg Kurz };
355f2582acfSGreg Kurz 
3563887d241SBalamuruhan S static void pnv_homer_class_init(ObjectClass *klass, void *data)
3573887d241SBalamuruhan S {
3583887d241SBalamuruhan S     DeviceClass *dc = DEVICE_CLASS(klass);
3593887d241SBalamuruhan S 
3603887d241SBalamuruhan S     dc->realize = pnv_homer_realize;
3613887d241SBalamuruhan S     dc->desc = "PowerNV HOMER Memory";
362*4f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_homer_properties);
3633887d241SBalamuruhan S }
3643887d241SBalamuruhan S 
3653887d241SBalamuruhan S static const TypeInfo pnv_homer_type_info = {
3663887d241SBalamuruhan S     .name          = TYPE_PNV_HOMER,
3673887d241SBalamuruhan S     .parent        = TYPE_DEVICE,
3683887d241SBalamuruhan S     .instance_size = sizeof(PnvHomer),
3693887d241SBalamuruhan S     .class_init    = pnv_homer_class_init,
3703887d241SBalamuruhan S     .class_size    = sizeof(PnvHomerClass),
3713887d241SBalamuruhan S     .abstract      = true,
3723887d241SBalamuruhan S };
3733887d241SBalamuruhan S 
3743887d241SBalamuruhan S static void pnv_homer_register_types(void)
3753887d241SBalamuruhan S {
3763887d241SBalamuruhan S     type_register_static(&pnv_homer_type_info);
3773887d241SBalamuruhan S     type_register_static(&pnv_homer_power8_type_info);
3783887d241SBalamuruhan S     type_register_static(&pnv_homer_power9_type_info);
3793887d241SBalamuruhan S }
3803887d241SBalamuruhan S 
3813887d241SBalamuruhan S type_init(pnv_homer_register_types);
382