diff options
author | RajithaY <rajithax.yerrumsetty@intel.com> | 2017-04-25 03:31:15 -0700 |
---|---|---|
committer | Rajitha Yerrumchetty <rajithax.yerrumsetty@intel.com> | 2017-05-22 06:48:08 +0000 |
commit | bb756eebdac6fd24e8919e2c43f7d2c8c4091f59 (patch) | |
tree | ca11e03542edf2d8f631efeca5e1626d211107e3 /qemu/hw/gpio | |
parent | a14b48d18a9ed03ec191cf16b162206998a895ce (diff) |
Adding qemu as a submodule of KVMFORNFV
This Patch includes the changes to add qemu as a submodule to
kvmfornfv repo and make use of the updated latest qemu for the
execution of all testcase
Change-Id: I1280af507a857675c7f81d30c95255635667bdd7
Signed-off-by:RajithaY<rajithax.yerrumsetty@intel.com>
Diffstat (limited to 'qemu/hw/gpio')
-rw-r--r-- | qemu/hw/gpio/Makefile.objs | 9 | ||||
-rw-r--r-- | qemu/hw/gpio/gpio_key.c | 104 | ||||
-rw-r--r-- | qemu/hw/gpio/imx_gpio.c | 350 | ||||
-rw-r--r-- | qemu/hw/gpio/max7310.c | 218 | ||||
-rw-r--r-- | qemu/hw/gpio/mpc8xxx.c | 218 | ||||
-rw-r--r-- | qemu/hw/gpio/omap_gpio.c | 822 | ||||
-rw-r--r-- | qemu/hw/gpio/pl061.c | 403 | ||||
-rw-r--r-- | qemu/hw/gpio/puv3_gpio.c | 146 | ||||
-rw-r--r-- | qemu/hw/gpio/zaurus.c | 302 |
9 files changed, 0 insertions, 2572 deletions
diff --git a/qemu/hw/gpio/Makefile.objs b/qemu/hw/gpio/Makefile.objs deleted file mode 100644 index a43c7cf44..000000000 --- a/qemu/hw/gpio/Makefile.objs +++ /dev/null @@ -1,9 +0,0 @@ -common-obj-$(CONFIG_MAX7310) += max7310.o -common-obj-$(CONFIG_PL061) += pl061.o -common-obj-$(CONFIG_PUV3) += puv3_gpio.o -common-obj-$(CONFIG_ZAURUS) += zaurus.o -common-obj-$(CONFIG_E500) += mpc8xxx.o -common-obj-$(CONFIG_GPIO_KEY) += gpio_key.o - -obj-$(CONFIG_OMAP) += omap_gpio.o -obj-$(CONFIG_IMX) += imx_gpio.o diff --git a/qemu/hw/gpio/gpio_key.c b/qemu/hw/gpio/gpio_key.c deleted file mode 100644 index ef287727b..000000000 --- a/qemu/hw/gpio/gpio_key.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * GPIO key - * - * Copyright (c) 2016 Linaro Limited - * - * Author: Shannon Zhao <shannon.zhao@linaro.org> - * - * Emulate a (human) keypress -- when the key is triggered by - * setting the incoming gpio line, the outbound irq line is - * raised for 100ms before being dropped again. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" - -#define TYPE_GPIOKEY "gpio-key" -#define GPIOKEY(obj) OBJECT_CHECK(GPIOKEYState, (obj), TYPE_GPIOKEY) -#define GPIO_KEY_LATENCY 100 /* 100ms */ - -typedef struct GPIOKEYState { - SysBusDevice parent_obj; - - QEMUTimer *timer; - qemu_irq irq; -} GPIOKEYState; - -static const VMStateDescription vmstate_gpio_key = { - .name = "gpio-key", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_TIMER_PTR(timer, GPIOKEYState), - VMSTATE_END_OF_LIST() - } -}; - -static void gpio_key_reset(DeviceState *dev) -{ - GPIOKEYState *s = GPIOKEY(dev); - - timer_del(s->timer); -} - -static void gpio_key_timer_expired(void *opaque) -{ - GPIOKEYState *s = (GPIOKEYState *)opaque; - - qemu_set_irq(s->irq, 0); - timer_del(s->timer); -} - -static void gpio_key_set_irq(void *opaque, int irq, int level) -{ - GPIOKEYState *s = (GPIOKEYState *)opaque; - - qemu_set_irq(s->irq, 1); - timer_mod(s->timer, - qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + GPIO_KEY_LATENCY); -} - -static void gpio_key_realize(DeviceState *dev, Error **errp) -{ - GPIOKEYState *s = GPIOKEY(dev); - SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - - sysbus_init_irq(sbd, &s->irq); - qdev_init_gpio_in(dev, gpio_key_set_irq, 1); - s->timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, gpio_key_timer_expired, s); -} - -static void gpio_key_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = gpio_key_realize; - dc->vmsd = &vmstate_gpio_key; - dc->reset = &gpio_key_reset; -} - -static const TypeInfo gpio_key_info = { - .name = TYPE_GPIOKEY, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(GPIOKEYState), - .class_init = gpio_key_class_init, -}; - -static void gpio_key_register_types(void) -{ - type_register_static(&gpio_key_info); -} - -type_init(gpio_key_register_types) diff --git a/qemu/hw/gpio/imx_gpio.c b/qemu/hw/gpio/imx_gpio.c deleted file mode 100644 index ed7e247f5..000000000 --- a/qemu/hw/gpio/imx_gpio.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * i.MX processors GPIO emulation. - * - * Copyright (C) 2015 Jean-Christophe Dubois <jcd@tribudubois.net> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "hw/gpio/imx_gpio.h" - -#ifndef DEBUG_IMX_GPIO -#define DEBUG_IMX_GPIO 0 -#endif - -typedef enum IMXGPIOLevel { - IMX_GPIO_LEVEL_LOW = 0, - IMX_GPIO_LEVEL_HIGH = 1, -} IMXGPIOLevel; - -#define DPRINTF(fmt, args...) \ - do { \ - if (DEBUG_IMX_GPIO) { \ - fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_GPIO, \ - __func__, ##args); \ - } \ - } while (0) - -static const char *imx_gpio_reg_name(uint32_t reg) -{ - switch (reg) { - case DR_ADDR: - return "DR"; - case GDIR_ADDR: - return "GDIR"; - case PSR_ADDR: - return "PSR"; - case ICR1_ADDR: - return "ICR1"; - case ICR2_ADDR: - return "ICR2"; - case IMR_ADDR: - return "IMR"; - case ISR_ADDR: - return "ISR"; - case EDGE_SEL_ADDR: - return "EDGE_SEL"; - default: - return "[?]"; - } -} - -static void imx_gpio_update_int(IMXGPIOState *s) -{ - if (s->has_upper_pin_irq) { - qemu_set_irq(s->irq[0], (s->isr & s->imr & 0x0000FFFF) ? 1 : 0); - qemu_set_irq(s->irq[1], (s->isr & s->imr & 0xFFFF0000) ? 1 : 0); - } else { - qemu_set_irq(s->irq[0], (s->isr & s->imr) ? 1 : 0); - } -} - -static void imx_gpio_set_int_line(IMXGPIOState *s, int line, IMXGPIOLevel level) -{ - /* if this signal isn't configured as an input signal, nothing to do */ - if (!extract32(s->gdir, line, 1)) { - return; - } - - /* When set, EDGE_SEL overrides the ICR config */ - if (extract32(s->edge_sel, line, 1)) { - /* we detect interrupt on rising and falling edge */ - if (extract32(s->psr, line, 1) != level) { - /* level changed */ - s->isr = deposit32(s->isr, line, 1, 1); - } - } else if (extract64(s->icr, 2*line + 1, 1)) { - /* interrupt is edge sensitive */ - if (extract32(s->psr, line, 1) != level) { - /* level changed */ - if (extract64(s->icr, 2*line, 1) != level) { - s->isr = deposit32(s->isr, line, 1, 1); - } - } - } else { - /* interrupt is level sensitive */ - if (extract64(s->icr, 2*line, 1) == level) { - s->isr = deposit32(s->isr, line, 1, 1); - } - } -} - -static void imx_gpio_set(void *opaque, int line, int level) -{ - IMXGPIOState *s = IMX_GPIO(opaque); - IMXGPIOLevel imx_level = level ? IMX_GPIO_LEVEL_HIGH : IMX_GPIO_LEVEL_LOW; - - imx_gpio_set_int_line(s, line, imx_level); - - /* this is an input signal, so set PSR */ - s->psr = deposit32(s->psr, line, 1, imx_level); - - imx_gpio_update_int(s); -} - -static void imx_gpio_set_all_int_lines(IMXGPIOState *s) -{ - int i; - - for (i = 0; i < IMX_GPIO_PIN_COUNT; i++) { - IMXGPIOLevel imx_level = extract32(s->psr, i, 1); - imx_gpio_set_int_line(s, i, imx_level); - } - - imx_gpio_update_int(s); -} - -static inline void imx_gpio_set_all_output_lines(IMXGPIOState *s) -{ - int i; - - for (i = 0; i < IMX_GPIO_PIN_COUNT; i++) { - /* - * if the line is set as output, then forward the line - * level to its user. - */ - if (extract32(s->gdir, i, 1) && s->output[i]) { - qemu_set_irq(s->output[i], extract32(s->dr, i, 1)); - } - } -} - -static uint64_t imx_gpio_read(void *opaque, hwaddr offset, unsigned size) -{ - IMXGPIOState *s = IMX_GPIO(opaque); - uint32_t reg_value = 0; - - switch (offset) { - case DR_ADDR: - /* - * depending on the "line" configuration, the bit values - * are coming either from DR or PSR - */ - reg_value = (s->dr & s->gdir) | (s->psr & ~s->gdir); - break; - - case GDIR_ADDR: - reg_value = s->gdir; - break; - - case PSR_ADDR: - reg_value = s->psr & ~s->gdir; - break; - - case ICR1_ADDR: - reg_value = extract64(s->icr, 0, 32); - break; - - case ICR2_ADDR: - reg_value = extract64(s->icr, 32, 32); - break; - - case IMR_ADDR: - reg_value = s->imr; - break; - - case ISR_ADDR: - reg_value = s->isr; - break; - - case EDGE_SEL_ADDR: - if (s->has_edge_sel) { - reg_value = s->edge_sel; - } else { - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: EDGE_SEL register not " - "present on this version of GPIO device\n", - TYPE_IMX_GPIO, __func__); - } - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" - HWADDR_PRIx "\n", TYPE_IMX_GPIO, __func__, offset); - break; - } - - DPRINTF("(%s) = 0x%" PRIx32 "\n", imx_gpio_reg_name(offset), reg_value); - - return reg_value; -} - -static void imx_gpio_write(void *opaque, hwaddr offset, uint64_t value, - unsigned size) -{ - IMXGPIOState *s = IMX_GPIO(opaque); - - DPRINTF("(%s, value = 0x%" PRIx32 ")\n", imx_gpio_reg_name(offset), - (uint32_t)value); - - switch (offset) { - case DR_ADDR: - s->dr = value; - imx_gpio_set_all_output_lines(s); - break; - - case GDIR_ADDR: - s->gdir = value; - imx_gpio_set_all_output_lines(s); - imx_gpio_set_all_int_lines(s); - break; - - case ICR1_ADDR: - s->icr = deposit64(s->icr, 0, 32, value); - imx_gpio_set_all_int_lines(s); - break; - - case ICR2_ADDR: - s->icr = deposit64(s->icr, 32, 32, value); - imx_gpio_set_all_int_lines(s); - break; - - case IMR_ADDR: - s->imr = value; - imx_gpio_update_int(s); - break; - - case ISR_ADDR: - s->isr |= ~value; - imx_gpio_set_all_int_lines(s); - break; - - case EDGE_SEL_ADDR: - if (s->has_edge_sel) { - s->edge_sel = value; - imx_gpio_set_all_int_lines(s); - } else { - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: EDGE_SEL register not " - "present on this version of GPIO device\n", - TYPE_IMX_GPIO, __func__); - } - break; - - default: - qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" - HWADDR_PRIx "\n", TYPE_IMX_GPIO, __func__, offset); - break; - } - - return; -} - -static const MemoryRegionOps imx_gpio_ops = { - .read = imx_gpio_read, - .write = imx_gpio_write, - .valid.min_access_size = 4, - .valid.max_access_size = 4, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static const VMStateDescription vmstate_imx_gpio = { - .name = TYPE_IMX_GPIO, - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(dr, IMXGPIOState), - VMSTATE_UINT32(gdir, IMXGPIOState), - VMSTATE_UINT32(psr, IMXGPIOState), - VMSTATE_UINT64(icr, IMXGPIOState), - VMSTATE_UINT32(imr, IMXGPIOState), - VMSTATE_UINT32(isr, IMXGPIOState), - VMSTATE_BOOL(has_edge_sel, IMXGPIOState), - VMSTATE_UINT32(edge_sel, IMXGPIOState), - VMSTATE_END_OF_LIST() - } -}; - -static Property imx_gpio_properties[] = { - DEFINE_PROP_BOOL("has-edge-sel", IMXGPIOState, has_edge_sel, true), - DEFINE_PROP_BOOL("has-upper-pin-irq", IMXGPIOState, has_upper_pin_irq, - false), - DEFINE_PROP_END_OF_LIST(), -}; - -static void imx_gpio_reset(DeviceState *dev) -{ - IMXGPIOState *s = IMX_GPIO(dev); - - s->dr = 0; - s->gdir = 0; - s->psr = 0; - s->icr = 0; - s->imr = 0; - s->isr = 0; - s->edge_sel = 0; - - imx_gpio_set_all_output_lines(s); - imx_gpio_update_int(s); -} - -static void imx_gpio_realize(DeviceState *dev, Error **errp) -{ - IMXGPIOState *s = IMX_GPIO(dev); - - memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpio_ops, s, - TYPE_IMX_GPIO, IMX_GPIO_MEM_SIZE); - - qdev_init_gpio_in(DEVICE(s), imx_gpio_set, IMX_GPIO_PIN_COUNT); - qdev_init_gpio_out(DEVICE(s), s->output, IMX_GPIO_PIN_COUNT); - - sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[0]); - sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[1]); - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); -} - -static void imx_gpio_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = imx_gpio_realize; - dc->reset = imx_gpio_reset; - dc->props = imx_gpio_properties; - dc->vmsd = &vmstate_imx_gpio; - dc->desc = "i.MX GPIO controller"; -} - -static const TypeInfo imx_gpio_info = { - .name = TYPE_IMX_GPIO, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(IMXGPIOState), - .class_init = imx_gpio_class_init, -}; - -static void imx_gpio_register_types(void) -{ - type_register_static(&imx_gpio_info); -} - -type_init(imx_gpio_register_types) diff --git a/qemu/hw/gpio/max7310.c b/qemu/hw/gpio/max7310.c deleted file mode 100644 index 1bd5eaf91..000000000 --- a/qemu/hw/gpio/max7310.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * MAX7310 8-port GPIO expansion chip. - * - * Copyright (c) 2006 Openedhand Ltd. - * Written by Andrzej Zaborowski <balrog@zabor.org> - * - * This file is licensed under GNU GPL. - */ - -#include "qemu/osdep.h" -#include "hw/i2c/i2c.h" - -#define TYPE_MAX7310 "max7310" -#define MAX7310(obj) OBJECT_CHECK(MAX7310State, (obj), TYPE_MAX7310) - -typedef struct MAX7310State { - I2CSlave parent_obj; - - int i2c_command_byte; - int len; - - uint8_t level; - uint8_t direction; - uint8_t polarity; - uint8_t status; - uint8_t command; - qemu_irq handler[8]; - qemu_irq *gpio_in; -} MAX7310State; - -static void max7310_reset(DeviceState *dev) -{ - MAX7310State *s = MAX7310(dev); - - s->level &= s->direction; - s->direction = 0xff; - s->polarity = 0xf0; - s->status = 0x01; - s->command = 0x00; -} - -static int max7310_rx(I2CSlave *i2c) -{ - MAX7310State *s = MAX7310(i2c); - - switch (s->command) { - case 0x00: /* Input port */ - return s->level ^ s->polarity; - break; - - case 0x01: /* Output port */ - return s->level & ~s->direction; - break; - - case 0x02: /* Polarity inversion */ - return s->polarity; - - case 0x03: /* Configuration */ - return s->direction; - - case 0x04: /* Timeout */ - return s->status; - break; - - case 0xff: /* Reserved */ - return 0xff; - - default: -#ifdef VERBOSE - printf("%s: unknown register %02x\n", __FUNCTION__, s->command); -#endif - break; - } - return 0xff; -} - -static int max7310_tx(I2CSlave *i2c, uint8_t data) -{ - MAX7310State *s = MAX7310(i2c); - uint8_t diff; - int line; - - if (s->len ++ > 1) { -#ifdef VERBOSE - printf("%s: message too long (%i bytes)\n", __FUNCTION__, s->len); -#endif - return 1; - } - - if (s->i2c_command_byte) { - s->command = data; - s->i2c_command_byte = 0; - return 0; - } - - switch (s->command) { - case 0x01: /* Output port */ - for (diff = (data ^ s->level) & ~s->direction; diff; - diff &= ~(1 << line)) { - line = ctz32(diff); - if (s->handler[line]) - qemu_set_irq(s->handler[line], (data >> line) & 1); - } - s->level = (s->level & s->direction) | (data & ~s->direction); - break; - - case 0x02: /* Polarity inversion */ - s->polarity = data; - break; - - case 0x03: /* Configuration */ - s->level &= ~(s->direction ^ data); - s->direction = data; - break; - - case 0x04: /* Timeout */ - s->status = data; - break; - - case 0x00: /* Input port - ignore writes */ - break; - default: -#ifdef VERBOSE - printf("%s: unknown register %02x\n", __FUNCTION__, s->command); -#endif - return 1; - } - - return 0; -} - -static void max7310_event(I2CSlave *i2c, enum i2c_event event) -{ - MAX7310State *s = MAX7310(i2c); - s->len = 0; - - switch (event) { - case I2C_START_SEND: - s->i2c_command_byte = 1; - break; - case I2C_FINISH: -#ifdef VERBOSE - if (s->len == 1) - printf("%s: message too short (%i bytes)\n", __FUNCTION__, s->len); -#endif - break; - default: - break; - } -} - -static const VMStateDescription vmstate_max7310 = { - .name = "max7310", - .version_id = 0, - .minimum_version_id = 0, - .fields = (VMStateField[]) { - VMSTATE_INT32(i2c_command_byte, MAX7310State), - VMSTATE_INT32(len, MAX7310State), - VMSTATE_UINT8(level, MAX7310State), - VMSTATE_UINT8(direction, MAX7310State), - VMSTATE_UINT8(polarity, MAX7310State), - VMSTATE_UINT8(status, MAX7310State), - VMSTATE_UINT8(command, MAX7310State), - VMSTATE_I2C_SLAVE(parent_obj, MAX7310State), - VMSTATE_END_OF_LIST() - } -}; - -static void max7310_gpio_set(void *opaque, int line, int level) -{ - MAX7310State *s = (MAX7310State *) opaque; - if (line >= ARRAY_SIZE(s->handler) || line < 0) - hw_error("bad GPIO line"); - - if (level) - s->level |= s->direction & (1 << line); - else - s->level &= ~(s->direction & (1 << line)); -} - -/* MAX7310 is SMBus-compatible (can be used with only SMBus protocols), - * but also accepts sequences that are not SMBus so return an I2C device. */ -static int max7310_init(I2CSlave *i2c) -{ - MAX7310State *s = MAX7310(i2c); - - qdev_init_gpio_in(&i2c->qdev, max7310_gpio_set, 8); - qdev_init_gpio_out(&i2c->qdev, s->handler, 8); - - return 0; -} - -static void max7310_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - I2CSlaveClass *k = I2C_SLAVE_CLASS(klass); - - k->init = max7310_init; - k->event = max7310_event; - k->recv = max7310_rx; - k->send = max7310_tx; - dc->reset = max7310_reset; - dc->vmsd = &vmstate_max7310; -} - -static const TypeInfo max7310_info = { - .name = TYPE_MAX7310, - .parent = TYPE_I2C_SLAVE, - .instance_size = sizeof(MAX7310State), - .class_init = max7310_class_init, -}; - -static void max7310_register_types(void) -{ - type_register_static(&max7310_info); -} - -type_init(max7310_register_types) diff --git a/qemu/hw/gpio/mpc8xxx.c b/qemu/hw/gpio/mpc8xxx.c deleted file mode 100644 index d14971946..000000000 --- a/qemu/hw/gpio/mpc8xxx.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * GPIO Controller for a lot of Freescale SoCs - * - * Copyright (C) 2014 Freescale Semiconductor, Inc. All rights reserved. - * - * Author: Alexander Graf, <agraf@suse.de> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" - -#define TYPE_MPC8XXX_GPIO "mpc8xxx_gpio" -#define MPC8XXX_GPIO(obj) OBJECT_CHECK(MPC8XXXGPIOState, (obj), TYPE_MPC8XXX_GPIO) - -typedef struct MPC8XXXGPIOState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - qemu_irq irq; - qemu_irq out[32]; - - uint32_t dir; - uint32_t odr; - uint32_t dat; - uint32_t ier; - uint32_t imr; - uint32_t icr; -} MPC8XXXGPIOState; - -static const VMStateDescription vmstate_mpc8xxx_gpio = { - .name = "mpc8xxx_gpio", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(dir, MPC8XXXGPIOState), - VMSTATE_UINT32(odr, MPC8XXXGPIOState), - VMSTATE_UINT32(dat, MPC8XXXGPIOState), - VMSTATE_UINT32(ier, MPC8XXXGPIOState), - VMSTATE_UINT32(imr, MPC8XXXGPIOState), - VMSTATE_UINT32(icr, MPC8XXXGPIOState), - VMSTATE_END_OF_LIST() - } -}; - -static void mpc8xxx_gpio_update(MPC8XXXGPIOState *s) -{ - qemu_set_irq(s->irq, !!(s->ier & s->imr)); -} - -static uint64_t mpc8xxx_gpio_read(void *opaque, hwaddr offset, - unsigned size) -{ - MPC8XXXGPIOState *s = (MPC8XXXGPIOState *)opaque; - - if (size != 4) { - /* All registers are 32bit */ - return 0; - } - - switch (offset) { - case 0x0: /* Direction */ - return s->dir; - case 0x4: /* Open Drain */ - return s->odr; - case 0x8: /* Data */ - return s->dat; - case 0xC: /* Interrupt Event */ - return s->ier; - case 0x10: /* Interrupt Mask */ - return s->imr; - case 0x14: /* Interrupt Control */ - return s->icr; - default: - return 0; - } -} - -static void mpc8xxx_write_data(MPC8XXXGPIOState *s, uint32_t new_data) -{ - uint32_t old_data = s->dat; - uint32_t diff = old_data ^ new_data; - int i; - - for (i = 0; i < 32; i++) { - uint32_t mask = 0x80000000 >> i; - if (!(diff & mask)) { - continue; - } - - if (s->dir & mask) { - /* Output */ - qemu_set_irq(s->out[i], (new_data & mask) != 0); - } - } - - s->dat = new_data; -} - -static void mpc8xxx_gpio_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - MPC8XXXGPIOState *s = (MPC8XXXGPIOState *)opaque; - - if (size != 4) { - /* All registers are 32bit */ - return; - } - - switch (offset) { - case 0x0: /* Direction */ - s->dir = value; - break; - case 0x4: /* Open Drain */ - s->odr = value; - break; - case 0x8: /* Data */ - mpc8xxx_write_data(s, value); - break; - case 0xC: /* Interrupt Event */ - s->ier &= ~value; - break; - case 0x10: /* Interrupt Mask */ - s->imr = value; - break; - case 0x14: /* Interrupt Control */ - s->icr = value; - break; - } - - mpc8xxx_gpio_update(s); -} - -static void mpc8xxx_gpio_reset(MPC8XXXGPIOState *s) -{ - s->dir = 0; - s->odr = 0; - s->dat = 0; - s->ier = 0; - s->imr = 0; - s->icr = 0; -} - -static void mpc8xxx_gpio_set_irq(void * opaque, int irq, int level) -{ - MPC8XXXGPIOState *s = (MPC8XXXGPIOState *)opaque; - uint32_t mask; - - mask = 0x80000000 >> irq; - if ((s->dir & mask) == 0) { - uint32_t old_value = s->dat & mask; - - s->dat &= ~mask; - if (level) - s->dat |= mask; - - if (!(s->icr & irq) || (old_value && !level)) { - s->ier |= mask; - } - - mpc8xxx_gpio_update(s); - } -} - -static const MemoryRegionOps mpc8xxx_gpio_ops = { - .read = mpc8xxx_gpio_read, - .write = mpc8xxx_gpio_write, - .endianness = DEVICE_BIG_ENDIAN, -}; - -static int mpc8xxx_gpio_initfn(SysBusDevice *sbd) -{ - DeviceState *dev = DEVICE(sbd); - MPC8XXXGPIOState *s = MPC8XXX_GPIO(dev); - - memory_region_init_io(&s->iomem, OBJECT(s), &mpc8xxx_gpio_ops, s, "mpc8xxx_gpio", 0x1000); - sysbus_init_mmio(sbd, &s->iomem); - sysbus_init_irq(sbd, &s->irq); - qdev_init_gpio_in(dev, mpc8xxx_gpio_set_irq, 32); - qdev_init_gpio_out(dev, s->out, 32); - mpc8xxx_gpio_reset(s); - return 0; -} - -static void mpc8xxx_gpio_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = mpc8xxx_gpio_initfn; - dc->vmsd = &vmstate_mpc8xxx_gpio; -} - -static const TypeInfo mpc8xxx_gpio_info = { - .name = TYPE_MPC8XXX_GPIO, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(MPC8XXXGPIOState), - .class_init = mpc8xxx_gpio_class_init, -}; - -static void mpc8xxx_gpio_register_types(void) -{ - type_register_static(&mpc8xxx_gpio_info); -} - -type_init(mpc8xxx_gpio_register_types) diff --git a/qemu/hw/gpio/omap_gpio.c b/qemu/hw/gpio/omap_gpio.c deleted file mode 100644 index 9b1b004fc..000000000 --- a/qemu/hw/gpio/omap_gpio.c +++ /dev/null @@ -1,822 +0,0 @@ -/* - * TI OMAP processors GPIO emulation. - * - * Copyright (C) 2006-2008 Andrzej Zaborowski <balrog@zabor.org> - * Copyright (C) 2007-2009 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/arm/omap.h" -#include "hw/sysbus.h" -#include "qemu/error-report.h" - -struct omap_gpio_s { - qemu_irq irq; - qemu_irq handler[16]; - - uint16_t inputs; - uint16_t outputs; - uint16_t dir; - uint16_t edge; - uint16_t mask; - uint16_t ints; - uint16_t pins; -}; - -#define TYPE_OMAP1_GPIO "omap-gpio" -#define OMAP1_GPIO(obj) \ - OBJECT_CHECK(struct omap_gpif_s, (obj), TYPE_OMAP1_GPIO) - -struct omap_gpif_s { - SysBusDevice parent_obj; - - MemoryRegion iomem; - int mpu_model; - void *clk; - struct omap_gpio_s omap1; -}; - -/* General-Purpose I/O of OMAP1 */ -static void omap_gpio_set(void *opaque, int line, int level) -{ - struct omap_gpio_s *s = &((struct omap_gpif_s *) opaque)->omap1; - uint16_t prev = s->inputs; - - if (level) - s->inputs |= 1 << line; - else - s->inputs &= ~(1 << line); - - if (((s->edge & s->inputs & ~prev) | (~s->edge & ~s->inputs & prev)) & - (1 << line) & s->dir & ~s->mask) { - s->ints |= 1 << line; - qemu_irq_raise(s->irq); - } -} - -static uint64_t omap_gpio_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap_gpio_s *s = (struct omap_gpio_s *) opaque; - int offset = addr & OMAP_MPUI_REG_MASK; - - if (size != 2) { - return omap_badwidth_read16(opaque, addr); - } - - switch (offset) { - case 0x00: /* DATA_INPUT */ - return s->inputs & s->pins; - - case 0x04: /* DATA_OUTPUT */ - return s->outputs; - - case 0x08: /* DIRECTION_CONTROL */ - return s->dir; - - case 0x0c: /* INTERRUPT_CONTROL */ - return s->edge; - - case 0x10: /* INTERRUPT_MASK */ - return s->mask; - - case 0x14: /* INTERRUPT_STATUS */ - return s->ints; - - case 0x18: /* PIN_CONTROL (not in OMAP310) */ - OMAP_BAD_REG(addr); - return s->pins; - } - - OMAP_BAD_REG(addr); - return 0; -} - -static void omap_gpio_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - struct omap_gpio_s *s = (struct omap_gpio_s *) opaque; - int offset = addr & OMAP_MPUI_REG_MASK; - uint16_t diff; - int ln; - - if (size != 2) { - omap_badwidth_write16(opaque, addr, value); - return; - } - - switch (offset) { - case 0x00: /* DATA_INPUT */ - OMAP_RO_REG(addr); - return; - - case 0x04: /* DATA_OUTPUT */ - diff = (s->outputs ^ value) & ~s->dir; - s->outputs = value; - while ((ln = ctz32(diff)) != 32) { - if (s->handler[ln]) - qemu_set_irq(s->handler[ln], (value >> ln) & 1); - diff &= ~(1 << ln); - } - break; - - case 0x08: /* DIRECTION_CONTROL */ - diff = s->outputs & (s->dir ^ value); - s->dir = value; - - value = s->outputs & ~s->dir; - while ((ln = ctz32(diff)) != 32) { - if (s->handler[ln]) - qemu_set_irq(s->handler[ln], (value >> ln) & 1); - diff &= ~(1 << ln); - } - break; - - case 0x0c: /* INTERRUPT_CONTROL */ - s->edge = value; - break; - - case 0x10: /* INTERRUPT_MASK */ - s->mask = value; - break; - - case 0x14: /* INTERRUPT_STATUS */ - s->ints &= ~value; - if (!s->ints) - qemu_irq_lower(s->irq); - break; - - case 0x18: /* PIN_CONTROL (not in OMAP310 TRM) */ - OMAP_BAD_REG(addr); - s->pins = value; - break; - - default: - OMAP_BAD_REG(addr); - return; - } -} - -/* *Some* sources say the memory region is 32-bit. */ -static const MemoryRegionOps omap_gpio_ops = { - .read = omap_gpio_read, - .write = omap_gpio_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void omap_gpio_reset(struct omap_gpio_s *s) -{ - s->inputs = 0; - s->outputs = ~0; - s->dir = ~0; - s->edge = ~0; - s->mask = ~0; - s->ints = 0; - s->pins = ~0; -} - -struct omap2_gpio_s { - qemu_irq irq[2]; - qemu_irq wkup; - qemu_irq *handler; - MemoryRegion iomem; - - uint8_t revision; - uint8_t config[2]; - uint32_t inputs; - uint32_t outputs; - uint32_t dir; - uint32_t level[2]; - uint32_t edge[2]; - uint32_t mask[2]; - uint32_t wumask; - uint32_t ints[2]; - uint32_t debounce; - uint8_t delay; -}; - -#define TYPE_OMAP2_GPIO "omap2-gpio" -#define OMAP2_GPIO(obj) \ - OBJECT_CHECK(struct omap2_gpif_s, (obj), TYPE_OMAP2_GPIO) - -struct omap2_gpif_s { - SysBusDevice parent_obj; - - MemoryRegion iomem; - int mpu_model; - void *iclk; - void *fclk[6]; - int modulecount; - struct omap2_gpio_s *modules; - qemu_irq *handler; - int autoidle; - int gpo; -}; - -/* General-Purpose Interface of OMAP2/3 */ -static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s, - int line) -{ - qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]); -} - -static void omap2_gpio_module_wake(struct omap2_gpio_s *s, int line) -{ - if (!(s->config[0] & (1 << 2))) /* ENAWAKEUP */ - return; - if (!(s->config[0] & (3 << 3))) /* Force Idle */ - return; - if (!(s->wumask & (1 << line))) - return; - - qemu_irq_raise(s->wkup); -} - -static inline void omap2_gpio_module_out_update(struct omap2_gpio_s *s, - uint32_t diff) -{ - int ln; - - s->outputs ^= diff; - diff &= ~s->dir; - while ((ln = ctz32(diff)) != 32) { - qemu_set_irq(s->handler[ln], (s->outputs >> ln) & 1); - diff &= ~(1 << ln); - } -} - -static void omap2_gpio_module_level_update(struct omap2_gpio_s *s, int line) -{ - s->ints[line] |= s->dir & - ((s->inputs & s->level[1]) | (~s->inputs & s->level[0])); - omap2_gpio_module_int_update(s, line); -} - -static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line) -{ - s->ints[0] |= 1 << line; - omap2_gpio_module_int_update(s, 0); - s->ints[1] |= 1 << line; - omap2_gpio_module_int_update(s, 1); - omap2_gpio_module_wake(s, line); -} - -static void omap2_gpio_set(void *opaque, int line, int level) -{ - struct omap2_gpif_s *p = opaque; - struct omap2_gpio_s *s = &p->modules[line >> 5]; - - line &= 31; - if (level) { - if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1])) - omap2_gpio_module_int(s, line); - s->inputs |= 1 << line; - } else { - if (s->dir & (1 << line) & ((s->inputs & s->edge[1]) | s->level[0])) - omap2_gpio_module_int(s, line); - s->inputs &= ~(1 << line); - } -} - -static void omap2_gpio_module_reset(struct omap2_gpio_s *s) -{ - s->config[0] = 0; - s->config[1] = 2; - s->ints[0] = 0; - s->ints[1] = 0; - s->mask[0] = 0; - s->mask[1] = 0; - s->wumask = 0; - s->dir = ~0; - s->level[0] = 0; - s->level[1] = 0; - s->edge[0] = 0; - s->edge[1] = 0; - s->debounce = 0; - s->delay = 0; -} - -static uint32_t omap2_gpio_module_read(void *opaque, hwaddr addr) -{ - struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; - - switch (addr) { - case 0x00: /* GPIO_REVISION */ - return s->revision; - - case 0x10: /* GPIO_SYSCONFIG */ - return s->config[0]; - - case 0x14: /* GPIO_SYSSTATUS */ - return 0x01; - - case 0x18: /* GPIO_IRQSTATUS1 */ - return s->ints[0]; - - case 0x1c: /* GPIO_IRQENABLE1 */ - case 0x60: /* GPIO_CLEARIRQENABLE1 */ - case 0x64: /* GPIO_SETIRQENABLE1 */ - return s->mask[0]; - - case 0x20: /* GPIO_WAKEUPENABLE */ - case 0x80: /* GPIO_CLEARWKUENA */ - case 0x84: /* GPIO_SETWKUENA */ - return s->wumask; - - case 0x28: /* GPIO_IRQSTATUS2 */ - return s->ints[1]; - - case 0x2c: /* GPIO_IRQENABLE2 */ - case 0x70: /* GPIO_CLEARIRQENABLE2 */ - case 0x74: /* GPIO_SETIREQNEABLE2 */ - return s->mask[1]; - - case 0x30: /* GPIO_CTRL */ - return s->config[1]; - - case 0x34: /* GPIO_OE */ - return s->dir; - - case 0x38: /* GPIO_DATAIN */ - return s->inputs; - - case 0x3c: /* GPIO_DATAOUT */ - case 0x90: /* GPIO_CLEARDATAOUT */ - case 0x94: /* GPIO_SETDATAOUT */ - return s->outputs; - - case 0x40: /* GPIO_LEVELDETECT0 */ - return s->level[0]; - - case 0x44: /* GPIO_LEVELDETECT1 */ - return s->level[1]; - - case 0x48: /* GPIO_RISINGDETECT */ - return s->edge[0]; - - case 0x4c: /* GPIO_FALLINGDETECT */ - return s->edge[1]; - - case 0x50: /* GPIO_DEBOUNCENABLE */ - return s->debounce; - - case 0x54: /* GPIO_DEBOUNCINGTIME */ - return s->delay; - } - - OMAP_BAD_REG(addr); - return 0; -} - -static void omap2_gpio_module_write(void *opaque, hwaddr addr, - uint32_t value) -{ - struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; - uint32_t diff; - int ln; - - switch (addr) { - case 0x00: /* GPIO_REVISION */ - case 0x14: /* GPIO_SYSSTATUS */ - case 0x38: /* GPIO_DATAIN */ - OMAP_RO_REG(addr); - break; - - case 0x10: /* GPIO_SYSCONFIG */ - if (((value >> 3) & 3) == 3) - fprintf(stderr, "%s: bad IDLEMODE value\n", __FUNCTION__); - if (value & 2) - omap2_gpio_module_reset(s); - s->config[0] = value & 0x1d; - break; - - case 0x18: /* GPIO_IRQSTATUS1 */ - if (s->ints[0] & value) { - s->ints[0] &= ~value; - omap2_gpio_module_level_update(s, 0); - } - break; - - case 0x1c: /* GPIO_IRQENABLE1 */ - s->mask[0] = value; - omap2_gpio_module_int_update(s, 0); - break; - - case 0x20: /* GPIO_WAKEUPENABLE */ - s->wumask = value; - break; - - case 0x28: /* GPIO_IRQSTATUS2 */ - if (s->ints[1] & value) { - s->ints[1] &= ~value; - omap2_gpio_module_level_update(s, 1); - } - break; - - case 0x2c: /* GPIO_IRQENABLE2 */ - s->mask[1] = value; - omap2_gpio_module_int_update(s, 1); - break; - - case 0x30: /* GPIO_CTRL */ - s->config[1] = value & 7; - break; - - case 0x34: /* GPIO_OE */ - diff = s->outputs & (s->dir ^ value); - s->dir = value; - - value = s->outputs & ~s->dir; - while ((ln = ctz32(diff)) != 32) { - diff &= ~(1 << ln); - qemu_set_irq(s->handler[ln], (value >> ln) & 1); - } - - omap2_gpio_module_level_update(s, 0); - omap2_gpio_module_level_update(s, 1); - break; - - case 0x3c: /* GPIO_DATAOUT */ - omap2_gpio_module_out_update(s, s->outputs ^ value); - break; - - case 0x40: /* GPIO_LEVELDETECT0 */ - s->level[0] = value; - omap2_gpio_module_level_update(s, 0); - omap2_gpio_module_level_update(s, 1); - break; - - case 0x44: /* GPIO_LEVELDETECT1 */ - s->level[1] = value; - omap2_gpio_module_level_update(s, 0); - omap2_gpio_module_level_update(s, 1); - break; - - case 0x48: /* GPIO_RISINGDETECT */ - s->edge[0] = value; - break; - - case 0x4c: /* GPIO_FALLINGDETECT */ - s->edge[1] = value; - break; - - case 0x50: /* GPIO_DEBOUNCENABLE */ - s->debounce = value; - break; - - case 0x54: /* GPIO_DEBOUNCINGTIME */ - s->delay = value; - break; - - case 0x60: /* GPIO_CLEARIRQENABLE1 */ - s->mask[0] &= ~value; - omap2_gpio_module_int_update(s, 0); - break; - - case 0x64: /* GPIO_SETIRQENABLE1 */ - s->mask[0] |= value; - omap2_gpio_module_int_update(s, 0); - break; - - case 0x70: /* GPIO_CLEARIRQENABLE2 */ - s->mask[1] &= ~value; - omap2_gpio_module_int_update(s, 1); - break; - - case 0x74: /* GPIO_SETIREQNEABLE2 */ - s->mask[1] |= value; - omap2_gpio_module_int_update(s, 1); - break; - - case 0x80: /* GPIO_CLEARWKUENA */ - s->wumask &= ~value; - break; - - case 0x84: /* GPIO_SETWKUENA */ - s->wumask |= value; - break; - - case 0x90: /* GPIO_CLEARDATAOUT */ - omap2_gpio_module_out_update(s, s->outputs & value); - break; - - case 0x94: /* GPIO_SETDATAOUT */ - omap2_gpio_module_out_update(s, ~s->outputs & value); - break; - - default: - OMAP_BAD_REG(addr); - return; - } -} - -static uint32_t omap2_gpio_module_readp(void *opaque, hwaddr addr) -{ - return omap2_gpio_module_read(opaque, addr & ~3) >> ((addr & 3) << 3); -} - -static void omap2_gpio_module_writep(void *opaque, hwaddr addr, - uint32_t value) -{ - uint32_t cur = 0; - uint32_t mask = 0xffff; - - switch (addr & ~3) { - case 0x00: /* GPIO_REVISION */ - case 0x14: /* GPIO_SYSSTATUS */ - case 0x38: /* GPIO_DATAIN */ - OMAP_RO_REG(addr); - break; - - case 0x10: /* GPIO_SYSCONFIG */ - case 0x1c: /* GPIO_IRQENABLE1 */ - case 0x20: /* GPIO_WAKEUPENABLE */ - case 0x2c: /* GPIO_IRQENABLE2 */ - case 0x30: /* GPIO_CTRL */ - case 0x34: /* GPIO_OE */ - case 0x3c: /* GPIO_DATAOUT */ - case 0x40: /* GPIO_LEVELDETECT0 */ - case 0x44: /* GPIO_LEVELDETECT1 */ - case 0x48: /* GPIO_RISINGDETECT */ - case 0x4c: /* GPIO_FALLINGDETECT */ - case 0x50: /* GPIO_DEBOUNCENABLE */ - case 0x54: /* GPIO_DEBOUNCINGTIME */ - cur = omap2_gpio_module_read(opaque, addr & ~3) & - ~(mask << ((addr & 3) << 3)); - - /* Fall through. */ - case 0x18: /* GPIO_IRQSTATUS1 */ - case 0x28: /* GPIO_IRQSTATUS2 */ - case 0x60: /* GPIO_CLEARIRQENABLE1 */ - case 0x64: /* GPIO_SETIRQENABLE1 */ - case 0x70: /* GPIO_CLEARIRQENABLE2 */ - case 0x74: /* GPIO_SETIREQNEABLE2 */ - case 0x80: /* GPIO_CLEARWKUENA */ - case 0x84: /* GPIO_SETWKUENA */ - case 0x90: /* GPIO_CLEARDATAOUT */ - case 0x94: /* GPIO_SETDATAOUT */ - value <<= (addr & 3) << 3; - omap2_gpio_module_write(opaque, addr, cur | value); - break; - - default: - OMAP_BAD_REG(addr); - return; - } -} - -static const MemoryRegionOps omap2_gpio_module_ops = { - .old_mmio = { - .read = { - omap2_gpio_module_readp, - omap2_gpio_module_readp, - omap2_gpio_module_read, - }, - .write = { - omap2_gpio_module_writep, - omap2_gpio_module_writep, - omap2_gpio_module_write, - }, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void omap_gpif_reset(DeviceState *dev) -{ - struct omap_gpif_s *s = OMAP1_GPIO(dev); - - omap_gpio_reset(&s->omap1); -} - -static void omap2_gpif_reset(DeviceState *dev) -{ - struct omap2_gpif_s *s = OMAP2_GPIO(dev); - int i; - - for (i = 0; i < s->modulecount; i++) { - omap2_gpio_module_reset(&s->modules[i]); - } - s->autoidle = 0; - s->gpo = 0; -} - -static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr, - unsigned size) -{ - struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque; - - switch (addr) { - case 0x00: /* IPGENERICOCPSPL_REVISION */ - return 0x18; - - case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */ - return s->autoidle; - - case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */ - return 0x01; - - case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */ - return 0x00; - - case 0x40: /* IPGENERICOCPSPL_GPO */ - return s->gpo; - - case 0x50: /* IPGENERICOCPSPL_GPI */ - return 0x00; - } - - OMAP_BAD_REG(addr); - return 0; -} - -static void omap2_gpif_top_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque; - - switch (addr) { - case 0x00: /* IPGENERICOCPSPL_REVISION */ - case 0x14: /* IPGENERICOCPSPL_SYSSTATUS */ - case 0x18: /* IPGENERICOCPSPL_IRQSTATUS */ - case 0x50: /* IPGENERICOCPSPL_GPI */ - OMAP_RO_REG(addr); - break; - - case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */ - if (value & (1 << 1)) /* SOFTRESET */ - omap2_gpif_reset(DEVICE(s)); - s->autoidle = value & 1; - break; - - case 0x40: /* IPGENERICOCPSPL_GPO */ - s->gpo = value & 1; - break; - - default: - OMAP_BAD_REG(addr); - return; - } -} - -static const MemoryRegionOps omap2_gpif_top_ops = { - .read = omap2_gpif_top_read, - .write = omap2_gpif_top_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static int omap_gpio_init(SysBusDevice *sbd) -{ - DeviceState *dev = DEVICE(sbd); - struct omap_gpif_s *s = OMAP1_GPIO(dev); - - if (!s->clk) { - error_report("omap-gpio: clk not connected"); - return -1; - } - qdev_init_gpio_in(dev, omap_gpio_set, 16); - qdev_init_gpio_out(dev, s->omap1.handler, 16); - sysbus_init_irq(sbd, &s->omap1.irq); - memory_region_init_io(&s->iomem, OBJECT(s), &omap_gpio_ops, &s->omap1, - "omap.gpio", 0x1000); - sysbus_init_mmio(sbd, &s->iomem); - return 0; -} - -static int omap2_gpio_init(SysBusDevice *sbd) -{ - DeviceState *dev = DEVICE(sbd); - struct omap2_gpif_s *s = OMAP2_GPIO(dev); - int i; - - if (!s->iclk) { - error_report("omap2-gpio: iclk not connected"); - return -1; - } - - s->modulecount = s->mpu_model < omap2430 ? 4 - : s->mpu_model < omap3430 ? 5 - : 6; - - for (i = 0; i < s->modulecount; i++) { - if (!s->fclk[i]) { - error_report("omap2-gpio: fclk%d not connected", i); - return -1; - } - } - - if (s->mpu_model < omap3430) { - memory_region_init_io(&s->iomem, OBJECT(s), &omap2_gpif_top_ops, s, - "omap2.gpio", 0x1000); - sysbus_init_mmio(sbd, &s->iomem); - } - - s->modules = g_new0(struct omap2_gpio_s, s->modulecount); - s->handler = g_new0(qemu_irq, s->modulecount * 32); - qdev_init_gpio_in(dev, omap2_gpio_set, s->modulecount * 32); - qdev_init_gpio_out(dev, s->handler, s->modulecount * 32); - - for (i = 0; i < s->modulecount; i++) { - struct omap2_gpio_s *m = &s->modules[i]; - - m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25; - m->handler = &s->handler[i * 32]; - sysbus_init_irq(sbd, &m->irq[0]); /* mpu irq */ - sysbus_init_irq(sbd, &m->irq[1]); /* dsp irq */ - sysbus_init_irq(sbd, &m->wkup); - memory_region_init_io(&m->iomem, OBJECT(s), &omap2_gpio_module_ops, m, - "omap.gpio-module", 0x1000); - sysbus_init_mmio(sbd, &m->iomem); - } - - return 0; -} - -/* Using qdev pointer properties for the clocks is not ideal. - * qdev should support a generic means of defining a 'port' with - * an arbitrary interface for connecting two devices. Then we - * could reframe the omap clock API in terms of clock ports, - * and get some type safety. For now the best qdev provides is - * passing an arbitrary pointer. - * (It's not possible to pass in the string which is the clock - * name, because this device does not have the necessary information - * (ie the struct omap_mpu_state_s*) to do the clockname to pointer - * translation.) - */ - -static Property omap_gpio_properties[] = { - DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0), - DEFINE_PROP_PTR("clk", struct omap_gpif_s, clk), - DEFINE_PROP_END_OF_LIST(), -}; - -static void omap_gpio_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = omap_gpio_init; - dc->reset = omap_gpif_reset; - dc->props = omap_gpio_properties; - /* Reason: pointer property "clk" */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo omap_gpio_info = { - .name = TYPE_OMAP1_GPIO, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(struct omap_gpif_s), - .class_init = omap_gpio_class_init, -}; - -static Property omap2_gpio_properties[] = { - DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0), - DEFINE_PROP_PTR("iclk", struct omap2_gpif_s, iclk), - DEFINE_PROP_PTR("fclk0", struct omap2_gpif_s, fclk[0]), - DEFINE_PROP_PTR("fclk1", struct omap2_gpif_s, fclk[1]), - DEFINE_PROP_PTR("fclk2", struct omap2_gpif_s, fclk[2]), - DEFINE_PROP_PTR("fclk3", struct omap2_gpif_s, fclk[3]), - DEFINE_PROP_PTR("fclk4", struct omap2_gpif_s, fclk[4]), - DEFINE_PROP_PTR("fclk5", struct omap2_gpif_s, fclk[5]), - DEFINE_PROP_END_OF_LIST(), -}; - -static void omap2_gpio_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = omap2_gpio_init; - dc->reset = omap2_gpif_reset; - dc->props = omap2_gpio_properties; - /* Reason: pointer properties "iclk", "fclk0", ..., "fclk5" */ - dc->cannot_instantiate_with_device_add_yet = true; -} - -static const TypeInfo omap2_gpio_info = { - .name = TYPE_OMAP2_GPIO, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(struct omap2_gpif_s), - .class_init = omap2_gpio_class_init, -}; - -static void omap_gpio_register_types(void) -{ - type_register_static(&omap_gpio_info); - type_register_static(&omap2_gpio_info); -} - -type_init(omap_gpio_register_types) diff --git a/qemu/hw/gpio/pl061.c b/qemu/hw/gpio/pl061.c deleted file mode 100644 index 29dc7fc38..000000000 --- a/qemu/hw/gpio/pl061.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Arm PrimeCell PL061 General Purpose IO with additional - * Luminary Micro Stellaris bits. - * - * Copyright (c) 2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licensed under the GPL. - */ - -#include "qemu/osdep.h" -#include "hw/sysbus.h" - -//#define DEBUG_PL061 1 - -#ifdef DEBUG_PL061 -#define DPRINTF(fmt, ...) \ -do { printf("pl061: " fmt , ## __VA_ARGS__); } while (0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "pl061: error: " fmt , ## __VA_ARGS__); exit(1);} while (0) -#else -#define DPRINTF(fmt, ...) do {} while(0) -#define BADF(fmt, ...) \ -do { fprintf(stderr, "pl061: error: " fmt , ## __VA_ARGS__);} while (0) -#endif - -static const uint8_t pl061_id[12] = - { 0x00, 0x00, 0x00, 0x00, 0x61, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; -static const uint8_t pl061_id_luminary[12] = - { 0x00, 0x00, 0x00, 0x00, 0x61, 0x00, 0x18, 0x01, 0x0d, 0xf0, 0x05, 0xb1 }; - -#define TYPE_PL061 "pl061" -#define PL061(obj) OBJECT_CHECK(PL061State, (obj), TYPE_PL061) - -typedef struct PL061State { - SysBusDevice parent_obj; - - MemoryRegion iomem; - uint32_t locked; - uint32_t data; - uint32_t old_out_data; - uint32_t old_in_data; - uint32_t dir; - uint32_t isense; - uint32_t ibe; - uint32_t iev; - uint32_t im; - uint32_t istate; - uint32_t afsel; - uint32_t dr2r; - uint32_t dr4r; - uint32_t dr8r; - uint32_t odr; - uint32_t pur; - uint32_t pdr; - uint32_t slr; - uint32_t den; - uint32_t cr; - uint32_t amsel; - qemu_irq irq; - qemu_irq out[8]; - const unsigned char *id; - uint32_t rsvd_start; /* reserved area: [rsvd_start, 0xfcc] */ -} PL061State; - -static const VMStateDescription vmstate_pl061 = { - .name = "pl061", - .version_id = 4, - .minimum_version_id = 4, - .fields = (VMStateField[]) { - VMSTATE_UINT32(locked, PL061State), - VMSTATE_UINT32(data, PL061State), - VMSTATE_UINT32(old_out_data, PL061State), - VMSTATE_UINT32(old_in_data, PL061State), - VMSTATE_UINT32(dir, PL061State), - VMSTATE_UINT32(isense, PL061State), - VMSTATE_UINT32(ibe, PL061State), - VMSTATE_UINT32(iev, PL061State), - VMSTATE_UINT32(im, PL061State), - VMSTATE_UINT32(istate, PL061State), - VMSTATE_UINT32(afsel, PL061State), - VMSTATE_UINT32(dr2r, PL061State), - VMSTATE_UINT32(dr4r, PL061State), - VMSTATE_UINT32(dr8r, PL061State), - VMSTATE_UINT32(odr, PL061State), - VMSTATE_UINT32(pur, PL061State), - VMSTATE_UINT32(pdr, PL061State), - VMSTATE_UINT32(slr, PL061State), - VMSTATE_UINT32(den, PL061State), - VMSTATE_UINT32(cr, PL061State), - VMSTATE_UINT32_V(amsel, PL061State, 2), - VMSTATE_END_OF_LIST() - } -}; - -static void pl061_update(PL061State *s) -{ - uint8_t changed; - uint8_t mask; - uint8_t out; - int i; - - DPRINTF("dir = %d, data = %d\n", s->dir, s->data); - - /* Outputs float high. */ - /* FIXME: This is board dependent. */ - out = (s->data & s->dir) | ~s->dir; - changed = s->old_out_data ^ out; - if (changed) { - s->old_out_data = out; - for (i = 0; i < 8; i++) { - mask = 1 << i; - if (changed & mask) { - DPRINTF("Set output %d = %d\n", i, (out & mask) != 0); - qemu_set_irq(s->out[i], (out & mask) != 0); - } - } - } - - /* Inputs */ - changed = (s->old_in_data ^ s->data) & ~s->dir; - if (changed) { - s->old_in_data = s->data; - for (i = 0; i < 8; i++) { - mask = 1 << i; - if (changed & mask) { - DPRINTF("Changed input %d = %d\n", i, (s->data & mask) != 0); - - if (!(s->isense & mask)) { - /* Edge interrupt */ - if (s->ibe & mask) { - /* Any edge triggers the interrupt */ - s->istate |= mask; - } else { - /* Edge is selected by IEV */ - s->istate |= ~(s->data ^ s->iev) & mask; - } - } - } - } - } - - /* Level interrupt */ - s->istate |= ~(s->data ^ s->iev) & s->isense; - - DPRINTF("istate = %02X\n", s->istate); - - qemu_set_irq(s->irq, (s->istate & s->im) != 0); -} - -static uint64_t pl061_read(void *opaque, hwaddr offset, - unsigned size) -{ - PL061State *s = (PL061State *)opaque; - - if (offset < 0x400) { - return s->data & (offset >> 2); - } - if (offset >= s->rsvd_start && offset <= 0xfcc) { - goto err_out; - } - if (offset >= 0xfd0 && offset < 0x1000) { - return s->id[(offset - 0xfd0) >> 2]; - } - switch (offset) { - case 0x400: /* Direction */ - return s->dir; - case 0x404: /* Interrupt sense */ - return s->isense; - case 0x408: /* Interrupt both edges */ - return s->ibe; - case 0x40c: /* Interrupt event */ - return s->iev; - case 0x410: /* Interrupt mask */ - return s->im; - case 0x414: /* Raw interrupt status */ - return s->istate; - case 0x418: /* Masked interrupt status */ - return s->istate & s->im; - case 0x420: /* Alternate function select */ - return s->afsel; - case 0x500: /* 2mA drive */ - return s->dr2r; - case 0x504: /* 4mA drive */ - return s->dr4r; - case 0x508: /* 8mA drive */ - return s->dr8r; - case 0x50c: /* Open drain */ - return s->odr; - case 0x510: /* Pull-up */ - return s->pur; - case 0x514: /* Pull-down */ - return s->pdr; - case 0x518: /* Slew rate control */ - return s->slr; - case 0x51c: /* Digital enable */ - return s->den; - case 0x520: /* Lock */ - return s->locked; - case 0x524: /* Commit */ - return s->cr; - case 0x528: /* Analog mode select */ - return s->amsel; - default: - break; - } -err_out: - qemu_log_mask(LOG_GUEST_ERROR, - "pl061_read: Bad offset %x\n", (int)offset); - return 0; -} - -static void pl061_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - PL061State *s = (PL061State *)opaque; - uint8_t mask; - - if (offset < 0x400) { - mask = (offset >> 2) & s->dir; - s->data = (s->data & ~mask) | (value & mask); - pl061_update(s); - return; - } - if (offset >= s->rsvd_start) { - goto err_out; - } - switch (offset) { - case 0x400: /* Direction */ - s->dir = value & 0xff; - break; - case 0x404: /* Interrupt sense */ - s->isense = value & 0xff; - break; - case 0x408: /* Interrupt both edges */ - s->ibe = value & 0xff; - break; - case 0x40c: /* Interrupt event */ - s->iev = value & 0xff; - break; - case 0x410: /* Interrupt mask */ - s->im = value & 0xff; - break; - case 0x41c: /* Interrupt clear */ - s->istate &= ~value; - break; - case 0x420: /* Alternate function select */ - mask = s->cr; - s->afsel = (s->afsel & ~mask) | (value & mask); - break; - case 0x500: /* 2mA drive */ - s->dr2r = value & 0xff; - break; - case 0x504: /* 4mA drive */ - s->dr4r = value & 0xff; - break; - case 0x508: /* 8mA drive */ - s->dr8r = value & 0xff; - break; - case 0x50c: /* Open drain */ - s->odr = value & 0xff; - break; - case 0x510: /* Pull-up */ - s->pur = value & 0xff; - break; - case 0x514: /* Pull-down */ - s->pdr = value & 0xff; - break; - case 0x518: /* Slew rate control */ - s->slr = value & 0xff; - break; - case 0x51c: /* Digital enable */ - s->den = value & 0xff; - break; - case 0x520: /* Lock */ - s->locked = (value != 0xacce551); - break; - case 0x524: /* Commit */ - if (!s->locked) - s->cr = value & 0xff; - break; - case 0x528: - s->amsel = value & 0xff; - break; - default: - goto err_out; - } - pl061_update(s); - return; -err_out: - qemu_log_mask(LOG_GUEST_ERROR, - "pl061_write: Bad offset %x\n", (int)offset); -} - -static void pl061_reset(DeviceState *dev) -{ - PL061State *s = PL061(dev); - - /* reset values from PL061 TRM, Stellaris LM3S5P31 & LM3S8962 Data Sheet */ - s->data = 0; - s->old_out_data = 0; - s->old_in_data = 0; - s->dir = 0; - s->isense = 0; - s->ibe = 0; - s->iev = 0; - s->im = 0; - s->istate = 0; - s->afsel = 0; - s->dr2r = 0xff; - s->dr4r = 0; - s->dr8r = 0; - s->odr = 0; - s->pur = 0; - s->pdr = 0; - s->slr = 0; - s->den = 0; - s->locked = 1; - s->cr = 0xff; - s->amsel = 0; -} - -static void pl061_set_irq(void * opaque, int irq, int level) -{ - PL061State *s = (PL061State *)opaque; - uint8_t mask; - - mask = 1 << irq; - if ((s->dir & mask) == 0) { - s->data &= ~mask; - if (level) - s->data |= mask; - pl061_update(s); - } -} - -static const MemoryRegionOps pl061_ops = { - .read = pl061_read, - .write = pl061_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static int pl061_initfn(SysBusDevice *sbd) -{ - DeviceState *dev = DEVICE(sbd); - PL061State *s = PL061(dev); - - memory_region_init_io(&s->iomem, OBJECT(s), &pl061_ops, s, "pl061", 0x1000); - sysbus_init_mmio(sbd, &s->iomem); - sysbus_init_irq(sbd, &s->irq); - qdev_init_gpio_in(dev, pl061_set_irq, 8); - qdev_init_gpio_out(dev, s->out, 8); - - return 0; -} - -static void pl061_luminary_init(Object *obj) -{ - PL061State *s = PL061(obj); - - s->id = pl061_id_luminary; - s->rsvd_start = 0x52c; -} - -static void pl061_init(Object *obj) -{ - PL061State *s = PL061(obj); - - s->id = pl061_id; - s->rsvd_start = 0x424; -} - -static void pl061_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = pl061_initfn; - dc->vmsd = &vmstate_pl061; - dc->reset = &pl061_reset; -} - -static const TypeInfo pl061_info = { - .name = TYPE_PL061, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(PL061State), - .instance_init = pl061_init, - .class_init = pl061_class_init, -}; - -static const TypeInfo pl061_luminary_info = { - .name = "pl061_luminary", - .parent = TYPE_PL061, - .instance_init = pl061_luminary_init, -}; - -static void pl061_register_types(void) -{ - type_register_static(&pl061_info); - type_register_static(&pl061_luminary_info); -} - -type_init(pl061_register_types) diff --git a/qemu/hw/gpio/puv3_gpio.c b/qemu/hw/gpio/puv3_gpio.c deleted file mode 100644 index 445afccf9..000000000 --- a/qemu/hw/gpio/puv3_gpio.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * GPIO device simulation in PKUnity SoC - * - * Copyright (C) 2010-2012 Guan Xuetao - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation, or any later version. - * See the COPYING file in the top-level directory. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/sysbus.h" - -#undef DEBUG_PUV3 -#include "hw/unicore32/puv3.h" - -#define TYPE_PUV3_GPIO "puv3_gpio" -#define PUV3_GPIO(obj) OBJECT_CHECK(PUV3GPIOState, (obj), TYPE_PUV3_GPIO) - -typedef struct PUV3GPIOState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - qemu_irq irq[9]; - - uint32_t reg_GPLR; - uint32_t reg_GPDR; - uint32_t reg_GPIR; -} PUV3GPIOState; - -static uint64_t puv3_gpio_read(void *opaque, hwaddr offset, - unsigned size) -{ - PUV3GPIOState *s = opaque; - uint32_t ret = 0; - - switch (offset) { - case 0x00: - ret = s->reg_GPLR; - break; - case 0x04: - ret = s->reg_GPDR; - break; - case 0x20: - ret = s->reg_GPIR; - break; - default: - DPRINTF("Bad offset 0x%x\n", offset); - } - DPRINTF("offset 0x%x, value 0x%x\n", offset, ret); - - return ret; -} - -static void puv3_gpio_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) -{ - PUV3GPIOState *s = opaque; - - DPRINTF("offset 0x%x, value 0x%x\n", offset, value); - switch (offset) { - case 0x04: - s->reg_GPDR = value; - break; - case 0x08: - if (s->reg_GPDR & value) { - s->reg_GPLR |= value; - } else { - DPRINTF("Write gpio input port error!"); - } - break; - case 0x0c: - if (s->reg_GPDR & value) { - s->reg_GPLR &= ~value; - } else { - DPRINTF("Write gpio input port error!"); - } - break; - case 0x10: /* GRER */ - case 0x14: /* GFER */ - case 0x18: /* GEDR */ - break; - case 0x20: /* GPIR */ - s->reg_GPIR = value; - break; - default: - DPRINTF("Bad offset 0x%x\n", offset); - } -} - -static const MemoryRegionOps puv3_gpio_ops = { - .read = puv3_gpio_read, - .write = puv3_gpio_write, - .impl = { - .min_access_size = 4, - .max_access_size = 4, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static int puv3_gpio_init(SysBusDevice *dev) -{ - PUV3GPIOState *s = PUV3_GPIO(dev); - - s->reg_GPLR = 0; - s->reg_GPDR = 0; - - /* FIXME: these irqs not handled yet */ - sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW0]); - sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW1]); - sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW2]); - sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW3]); - sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW4]); - sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW5]); - sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW6]); - sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW7]); - sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOHIGH]); - - memory_region_init_io(&s->iomem, OBJECT(s), &puv3_gpio_ops, s, "puv3_gpio", - PUV3_REGS_OFFSET); - sysbus_init_mmio(dev, &s->iomem); - - return 0; -} - -static void puv3_gpio_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); - - sdc->init = puv3_gpio_init; -} - -static const TypeInfo puv3_gpio_info = { - .name = TYPE_PUV3_GPIO, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(PUV3GPIOState), - .class_init = puv3_gpio_class_init, -}; - -static void puv3_gpio_register_type(void) -{ - type_register_static(&puv3_gpio_info); -} - -type_init(puv3_gpio_register_type) diff --git a/qemu/hw/gpio/zaurus.c b/qemu/hw/gpio/zaurus.c deleted file mode 100644 index 555da281c..000000000 --- a/qemu/hw/gpio/zaurus.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2006-2008 Openedhand Ltd. - * Written by Andrzej Zaborowski <balrog@zabor.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ -#include "qemu/osdep.h" -#include "hw/hw.h" -#include "hw/arm/sharpsl.h" -#include "hw/sysbus.h" - -#undef REG_FMT -#define REG_FMT "0x%02lx" - -/* SCOOP devices */ - -#define TYPE_SCOOP "scoop" -#define SCOOP(obj) OBJECT_CHECK(ScoopInfo, (obj), TYPE_SCOOP) - -typedef struct ScoopInfo ScoopInfo; -struct ScoopInfo { - SysBusDevice parent_obj; - - qemu_irq handler[16]; - MemoryRegion iomem; - uint16_t status; - uint16_t power; - uint32_t gpio_level; - uint32_t gpio_dir; - uint32_t prev_level; - - uint16_t mcr; - uint16_t cdr; - uint16_t ccr; - uint16_t irr; - uint16_t imr; - uint16_t isr; -}; - -#define SCOOP_MCR 0x00 -#define SCOOP_CDR 0x04 -#define SCOOP_CSR 0x08 -#define SCOOP_CPR 0x0c -#define SCOOP_CCR 0x10 -#define SCOOP_IRR_IRM 0x14 -#define SCOOP_IMR 0x18 -#define SCOOP_ISR 0x1c -#define SCOOP_GPCR 0x20 -#define SCOOP_GPWR 0x24 -#define SCOOP_GPRR 0x28 - -static inline void scoop_gpio_handler_update(ScoopInfo *s) { - uint32_t level, diff; - int bit; - level = s->gpio_level & s->gpio_dir; - - for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) { - bit = ctz32(diff); - qemu_set_irq(s->handler[bit], (level >> bit) & 1); - } - - s->prev_level = level; -} - -static uint64_t scoop_read(void *opaque, hwaddr addr, - unsigned size) -{ - ScoopInfo *s = (ScoopInfo *) opaque; - - switch (addr & 0x3f) { - case SCOOP_MCR: - return s->mcr; - case SCOOP_CDR: - return s->cdr; - case SCOOP_CSR: - return s->status; - case SCOOP_CPR: - return s->power; - case SCOOP_CCR: - return s->ccr; - case SCOOP_IRR_IRM: - return s->irr; - case SCOOP_IMR: - return s->imr; - case SCOOP_ISR: - return s->isr; - case SCOOP_GPCR: - return s->gpio_dir; - case SCOOP_GPWR: - case SCOOP_GPRR: - return s->gpio_level; - default: - zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr); - } - - return 0; -} - -static void scoop_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - ScoopInfo *s = (ScoopInfo *) opaque; - value &= 0xffff; - - switch (addr & 0x3f) { - case SCOOP_MCR: - s->mcr = value; - break; - case SCOOP_CDR: - s->cdr = value; - break; - case SCOOP_CPR: - s->power = value; - if (value & 0x80) - s->power |= 0x8040; - break; - case SCOOP_CCR: - s->ccr = value; - break; - case SCOOP_IRR_IRM: - s->irr = value; - break; - case SCOOP_IMR: - s->imr = value; - break; - case SCOOP_ISR: - s->isr = value; - break; - case SCOOP_GPCR: - s->gpio_dir = value; - scoop_gpio_handler_update(s); - break; - case SCOOP_GPWR: - case SCOOP_GPRR: /* GPRR is probably R/O in real HW */ - s->gpio_level = value & s->gpio_dir; - scoop_gpio_handler_update(s); - break; - default: - zaurus_printf("Bad register offset " REG_FMT "\n", (unsigned long)addr); - } -} - -static const MemoryRegionOps scoop_ops = { - .read = scoop_read, - .write = scoop_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void scoop_gpio_set(void *opaque, int line, int level) -{ - ScoopInfo *s = (ScoopInfo *) opaque; - - if (level) - s->gpio_level |= (1 << line); - else - s->gpio_level &= ~(1 << line); -} - -static int scoop_init(SysBusDevice *sbd) -{ - DeviceState *dev = DEVICE(sbd); - ScoopInfo *s = SCOOP(dev); - - s->status = 0x02; - qdev_init_gpio_out(dev, s->handler, 16); - qdev_init_gpio_in(dev, scoop_gpio_set, 16); - memory_region_init_io(&s->iomem, OBJECT(s), &scoop_ops, s, "scoop", 0x1000); - - sysbus_init_mmio(sbd, &s->iomem); - - return 0; -} - -static int scoop_post_load(void *opaque, int version_id) -{ - ScoopInfo *s = (ScoopInfo *) opaque; - int i; - uint32_t level; - - level = s->gpio_level & s->gpio_dir; - - for (i = 0; i < 16; i++) { - qemu_set_irq(s->handler[i], (level >> i) & 1); - } - - s->prev_level = level; - - return 0; -} - -static bool is_version_0 (void *opaque, int version_id) -{ - return version_id == 0; -} - -static bool vmstate_scoop_validate(void *opaque, int version_id) -{ - ScoopInfo *s = opaque; - - return !(s->prev_level & 0xffff0000) && - !(s->gpio_level & 0xffff0000) && - !(s->gpio_dir & 0xffff0000); -} - -static const VMStateDescription vmstate_scoop_regs = { - .name = "scoop", - .version_id = 1, - .minimum_version_id = 0, - .post_load = scoop_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT16(status, ScoopInfo), - VMSTATE_UINT16(power, ScoopInfo), - VMSTATE_UINT32(gpio_level, ScoopInfo), - VMSTATE_UINT32(gpio_dir, ScoopInfo), - VMSTATE_UINT32(prev_level, ScoopInfo), - VMSTATE_VALIDATE("irq levels are 16 bit", vmstate_scoop_validate), - VMSTATE_UINT16(mcr, ScoopInfo), - VMSTATE_UINT16(cdr, ScoopInfo), - VMSTATE_UINT16(ccr, ScoopInfo), - VMSTATE_UINT16(irr, ScoopInfo), - VMSTATE_UINT16(imr, ScoopInfo), - VMSTATE_UINT16(isr, ScoopInfo), - VMSTATE_UNUSED_TEST(is_version_0, 2), - VMSTATE_END_OF_LIST(), - }, -}; - -static void scoop_sysbus_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = scoop_init; - dc->desc = "Scoop2 Sharp custom ASIC"; - dc->vmsd = &vmstate_scoop_regs; -} - -static const TypeInfo scoop_sysbus_info = { - .name = TYPE_SCOOP, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(ScoopInfo), - .class_init = scoop_sysbus_class_init, -}; - -static void scoop_register_types(void) -{ - type_register_static(&scoop_sysbus_info); -} - -type_init(scoop_register_types) - -/* Write the bootloader parameters memory area. */ - -#define MAGIC_CHG(a, b, c, d) ((d << 24) | (c << 16) | (b << 8) | a) - -static struct QEMU_PACKED sl_param_info { - uint32_t comadj_keyword; - int32_t comadj; - - uint32_t uuid_keyword; - char uuid[16]; - - uint32_t touch_keyword; - int32_t touch_xp; - int32_t touch_yp; - int32_t touch_xd; - int32_t touch_yd; - - uint32_t adadj_keyword; - int32_t adadj; - - uint32_t phad_keyword; - int32_t phadadj; -} zaurus_bootparam = { - .comadj_keyword = MAGIC_CHG('C', 'M', 'A', 'D'), - .comadj = 125, - .uuid_keyword = MAGIC_CHG('U', 'U', 'I', 'D'), - .uuid = { -1 }, - .touch_keyword = MAGIC_CHG('T', 'U', 'C', 'H'), - .touch_xp = -1, - .adadj_keyword = MAGIC_CHG('B', 'V', 'A', 'D'), - .adadj = -1, - .phad_keyword = MAGIC_CHG('P', 'H', 'A', 'D'), - .phadadj = 0x01, -}; - -void sl_bootparam_write(hwaddr ptr) -{ - cpu_physical_memory_write(ptr, &zaurus_bootparam, - sizeof(struct sl_param_info)); -} |