1*7c1c69bcSCédric Le Goater /* 2*7c1c69bcSCédric Le Goater * ASPEED AST2400 SMC Controller (SPI Flash Only) 3*7c1c69bcSCédric Le Goater * 4*7c1c69bcSCédric Le Goater * Copyright (C) 2016 IBM Corp. 5*7c1c69bcSCédric Le Goater * 6*7c1c69bcSCédric Le Goater * Permission is hereby granted, free of charge, to any person obtaining a copy 7*7c1c69bcSCédric Le Goater * of this software and associated documentation files (the "Software"), to deal 8*7c1c69bcSCédric Le Goater * in the Software without restriction, including without limitation the rights 9*7c1c69bcSCédric Le Goater * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10*7c1c69bcSCédric Le Goater * copies of the Software, and to permit persons to whom the Software is 11*7c1c69bcSCédric Le Goater * furnished to do so, subject to the following conditions: 12*7c1c69bcSCédric Le Goater * 13*7c1c69bcSCédric Le Goater * The above copyright notice and this permission notice shall be included in 14*7c1c69bcSCédric Le Goater * all copies or substantial portions of the Software. 15*7c1c69bcSCédric Le Goater * 16*7c1c69bcSCédric Le Goater * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17*7c1c69bcSCédric Le Goater * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18*7c1c69bcSCédric Le Goater * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19*7c1c69bcSCédric Le Goater * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20*7c1c69bcSCédric Le Goater * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21*7c1c69bcSCédric Le Goater * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22*7c1c69bcSCédric Le Goater * THE SOFTWARE. 23*7c1c69bcSCédric Le Goater */ 24*7c1c69bcSCédric Le Goater 25*7c1c69bcSCédric Le Goater #include "qemu/osdep.h" 26*7c1c69bcSCédric Le Goater #include "hw/sysbus.h" 27*7c1c69bcSCédric Le Goater #include "sysemu/sysemu.h" 28*7c1c69bcSCédric Le Goater #include "qemu/log.h" 29*7c1c69bcSCédric Le Goater #include "include/qemu/error-report.h" 30*7c1c69bcSCédric Le Goater #include "exec/address-spaces.h" 31*7c1c69bcSCédric Le Goater 32*7c1c69bcSCédric Le Goater #include "hw/ssi/aspeed_smc.h" 33*7c1c69bcSCédric Le Goater 34*7c1c69bcSCédric Le Goater /* CE Type Setting Register */ 35*7c1c69bcSCédric Le Goater #define R_CONF (0x00 / 4) 36*7c1c69bcSCédric Le Goater #define CONF_LEGACY_DISABLE (1 << 31) 37*7c1c69bcSCédric Le Goater #define CONF_ENABLE_W4 20 38*7c1c69bcSCédric Le Goater #define CONF_ENABLE_W3 19 39*7c1c69bcSCédric Le Goater #define CONF_ENABLE_W2 18 40*7c1c69bcSCédric Le Goater #define CONF_ENABLE_W1 17 41*7c1c69bcSCédric Le Goater #define CONF_ENABLE_W0 16 42*7c1c69bcSCédric Le Goater #define CONF_FLASH_TYPE4 9 43*7c1c69bcSCédric Le Goater #define CONF_FLASH_TYPE3 7 44*7c1c69bcSCédric Le Goater #define CONF_FLASH_TYPE2 5 45*7c1c69bcSCédric Le Goater #define CONF_FLASH_TYPE1 3 46*7c1c69bcSCédric Le Goater #define CONF_FLASH_TYPE0 1 47*7c1c69bcSCédric Le Goater 48*7c1c69bcSCédric Le Goater /* CE Control Register */ 49*7c1c69bcSCédric Le Goater #define R_CE_CTRL (0x04 / 4) 50*7c1c69bcSCédric Le Goater #define CTRL_EXTENDED4 4 /* 32 bit addressing for SPI */ 51*7c1c69bcSCédric Le Goater #define CTRL_EXTENDED3 3 /* 32 bit addressing for SPI */ 52*7c1c69bcSCédric Le Goater #define CTRL_EXTENDED2 2 /* 32 bit addressing for SPI */ 53*7c1c69bcSCédric Le Goater #define CTRL_EXTENDED1 1 /* 32 bit addressing for SPI */ 54*7c1c69bcSCédric Le Goater #define CTRL_EXTENDED0 0 /* 32 bit addressing for SPI */ 55*7c1c69bcSCédric Le Goater 56*7c1c69bcSCédric Le Goater /* Interrupt Control and Status Register */ 57*7c1c69bcSCédric Le Goater #define R_INTR_CTRL (0x08 / 4) 58*7c1c69bcSCédric Le Goater #define INTR_CTRL_DMA_STATUS (1 << 11) 59*7c1c69bcSCédric Le Goater #define INTR_CTRL_CMD_ABORT_STATUS (1 << 10) 60*7c1c69bcSCédric Le Goater #define INTR_CTRL_WRITE_PROTECT_STATUS (1 << 9) 61*7c1c69bcSCédric Le Goater #define INTR_CTRL_DMA_EN (1 << 3) 62*7c1c69bcSCédric Le Goater #define INTR_CTRL_CMD_ABORT_EN (1 << 2) 63*7c1c69bcSCédric Le Goater #define INTR_CTRL_WRITE_PROTECT_EN (1 << 1) 64*7c1c69bcSCédric Le Goater 65*7c1c69bcSCédric Le Goater /* CEx Control Register */ 66*7c1c69bcSCédric Le Goater #define R_CTRL0 (0x10 / 4) 67*7c1c69bcSCédric Le Goater #define CTRL_CMD_SHIFT 16 68*7c1c69bcSCédric Le Goater #define CTRL_CMD_MASK 0xff 69*7c1c69bcSCédric Le Goater #define CTRL_CE_STOP_ACTIVE (1 << 2) 70*7c1c69bcSCédric Le Goater #define CTRL_CMD_MODE_MASK 0x3 71*7c1c69bcSCédric Le Goater #define CTRL_READMODE 0x0 72*7c1c69bcSCédric Le Goater #define CTRL_FREADMODE 0x1 73*7c1c69bcSCédric Le Goater #define CTRL_WRITEMODE 0x2 74*7c1c69bcSCédric Le Goater #define CTRL_USERMODE 0x3 75*7c1c69bcSCédric Le Goater #define R_CTRL1 (0x14 / 4) 76*7c1c69bcSCédric Le Goater #define R_CTRL2 (0x18 / 4) 77*7c1c69bcSCédric Le Goater #define R_CTRL3 (0x1C / 4) 78*7c1c69bcSCédric Le Goater #define R_CTRL4 (0x20 / 4) 79*7c1c69bcSCédric Le Goater 80*7c1c69bcSCédric Le Goater /* CEx Segment Address Register */ 81*7c1c69bcSCédric Le Goater #define R_SEG_ADDR0 (0x30 / 4) 82*7c1c69bcSCédric Le Goater #define SEG_SIZE_SHIFT 24 /* 8MB units */ 83*7c1c69bcSCédric Le Goater #define SEG_SIZE_MASK 0x7f 84*7c1c69bcSCédric Le Goater #define SEG_START_SHIFT 16 /* address bit [A29-A23] */ 85*7c1c69bcSCédric Le Goater #define SEG_START_MASK 0x7f 86*7c1c69bcSCédric Le Goater #define R_SEG_ADDR1 (0x34 / 4) 87*7c1c69bcSCédric Le Goater #define R_SEG_ADDR2 (0x38 / 4) 88*7c1c69bcSCédric Le Goater #define R_SEG_ADDR3 (0x3C / 4) 89*7c1c69bcSCédric Le Goater #define R_SEG_ADDR4 (0x40 / 4) 90*7c1c69bcSCédric Le Goater 91*7c1c69bcSCédric Le Goater /* Misc Control Register #1 */ 92*7c1c69bcSCédric Le Goater #define R_MISC_CTRL1 (0x50 / 4) 93*7c1c69bcSCédric Le Goater 94*7c1c69bcSCédric Le Goater /* Misc Control Register #2 */ 95*7c1c69bcSCédric Le Goater #define R_MISC_CTRL2 (0x54 / 4) 96*7c1c69bcSCédric Le Goater 97*7c1c69bcSCédric Le Goater /* DMA Control/Status Register */ 98*7c1c69bcSCédric Le Goater #define R_DMA_CTRL (0x80 / 4) 99*7c1c69bcSCédric Le Goater #define DMA_CTRL_DELAY_MASK 0xf 100*7c1c69bcSCédric Le Goater #define DMA_CTRL_DELAY_SHIFT 8 101*7c1c69bcSCédric Le Goater #define DMA_CTRL_FREQ_MASK 0xf 102*7c1c69bcSCédric Le Goater #define DMA_CTRL_FREQ_SHIFT 4 103*7c1c69bcSCédric Le Goater #define DMA_CTRL_MODE (1 << 3) 104*7c1c69bcSCédric Le Goater #define DMA_CTRL_CKSUM (1 << 2) 105*7c1c69bcSCédric Le Goater #define DMA_CTRL_DIR (1 << 1) 106*7c1c69bcSCédric Le Goater #define DMA_CTRL_EN (1 << 0) 107*7c1c69bcSCédric Le Goater 108*7c1c69bcSCédric Le Goater /* DMA Flash Side Address */ 109*7c1c69bcSCédric Le Goater #define R_DMA_FLASH_ADDR (0x84 / 4) 110*7c1c69bcSCédric Le Goater 111*7c1c69bcSCédric Le Goater /* DMA DRAM Side Address */ 112*7c1c69bcSCédric Le Goater #define R_DMA_DRAM_ADDR (0x88 / 4) 113*7c1c69bcSCédric Le Goater 114*7c1c69bcSCédric Le Goater /* DMA Length Register */ 115*7c1c69bcSCédric Le Goater #define R_DMA_LEN (0x8C / 4) 116*7c1c69bcSCédric Le Goater 117*7c1c69bcSCédric Le Goater /* Checksum Calculation Result */ 118*7c1c69bcSCédric Le Goater #define R_DMA_CHECKSUM (0x90 / 4) 119*7c1c69bcSCédric Le Goater 120*7c1c69bcSCédric Le Goater /* Misc Control Register #2 */ 121*7c1c69bcSCédric Le Goater #define R_TIMINGS (0x94 / 4) 122*7c1c69bcSCédric Le Goater 123*7c1c69bcSCédric Le Goater /* SPI controller registers and bits */ 124*7c1c69bcSCédric Le Goater #define R_SPI_CONF (0x00 / 4) 125*7c1c69bcSCédric Le Goater #define SPI_CONF_ENABLE_W0 0 126*7c1c69bcSCédric Le Goater #define R_SPI_CTRL0 (0x4 / 4) 127*7c1c69bcSCédric Le Goater #define R_SPI_MISC_CTRL (0x10 / 4) 128*7c1c69bcSCédric Le Goater #define R_SPI_TIMINGS (0x14 / 4) 129*7c1c69bcSCédric Le Goater 130*7c1c69bcSCédric Le Goater static const AspeedSMCController controllers[] = { 131*7c1c69bcSCédric Le Goater { "aspeed.smc.smc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS, 132*7c1c69bcSCédric Le Goater CONF_ENABLE_W0, 5 }, 133*7c1c69bcSCédric Le Goater { "aspeed.smc.fmc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS, 134*7c1c69bcSCédric Le Goater CONF_ENABLE_W0, 5 }, 135*7c1c69bcSCédric Le Goater { "aspeed.smc.spi", R_SPI_CONF, 0xff, R_SPI_CTRL0, R_SPI_TIMINGS, 136*7c1c69bcSCédric Le Goater SPI_CONF_ENABLE_W0, 1 }, 137*7c1c69bcSCédric Le Goater }; 138*7c1c69bcSCédric Le Goater 139*7c1c69bcSCédric Le Goater static bool aspeed_smc_is_ce_stop_active(const AspeedSMCState *s, int cs) 140*7c1c69bcSCédric Le Goater { 141*7c1c69bcSCédric Le Goater return s->regs[s->r_ctrl0 + cs] & CTRL_CE_STOP_ACTIVE; 142*7c1c69bcSCédric Le Goater } 143*7c1c69bcSCédric Le Goater 144*7c1c69bcSCédric Le Goater static void aspeed_smc_update_cs(const AspeedSMCState *s) 145*7c1c69bcSCédric Le Goater { 146*7c1c69bcSCédric Le Goater int i; 147*7c1c69bcSCédric Le Goater 148*7c1c69bcSCédric Le Goater for (i = 0; i < s->num_cs; ++i) { 149*7c1c69bcSCédric Le Goater qemu_set_irq(s->cs_lines[i], aspeed_smc_is_ce_stop_active(s, i)); 150*7c1c69bcSCédric Le Goater } 151*7c1c69bcSCédric Le Goater } 152*7c1c69bcSCédric Le Goater 153*7c1c69bcSCédric Le Goater static void aspeed_smc_reset(DeviceState *d) 154*7c1c69bcSCédric Le Goater { 155*7c1c69bcSCédric Le Goater AspeedSMCState *s = ASPEED_SMC(d); 156*7c1c69bcSCédric Le Goater int i; 157*7c1c69bcSCédric Le Goater 158*7c1c69bcSCédric Le Goater memset(s->regs, 0, sizeof s->regs); 159*7c1c69bcSCédric Le Goater 160*7c1c69bcSCédric Le Goater /* Unselect all slaves */ 161*7c1c69bcSCédric Le Goater for (i = 0; i < s->num_cs; ++i) { 162*7c1c69bcSCédric Le Goater s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE; 163*7c1c69bcSCédric Le Goater } 164*7c1c69bcSCédric Le Goater 165*7c1c69bcSCédric Le Goater aspeed_smc_update_cs(s); 166*7c1c69bcSCédric Le Goater } 167*7c1c69bcSCédric Le Goater 168*7c1c69bcSCédric Le Goater static bool aspeed_smc_is_implemented(AspeedSMCState *s, hwaddr addr) 169*7c1c69bcSCédric Le Goater { 170*7c1c69bcSCédric Le Goater return (addr == s->r_conf || addr == s->r_timings || addr == s->r_ce_ctrl || 171*7c1c69bcSCédric Le Goater (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs)); 172*7c1c69bcSCédric Le Goater } 173*7c1c69bcSCédric Le Goater 174*7c1c69bcSCédric Le Goater static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size) 175*7c1c69bcSCédric Le Goater { 176*7c1c69bcSCédric Le Goater AspeedSMCState *s = ASPEED_SMC(opaque); 177*7c1c69bcSCédric Le Goater 178*7c1c69bcSCédric Le Goater addr >>= 2; 179*7c1c69bcSCédric Le Goater 180*7c1c69bcSCédric Le Goater if (addr >= ARRAY_SIZE(s->regs)) { 181*7c1c69bcSCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, 182*7c1c69bcSCédric Le Goater "%s: Out-of-bounds read at 0x%" HWADDR_PRIx "\n", 183*7c1c69bcSCédric Le Goater __func__, addr); 184*7c1c69bcSCédric Le Goater return 0; 185*7c1c69bcSCédric Le Goater } 186*7c1c69bcSCédric Le Goater 187*7c1c69bcSCédric Le Goater if (!aspeed_smc_is_implemented(s, addr)) { 188*7c1c69bcSCédric Le Goater qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n", 189*7c1c69bcSCédric Le Goater __func__, addr); 190*7c1c69bcSCédric Le Goater return 0; 191*7c1c69bcSCédric Le Goater } 192*7c1c69bcSCédric Le Goater 193*7c1c69bcSCédric Le Goater return s->regs[addr]; 194*7c1c69bcSCédric Le Goater } 195*7c1c69bcSCédric Le Goater 196*7c1c69bcSCédric Le Goater static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data, 197*7c1c69bcSCédric Le Goater unsigned int size) 198*7c1c69bcSCédric Le Goater { 199*7c1c69bcSCédric Le Goater AspeedSMCState *s = ASPEED_SMC(opaque); 200*7c1c69bcSCédric Le Goater uint32_t value = data; 201*7c1c69bcSCédric Le Goater 202*7c1c69bcSCédric Le Goater addr >>= 2; 203*7c1c69bcSCédric Le Goater 204*7c1c69bcSCédric Le Goater if (addr >= ARRAY_SIZE(s->regs)) { 205*7c1c69bcSCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, 206*7c1c69bcSCédric Le Goater "%s: Out-of-bounds write at 0x%" HWADDR_PRIx "\n", 207*7c1c69bcSCédric Le Goater __func__, addr); 208*7c1c69bcSCédric Le Goater return; 209*7c1c69bcSCédric Le Goater } 210*7c1c69bcSCédric Le Goater 211*7c1c69bcSCédric Le Goater if (!aspeed_smc_is_implemented(s, addr)) { 212*7c1c69bcSCédric Le Goater qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n", 213*7c1c69bcSCédric Le Goater __func__, addr); 214*7c1c69bcSCédric Le Goater return; 215*7c1c69bcSCédric Le Goater } 216*7c1c69bcSCédric Le Goater 217*7c1c69bcSCédric Le Goater /* 218*7c1c69bcSCédric Le Goater * Not much to do apart from storing the value and set the cs 219*7c1c69bcSCédric Le Goater * lines if the register is a controlling one. 220*7c1c69bcSCédric Le Goater */ 221*7c1c69bcSCédric Le Goater s->regs[addr] = value; 222*7c1c69bcSCédric Le Goater if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) { 223*7c1c69bcSCédric Le Goater aspeed_smc_update_cs(s); 224*7c1c69bcSCédric Le Goater } 225*7c1c69bcSCédric Le Goater } 226*7c1c69bcSCédric Le Goater 227*7c1c69bcSCédric Le Goater static const MemoryRegionOps aspeed_smc_ops = { 228*7c1c69bcSCédric Le Goater .read = aspeed_smc_read, 229*7c1c69bcSCédric Le Goater .write = aspeed_smc_write, 230*7c1c69bcSCédric Le Goater .endianness = DEVICE_LITTLE_ENDIAN, 231*7c1c69bcSCédric Le Goater .valid.unaligned = true, 232*7c1c69bcSCédric Le Goater }; 233*7c1c69bcSCédric Le Goater 234*7c1c69bcSCédric Le Goater static void aspeed_smc_realize(DeviceState *dev, Error **errp) 235*7c1c69bcSCédric Le Goater { 236*7c1c69bcSCédric Le Goater SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 237*7c1c69bcSCédric Le Goater AspeedSMCState *s = ASPEED_SMC(dev); 238*7c1c69bcSCédric Le Goater AspeedSMCClass *mc = ASPEED_SMC_GET_CLASS(s); 239*7c1c69bcSCédric Le Goater int i; 240*7c1c69bcSCédric Le Goater 241*7c1c69bcSCédric Le Goater s->ctrl = mc->ctrl; 242*7c1c69bcSCédric Le Goater 243*7c1c69bcSCédric Le Goater /* keep a copy under AspeedSMCState to speed up accesses */ 244*7c1c69bcSCédric Le Goater s->r_conf = s->ctrl->r_conf; 245*7c1c69bcSCédric Le Goater s->r_ce_ctrl = s->ctrl->r_ce_ctrl; 246*7c1c69bcSCédric Le Goater s->r_ctrl0 = s->ctrl->r_ctrl0; 247*7c1c69bcSCédric Le Goater s->r_timings = s->ctrl->r_timings; 248*7c1c69bcSCédric Le Goater s->conf_enable_w0 = s->ctrl->conf_enable_w0; 249*7c1c69bcSCédric Le Goater 250*7c1c69bcSCédric Le Goater /* Enforce some real HW limits */ 251*7c1c69bcSCédric Le Goater if (s->num_cs > s->ctrl->max_slaves) { 252*7c1c69bcSCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, "%s: num_cs cannot exceed: %d\n", 253*7c1c69bcSCédric Le Goater __func__, s->ctrl->max_slaves); 254*7c1c69bcSCédric Le Goater s->num_cs = s->ctrl->max_slaves; 255*7c1c69bcSCédric Le Goater } 256*7c1c69bcSCédric Le Goater 257*7c1c69bcSCédric Le Goater s->spi = ssi_create_bus(dev, "spi"); 258*7c1c69bcSCédric Le Goater 259*7c1c69bcSCédric Le Goater /* Setup cs_lines for slaves */ 260*7c1c69bcSCédric Le Goater sysbus_init_irq(sbd, &s->irq); 261*7c1c69bcSCédric Le Goater s->cs_lines = g_new0(qemu_irq, s->num_cs); 262*7c1c69bcSCédric Le Goater ssi_auto_connect_slaves(dev, s->cs_lines, s->spi); 263*7c1c69bcSCédric Le Goater 264*7c1c69bcSCédric Le Goater for (i = 0; i < s->num_cs; ++i) { 265*7c1c69bcSCédric Le Goater sysbus_init_irq(sbd, &s->cs_lines[i]); 266*7c1c69bcSCédric Le Goater } 267*7c1c69bcSCédric Le Goater 268*7c1c69bcSCédric Le Goater aspeed_smc_reset(dev); 269*7c1c69bcSCédric Le Goater 270*7c1c69bcSCédric Le Goater memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_ops, s, 271*7c1c69bcSCédric Le Goater s->ctrl->name, ASPEED_SMC_R_MAX * 4); 272*7c1c69bcSCédric Le Goater sysbus_init_mmio(sbd, &s->mmio); 273*7c1c69bcSCédric Le Goater } 274*7c1c69bcSCédric Le Goater 275*7c1c69bcSCédric Le Goater static const VMStateDescription vmstate_aspeed_smc = { 276*7c1c69bcSCédric Le Goater .name = "aspeed.smc", 277*7c1c69bcSCédric Le Goater .version_id = 1, 278*7c1c69bcSCédric Le Goater .minimum_version_id = 1, 279*7c1c69bcSCédric Le Goater .fields = (VMStateField[]) { 280*7c1c69bcSCédric Le Goater VMSTATE_UINT32_ARRAY(regs, AspeedSMCState, ASPEED_SMC_R_MAX), 281*7c1c69bcSCédric Le Goater VMSTATE_END_OF_LIST() 282*7c1c69bcSCédric Le Goater } 283*7c1c69bcSCédric Le Goater }; 284*7c1c69bcSCédric Le Goater 285*7c1c69bcSCédric Le Goater static Property aspeed_smc_properties[] = { 286*7c1c69bcSCédric Le Goater DEFINE_PROP_UINT32("num-cs", AspeedSMCState, num_cs, 1), 287*7c1c69bcSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 288*7c1c69bcSCédric Le Goater }; 289*7c1c69bcSCédric Le Goater 290*7c1c69bcSCédric Le Goater static void aspeed_smc_class_init(ObjectClass *klass, void *data) 291*7c1c69bcSCédric Le Goater { 292*7c1c69bcSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 293*7c1c69bcSCédric Le Goater AspeedSMCClass *mc = ASPEED_SMC_CLASS(klass); 294*7c1c69bcSCédric Le Goater 295*7c1c69bcSCédric Le Goater dc->realize = aspeed_smc_realize; 296*7c1c69bcSCédric Le Goater dc->reset = aspeed_smc_reset; 297*7c1c69bcSCédric Le Goater dc->props = aspeed_smc_properties; 298*7c1c69bcSCédric Le Goater dc->vmsd = &vmstate_aspeed_smc; 299*7c1c69bcSCédric Le Goater mc->ctrl = data; 300*7c1c69bcSCédric Le Goater } 301*7c1c69bcSCédric Le Goater 302*7c1c69bcSCédric Le Goater static const TypeInfo aspeed_smc_info = { 303*7c1c69bcSCédric Le Goater .name = TYPE_ASPEED_SMC, 304*7c1c69bcSCédric Le Goater .parent = TYPE_SYS_BUS_DEVICE, 305*7c1c69bcSCédric Le Goater .instance_size = sizeof(AspeedSMCState), 306*7c1c69bcSCédric Le Goater .class_size = sizeof(AspeedSMCClass), 307*7c1c69bcSCédric Le Goater .abstract = true, 308*7c1c69bcSCédric Le Goater }; 309*7c1c69bcSCédric Le Goater 310*7c1c69bcSCédric Le Goater static void aspeed_smc_register_types(void) 311*7c1c69bcSCédric Le Goater { 312*7c1c69bcSCédric Le Goater int i; 313*7c1c69bcSCédric Le Goater 314*7c1c69bcSCédric Le Goater type_register_static(&aspeed_smc_info); 315*7c1c69bcSCédric Le Goater for (i = 0; i < ARRAY_SIZE(controllers); ++i) { 316*7c1c69bcSCédric Le Goater TypeInfo ti = { 317*7c1c69bcSCédric Le Goater .name = controllers[i].name, 318*7c1c69bcSCédric Le Goater .parent = TYPE_ASPEED_SMC, 319*7c1c69bcSCédric Le Goater .class_init = aspeed_smc_class_init, 320*7c1c69bcSCédric Le Goater .class_data = (void *)&controllers[i], 321*7c1c69bcSCédric Le Goater }; 322*7c1c69bcSCédric Le Goater type_register(&ti); 323*7c1c69bcSCédric Le Goater } 324*7c1c69bcSCédric Le Goater } 325*7c1c69bcSCédric Le Goater 326*7c1c69bcSCédric Le Goater type_init(aspeed_smc_register_types) 327