cfam.c (c3709fde5955d13f6d4f86ab46ef3cc2288ca65e) | cfam.c (f5e80be3922945c51a85aa08c4dfab0a2f3aacc5) |
---|---|
1/* 2 * SPDX-License-Identifier: GPL-2.0-or-later | 1/* 2 * SPDX-License-Identifier: GPL-2.0-or-later |
3 * Copyright (C) 2024 IBM Corp. | 3 * Copyright (C) 2023 IBM Corp. |
4 * 5 * IBM Common FRU Access Macro 6 */ 7 8#include "qemu/osdep.h" | 4 * 5 * IBM Common FRU Access Macro 6 */ 7 8#include "qemu/osdep.h" |
9#include "qemu/units.h" | |
10 11#include "qapi/error.h" 12#include "trace.h" 13 14#include "hw/fsi/cfam.h" 15#include "hw/fsi/fsi.h" 16 17#include "hw/qdev-properties.h" 18 | 9 10#include "qapi/error.h" 11#include "trace.h" 12 13#include "hw/fsi/cfam.h" 14#include "hw/fsi/fsi.h" 15 16#include "hw/qdev-properties.h" 17 |
19#define ENGINE_CONFIG_NEXT BIT(31) | 18#define ENGINE_CONFIG_NEXT BE_BIT(0) |
20#define ENGINE_CONFIG_TYPE_PEEK (0x02 << 4) 21#define ENGINE_CONFIG_TYPE_FSI (0x03 << 4) 22#define ENGINE_CONFIG_TYPE_SCRATCHPAD (0x06 << 4) 23 | 19#define ENGINE_CONFIG_TYPE_PEEK (0x02 << 4) 20#define ENGINE_CONFIG_TYPE_FSI (0x03 << 4) 21#define ENGINE_CONFIG_TYPE_SCRATCHPAD (0x06 << 4) 22 |
24/* Valid, slots, version, type, crc */ 25#define CFAM_CONFIG_REG(__VER, __TYPE, __CRC) \ 26 (ENGINE_CONFIG_NEXT | \ 27 0x00010000 | \ 28 (__VER) | \ 29 (__TYPE) | \ 30 (__CRC)) 31 | |
32#define TO_REG(x) ((x) >> 2) 33 | 23#define TO_REG(x) ((x) >> 2) 24 |
25#define CFAM_ENGINE_CONFIG TO_REG(0x04) 26 |
|
34#define CFAM_CONFIG_CHIP_ID TO_REG(0x00) | 27#define CFAM_CONFIG_CHIP_ID TO_REG(0x00) |
35#define CFAM_CONFIG_PEEK_STATUS TO_REG(0x04) | |
36#define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15 37#define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de0000 38 39static uint64_t fsi_cfam_config_read(void *opaque, hwaddr addr, unsigned size) 40{ | 28#define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15 29#define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de0000 30 31static uint64_t fsi_cfam_config_read(void *opaque, hwaddr addr, unsigned size) 32{ |
33 FSICFAMState *cfam = FSI_CFAM(opaque); 34 BusChild *kid; 35 int i; 36 |
|
41 trace_fsi_cfam_config_read(addr, size); 42 43 switch (addr) { 44 case 0x00: 45 return CFAM_CONFIG_CHIP_ID_P9; 46 case 0x04: | 37 trace_fsi_cfam_config_read(addr, size); 38 39 switch (addr) { 40 case 0x00: 41 return CFAM_CONFIG_CHIP_ID_P9; 42 case 0x04: |
47 return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_PEEK, 0xc); | 43 return ENGINE_CONFIG_NEXT | /* valid */ 44 0x00010000 | /* slots */ 45 0x00001000 | /* version */ 46 ENGINE_CONFIG_TYPE_PEEK | /* type */ 47 0x0000000c; /* crc */ |
48 case 0x08: | 48 case 0x08: |
49 return CFAM_CONFIG_REG(0x5000, ENGINE_CONFIG_TYPE_FSI, 0xa); 50 case 0xc: 51 return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_SCRATCHPAD, 0x7); | 49 return ENGINE_CONFIG_NEXT | /* valid */ 50 0x00010000 | /* slots */ 51 0x00005000 | /* version */ 52 ENGINE_CONFIG_TYPE_FSI | /* type */ 53 0x0000000a; /* crc */ 54 break; |
52 default: | 55 default: |
56 /* The config table contains different engines from 0xc onwards. */ 57 i = 0xc; 58 QTAILQ_FOREACH(kid, &cfam->lbus.bus.children, sibling) { 59 if (i == addr) { 60 DeviceState *ds = kid->child; 61 FSILBusDevice *dev = FSI_LBUS_DEVICE(ds); 62 return FSI_LBUS_DEVICE_GET_CLASS(dev)->config; 63 } 64 i += size; 65 } 66 67 if (i == addr) { 68 return 0; 69 } 70 |
|
53 /* | 71 /* |
54 * The config table contains different engines from 0xc onwards. 55 * The scratch pad is already added at address 0xc. We need to add 56 * future engines from address 0x10 onwards. Returning 0 as engine 57 * is not implemented. | 72 * As per FSI specification, This is a magic value at address 0 of 73 * given FSI port. This causes FSI master to send BREAK command for 74 * initialization and recovery. |
58 */ | 75 */ |
59 return 0; | 76 return CFAM_CONFIG_CHIP_ID_BREAK; |
60 } 61} 62 63static void fsi_cfam_config_write(void *opaque, hwaddr addr, uint64_t data, 64 unsigned size) 65{ 66 FSICFAMState *cfam = FSI_CFAM(opaque); 67 68 trace_fsi_cfam_config_write(addr, size, data); 69 70 switch (TO_REG(addr)) { 71 case CFAM_CONFIG_CHIP_ID: | 77 } 78} 79 80static void fsi_cfam_config_write(void *opaque, hwaddr addr, uint64_t data, 81 unsigned size) 82{ 83 FSICFAMState *cfam = FSI_CFAM(opaque); 84 85 trace_fsi_cfam_config_write(addr, size, data); 86 87 switch (TO_REG(addr)) { 88 case CFAM_CONFIG_CHIP_ID: |
72 case CFAM_CONFIG_PEEK_STATUS: | 89 case CFAM_CONFIG_CHIP_ID + 4: |
73 if (data == CFAM_CONFIG_CHIP_ID_BREAK) { 74 bus_cold_reset(BUS(&cfam->lbus)); 75 } | 90 if (data == CFAM_CONFIG_CHIP_ID_BREAK) { 91 bus_cold_reset(BUS(&cfam->lbus)); 92 } |
76 break; | 93 break; |
77 default: 78 trace_fsi_cfam_config_write_noaddr(addr, size, data); 79 } 80} 81 82static const struct MemoryRegionOps cfam_config_ops = { 83 .read = fsi_cfam_config_read, 84 .write = fsi_cfam_config_write, --- 34 unchanged lines hidden (view full) --- 119 120static void fsi_cfam_realize(DeviceState *dev, Error **errp) 121{ 122 FSICFAMState *cfam = FSI_CFAM(dev); 123 FSISlaveState *slave = FSI_SLAVE(dev); 124 125 /* Each slave has a 2MiB address space */ 126 memory_region_init_io(&cfam->mr, OBJECT(cfam), &fsi_cfam_unimplemented_ops, | 94 default: 95 trace_fsi_cfam_config_write_noaddr(addr, size, data); 96 } 97} 98 99static const struct MemoryRegionOps cfam_config_ops = { 100 .read = fsi_cfam_config_read, 101 .write = fsi_cfam_config_write, --- 34 unchanged lines hidden (view full) --- 136 137static void fsi_cfam_realize(DeviceState *dev, Error **errp) 138{ 139 FSICFAMState *cfam = FSI_CFAM(dev); 140 FSISlaveState *slave = FSI_SLAVE(dev); 141 142 /* Each slave has a 2MiB address space */ 143 memory_region_init_io(&cfam->mr, OBJECT(cfam), &fsi_cfam_unimplemented_ops, |
127 cfam, TYPE_FSI_CFAM, 2 * MiB); | 144 cfam, TYPE_FSI_CFAM, 2 * 1024 * 1024); 145 address_space_init(&cfam->as, &cfam->mr, TYPE_FSI_CFAM); |
128 129 qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_FSI_LBUS, DEVICE(cfam), 130 NULL); 131 132 memory_region_init_io(&cfam->config_iomem, OBJECT(cfam), &cfam_config_ops, 133 cfam, TYPE_FSI_CFAM ".config", 0x400); 134 135 memory_region_add_subregion(&cfam->mr, 0, &cfam->config_iomem); 136 memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem); 137 memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr); 138 139 /* Add scratchpad engine */ | 146 147 qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_FSI_LBUS, DEVICE(cfam), 148 NULL); 149 150 memory_region_init_io(&cfam->config_iomem, OBJECT(cfam), &cfam_config_ops, 151 cfam, TYPE_FSI_CFAM ".config", 0x400); 152 153 memory_region_add_subregion(&cfam->mr, 0, &cfam->config_iomem); 154 memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem); 155 memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr); 156 157 /* Add scratchpad engine */ |
140 if (!qdev_realize(DEVICE(&cfam->scratchpad), BUS(&cfam->lbus), errp)) { | 158 if (!qdev_realize_and_unref(DEVICE(&cfam->scratchpad), BUS(&cfam->lbus), 159 errp)) { |
141 return; 142 } 143 | 160 return; 161 } 162 |
163 /* TODO: clarify scratchpad mapping */ |
|
144 FSILBusDevice *fsi_dev = FSI_LBUS_DEVICE(&cfam->scratchpad); 145 memory_region_add_subregion(&cfam->lbus.mr, 0, &fsi_dev->iomem); 146} 147 148static void fsi_cfam_class_init(ObjectClass *klass, void *data) 149{ 150 DeviceClass *dc = DEVICE_CLASS(klass); 151 dc->bus_type = TYPE_FSI_BUS; 152 dc->realize = fsi_cfam_realize; 153} 154 155static const TypeInfo fsi_cfam_info = { 156 .name = TYPE_FSI_CFAM, 157 .parent = TYPE_FSI_SLAVE, 158 .instance_init = fsi_cfam_instance_init, 159 .instance_size = sizeof(FSICFAMState), 160 .class_init = fsi_cfam_class_init, 161}; 162 | 164 FSILBusDevice *fsi_dev = FSI_LBUS_DEVICE(&cfam->scratchpad); 165 memory_region_add_subregion(&cfam->lbus.mr, 0, &fsi_dev->iomem); 166} 167 168static void fsi_cfam_class_init(ObjectClass *klass, void *data) 169{ 170 DeviceClass *dc = DEVICE_CLASS(klass); 171 dc->bus_type = TYPE_FSI_BUS; 172 dc->realize = fsi_cfam_realize; 173} 174 175static const TypeInfo fsi_cfam_info = { 176 .name = TYPE_FSI_CFAM, 177 .parent = TYPE_FSI_SLAVE, 178 .instance_init = fsi_cfam_instance_init, 179 .instance_size = sizeof(FSICFAMState), 180 .class_init = fsi_cfam_class_init, 181}; 182 |
183static uint64_t fsi_scratchpad_read(void *opaque, hwaddr addr, unsigned size) 184{ 185 FSIScratchPad *s = SCRATCHPAD(opaque); 186 187 trace_fsi_scratchpad_read(addr, size); 188 189 if (addr) { 190 return 0; 191 } 192 193 return s->reg; 194} 195 196static void fsi_scratchpad_write(void *opaque, hwaddr addr, uint64_t data, 197 unsigned size) 198{ 199 FSIScratchPad *s = SCRATCHPAD(opaque); 200 201 trace_fsi_scratchpad_write(addr, size, data); 202 203 if (addr) { 204 return; 205 } 206 207 s->reg = data; 208} 209 210static const struct MemoryRegionOps scratchpad_ops = { 211 .read = fsi_scratchpad_read, 212 .write = fsi_scratchpad_write, 213 .endianness = DEVICE_BIG_ENDIAN, 214}; 215 216static void fsi_scratchpad_realize(DeviceState *dev, Error **errp) 217{ 218 FSILBusDevice *ldev = FSI_LBUS_DEVICE(dev); 219 220 memory_region_init_io(&ldev->iomem, OBJECT(ldev), &scratchpad_ops, 221 ldev, TYPE_FSI_SCRATCHPAD, 0x400); 222} 223 224static void fsi_scratchpad_reset(DeviceState *dev) 225{ 226 FSIScratchPad *s = SCRATCHPAD(dev); 227 228 s->reg = 0; 229} 230 231static void fsi_scratchpad_class_init(ObjectClass *klass, void *data) 232{ 233 DeviceClass *dc = DEVICE_CLASS(klass); 234 FSILBusDeviceClass *ldc = FSI_LBUS_DEVICE_CLASS(klass); 235 236 dc->realize = fsi_scratchpad_realize; 237 dc->reset = fsi_scratchpad_reset; 238 239 ldc->config = 240 ENGINE_CONFIG_NEXT | /* valid */ 241 0x00010000 | /* slots */ 242 0x00001000 | /* version */ 243 ENGINE_CONFIG_TYPE_SCRATCHPAD | /* type */ 244 0x00000007; /* crc */ 245} 246 247static const TypeInfo fsi_scratchpad_info = { 248 .name = TYPE_FSI_SCRATCHPAD, 249 .parent = TYPE_FSI_LBUS_DEVICE, 250 .instance_size = sizeof(FSIScratchPad), 251 .class_init = fsi_scratchpad_class_init, 252 .class_size = sizeof(FSILBusDeviceClass), 253}; 254 |
|
163static void fsi_cfam_register_types(void) 164{ | 255static void fsi_cfam_register_types(void) 256{ |
257 type_register_static(&fsi_scratchpad_info); |
|
165 type_register_static(&fsi_cfam_info); 166} 167 168type_init(fsi_cfam_register_types); | 258 type_register_static(&fsi_cfam_info); 259} 260 261type_init(fsi_cfam_register_types); |