1*f5e80be3SNinad Palsule /*
2*f5e80be3SNinad Palsule * SPDX-License-Identifier: GPL-2.0-or-later
3*f5e80be3SNinad Palsule * Copyright (C) 2024 IBM Corp.
4*f5e80be3SNinad Palsule *
5*f5e80be3SNinad Palsule * IBM Common FRU Access Macro
6*f5e80be3SNinad Palsule */
7*f5e80be3SNinad Palsule
8*f5e80be3SNinad Palsule #include "qemu/osdep.h"
9*f5e80be3SNinad Palsule #include "qemu/units.h"
10*f5e80be3SNinad Palsule
11*f5e80be3SNinad Palsule #include "qapi/error.h"
12*f5e80be3SNinad Palsule #include "trace.h"
13*f5e80be3SNinad Palsule
14*f5e80be3SNinad Palsule #include "hw/fsi/cfam.h"
15*f5e80be3SNinad Palsule #include "hw/fsi/fsi.h"
16*f5e80be3SNinad Palsule
17*f5e80be3SNinad Palsule #include "hw/qdev-properties.h"
18*f5e80be3SNinad Palsule
19*f5e80be3SNinad Palsule #define ENGINE_CONFIG_NEXT BIT(31)
20*f5e80be3SNinad Palsule #define ENGINE_CONFIG_TYPE_PEEK (0x02 << 4)
21*f5e80be3SNinad Palsule #define ENGINE_CONFIG_TYPE_FSI (0x03 << 4)
22*f5e80be3SNinad Palsule #define ENGINE_CONFIG_TYPE_SCRATCHPAD (0x06 << 4)
23*f5e80be3SNinad Palsule
24*f5e80be3SNinad Palsule /* Valid, slots, version, type, crc */
25*f5e80be3SNinad Palsule #define CFAM_CONFIG_REG(__VER, __TYPE, __CRC) \
26*f5e80be3SNinad Palsule (ENGINE_CONFIG_NEXT | \
27*f5e80be3SNinad Palsule 0x00010000 | \
28*f5e80be3SNinad Palsule (__VER) | \
29*f5e80be3SNinad Palsule (__TYPE) | \
30*f5e80be3SNinad Palsule (__CRC))
31*f5e80be3SNinad Palsule
32*f5e80be3SNinad Palsule #define TO_REG(x) ((x) >> 2)
33*f5e80be3SNinad Palsule
34*f5e80be3SNinad Palsule #define CFAM_CONFIG_CHIP_ID TO_REG(0x00)
35*f5e80be3SNinad Palsule #define CFAM_CONFIG_PEEK_STATUS TO_REG(0x04)
36*f5e80be3SNinad Palsule #define CFAM_CONFIG_CHIP_ID_P9 0xc0022d15
37*f5e80be3SNinad Palsule #define CFAM_CONFIG_CHIP_ID_BREAK 0xc0de0000
38*f5e80be3SNinad Palsule
fsi_cfam_config_read(void * opaque,hwaddr addr,unsigned size)39*f5e80be3SNinad Palsule static uint64_t fsi_cfam_config_read(void *opaque, hwaddr addr, unsigned size)
40*f5e80be3SNinad Palsule {
41*f5e80be3SNinad Palsule trace_fsi_cfam_config_read(addr, size);
42*f5e80be3SNinad Palsule
43*f5e80be3SNinad Palsule switch (addr) {
44*f5e80be3SNinad Palsule case 0x00:
45*f5e80be3SNinad Palsule return CFAM_CONFIG_CHIP_ID_P9;
46*f5e80be3SNinad Palsule case 0x04:
47*f5e80be3SNinad Palsule return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_PEEK, 0xc);
48*f5e80be3SNinad Palsule case 0x08:
49*f5e80be3SNinad Palsule return CFAM_CONFIG_REG(0x5000, ENGINE_CONFIG_TYPE_FSI, 0xa);
50*f5e80be3SNinad Palsule case 0xc:
51*f5e80be3SNinad Palsule return CFAM_CONFIG_REG(0x1000, ENGINE_CONFIG_TYPE_SCRATCHPAD, 0x7);
52*f5e80be3SNinad Palsule default:
53*f5e80be3SNinad Palsule /*
54*f5e80be3SNinad Palsule * The config table contains different engines from 0xc onwards.
55*f5e80be3SNinad Palsule * The scratch pad is already added at address 0xc. We need to add
56*f5e80be3SNinad Palsule * future engines from address 0x10 onwards. Returning 0 as engine
57*f5e80be3SNinad Palsule * is not implemented.
58*f5e80be3SNinad Palsule */
59*f5e80be3SNinad Palsule return 0;
60*f5e80be3SNinad Palsule }
61*f5e80be3SNinad Palsule }
62*f5e80be3SNinad Palsule
fsi_cfam_config_write(void * opaque,hwaddr addr,uint64_t data,unsigned size)63*f5e80be3SNinad Palsule static void fsi_cfam_config_write(void *opaque, hwaddr addr, uint64_t data,
64*f5e80be3SNinad Palsule unsigned size)
65*f5e80be3SNinad Palsule {
66*f5e80be3SNinad Palsule FSICFAMState *cfam = FSI_CFAM(opaque);
67*f5e80be3SNinad Palsule
68*f5e80be3SNinad Palsule trace_fsi_cfam_config_write(addr, size, data);
69*f5e80be3SNinad Palsule
70*f5e80be3SNinad Palsule switch (TO_REG(addr)) {
71*f5e80be3SNinad Palsule case CFAM_CONFIG_CHIP_ID:
72*f5e80be3SNinad Palsule case CFAM_CONFIG_PEEK_STATUS:
73*f5e80be3SNinad Palsule if (data == CFAM_CONFIG_CHIP_ID_BREAK) {
74*f5e80be3SNinad Palsule bus_cold_reset(BUS(&cfam->lbus));
75*f5e80be3SNinad Palsule }
76*f5e80be3SNinad Palsule break;
77*f5e80be3SNinad Palsule default:
78*f5e80be3SNinad Palsule trace_fsi_cfam_config_write_noaddr(addr, size, data);
79*f5e80be3SNinad Palsule }
80*f5e80be3SNinad Palsule }
81*f5e80be3SNinad Palsule
82*f5e80be3SNinad Palsule static const struct MemoryRegionOps cfam_config_ops = {
83*f5e80be3SNinad Palsule .read = fsi_cfam_config_read,
84*f5e80be3SNinad Palsule .write = fsi_cfam_config_write,
85*f5e80be3SNinad Palsule .valid.max_access_size = 4,
86*f5e80be3SNinad Palsule .valid.min_access_size = 4,
87*f5e80be3SNinad Palsule .impl.max_access_size = 4,
88*f5e80be3SNinad Palsule .impl.min_access_size = 4,
89*f5e80be3SNinad Palsule .endianness = DEVICE_BIG_ENDIAN,
90*f5e80be3SNinad Palsule };
91*f5e80be3SNinad Palsule
fsi_cfam_unimplemented_read(void * opaque,hwaddr addr,unsigned size)92*f5e80be3SNinad Palsule static uint64_t fsi_cfam_unimplemented_read(void *opaque, hwaddr addr,
93*f5e80be3SNinad Palsule unsigned size)
94*f5e80be3SNinad Palsule {
95*f5e80be3SNinad Palsule trace_fsi_cfam_unimplemented_read(addr, size);
96*f5e80be3SNinad Palsule
97*f5e80be3SNinad Palsule return 0;
98*f5e80be3SNinad Palsule }
99*f5e80be3SNinad Palsule
fsi_cfam_unimplemented_write(void * opaque,hwaddr addr,uint64_t data,unsigned size)100*f5e80be3SNinad Palsule static void fsi_cfam_unimplemented_write(void *opaque, hwaddr addr,
101*f5e80be3SNinad Palsule uint64_t data, unsigned size)
102*f5e80be3SNinad Palsule {
103*f5e80be3SNinad Palsule trace_fsi_cfam_unimplemented_write(addr, size, data);
104*f5e80be3SNinad Palsule }
105*f5e80be3SNinad Palsule
106*f5e80be3SNinad Palsule static const struct MemoryRegionOps fsi_cfam_unimplemented_ops = {
107*f5e80be3SNinad Palsule .read = fsi_cfam_unimplemented_read,
108*f5e80be3SNinad Palsule .write = fsi_cfam_unimplemented_write,
109*f5e80be3SNinad Palsule .endianness = DEVICE_BIG_ENDIAN,
110*f5e80be3SNinad Palsule };
111*f5e80be3SNinad Palsule
fsi_cfam_instance_init(Object * obj)112*f5e80be3SNinad Palsule static void fsi_cfam_instance_init(Object *obj)
113*f5e80be3SNinad Palsule {
114*f5e80be3SNinad Palsule FSICFAMState *s = FSI_CFAM(obj);
115*f5e80be3SNinad Palsule
116*f5e80be3SNinad Palsule object_initialize_child(obj, "scratchpad", &s->scratchpad,
117*f5e80be3SNinad Palsule TYPE_FSI_SCRATCHPAD);
118*f5e80be3SNinad Palsule }
119*f5e80be3SNinad Palsule
fsi_cfam_realize(DeviceState * dev,Error ** errp)120*f5e80be3SNinad Palsule static void fsi_cfam_realize(DeviceState *dev, Error **errp)
121*f5e80be3SNinad Palsule {
122*f5e80be3SNinad Palsule FSICFAMState *cfam = FSI_CFAM(dev);
123*f5e80be3SNinad Palsule FSISlaveState *slave = FSI_SLAVE(dev);
124*f5e80be3SNinad Palsule
125*f5e80be3SNinad Palsule /* Each slave has a 2MiB address space */
126*f5e80be3SNinad Palsule memory_region_init_io(&cfam->mr, OBJECT(cfam), &fsi_cfam_unimplemented_ops,
127*f5e80be3SNinad Palsule cfam, TYPE_FSI_CFAM, 2 * MiB);
128*f5e80be3SNinad Palsule
129*f5e80be3SNinad Palsule qbus_init(&cfam->lbus, sizeof(cfam->lbus), TYPE_FSI_LBUS, DEVICE(cfam),
130*f5e80be3SNinad Palsule NULL);
131*f5e80be3SNinad Palsule
132*f5e80be3SNinad Palsule memory_region_init_io(&cfam->config_iomem, OBJECT(cfam), &cfam_config_ops,
133*f5e80be3SNinad Palsule cfam, TYPE_FSI_CFAM ".config", 0x400);
134*f5e80be3SNinad Palsule
135*f5e80be3SNinad Palsule memory_region_add_subregion(&cfam->mr, 0, &cfam->config_iomem);
136*f5e80be3SNinad Palsule memory_region_add_subregion(&cfam->mr, 0x800, &slave->iomem);
137*f5e80be3SNinad Palsule memory_region_add_subregion(&cfam->mr, 0xc00, &cfam->lbus.mr);
138*f5e80be3SNinad Palsule
139*f5e80be3SNinad Palsule /* Add scratchpad engine */
140*f5e80be3SNinad Palsule if (!qdev_realize(DEVICE(&cfam->scratchpad), BUS(&cfam->lbus), errp)) {
141*f5e80be3SNinad Palsule return;
142*f5e80be3SNinad Palsule }
143*f5e80be3SNinad Palsule
144*f5e80be3SNinad Palsule FSILBusDevice *fsi_dev = FSI_LBUS_DEVICE(&cfam->scratchpad);
145*f5e80be3SNinad Palsule memory_region_add_subregion(&cfam->lbus.mr, 0, &fsi_dev->iomem);
146*f5e80be3SNinad Palsule }
147*f5e80be3SNinad Palsule
fsi_cfam_class_init(ObjectClass * klass,void * data)148*f5e80be3SNinad Palsule static void fsi_cfam_class_init(ObjectClass *klass, void *data)
149*f5e80be3SNinad Palsule {
150*f5e80be3SNinad Palsule DeviceClass *dc = DEVICE_CLASS(klass);
151*f5e80be3SNinad Palsule dc->bus_type = TYPE_FSI_BUS;
152*f5e80be3SNinad Palsule dc->realize = fsi_cfam_realize;
153*f5e80be3SNinad Palsule }
154*f5e80be3SNinad Palsule
155*f5e80be3SNinad Palsule static const TypeInfo fsi_cfam_info = {
156*f5e80be3SNinad Palsule .name = TYPE_FSI_CFAM,
157*f5e80be3SNinad Palsule .parent = TYPE_FSI_SLAVE,
158*f5e80be3SNinad Palsule .instance_init = fsi_cfam_instance_init,
159*f5e80be3SNinad Palsule .instance_size = sizeof(FSICFAMState),
160*f5e80be3SNinad Palsule .class_init = fsi_cfam_class_init,
161*f5e80be3SNinad Palsule };
162*f5e80be3SNinad Palsule
fsi_cfam_register_types(void)163*f5e80be3SNinad Palsule static void fsi_cfam_register_types(void)
164*f5e80be3SNinad Palsule {
165*f5e80be3SNinad Palsule type_register_static(&fsi_cfam_info);
166*f5e80be3SNinad Palsule }
167*f5e80be3SNinad Palsule
168*f5e80be3SNinad Palsule type_init(fsi_cfam_register_types);
169*f5e80be3SNinad Palsule