diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-04-03 18:06:08 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-04-08 18:13:16 +0200 |
commit | e28bee8ee654b81f4688a505e56ade0692174b5c (patch) | |
tree | 10957fa9975ffda17a02c1001c10656044830892 /hw/arm_sysctl.c | |
parent | 914e29d28052dbe5a4f41b71eaf8c7bb19ac0929 (diff) |
hw: move other devices to hw/misc/, configure with default-configs/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/arm_sysctl.c')
-rw-r--r-- | hw/arm_sysctl.c | 649 |
1 files changed, 0 insertions, 649 deletions
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c deleted file mode 100644 index c8b55a8349..0000000000 --- a/hw/arm_sysctl.c +++ /dev/null @@ -1,649 +0,0 @@ -/* - * Status and system control registers for ARM RealView/Versatile boards. - * - * Copyright (c) 2006-2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licensed under the GPL. - */ - -#include "hw/hw.h" -#include "qemu/timer.h" -#include "qemu/bitops.h" -#include "hw/sysbus.h" -#include "hw/arm/primecell.h" -#include "sysemu/sysemu.h" - -#define LOCK_VALUE 0xa05f - -typedef struct { - SysBusDevice busdev; - MemoryRegion iomem; - qemu_irq pl110_mux_ctrl; - - uint32_t sys_id; - uint32_t leds; - uint16_t lockval; - uint32_t cfgdata1; - uint32_t cfgdata2; - uint32_t flags; - uint32_t nvflags; - uint32_t resetlevel; - uint32_t proc_id; - uint32_t sys_mci; - uint32_t sys_cfgdata; - uint32_t sys_cfgctrl; - uint32_t sys_cfgstat; - uint32_t sys_clcd; - uint32_t mb_clock[6]; - uint32_t *db_clock; - uint32_t db_num_vsensors; - uint32_t *db_voltage; - uint32_t db_num_clocks; - uint32_t *db_clock_reset; -} arm_sysctl_state; - -static const VMStateDescription vmstate_arm_sysctl = { - .name = "realview_sysctl", - .version_id = 4, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(leds, arm_sysctl_state), - VMSTATE_UINT16(lockval, arm_sysctl_state), - VMSTATE_UINT32(cfgdata1, arm_sysctl_state), - VMSTATE_UINT32(cfgdata2, arm_sysctl_state), - VMSTATE_UINT32(flags, arm_sysctl_state), - VMSTATE_UINT32(nvflags, arm_sysctl_state), - VMSTATE_UINT32(resetlevel, arm_sysctl_state), - VMSTATE_UINT32_V(sys_mci, arm_sysctl_state, 2), - VMSTATE_UINT32_V(sys_cfgdata, arm_sysctl_state, 2), - VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2), - VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2), - VMSTATE_UINT32_V(sys_clcd, arm_sysctl_state, 3), - VMSTATE_UINT32_ARRAY_V(mb_clock, arm_sysctl_state, 6, 4), - VMSTATE_VARRAY_UINT32(db_clock, arm_sysctl_state, db_num_clocks, - 4, vmstate_info_uint32, uint32_t), - VMSTATE_END_OF_LIST() - } -}; - -/* The PB926 actually uses a different format for - * its SYS_ID register. Fortunately the bits which are - * board type on later boards are distinct. - */ -#define BOARD_ID_PB926 0x100 -#define BOARD_ID_EB 0x140 -#define BOARD_ID_PBA8 0x178 -#define BOARD_ID_PBX 0x182 -#define BOARD_ID_VEXPRESS 0x190 - -static int board_id(arm_sysctl_state *s) -{ - /* Extract the board ID field from the SYS_ID register value */ - return (s->sys_id >> 16) & 0xfff; -} - -static void arm_sysctl_reset(DeviceState *d) -{ - arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, SYS_BUS_DEVICE(d)); - int i; - - s->leds = 0; - s->lockval = 0; - s->cfgdata1 = 0; - s->cfgdata2 = 0; - s->flags = 0; - s->resetlevel = 0; - /* Motherboard oscillators (in Hz) */ - s->mb_clock[0] = 50000000; /* Static memory clock: 50MHz */ - s->mb_clock[1] = 23750000; /* motherboard CLCD clock: 23.75MHz */ - s->mb_clock[2] = 24000000; /* IO FPGA peripheral clock: 24MHz */ - s->mb_clock[3] = 24000000; /* IO FPGA reserved clock: 24MHz */ - s->mb_clock[4] = 24000000; /* System bus global clock: 24MHz */ - s->mb_clock[5] = 24000000; /* IO FPGA reserved clock: 24MHz */ - /* Daughterboard oscillators: reset from property values */ - for (i = 0; i < s->db_num_clocks; i++) { - s->db_clock[i] = s->db_clock_reset[i]; - } - if (board_id(s) == BOARD_ID_VEXPRESS) { - /* On VExpress this register will RAZ/WI */ - s->sys_clcd = 0; - } else { - /* All others: CLCDID 0x1f, indicating VGA */ - s->sys_clcd = 0x1f00; - } -} - -static uint64_t arm_sysctl_read(void *opaque, hwaddr offset, - unsigned size) -{ - arm_sysctl_state *s = (arm_sysctl_state *)opaque; - - switch (offset) { - case 0x00: /* ID */ - return s->sys_id; - case 0x04: /* SW */ - /* General purpose hardware switches. - We don't have a useful way of exposing these to the user. */ - return 0; - case 0x08: /* LED */ - return s->leds; - case 0x20: /* LOCK */ - return s->lockval; - case 0x0c: /* OSC0 */ - case 0x10: /* OSC1 */ - case 0x14: /* OSC2 */ - case 0x18: /* OSC3 */ - case 0x1c: /* OSC4 */ - case 0x24: /* 100HZ */ - /* ??? Implement these. */ - return 0; - case 0x28: /* CFGDATA1 */ - return s->cfgdata1; - case 0x2c: /* CFGDATA2 */ - return s->cfgdata2; - case 0x30: /* FLAGS */ - return s->flags; - case 0x38: /* NVFLAGS */ - return s->nvflags; - case 0x40: /* RESETCTL */ - if (board_id(s) == BOARD_ID_VEXPRESS) { - /* reserved: RAZ/WI */ - return 0; - } - return s->resetlevel; - case 0x44: /* PCICTL */ - return 1; - case 0x48: /* MCI */ - return s->sys_mci; - case 0x4c: /* FLASH */ - return 0; - case 0x50: /* CLCD */ - return s->sys_clcd; - case 0x54: /* CLCDSER */ - return 0; - case 0x58: /* BOOTCS */ - return 0; - case 0x5c: /* 24MHz */ - return muldiv64(qemu_get_clock_ns(vm_clock), 24000000, get_ticks_per_sec()); - case 0x60: /* MISC */ - return 0; - case 0x84: /* PROCID0 */ - return s->proc_id; - case 0x88: /* PROCID1 */ - return 0xff000000; - case 0x64: /* DMAPSR0 */ - case 0x68: /* DMAPSR1 */ - case 0x6c: /* DMAPSR2 */ - case 0x70: /* IOSEL */ - case 0x74: /* PLDCTL */ - case 0x80: /* BUSID */ - case 0x8c: /* OSCRESET0 */ - case 0x90: /* OSCRESET1 */ - case 0x94: /* OSCRESET2 */ - case 0x98: /* OSCRESET3 */ - case 0x9c: /* OSCRESET4 */ - case 0xc0: /* SYS_TEST_OSC0 */ - case 0xc4: /* SYS_TEST_OSC1 */ - case 0xc8: /* SYS_TEST_OSC2 */ - case 0xcc: /* SYS_TEST_OSC3 */ - case 0xd0: /* SYS_TEST_OSC4 */ - return 0; - case 0xa0: /* SYS_CFGDATA */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - return s->sys_cfgdata; - case 0xa4: /* SYS_CFGCTRL */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - return s->sys_cfgctrl; - case 0xa8: /* SYS_CFGSTAT */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - return s->sys_cfgstat; - default: - bad_reg: - qemu_log_mask(LOG_GUEST_ERROR, - "arm_sysctl_read: Bad register offset 0x%x\n", - (int)offset); - return 0; - } -} - -/* SYS_CFGCTRL functions */ -#define SYS_CFG_OSC 1 -#define SYS_CFG_VOLT 2 -#define SYS_CFG_AMP 3 -#define SYS_CFG_TEMP 4 -#define SYS_CFG_RESET 5 -#define SYS_CFG_SCC 6 -#define SYS_CFG_MUXFPGA 7 -#define SYS_CFG_SHUTDOWN 8 -#define SYS_CFG_REBOOT 9 -#define SYS_CFG_DVIMODE 11 -#define SYS_CFG_POWER 12 -#define SYS_CFG_ENERGY 13 - -/* SYS_CFGCTRL site field values */ -#define SYS_CFG_SITE_MB 0 -#define SYS_CFG_SITE_DB1 1 -#define SYS_CFG_SITE_DB2 2 - -/** - * vexpress_cfgctrl_read: - * @s: arm_sysctl_state pointer - * @dcc, @function, @site, @position, @device: split out values from - * SYS_CFGCTRL register - * @val: pointer to where to put the read data on success - * - * Handle a VExpress SYS_CFGCTRL register read. On success, return true and - * write the read value to *val. On failure, return false (and val may - * or may not be written to). - */ -static bool vexpress_cfgctrl_read(arm_sysctl_state *s, unsigned int dcc, - unsigned int function, unsigned int site, - unsigned int position, unsigned int device, - uint32_t *val) -{ - /* We don't support anything other than DCC 0, board stack position 0 - * or sites other than motherboard/daughterboard: - */ - if (dcc != 0 || position != 0 || - (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) { - goto cfgctrl_unimp; - } - - switch (function) { - case SYS_CFG_VOLT: - if (site == SYS_CFG_SITE_DB1 && device < s->db_num_vsensors) { - *val = s->db_voltage[device]; - return true; - } - if (site == SYS_CFG_SITE_MB && device == 0) { - /* There is only one motherboard voltage sensor: - * VIO : 3.3V : bus voltage between mother and daughterboard - */ - *val = 3300000; - return true; - } - break; - case SYS_CFG_OSC: - if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) { - /* motherboard clock */ - *val = s->mb_clock[device]; - return true; - } - if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) { - /* daughterboard clock */ - *val = s->db_clock[device]; - return true; - } - break; - default: - break; - } - -cfgctrl_unimp: - qemu_log_mask(LOG_UNIMP, - "arm_sysctl: Unimplemented SYS_CFGCTRL read of function " - "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n", - function, dcc, site, position, device); - return false; -} - -/** - * vexpress_cfgctrl_write: - * @s: arm_sysctl_state pointer - * @dcc, @function, @site, @position, @device: split out values from - * SYS_CFGCTRL register - * @val: data to write - * - * Handle a VExpress SYS_CFGCTRL register write. On success, return true. - * On failure, return false. - */ -static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc, - unsigned int function, unsigned int site, - unsigned int position, unsigned int device, - uint32_t val) -{ - /* We don't support anything other than DCC 0, board stack position 0 - * or sites other than motherboard/daughterboard: - */ - if (dcc != 0 || position != 0 || - (site != SYS_CFG_SITE_MB && site != SYS_CFG_SITE_DB1)) { - goto cfgctrl_unimp; - } - - switch (function) { - case SYS_CFG_OSC: - if (site == SYS_CFG_SITE_MB && device < sizeof(s->mb_clock)) { - /* motherboard clock */ - s->mb_clock[device] = val; - return true; - } - if (site == SYS_CFG_SITE_DB1 && device < s->db_num_clocks) { - /* daughterboard clock */ - s->db_clock[device] = val; - return true; - } - break; - case SYS_CFG_MUXFPGA: - if (site == SYS_CFG_SITE_MB && device == 0) { - /* Select whether video output comes from motherboard - * or daughterboard: log and ignore as QEMU doesn't - * support this. - */ - qemu_log_mask(LOG_UNIMP, "arm_sysctl: selection of video output " - "not supported, ignoring\n"); - return true; - } - break; - case SYS_CFG_SHUTDOWN: - if (site == SYS_CFG_SITE_MB && device == 0) { - qemu_system_shutdown_request(); - return true; - } - break; - case SYS_CFG_REBOOT: - if (site == SYS_CFG_SITE_MB && device == 0) { - qemu_system_reset_request(); - return true; - } - break; - case SYS_CFG_DVIMODE: - if (site == SYS_CFG_SITE_MB && device == 0) { - /* Selecting DVI mode is meaningless for QEMU: we will - * always display the output correctly according to the - * pixel height/width programmed into the CLCD controller. - */ - return true; - } - default: - break; - } - -cfgctrl_unimp: - qemu_log_mask(LOG_UNIMP, - "arm_sysctl: Unimplemented SYS_CFGCTRL write of function " - "0x%x DCC 0x%x site 0x%x position 0x%x device 0x%x\n", - function, dcc, site, position, device); - return false; -} - -static void arm_sysctl_write(void *opaque, hwaddr offset, - uint64_t val, unsigned size) -{ - arm_sysctl_state *s = (arm_sysctl_state *)opaque; - - switch (offset) { - case 0x08: /* LED */ - s->leds = val; - break; - case 0x0c: /* OSC0 */ - case 0x10: /* OSC1 */ - case 0x14: /* OSC2 */ - case 0x18: /* OSC3 */ - case 0x1c: /* OSC4 */ - /* ??? */ - break; - case 0x20: /* LOCK */ - if (val == LOCK_VALUE) - s->lockval = val; - else - s->lockval = val & 0x7fff; - break; - case 0x28: /* CFGDATA1 */ - /* ??? Need to implement this. */ - s->cfgdata1 = val; - break; - case 0x2c: /* CFGDATA2 */ - /* ??? Need to implement this. */ - s->cfgdata2 = val; - break; - case 0x30: /* FLAGSSET */ - s->flags |= val; - break; - case 0x34: /* FLAGSCLR */ - s->flags &= ~val; - break; - case 0x38: /* NVFLAGSSET */ - s->nvflags |= val; - break; - case 0x3c: /* NVFLAGSCLR */ - s->nvflags &= ~val; - break; - case 0x40: /* RESETCTL */ - switch (board_id(s)) { - case BOARD_ID_PB926: - if (s->lockval == LOCK_VALUE) { - s->resetlevel = val; - if (val & 0x100) { - qemu_system_reset_request(); - } - } - break; - case BOARD_ID_PBX: - case BOARD_ID_PBA8: - if (s->lockval == LOCK_VALUE) { - s->resetlevel = val; - if (val & 0x04) { - qemu_system_reset_request(); - } - } - break; - case BOARD_ID_VEXPRESS: - case BOARD_ID_EB: - default: - /* reserved: RAZ/WI */ - break; - } - break; - case 0x44: /* PCICTL */ - /* nothing to do. */ - break; - case 0x4c: /* FLASH */ - break; - case 0x50: /* CLCD */ - switch (board_id(s)) { - case BOARD_ID_PB926: - /* On 926 bits 13:8 are R/O, bits 1:0 control - * the mux that defines how to interpret the PL110 - * graphics format, and other bits are r/w but we - * don't implement them to do anything. - */ - s->sys_clcd &= 0x3f00; - s->sys_clcd |= val & ~0x3f00; - qemu_set_irq(s->pl110_mux_ctrl, val & 3); - break; - case BOARD_ID_EB: - /* The EB is the same except that there is no mux since - * the EB has a PL111. - */ - s->sys_clcd &= 0x3f00; - s->sys_clcd |= val & ~0x3f00; - break; - case BOARD_ID_PBA8: - case BOARD_ID_PBX: - /* On PBA8 and PBX bit 7 is r/w and all other bits - * are either r/o or RAZ/WI. - */ - s->sys_clcd &= (1 << 7); - s->sys_clcd |= val & ~(1 << 7); - break; - case BOARD_ID_VEXPRESS: - default: - /* On VExpress this register is unimplemented and will RAZ/WI */ - break; - } - break; - case 0x54: /* CLCDSER */ - case 0x64: /* DMAPSR0 */ - case 0x68: /* DMAPSR1 */ - case 0x6c: /* DMAPSR2 */ - case 0x70: /* IOSEL */ - case 0x74: /* PLDCTL */ - case 0x80: /* BUSID */ - case 0x84: /* PROCID0 */ - case 0x88: /* PROCID1 */ - case 0x8c: /* OSCRESET0 */ - case 0x90: /* OSCRESET1 */ - case 0x94: /* OSCRESET2 */ - case 0x98: /* OSCRESET3 */ - case 0x9c: /* OSCRESET4 */ - break; - case 0xa0: /* SYS_CFGDATA */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - s->sys_cfgdata = val; - return; - case 0xa4: /* SYS_CFGCTRL */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - /* Undefined bits [19:18] are RAZ/WI, and writing to - * the start bit just triggers the action; it always reads - * as zero. - */ - s->sys_cfgctrl = val & ~((3 << 18) | (1 << 31)); - if (val & (1 << 31)) { - /* Start bit set -- actually do something */ - unsigned int dcc = extract32(s->sys_cfgctrl, 26, 4); - unsigned int function = extract32(s->sys_cfgctrl, 20, 6); - unsigned int site = extract32(s->sys_cfgctrl, 16, 2); - unsigned int position = extract32(s->sys_cfgctrl, 12, 4); - unsigned int device = extract32(s->sys_cfgctrl, 0, 12); - s->sys_cfgstat = 1; /* complete */ - if (s->sys_cfgctrl & (1 << 30)) { - if (!vexpress_cfgctrl_write(s, dcc, function, site, position, - device, s->sys_cfgdata)) { - s->sys_cfgstat |= 2; /* error */ - } - } else { - uint32_t val; - if (!vexpress_cfgctrl_read(s, dcc, function, site, position, - device, &val)) { - s->sys_cfgstat |= 2; /* error */ - } else { - s->sys_cfgdata = val; - } - } - } - s->sys_cfgctrl &= ~(1 << 31); - return; - case 0xa8: /* SYS_CFGSTAT */ - if (board_id(s) != BOARD_ID_VEXPRESS) { - goto bad_reg; - } - s->sys_cfgstat = val & 3; - return; - default: - bad_reg: - qemu_log_mask(LOG_GUEST_ERROR, - "arm_sysctl_write: Bad register offset 0x%x\n", - (int)offset); - return; - } -} - -static const MemoryRegionOps arm_sysctl_ops = { - .read = arm_sysctl_read, - .write = arm_sysctl_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void arm_sysctl_gpio_set(void *opaque, int line, int level) -{ - arm_sysctl_state *s = (arm_sysctl_state *)opaque; - switch (line) { - case ARM_SYSCTL_GPIO_MMC_WPROT: - { - /* For PB926 and EB write-protect is bit 2 of SYS_MCI; - * for all later boards it is bit 1. - */ - int bit = 2; - if ((board_id(s) == BOARD_ID_PB926) || (board_id(s) == BOARD_ID_EB)) { - bit = 4; - } - s->sys_mci &= ~bit; - if (level) { - s->sys_mci |= bit; - } - break; - } - case ARM_SYSCTL_GPIO_MMC_CARDIN: - s->sys_mci &= ~1; - if (level) { - s->sys_mci |= 1; - } - break; - } -} - -static void arm_sysctl_init(Object *obj) -{ - DeviceState *dev = DEVICE(obj); - SysBusDevice *sd = SYS_BUS_DEVICE(obj); - arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sd); - - memory_region_init_io(&s->iomem, &arm_sysctl_ops, s, "arm-sysctl", 0x1000); - sysbus_init_mmio(sd, &s->iomem); - qdev_init_gpio_in(dev, arm_sysctl_gpio_set, 2); - qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1); -} - -static void arm_sysctl_realize(DeviceState *d, Error **errp) -{ - arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, SYS_BUS_DEVICE(d)); - s->db_clock = g_new0(uint32_t, s->db_num_clocks); -} - -static void arm_sysctl_finalize(Object *obj) -{ - SysBusDevice *dev = SYS_BUS_DEVICE(obj); - arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, dev); - g_free(s->db_voltage); - g_free(s->db_clock); - g_free(s->db_clock_reset); -} - -static Property arm_sysctl_properties[] = { - DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0), - DEFINE_PROP_UINT32("proc_id", arm_sysctl_state, proc_id, 0), - /* Daughterboard power supply voltages (as reported via SYS_CFG) */ - DEFINE_PROP_ARRAY("db-voltage", arm_sysctl_state, db_num_vsensors, - db_voltage, qdev_prop_uint32, uint32_t), - /* Daughterboard clock reset values (as reported via SYS_CFG) */ - DEFINE_PROP_ARRAY("db-clock", arm_sysctl_state, db_num_clocks, - db_clock_reset, qdev_prop_uint32, uint32_t), - DEFINE_PROP_END_OF_LIST(), -}; - -static void arm_sysctl_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = arm_sysctl_realize; - dc->reset = arm_sysctl_reset; - dc->vmsd = &vmstate_arm_sysctl; - dc->props = arm_sysctl_properties; -} - -static const TypeInfo arm_sysctl_info = { - .name = "realview_sysctl", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(arm_sysctl_state), - .instance_init = arm_sysctl_init, - .instance_finalize = arm_sysctl_finalize, - .class_init = arm_sysctl_class_init, -}; - -static void arm_sysctl_register_types(void) -{ - type_register_static(&arm_sysctl_info); -} - -type_init(arm_sysctl_register_types) |