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" 24*32cad1ffSPhilippe 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 323887d241SBalamuruhan S 333887d241SBalamuruhan S static bool core_max_array(PnvHomer *homer, hwaddr addr) 343887d241SBalamuruhan S { 353887d241SBalamuruhan S int i; 363887d241SBalamuruhan S PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer); 373887d241SBalamuruhan S 383887d241SBalamuruhan S for (i = 0; i <= homer->chip->nr_cores; i++) { 393887d241SBalamuruhan S if (addr == (hmrc->core_max_base + i)) { 403887d241SBalamuruhan S return true; 413887d241SBalamuruhan S } 423887d241SBalamuruhan S } 433887d241SBalamuruhan S return false; 443887d241SBalamuruhan S } 453887d241SBalamuruhan S 463887d241SBalamuruhan S /* P8 Pstate table */ 473887d241SBalamuruhan S 483887d241SBalamuruhan S #define PNV8_OCC_PSTATE_VERSION 0x1f8001 493887d241SBalamuruhan S #define PNV8_OCC_PSTATE_MIN 0x1f8003 503887d241SBalamuruhan S #define PNV8_OCC_PSTATE_VALID 0x1f8000 513887d241SBalamuruhan S #define PNV8_OCC_PSTATE_THROTTLE 0x1f8002 523887d241SBalamuruhan S #define PNV8_OCC_PSTATE_NOM 0x1f8004 533887d241SBalamuruhan S #define PNV8_OCC_PSTATE_TURBO 0x1f8005 543887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ULTRA_TURBO 0x1f8006 553887d241SBalamuruhan S #define PNV8_OCC_PSTATE_DATA 0x1f8008 563887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ID_ZERO 0x1f8010 573887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ID_ONE 0x1f8018 583887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ID_TWO 0x1f8020 593887d241SBalamuruhan S #define PNV8_OCC_VDD_VOLTAGE_IDENTIFIER 0x1f8012 603887d241SBalamuruhan S #define PNV8_OCC_VCS_VOLTAGE_IDENTIFIER 0x1f8013 613887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ZERO_FREQUENCY 0x1f8014 623887d241SBalamuruhan S #define PNV8_OCC_PSTATE_ONE_FREQUENCY 0x1f801c 633887d241SBalamuruhan S #define PNV8_OCC_PSTATE_TWO_FREQUENCY 0x1f8024 643887d241SBalamuruhan S #define PNV8_CORE_MAX_BASE 0x1f8810 653887d241SBalamuruhan S 663887d241SBalamuruhan S 673887d241SBalamuruhan S static uint64_t pnv_power8_homer_read(void *opaque, hwaddr addr, 683887d241SBalamuruhan S unsigned size) 693887d241SBalamuruhan S { 703887d241SBalamuruhan S PnvHomer *homer = PNV_HOMER(opaque); 713887d241SBalamuruhan S 723887d241SBalamuruhan S switch (addr) { 733887d241SBalamuruhan S case PNV8_OCC_PSTATE_VERSION: 743887d241SBalamuruhan S case PNV8_OCC_PSTATE_MIN: 753887d241SBalamuruhan S case PNV8_OCC_PSTATE_ID_ZERO: 763887d241SBalamuruhan S return 0; 773887d241SBalamuruhan S case PNV8_OCC_PSTATE_VALID: 783887d241SBalamuruhan S case PNV8_OCC_PSTATE_THROTTLE: 793887d241SBalamuruhan S case PNV8_OCC_PSTATE_NOM: 803887d241SBalamuruhan S case PNV8_OCC_PSTATE_TURBO: 813887d241SBalamuruhan S case PNV8_OCC_PSTATE_ID_ONE: 823887d241SBalamuruhan S case PNV8_OCC_VDD_VOLTAGE_IDENTIFIER: 833887d241SBalamuruhan S case PNV8_OCC_VCS_VOLTAGE_IDENTIFIER: 843887d241SBalamuruhan S return 1; 853887d241SBalamuruhan S case PNV8_OCC_PSTATE_ULTRA_TURBO: 863887d241SBalamuruhan S case PNV8_OCC_PSTATE_ID_TWO: 873887d241SBalamuruhan S return 2; 883887d241SBalamuruhan S case PNV8_OCC_PSTATE_DATA: 893887d241SBalamuruhan S return 0x1000000000000000; 903887d241SBalamuruhan S /* P8 frequency for 0, 1, and 2 pstates */ 913887d241SBalamuruhan S case PNV8_OCC_PSTATE_ZERO_FREQUENCY: 923887d241SBalamuruhan S case PNV8_OCC_PSTATE_ONE_FREQUENCY: 933887d241SBalamuruhan S case PNV8_OCC_PSTATE_TWO_FREQUENCY: 943887d241SBalamuruhan S return 3000; 953887d241SBalamuruhan S } 963887d241SBalamuruhan S /* pstate table core max array */ 973887d241SBalamuruhan S if (core_max_array(homer, addr)) { 983887d241SBalamuruhan S return 1; 993887d241SBalamuruhan S } 1003887d241SBalamuruhan S return 0; 1013887d241SBalamuruhan S } 1023887d241SBalamuruhan S 1033887d241SBalamuruhan S static void pnv_power8_homer_write(void *opaque, hwaddr addr, 1043887d241SBalamuruhan S uint64_t val, unsigned size) 1053887d241SBalamuruhan S { 1063887d241SBalamuruhan S /* callback function defined to homer write */ 1073887d241SBalamuruhan S return; 1083887d241SBalamuruhan S } 1093887d241SBalamuruhan S 1103887d241SBalamuruhan S static const MemoryRegionOps pnv_power8_homer_ops = { 1113887d241SBalamuruhan S .read = pnv_power8_homer_read, 1123887d241SBalamuruhan S .write = pnv_power8_homer_write, 1133887d241SBalamuruhan S .valid.min_access_size = 1, 1143887d241SBalamuruhan S .valid.max_access_size = 8, 1153887d241SBalamuruhan S .impl.min_access_size = 1, 1163887d241SBalamuruhan S .impl.max_access_size = 8, 1173887d241SBalamuruhan S .endianness = DEVICE_BIG_ENDIAN, 1183887d241SBalamuruhan S }; 1193887d241SBalamuruhan S 1208f092316SCédric Le Goater /* P8 PBA BARs */ 1218f092316SCédric Le Goater #define PBA_BAR0 0x00 1228f092316SCédric Le Goater #define PBA_BAR1 0x01 1238f092316SCédric Le Goater #define PBA_BAR2 0x02 1248f092316SCédric Le Goater #define PBA_BAR3 0x03 1258f092316SCédric Le Goater #define PBA_BARMASK0 0x04 1268f092316SCédric Le Goater #define PBA_BARMASK1 0x05 1278f092316SCédric Le Goater #define PBA_BARMASK2 0x06 1288f092316SCédric Le Goater #define PBA_BARMASK3 0x07 1298f092316SCédric Le Goater 1308f092316SCédric Le Goater static uint64_t pnv_homer_power8_pba_read(void *opaque, hwaddr addr, 1318f092316SCédric Le Goater unsigned size) 1328f092316SCédric Le Goater { 1338f092316SCédric Le Goater PnvHomer *homer = PNV_HOMER(opaque); 1348f092316SCédric Le Goater PnvChip *chip = homer->chip; 1358f092316SCédric Le Goater uint32_t reg = addr >> 3; 1368f092316SCédric Le Goater uint64_t val = 0; 1378f092316SCédric Le Goater 1388f092316SCédric Le Goater switch (reg) { 1398f092316SCédric Le Goater case PBA_BAR0: 1408f092316SCédric Le Goater val = PNV_HOMER_BASE(chip); 1418f092316SCédric Le Goater break; 1428f092316SCédric Le Goater case PBA_BARMASK0: /* P8 homer region mask */ 1438f092316SCédric Le Goater val = (PNV_HOMER_SIZE - 1) & 0x300000; 1448f092316SCédric Le Goater break; 1458f092316SCédric Le Goater case PBA_BAR3: /* P8 occ common area */ 1468f092316SCédric Le Goater val = PNV_OCC_COMMON_AREA_BASE; 1478f092316SCédric Le Goater break; 1488f092316SCédric Le Goater case PBA_BARMASK3: /* P8 occ common area mask */ 1498f092316SCédric Le Goater val = (PNV_OCC_COMMON_AREA_SIZE - 1) & 0x700000; 1508f092316SCédric Le Goater break; 1518f092316SCédric Le Goater default: 1528f092316SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%" 1538f092316SCédric Le Goater HWADDR_PRIx "\n", addr >> 3); 1548f092316SCédric Le Goater } 1558f092316SCédric Le Goater return val; 1568f092316SCédric Le Goater } 1578f092316SCédric Le Goater 1588f092316SCédric Le Goater static void pnv_homer_power8_pba_write(void *opaque, hwaddr addr, 1598f092316SCédric Le Goater uint64_t val, unsigned size) 1608f092316SCédric Le Goater { 1618f092316SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%" 1628f092316SCédric Le Goater HWADDR_PRIx "\n", addr >> 3); 1638f092316SCédric Le Goater } 1648f092316SCédric Le Goater 1658f092316SCédric Le Goater static const MemoryRegionOps pnv_homer_power8_pba_ops = { 1668f092316SCédric Le Goater .read = pnv_homer_power8_pba_read, 1678f092316SCédric Le Goater .write = pnv_homer_power8_pba_write, 1688f092316SCédric Le Goater .valid.min_access_size = 8, 1698f092316SCédric Le Goater .valid.max_access_size = 8, 1708f092316SCédric Le Goater .impl.min_access_size = 8, 1718f092316SCédric Le Goater .impl.max_access_size = 8, 1728f092316SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 1738f092316SCédric Le Goater }; 1748f092316SCédric Le Goater 1753887d241SBalamuruhan S static void pnv_homer_power8_class_init(ObjectClass *klass, void *data) 1763887d241SBalamuruhan S { 1773887d241SBalamuruhan S PnvHomerClass *homer = PNV_HOMER_CLASS(klass); 1783887d241SBalamuruhan S 1798f092316SCédric Le Goater homer->pba_size = PNV_XSCOM_PBA_SIZE; 1808f092316SCédric Le Goater homer->pba_ops = &pnv_homer_power8_pba_ops; 1813887d241SBalamuruhan S homer->homer_size = PNV_HOMER_SIZE; 1823887d241SBalamuruhan S homer->homer_ops = &pnv_power8_homer_ops; 1833887d241SBalamuruhan S homer->core_max_base = PNV8_CORE_MAX_BASE; 1843887d241SBalamuruhan S } 1853887d241SBalamuruhan S 1863887d241SBalamuruhan S static const TypeInfo pnv_homer_power8_type_info = { 1873887d241SBalamuruhan S .name = TYPE_PNV8_HOMER, 1883887d241SBalamuruhan S .parent = TYPE_PNV_HOMER, 1893887d241SBalamuruhan S .instance_size = sizeof(PnvHomer), 1903887d241SBalamuruhan S .class_init = pnv_homer_power8_class_init, 1913887d241SBalamuruhan S }; 1923887d241SBalamuruhan S 1933887d241SBalamuruhan S /* P9 Pstate table */ 1943887d241SBalamuruhan S 1953887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ID_ZERO 0xe2018 1963887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ID_ONE 0xe2020 1973887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ID_TWO 0xe2028 1983887d241SBalamuruhan S #define PNV9_OCC_PSTATE_DATA 0xe2000 1993887d241SBalamuruhan S #define PNV9_OCC_PSTATE_DATA_AREA 0xe2008 2003887d241SBalamuruhan S #define PNV9_OCC_PSTATE_MIN 0xe2003 2013887d241SBalamuruhan S #define PNV9_OCC_PSTATE_NOM 0xe2004 2023887d241SBalamuruhan S #define PNV9_OCC_PSTATE_TURBO 0xe2005 2033887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ULTRA_TURBO 0xe2818 2043887d241SBalamuruhan S #define PNV9_OCC_MAX_PSTATE_ULTRA_TURBO 0xe2006 2053887d241SBalamuruhan S #define PNV9_OCC_PSTATE_MAJOR_VERSION 0xe2001 2063887d241SBalamuruhan S #define PNV9_OCC_OPAL_RUNTIME_DATA 0xe2b85 2073887d241SBalamuruhan S #define PNV9_CHIP_HOMER_IMAGE_POINTER 0x200008 2083887d241SBalamuruhan S #define PNV9_CHIP_HOMER_BASE 0x0 2093887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ZERO_FREQUENCY 0xe201c 2103887d241SBalamuruhan S #define PNV9_OCC_PSTATE_ONE_FREQUENCY 0xe2024 2113887d241SBalamuruhan S #define PNV9_OCC_PSTATE_TWO_FREQUENCY 0xe202c 2123887d241SBalamuruhan S #define PNV9_OCC_ROLE_MASTER_OR_SLAVE 0xe2002 2133887d241SBalamuruhan S #define PNV9_CORE_MAX_BASE 0xe2819 2143887d241SBalamuruhan S 2153887d241SBalamuruhan S 2163887d241SBalamuruhan S static uint64_t pnv_power9_homer_read(void *opaque, hwaddr addr, 2173887d241SBalamuruhan S unsigned size) 2183887d241SBalamuruhan S { 2193887d241SBalamuruhan S PnvHomer *homer = PNV_HOMER(opaque); 2203887d241SBalamuruhan S 2213887d241SBalamuruhan S switch (addr) { 2223887d241SBalamuruhan S case PNV9_OCC_MAX_PSTATE_ULTRA_TURBO: 2233887d241SBalamuruhan S case PNV9_OCC_PSTATE_ID_ZERO: 2243887d241SBalamuruhan S return 0; 2253887d241SBalamuruhan S case PNV9_OCC_PSTATE_DATA: 2263887d241SBalamuruhan S case PNV9_OCC_ROLE_MASTER_OR_SLAVE: 2273887d241SBalamuruhan S case PNV9_OCC_PSTATE_NOM: 2283887d241SBalamuruhan S case PNV9_OCC_PSTATE_TURBO: 2293887d241SBalamuruhan S case PNV9_OCC_PSTATE_ID_ONE: 2303887d241SBalamuruhan S case PNV9_OCC_PSTATE_ULTRA_TURBO: 2313887d241SBalamuruhan S case PNV9_OCC_OPAL_RUNTIME_DATA: 2323887d241SBalamuruhan S return 1; 2333887d241SBalamuruhan S case PNV9_OCC_PSTATE_MIN: 2343887d241SBalamuruhan S case PNV9_OCC_PSTATE_ID_TWO: 2353887d241SBalamuruhan S return 2; 2363887d241SBalamuruhan S 2373887d241SBalamuruhan S /* 3000 khz frequency for 0, 1, and 2 pstates */ 2383887d241SBalamuruhan S case PNV9_OCC_PSTATE_ZERO_FREQUENCY: 2393887d241SBalamuruhan S case PNV9_OCC_PSTATE_ONE_FREQUENCY: 2403887d241SBalamuruhan S case PNV9_OCC_PSTATE_TWO_FREQUENCY: 2413887d241SBalamuruhan S return 3000; 2423887d241SBalamuruhan S case PNV9_OCC_PSTATE_MAJOR_VERSION: 2433887d241SBalamuruhan S return 0x90; 2443887d241SBalamuruhan S case PNV9_CHIP_HOMER_BASE: 2453887d241SBalamuruhan S case PNV9_OCC_PSTATE_DATA_AREA: 2463887d241SBalamuruhan S case PNV9_CHIP_HOMER_IMAGE_POINTER: 2473887d241SBalamuruhan S return 0x1000000000000000; 2483887d241SBalamuruhan S } 2493887d241SBalamuruhan S /* pstate table core max array */ 2503887d241SBalamuruhan S if (core_max_array(homer, addr)) { 2513887d241SBalamuruhan S return 1; 2523887d241SBalamuruhan S } 2533887d241SBalamuruhan S return 0; 2543887d241SBalamuruhan S } 2553887d241SBalamuruhan S 2563887d241SBalamuruhan S static void pnv_power9_homer_write(void *opaque, hwaddr addr, 2573887d241SBalamuruhan S uint64_t val, unsigned size) 2583887d241SBalamuruhan S { 2593887d241SBalamuruhan S /* callback function defined to homer write */ 2603887d241SBalamuruhan S return; 2613887d241SBalamuruhan S } 2623887d241SBalamuruhan S 2633887d241SBalamuruhan S static const MemoryRegionOps pnv_power9_homer_ops = { 2643887d241SBalamuruhan S .read = pnv_power9_homer_read, 2653887d241SBalamuruhan S .write = pnv_power9_homer_write, 2663887d241SBalamuruhan S .valid.min_access_size = 1, 2673887d241SBalamuruhan S .valid.max_access_size = 8, 2683887d241SBalamuruhan S .impl.min_access_size = 1, 2693887d241SBalamuruhan S .impl.max_access_size = 8, 2703887d241SBalamuruhan S .endianness = DEVICE_BIG_ENDIAN, 2713887d241SBalamuruhan S }; 2723887d241SBalamuruhan S 2738f092316SCédric Le Goater static uint64_t pnv_homer_power9_pba_read(void *opaque, hwaddr addr, 2748f092316SCédric Le Goater unsigned size) 2758f092316SCédric Le Goater { 2768f092316SCédric Le Goater PnvHomer *homer = PNV_HOMER(opaque); 2778f092316SCédric Le Goater PnvChip *chip = homer->chip; 2788f092316SCédric Le Goater uint32_t reg = addr >> 3; 2798f092316SCédric Le Goater uint64_t val = 0; 2808f092316SCédric Le Goater 2818f092316SCédric Le Goater switch (reg) { 2828f092316SCédric Le Goater case PBA_BAR0: 2838f092316SCédric Le Goater val = PNV9_HOMER_BASE(chip); 2848f092316SCédric Le Goater break; 2858f092316SCédric Le Goater case PBA_BARMASK0: /* P9 homer region mask */ 2868f092316SCédric Le Goater val = (PNV9_HOMER_SIZE - 1) & 0x300000; 2878f092316SCédric Le Goater break; 2888f092316SCédric Le Goater case PBA_BAR2: /* P9 occ common area */ 2898f092316SCédric Le Goater val = PNV9_OCC_COMMON_AREA_BASE; 2908f092316SCédric Le Goater break; 2918f092316SCédric Le Goater case PBA_BARMASK2: /* P9 occ common area size */ 2928f092316SCédric Le Goater val = (PNV9_OCC_COMMON_AREA_SIZE - 1) & 0x700000; 2938f092316SCédric Le Goater break; 2948f092316SCédric Le Goater default: 2958f092316SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%" 2968f092316SCédric Le Goater HWADDR_PRIx "\n", addr >> 3); 2978f092316SCédric Le Goater } 2988f092316SCédric Le Goater return val; 2998f092316SCédric Le Goater } 3008f092316SCédric Le Goater 3018f092316SCédric Le Goater static void pnv_homer_power9_pba_write(void *opaque, hwaddr addr, 3028f092316SCédric Le Goater uint64_t val, unsigned size) 3038f092316SCédric Le Goater { 3048f092316SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%" 3058f092316SCédric Le Goater HWADDR_PRIx "\n", addr >> 3); 3068f092316SCédric Le Goater } 3078f092316SCédric Le Goater 3088f092316SCédric Le Goater static const MemoryRegionOps pnv_homer_power9_pba_ops = { 3098f092316SCédric Le Goater .read = pnv_homer_power9_pba_read, 3108f092316SCédric Le Goater .write = pnv_homer_power9_pba_write, 3118f092316SCédric Le Goater .valid.min_access_size = 8, 3128f092316SCédric Le Goater .valid.max_access_size = 8, 3138f092316SCédric Le Goater .impl.min_access_size = 8, 3148f092316SCédric Le Goater .impl.max_access_size = 8, 3158f092316SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 3168f092316SCédric Le Goater }; 3178f092316SCédric Le Goater 3183887d241SBalamuruhan S static void pnv_homer_power9_class_init(ObjectClass *klass, void *data) 3193887d241SBalamuruhan S { 3203887d241SBalamuruhan S PnvHomerClass *homer = PNV_HOMER_CLASS(klass); 3213887d241SBalamuruhan S 3228f092316SCédric Le Goater homer->pba_size = PNV9_XSCOM_PBA_SIZE; 3238f092316SCédric Le Goater homer->pba_ops = &pnv_homer_power9_pba_ops; 3243887d241SBalamuruhan S homer->homer_size = PNV9_HOMER_SIZE; 3253887d241SBalamuruhan S homer->homer_ops = &pnv_power9_homer_ops; 3263887d241SBalamuruhan S homer->core_max_base = PNV9_CORE_MAX_BASE; 3273887d241SBalamuruhan S } 3283887d241SBalamuruhan S 3293887d241SBalamuruhan S static const TypeInfo pnv_homer_power9_type_info = { 3303887d241SBalamuruhan S .name = TYPE_PNV9_HOMER, 3313887d241SBalamuruhan S .parent = TYPE_PNV_HOMER, 3323887d241SBalamuruhan S .instance_size = sizeof(PnvHomer), 3333887d241SBalamuruhan S .class_init = pnv_homer_power9_class_init, 3343887d241SBalamuruhan S }; 3353887d241SBalamuruhan S 33692499676SCédric Le Goater static uint64_t pnv_homer_power10_pba_read(void *opaque, hwaddr addr, 33792499676SCédric Le Goater unsigned size) 33892499676SCédric Le Goater { 33992499676SCédric Le Goater PnvHomer *homer = PNV_HOMER(opaque); 34092499676SCédric Le Goater PnvChip *chip = homer->chip; 34192499676SCédric Le Goater uint32_t reg = addr >> 3; 34292499676SCédric Le Goater uint64_t val = 0; 34392499676SCédric Le Goater 34492499676SCédric Le Goater switch (reg) { 34592499676SCédric Le Goater case PBA_BAR0: 34692499676SCédric Le Goater val = PNV10_HOMER_BASE(chip); 34792499676SCédric Le Goater break; 34892499676SCédric Le Goater case PBA_BARMASK0: /* P10 homer region mask */ 34992499676SCédric Le Goater val = (PNV10_HOMER_SIZE - 1) & 0x300000; 35092499676SCédric Le Goater break; 35192499676SCédric Le Goater case PBA_BAR2: /* P10 occ common area */ 35292499676SCédric Le Goater val = PNV10_OCC_COMMON_AREA_BASE; 35392499676SCédric Le Goater break; 35492499676SCédric Le Goater case PBA_BARMASK2: /* P10 occ common area size */ 35592499676SCédric Le Goater val = (PNV10_OCC_COMMON_AREA_SIZE - 1) & 0x700000; 35692499676SCédric Le Goater break; 35792499676SCédric Le Goater default: 35892499676SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%" 35992499676SCédric Le Goater HWADDR_PRIx "\n", addr >> 3); 36092499676SCédric Le Goater } 36192499676SCédric Le Goater return val; 36292499676SCédric Le Goater } 36392499676SCédric Le Goater 36492499676SCédric Le Goater static void pnv_homer_power10_pba_write(void *opaque, hwaddr addr, 36592499676SCédric Le Goater uint64_t val, unsigned size) 36692499676SCédric Le Goater { 36792499676SCédric Le Goater qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%" 36892499676SCédric Le Goater HWADDR_PRIx "\n", addr >> 3); 36992499676SCédric Le Goater } 37092499676SCédric Le Goater 37192499676SCédric Le Goater static const MemoryRegionOps pnv_homer_power10_pba_ops = { 37292499676SCédric Le Goater .read = pnv_homer_power10_pba_read, 37392499676SCédric Le Goater .write = pnv_homer_power10_pba_write, 37492499676SCédric Le Goater .valid.min_access_size = 8, 37592499676SCédric Le Goater .valid.max_access_size = 8, 37692499676SCédric Le Goater .impl.min_access_size = 8, 37792499676SCédric Le Goater .impl.max_access_size = 8, 37892499676SCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 37992499676SCédric Le Goater }; 38092499676SCédric Le Goater 38192499676SCédric Le Goater static void pnv_homer_power10_class_init(ObjectClass *klass, void *data) 38292499676SCédric Le Goater { 38392499676SCédric Le Goater PnvHomerClass *homer = PNV_HOMER_CLASS(klass); 38492499676SCédric Le Goater 38592499676SCédric Le Goater homer->pba_size = PNV10_XSCOM_PBA_SIZE; 38692499676SCédric Le Goater homer->pba_ops = &pnv_homer_power10_pba_ops; 38792499676SCédric Le Goater homer->homer_size = PNV10_HOMER_SIZE; 38892499676SCédric Le Goater homer->homer_ops = &pnv_power9_homer_ops; /* TODO */ 38992499676SCédric Le Goater homer->core_max_base = PNV9_CORE_MAX_BASE; 39092499676SCédric Le Goater } 39192499676SCédric Le Goater 39292499676SCédric Le Goater static const TypeInfo pnv_homer_power10_type_info = { 39392499676SCédric Le Goater .name = TYPE_PNV10_HOMER, 39492499676SCédric Le Goater .parent = TYPE_PNV_HOMER, 39592499676SCédric Le Goater .instance_size = sizeof(PnvHomer), 39692499676SCédric Le Goater .class_init = pnv_homer_power10_class_init, 39792499676SCédric Le Goater }; 39892499676SCédric Le Goater 3993887d241SBalamuruhan S static void pnv_homer_realize(DeviceState *dev, Error **errp) 4003887d241SBalamuruhan S { 4013887d241SBalamuruhan S PnvHomer *homer = PNV_HOMER(dev); 4023887d241SBalamuruhan S PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer); 4033887d241SBalamuruhan S 404f2582acfSGreg Kurz assert(homer->chip); 405f2582acfSGreg Kurz 4068f092316SCédric Le Goater pnv_xscom_region_init(&homer->pba_regs, OBJECT(dev), hmrc->pba_ops, 4078f092316SCédric Le Goater homer, "xscom-pba", hmrc->pba_size); 4088f092316SCédric Le Goater 4093887d241SBalamuruhan S /* homer region */ 4103887d241SBalamuruhan S memory_region_init_io(&homer->regs, OBJECT(dev), 4113887d241SBalamuruhan S hmrc->homer_ops, homer, "homer-main-memory", 4123887d241SBalamuruhan S hmrc->homer_size); 4133887d241SBalamuruhan S } 4143887d241SBalamuruhan S 41590f5755eSRichard Henderson static const Property pnv_homer_properties[] = { 416f2582acfSGreg Kurz DEFINE_PROP_LINK("chip", PnvHomer, chip, TYPE_PNV_CHIP, PnvChip *), 417f2582acfSGreg Kurz DEFINE_PROP_END_OF_LIST(), 418f2582acfSGreg Kurz }; 419f2582acfSGreg Kurz 4203887d241SBalamuruhan S static void pnv_homer_class_init(ObjectClass *klass, void *data) 4213887d241SBalamuruhan S { 4223887d241SBalamuruhan S DeviceClass *dc = DEVICE_CLASS(klass); 4233887d241SBalamuruhan S 4243887d241SBalamuruhan S dc->realize = pnv_homer_realize; 4253887d241SBalamuruhan S dc->desc = "PowerNV HOMER Memory"; 4264f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_homer_properties); 42723a782ebSCédric Le Goater dc->user_creatable = false; 4283887d241SBalamuruhan S } 4293887d241SBalamuruhan S 4303887d241SBalamuruhan S static const TypeInfo pnv_homer_type_info = { 4313887d241SBalamuruhan S .name = TYPE_PNV_HOMER, 4323887d241SBalamuruhan S .parent = TYPE_DEVICE, 4333887d241SBalamuruhan S .instance_size = sizeof(PnvHomer), 4343887d241SBalamuruhan S .class_init = pnv_homer_class_init, 4353887d241SBalamuruhan S .class_size = sizeof(PnvHomerClass), 4363887d241SBalamuruhan S .abstract = true, 4373887d241SBalamuruhan S }; 4383887d241SBalamuruhan S 4393887d241SBalamuruhan S static void pnv_homer_register_types(void) 4403887d241SBalamuruhan S { 4413887d241SBalamuruhan S type_register_static(&pnv_homer_type_info); 4423887d241SBalamuruhan S type_register_static(&pnv_homer_power8_type_info); 4433887d241SBalamuruhan S type_register_static(&pnv_homer_power9_type_info); 44492499676SCédric Le Goater type_register_static(&pnv_homer_power10_type_info); 4453887d241SBalamuruhan S } 4463887d241SBalamuruhan S 4473887d241SBalamuruhan S type_init(pnv_homer_register_types); 448