hw/omap_gpio.c: Convert to qdev

Convert the OMAP GPIO module to qdev.

Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
[Riku Voipio: Fixes and restructuring patchset]
Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
[Peter Maydell: More fixes and cleanups for upstream submission]
Signed-off-by:  Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski@intel.com>
This commit is contained in:
Juha Riihimäki 2011-07-29 16:35:17 +01:00 committed by Andrzej Zaborowski
parent 0a34f96690
commit 77831c204f
6 changed files with 219 additions and 174 deletions

View File

@ -134,9 +134,9 @@ static void n800_mmc_cs_cb(void *opaque, int line, int level)
static void n8x0_gpio_setup(struct n800_s *s) static void n8x0_gpio_setup(struct n800_s *s)
{ {
qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1); qemu_irq *mmc_cs = qemu_allocate_irqs(n800_mmc_cs_cb, s->cpu->mmc, 1);
omap2_gpio_out_set(s->cpu->gpif, N8X0_MMC_CS_GPIO, mmc_cs[0]); qdev_connect_gpio_out(s->cpu->gpio, N8X0_MMC_CS_GPIO, mmc_cs[0]);
qemu_irq_lower(omap2_gpio_in_get(s->cpu->gpif, N800_BAT_COVER_GPIO)[0]); qemu_irq_lower(qdev_get_gpio_in(s->cpu->gpio, N800_BAT_COVER_GPIO));
} }
#define MAEMO_CAL_HEADER(...) \ #define MAEMO_CAL_HEADER(...) \
@ -168,8 +168,8 @@ static void n8x0_nand_setup(struct n800_s *s)
omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update, omap_gpmc_attach(s->cpu->gpmc, N8X0_ONENAND_CS, 0, onenand_base_update,
onenand_base_unmap, onenand_base_unmap,
(s->nand = onenand_init(0xec4800, 1, (s->nand = onenand_init(0xec4800, 1,
omap2_gpio_in_get(s->cpu->gpif, qdev_get_gpio_in(s->cpu->gpio,
N8X0_ONENAND_GPIO)[0]))); N8X0_ONENAND_GPIO))));
otp_region = onenand_raw_otp(s->nand); otp_region = onenand_raw_otp(s->nand);
memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac)); memcpy(otp_region + 0x000, n8x0_cal_wlan_mac, sizeof(n8x0_cal_wlan_mac));
@ -180,7 +180,7 @@ static void n8x0_nand_setup(struct n800_s *s)
static void n8x0_i2c_setup(struct n800_s *s) static void n8x0_i2c_setup(struct n800_s *s)
{ {
DeviceState *dev; DeviceState *dev;
qemu_irq tmp_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TMP105_GPIO)[0]; qemu_irq tmp_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TMP105_GPIO);
/* Attach the CPU on one end of our I2C bus. */ /* Attach the CPU on one end of our I2C bus. */
s->i2c = omap_i2c_bus(s->cpu->i2c[0]); s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
@ -249,8 +249,8 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
/* XXX: are the three pins inverted inside the chip between the /* XXX: are the three pins inverted inside the chip between the
* tsc and the cpu (N4111)? */ * tsc and the cpu (N4111)? */
qemu_irq penirq = NULL; /* NC */ qemu_irq penirq = NULL; /* NC */
qemu_irq kbirq = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_KP_IRQ_GPIO)[0]; qemu_irq kbirq = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_KP_IRQ_GPIO);
qemu_irq dav = omap2_gpio_in_get(s->cpu->gpif, N800_TSC_TS_GPIO)[0]; qemu_irq dav = qdev_get_gpio_in(s->cpu->gpio, N800_TSC_TS_GPIO);
s->ts.chip = tsc2301_init(penirq, kbirq, dav); s->ts.chip = tsc2301_init(penirq, kbirq, dav);
s->ts.opaque = s->ts.chip->opaque; s->ts.opaque = s->ts.chip->opaque;
@ -269,7 +269,7 @@ static void n800_tsc_kbd_setup(struct n800_s *s)
static void n810_tsc_setup(struct n800_s *s) static void n810_tsc_setup(struct n800_s *s)
{ {
qemu_irq pintdav = omap2_gpio_in_get(s->cpu->gpif, N810_TSC_TS_GPIO)[0]; qemu_irq pintdav = qdev_get_gpio_in(s->cpu->gpio, N810_TSC_TS_GPIO);
s->ts.opaque = tsc2005_init(pintdav); s->ts.opaque = tsc2005_init(pintdav);
s->ts.txrx = tsc2005_txrx; s->ts.txrx = tsc2005_txrx;
@ -361,7 +361,7 @@ static int n810_keys[0x80] = {
static void n810_kbd_setup(struct n800_s *s) static void n810_kbd_setup(struct n800_s *s)
{ {
qemu_irq kbd_irq = omap2_gpio_in_get(s->cpu->gpif, N810_KEYBOARD_GPIO)[0]; qemu_irq kbd_irq = qdev_get_gpio_in(s->cpu->gpio, N810_KEYBOARD_GPIO);
DeviceState *dev; DeviceState *dev;
int i; int i;
@ -726,15 +726,15 @@ static void n8x0_dss_setup(struct n800_s *s)
static void n8x0_cbus_setup(struct n800_s *s) static void n8x0_cbus_setup(struct n800_s *s)
{ {
qemu_irq dat_out = omap2_gpio_in_get(s->cpu->gpif, N8X0_CBUS_DAT_GPIO)[0]; qemu_irq dat_out = qdev_get_gpio_in(s->cpu->gpio, N8X0_CBUS_DAT_GPIO);
qemu_irq retu_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_RETU_GPIO)[0]; qemu_irq retu_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_RETU_GPIO);
qemu_irq tahvo_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TAHVO_GPIO)[0]; qemu_irq tahvo_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TAHVO_GPIO);
CBus *cbus = cbus_init(dat_out); CBus *cbus = cbus_init(dat_out);
omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_CLK_GPIO, cbus->clk); qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_CLK_GPIO, cbus->clk);
omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_DAT_GPIO, cbus->dat); qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_DAT_GPIO, cbus->dat);
omap2_gpio_out_set(s->cpu->gpif, N8X0_CBUS_SEL_GPIO, cbus->sel); qdev_connect_gpio_out(s->cpu->gpio, N8X0_CBUS_SEL_GPIO, cbus->sel);
cbus_attach(cbus, s->retu = retu_init(retu_irq, 1)); cbus_attach(cbus, s->retu = retu_init(retu_irq, 1));
cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1)); cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
@ -743,12 +743,11 @@ static void n8x0_cbus_setup(struct n800_s *s)
static void n8x0_uart_setup(struct n800_s *s) static void n8x0_uart_setup(struct n800_s *s)
{ {
CharDriverState *radio = uart_hci_init( CharDriverState *radio = uart_hci_init(
omap2_gpio_in_get(s->cpu->gpif, qdev_get_gpio_in(s->cpu->gpio, N8X0_BT_HOST_WKUP_GPIO));
N8X0_BT_HOST_WKUP_GPIO)[0]);
omap2_gpio_out_set(s->cpu->gpif, N8X0_BT_RESET_GPIO, qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_RESET_GPIO,
csrhci_pins_get(radio)[csrhci_pin_reset]); csrhci_pins_get(radio)[csrhci_pin_reset]);
omap2_gpio_out_set(s->cpu->gpif, N8X0_BT_WKUP_GPIO, qdev_connect_gpio_out(s->cpu->gpio, N8X0_BT_WKUP_GPIO,
csrhci_pins_get(radio)[csrhci_pin_wakeup]); csrhci_pins_get(radio)[csrhci_pin_wakeup]);
omap_uart_attach(s->cpu->uart[BT_UART], radio); omap_uart_attach(s->cpu->uart[BT_UART], radio);
@ -763,7 +762,7 @@ static void n8x0_usb_power_cb(void *opaque, int line, int level)
static void n8x0_usb_setup(struct n800_s *s) static void n8x0_usb_setup(struct n800_s *s)
{ {
qemu_irq tusb_irq = omap2_gpio_in_get(s->cpu->gpif, N8X0_TUSB_INT_GPIO)[0]; qemu_irq tusb_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TUSB_INT_GPIO);
qemu_irq tusb_pwr = qemu_allocate_irqs(n8x0_usb_power_cb, s, 1)[0]; qemu_irq tusb_pwr = qemu_allocate_irqs(n8x0_usb_power_cb, s, 1)[0];
TUSBState *tusb = tusb6010_init(tusb_irq); TUSBState *tusb = tusb6010_init(tusb_irq);
@ -774,7 +773,7 @@ static void n8x0_usb_setup(struct n800_s *s)
tusb6010_sync_io(tusb), NULL, NULL, tusb); tusb6010_sync_io(tusb), NULL, NULL, tusb);
s->usb = tusb; s->usb = tusb;
omap2_gpio_out_set(s->cpu->gpif, N8X0_TUSB_ENABLE_GPIO, tusb_pwr); qdev_connect_gpio_out(s->cpu->gpio, N8X0_TUSB_ENABLE_GPIO, tusb_pwr);
} }
/* Setup done before the main bootloader starts by some early setup code /* Setup done before the main bootloader starts by some early setup code
@ -1020,7 +1019,7 @@ static void n8x0_boot_init(void *opaque)
/* If the machine has a slided keyboard, open it */ /* If the machine has a slided keyboard, open it */
if (s->kbd) if (s->kbd)
qemu_irq_raise(omap2_gpio_in_get(s->cpu->gpif, N810_SLIDE_GPIO)[0]); qemu_irq_raise(qdev_get_gpio_in(s->cpu->gpio, N810_SLIDE_GPIO));
} }
#define OMAP_TAG_NOKIA_BT 0x4e01 #define OMAP_TAG_NOKIA_BT 0x4e01

View File

@ -683,22 +683,6 @@ qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler); void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down); void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
/* omap1 gpio module interface */
struct omap_gpio_s;
struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
qemu_irq irq, omap_clk clk);
void omap_gpio_reset(struct omap_gpio_s *s);
qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s);
void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler);
/* omap2 gpio interface */
struct omap_gpif_s;
struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta,
qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules);
void omap_gpif_reset(struct omap_gpif_s *s);
qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start);
void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler);
struct uWireSlave { struct uWireSlave {
uint16_t (*receive)(void *opaque); uint16_t (*receive)(void *opaque);
void (*send)(void *opaque, uint16_t data); void (*send)(void *opaque, uint16_t data);
@ -852,7 +836,7 @@ struct omap_mpu_state_s {
/* MPUI-TIPB peripherals */ /* MPUI-TIPB peripherals */
struct omap_uart_s *uart[3]; struct omap_uart_s *uart[3];
struct omap_gpio_s *gpio; DeviceState *gpio;
struct omap_mcbsp_s *mcbsp1; struct omap_mcbsp_s *mcbsp1;
struct omap_mcbsp_s *mcbsp3; struct omap_mcbsp_s *mcbsp3;
@ -950,8 +934,6 @@ struct omap_mpu_state_s {
struct omap_gpmc_s *gpmc; struct omap_gpmc_s *gpmc;
struct omap_sysctl_s *sysc; struct omap_sysctl_s *sysc;
struct omap_gpif_s *gpif;
struct omap_mcspi_s *mcspi[2]; struct omap_mcspi_s *mcspi[2];
struct omap_dss_s *dss; struct omap_dss_s *dss;

View File

@ -27,6 +27,7 @@
#include "pc.h" #include "pc.h"
#include "blockdev.h" #include "blockdev.h"
#include "range.h" #include "range.h"
#include "sysbus.h"
/* Should signal the TCMI/GPMC */ /* Should signal the TCMI/GPMC */
uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr) uint32_t omap_badwidth_read8(void *opaque, target_phys_addr_t addr)
@ -3585,7 +3586,6 @@ static void omap1_mpu_reset(void *opaque)
omap_uart_reset(mpu->uart[2]); omap_uart_reset(mpu->uart[2]);
omap_mmc_reset(mpu->mmc); omap_mmc_reset(mpu->mmc);
omap_mpuio_reset(mpu->mpuio); omap_mpuio_reset(mpu->mpuio);
omap_gpio_reset(mpu->gpio);
omap_uwire_reset(mpu->microwire); omap_uwire_reset(mpu->microwire);
omap_pwl_reset(mpu); omap_pwl_reset(mpu);
omap_pwt_reset(mpu); omap_pwt_reset(mpu);
@ -3845,8 +3845,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size,
s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO], s->irq[1][OMAP_INT_KEYBOARD], s->irq[1][OMAP_INT_MPUIO],
s->wakeup, omap_findclk(s, "clk32-kHz")); s->wakeup, omap_findclk(s, "clk32-kHz"));
s->gpio = omap_gpio_init(0xfffce000, s->irq[0][OMAP_INT_GPIO_BANK1], s->gpio = qdev_create(NULL, "omap-gpio");
omap_findclk(s, "arm_gpio_ck")); qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
qdev_init_nofail(s->gpio);
sysbus_connect_irq(sysbus_from_qdev(s->gpio), 0,
s->irq[0][OMAP_INT_GPIO_BANK1]);
sysbus_mmio_map(sysbus_from_qdev(s->gpio), 0, 0xfffce000);
s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX], s->microwire = omap_uwire_init(0xfffb3000, &s->irq[1][OMAP_INT_uWireTX],
s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck")); s->drq[OMAP_DMA_UWIRE_TX], omap_findclk(s, "mpuper_ck"));

View File

@ -27,6 +27,7 @@
#include "qemu-char.h" #include "qemu-char.h"
#include "flash.h" #include "flash.h"
#include "soc_dma.h" #include "soc_dma.h"
#include "sysbus.h"
#include "audio/audio.h" #include "audio/audio.h"
/* Enhanced Audio Controller (CODEC only) */ /* Enhanced Audio Controller (CODEC only) */
@ -2203,7 +2204,6 @@ static void omap2_mpu_reset(void *opaque)
omap_uart_reset(mpu->uart[1]); omap_uart_reset(mpu->uart[1]);
omap_uart_reset(mpu->uart[2]); omap_uart_reset(mpu->uart[2]);
omap_mmc_reset(mpu->mmc); omap_mmc_reset(mpu->mmc);
omap_gpif_reset(mpu->gpif);
omap_mcspi_reset(mpu->mcspi[0]); omap_mcspi_reset(mpu->mcspi[0]);
omap_mcspi_reset(mpu->mcspi[1]); omap_mcspi_reset(mpu->mcspi[1]);
omap_i2c_reset(mpu->i2c[0]); omap_i2c_reset(mpu->i2c[0]);
@ -2232,9 +2232,10 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
ram_addr_t sram_base, q2_base; ram_addr_t sram_base, q2_base;
qemu_irq *cpu_irq; qemu_irq *cpu_irq;
qemu_irq dma_irqs[4]; qemu_irq dma_irqs[4];
omap_clk gpio_clks[4];
DriveInfo *dinfo; DriveInfo *dinfo;
int i; int i;
SysBusDevice *busdev;
struct omap_target_agent_s *ta;
/* Core */ /* Core */
s->mpu_model = omap2420; s->mpu_model = omap2420;
@ -2377,13 +2378,28 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
omap_findclk(s, "i2c2.fclk"), omap_findclk(s, "i2c2.fclk"),
omap_findclk(s, "i2c2.iclk")); omap_findclk(s, "i2c2.iclk"));
gpio_clks[0] = omap_findclk(s, "gpio1_dbclk"); s->gpio = qdev_create(NULL, "omap2-gpio");
gpio_clks[1] = omap_findclk(s, "gpio2_dbclk"); qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
gpio_clks[2] = omap_findclk(s, "gpio3_dbclk"); qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk"));
gpio_clks[3] = omap_findclk(s, "gpio4_dbclk"); qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk"));
s->gpif = omap2_gpio_init(omap_l4ta(s->l4, 3), qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk"));
&s->irq[0][OMAP_INT_24XX_GPIO_BANK1], qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk"));
gpio_clks, omap_findclk(s, "gpio_iclk"), 4); qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk"));
if (s->mpu_model == omap2430) {
qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
}
qdev_init_nofail(s->gpio);
busdev = sysbus_from_qdev(s->gpio);
sysbus_connect_irq(busdev, 0, s->irq[0][OMAP_INT_24XX_GPIO_BANK1]);
sysbus_connect_irq(busdev, 3, s->irq[0][OMAP_INT_24XX_GPIO_BANK2]);
sysbus_connect_irq(busdev, 6, s->irq[0][OMAP_INT_24XX_GPIO_BANK3]);
sysbus_connect_irq(busdev, 9, s->irq[0][OMAP_INT_24XX_GPIO_BANK4]);
ta = omap_l4ta(s->l4, 3);
sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
sysbus_mmio_map(busdev, 2, omap_l4_region_base(ta, 2));
sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
s->sdrc = omap_sdrc_init(0x68009000); s->sdrc = omap_sdrc_init(0x68009000);
s->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]); s->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]);

View File

@ -20,10 +20,10 @@
#include "hw.h" #include "hw.h"
#include "omap.h" #include "omap.h"
/* General-Purpose I/O */ #include "sysbus.h"
struct omap_gpio_s { struct omap_gpio_s {
qemu_irq irq; qemu_irq irq;
qemu_irq *in;
qemu_irq handler[16]; qemu_irq handler[16];
uint16_t inputs; uint16_t inputs;
@ -35,9 +35,17 @@ struct omap_gpio_s {
uint16_t pins; uint16_t pins;
}; };
struct omap_gpif_s {
SysBusDevice busdev;
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) static void omap_gpio_set(void *opaque, int line, int level)
{ {
struct omap_gpio_s *s = (struct omap_gpio_s *) opaque; struct omap_gpio_s *s = &((struct omap_gpif_s *) opaque)->omap1;
uint16_t prev = s->inputs; uint16_t prev = s->inputs;
if (level) if (level)
@ -160,7 +168,7 @@ static CPUWriteMemoryFunc * const omap_gpio_writefn[] = {
omap_badwidth_write16, omap_badwidth_write16,
}; };
void omap_gpio_reset(struct omap_gpio_s *s) static void omap_gpio_reset(struct omap_gpio_s *s)
{ {
s->inputs = 0; s->inputs = 0;
s->outputs = ~0; s->outputs = ~0;
@ -171,43 +179,12 @@ void omap_gpio_reset(struct omap_gpio_s *s)
s->pins = ~0; s->pins = ~0;
} }
struct omap_gpio_s *omap_gpio_init(target_phys_addr_t base,
qemu_irq irq, omap_clk clk)
{
int iomemtype;
struct omap_gpio_s *s = (struct omap_gpio_s *)
qemu_mallocz(sizeof(struct omap_gpio_s));
s->irq = irq;
s->in = qemu_allocate_irqs(omap_gpio_set, s, 16);
omap_gpio_reset(s);
iomemtype = cpu_register_io_memory(omap_gpio_readfn,
omap_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
cpu_register_physical_memory(base, 0x1000, iomemtype);
return s;
}
qemu_irq *omap_gpio_in_get(struct omap_gpio_s *s)
{
return s->in;
}
void omap_gpio_out_set(struct omap_gpio_s *s, int line, qemu_irq handler)
{
if (line >= 16 || line < 0)
hw_error("%s: No GPIO line %i\n", __FUNCTION__, line);
s->handler[line] = handler;
}
/* General-Purpose Interface of OMAP2 */
struct omap2_gpio_s { struct omap2_gpio_s {
qemu_irq irq[2]; qemu_irq irq[2];
qemu_irq wkup; qemu_irq wkup;
qemu_irq *in; qemu_irq *handler;
qemu_irq handler[32];
uint8_t revision;
uint8_t config[2]; uint8_t config[2];
uint32_t inputs; uint32_t inputs;
uint32_t outputs; uint32_t outputs;
@ -221,8 +198,21 @@ struct omap2_gpio_s {
uint8_t delay; uint8_t delay;
}; };
struct omap2_gpif_s {
SysBusDevice busdev;
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, static inline void omap2_gpio_module_int_update(struct omap2_gpio_s *s,
int line) int line)
{ {
qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]); qemu_set_irq(s->irq[line], s->ints[line] & s->mask[line]);
} }
@ -269,10 +259,12 @@ static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
omap2_gpio_module_wake(s, line); omap2_gpio_module_wake(s, line);
} }
static void omap2_gpio_module_set(void *opaque, int line, int level) static void omap2_gpio_set(void *opaque, int line, int level)
{ {
struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque; struct omap2_gpif_s *p = opaque;
struct omap2_gpio_s *s = &p->modules[line >> 5];
line &= 31;
if (level) { if (level) {
if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1])) if (s->dir & (1 << line) & ((~s->inputs & s->edge[0]) | s->level[1]))
omap2_gpio_module_int(s, line); omap2_gpio_module_int(s, line);
@ -308,7 +300,7 @@ static uint32_t omap2_gpio_module_read(void *opaque, target_phys_addr_t addr)
switch (addr) { switch (addr) {
case 0x00: /* GPIO_REVISION */ case 0x00: /* GPIO_REVISION */
return 0x18; return s->revision;
case 0x10: /* GPIO_SYSCONFIG */ case 0x10: /* GPIO_SYSCONFIG */
return s->config[0]; return s->config[0];
@ -583,45 +575,28 @@ static CPUWriteMemoryFunc * const omap2_gpio_module_writefn[] = {
omap2_gpio_module_write, omap2_gpio_module_write,
}; };
static void omap2_gpio_module_init(struct omap2_gpio_s *s, static void omap_gpif_reset(DeviceState *dev)
struct omap_target_agent_s *ta, int region,
qemu_irq mpu, qemu_irq dsp, qemu_irq wkup,
omap_clk fclk, omap_clk iclk)
{ {
int iomemtype; struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s,
sysbus_from_qdev(dev));
s->irq[0] = mpu; omap_gpio_reset(&s->omap1);
s->irq[1] = dsp;
s->wkup = wkup;
s->in = qemu_allocate_irqs(omap2_gpio_module_set, s, 32);
iomemtype = l4_register_io_memory(omap2_gpio_module_readfn,
omap2_gpio_module_writefn, s);
omap_l4_attach(ta, region, iomemtype);
} }
struct omap_gpif_s { static void omap2_gpif_reset(DeviceState *dev)
struct omap2_gpio_s module[5];
int modules;
int autoidle;
int gpo;
};
void omap_gpif_reset(struct omap_gpif_s *s)
{ {
int i; int i;
struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s,
for (i = 0; i < s->modules; i ++) sysbus_from_qdev(dev));
omap2_gpio_module_reset(s->module + i); for (i = 0; i < s->modulecount; i++) {
omap2_gpio_module_reset(&s->modules[i]);
}
s->autoidle = 0; s->autoidle = 0;
s->gpo = 0; s->gpo = 0;
} }
static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr) static uint32_t omap2_gpif_top_read(void *opaque, target_phys_addr_t addr)
{ {
struct omap_gpif_s *s = (struct omap_gpif_s *) opaque; struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
switch (addr) { switch (addr) {
case 0x00: /* IPGENERICOCPSPL_REVISION */ case 0x00: /* IPGENERICOCPSPL_REVISION */
@ -647,10 +622,10 @@ static uint32_t omap_gpif_top_read(void *opaque, target_phys_addr_t addr)
return 0; return 0;
} }
static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr, static void omap2_gpif_top_write(void *opaque, target_phys_addr_t addr,
uint32_t value) uint32_t value)
{ {
struct omap_gpif_s *s = (struct omap_gpif_s *) opaque; struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
switch (addr) { switch (addr) {
case 0x00: /* IPGENERICOCPSPL_REVISION */ case 0x00: /* IPGENERICOCPSPL_REVISION */
@ -662,7 +637,7 @@ static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */ case 0x10: /* IPGENERICOCPSPL_SYSCONFIG */
if (value & (1 << 1)) /* SOFTRESET */ if (value & (1 << 1)) /* SOFTRESET */
omap_gpif_reset(s); omap2_gpif_reset(&s->busdev.qdev);
s->autoidle = value & 1; s->autoidle = value & 1;
break; break;
@ -676,50 +651,119 @@ static void omap_gpif_top_write(void *opaque, target_phys_addr_t addr,
} }
} }
static CPUReadMemoryFunc * const omap_gpif_top_readfn[] = { static CPUReadMemoryFunc * const omap2_gpif_top_readfn[] = {
omap_gpif_top_read, omap2_gpif_top_read,
omap_gpif_top_read, omap2_gpif_top_read,
omap_gpif_top_read, omap2_gpif_top_read,
}; };
static CPUWriteMemoryFunc * const omap_gpif_top_writefn[] = { static CPUWriteMemoryFunc * const omap2_gpif_top_writefn[] = {
omap_gpif_top_write, omap2_gpif_top_write,
omap_gpif_top_write, omap2_gpif_top_write,
omap_gpif_top_write, omap2_gpif_top_write,
}; };
struct omap_gpif_s *omap2_gpio_init(struct omap_target_agent_s *ta, static int omap_gpio_init(SysBusDevice *dev)
qemu_irq *irq, omap_clk *fclk, omap_clk iclk, int modules)
{ {
int iomemtype, i; struct omap_gpif_s *s = FROM_SYSBUS(struct omap_gpif_s, dev);
struct omap_gpif_s *s = (struct omap_gpif_s *) if (!s->clk) {
qemu_mallocz(sizeof(struct omap_gpif_s)); hw_error("omap-gpio: clk not connected\n");
int region[4] = { 0, 2, 4, 5 }; }
qdev_init_gpio_in(&dev->qdev, omap_gpio_set, 16);
s->modules = modules; qdev_init_gpio_out(&dev->qdev, s->omap1.handler, 16);
for (i = 0; i < modules; i ++) sysbus_init_irq(dev, &s->omap1.irq);
omap2_gpio_module_init(s->module + i, ta, region[i], sysbus_init_mmio(dev, 0x1000,
irq[i], NULL, NULL, fclk[i], iclk); cpu_register_io_memory(omap_gpio_readfn,
omap_gpio_writefn,
omap_gpif_reset(s); &s->omap1,
DEVICE_NATIVE_ENDIAN));
iomemtype = l4_register_io_memory(omap_gpif_top_readfn, return 0;
omap_gpif_top_writefn, s);
omap_l4_attach(ta, 1, iomemtype);
return s;
} }
qemu_irq *omap2_gpio_in_get(struct omap_gpif_s *s, int start) static int omap2_gpio_init(SysBusDevice *dev)
{ {
if (start >= s->modules * 32 || start < 0) int i;
hw_error("%s: No GPIO line %i\n", __FUNCTION__, start); struct omap2_gpif_s *s = FROM_SYSBUS(struct omap2_gpif_s, dev);
return s->module[start >> 5].in + (start & 31); if (!s->iclk) {
hw_error("omap2-gpio: iclk not connected\n");
}
if (s->mpu_model < omap3430) {
s->modulecount = (s->mpu_model < omap2430) ? 4 : 5;
sysbus_init_mmio(dev, 0x1000,
cpu_register_io_memory(omap2_gpif_top_readfn,
omap2_gpif_top_writefn, s,
DEVICE_NATIVE_ENDIAN));
} else {
s->modulecount = 6;
}
s->modules = qemu_mallocz(s->modulecount * sizeof(struct omap2_gpio_s));
s->handler = qemu_mallocz(s->modulecount * 32 * sizeof(qemu_irq));
qdev_init_gpio_in(&dev->qdev, omap2_gpio_set, s->modulecount * 32);
qdev_init_gpio_out(&dev->qdev, s->handler, s->modulecount * 32);
for (i = 0; i < s->modulecount; i++) {
struct omap2_gpio_s *m = &s->modules[i];
if (!s->fclk[i]) {
hw_error("omap2-gpio: fclk%d not connected\n", i);
}
m->revision = (s->mpu_model < omap3430) ? 0x18 : 0x25;
m->handler = &s->handler[i * 32];
sysbus_init_irq(dev, &m->irq[0]); /* mpu irq */
sysbus_init_irq(dev, &m->irq[1]); /* dsp irq */
sysbus_init_irq(dev, &m->wkup);
sysbus_init_mmio(dev, 0x1000,
cpu_register_io_memory(omap2_gpio_module_readfn,
omap2_gpio_module_writefn,
m, DEVICE_NATIVE_ENDIAN));
}
return 0;
} }
void omap2_gpio_out_set(struct omap_gpif_s *s, int line, qemu_irq handler) /* 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 SysBusDeviceInfo omap_gpio_info = {
.init = omap_gpio_init,
.qdev.name = "omap-gpio",
.qdev.size = sizeof(struct omap_gpif_s),
.qdev.reset = omap_gpif_reset,
.qdev.props = (Property[]) {
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 SysBusDeviceInfo omap2_gpio_info = {
.init = omap2_gpio_init,
.qdev.name = "omap2-gpio",
.qdev.size = sizeof(struct omap2_gpif_s),
.qdev.reset = omap2_gpif_reset,
.qdev.props = (Property[]) {
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 omap_gpio_register_device(void)
{ {
if (line >= s->modules * 32 || line < 0) sysbus_register_withprop(&omap_gpio_info);
hw_error("%s: No GPIO line %i\n", __FUNCTION__, line); sysbus_register_withprop(&omap2_gpio_info);
s->module[line >> 5].handler[line & 31] = handler;
} }
device_init(omap_gpio_register_device)

View File

@ -94,7 +94,7 @@ static void palmte_microwire_setup(struct omap_mpu_state_s *cpu)
{ {
uWireSlave *tsc; uWireSlave *tsc;
tsc = tsc2102_init(omap_gpio_in_get(cpu->gpio)[PALMTE_PINTDAV_GPIO]); tsc = tsc2102_init(qdev_get_gpio_in(cpu->gpio, PALMTE_PINTDAV_GPIO));
omap_uwire_attach(cpu->microwire, tsc, 0); omap_uwire_attach(cpu->microwire, tsc, 0);
omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc)); omap_mcbsp_i2s_attach(cpu->mcbsp1, tsc210x_codec(tsc));
@ -163,24 +163,24 @@ static void palmte_gpio_setup(struct omap_mpu_state_s *cpu)
qemu_irq *misc_gpio; qemu_irq *misc_gpio;
omap_mmc_handlers(cpu->mmc, omap_mmc_handlers(cpu->mmc,
omap_gpio_in_get(cpu->gpio)[PALMTE_MMC_WP_GPIO], qdev_get_gpio_in(cpu->gpio, PALMTE_MMC_WP_GPIO),
qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio) qemu_irq_invert(omap_mpuio_in_get(cpu->mpuio)
[PALMTE_MMC_SWITCH_GPIO])); [PALMTE_MMC_SWITCH_GPIO]));
misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7); misc_gpio = qemu_allocate_irqs(palmte_onoff_gpios, cpu, 7);
omap_gpio_out_set(cpu->gpio, PALMTE_MMC_POWER_GPIO, misc_gpio[0]); qdev_connect_gpio_out(cpu->gpio, PALMTE_MMC_POWER_GPIO, misc_gpio[0]);
omap_gpio_out_set(cpu->gpio, PALMTE_SPEAKER_GPIO, misc_gpio[1]); qdev_connect_gpio_out(cpu->gpio, PALMTE_SPEAKER_GPIO, misc_gpio[1]);
omap_gpio_out_set(cpu->gpio, 11, misc_gpio[2]); qdev_connect_gpio_out(cpu->gpio, 11, misc_gpio[2]);
omap_gpio_out_set(cpu->gpio, 12, misc_gpio[3]); qdev_connect_gpio_out(cpu->gpio, 12, misc_gpio[3]);
omap_gpio_out_set(cpu->gpio, 13, misc_gpio[4]); qdev_connect_gpio_out(cpu->gpio, 13, misc_gpio[4]);
omap_mpuio_out_set(cpu->mpuio, 1, misc_gpio[5]); omap_mpuio_out_set(cpu->mpuio, 1, misc_gpio[5]);
omap_mpuio_out_set(cpu->mpuio, 3, misc_gpio[6]); omap_mpuio_out_set(cpu->mpuio, 3, misc_gpio[6]);
/* Reset some inputs to initial state. */ /* Reset some inputs to initial state. */
qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_USBDETECT_GPIO]); qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USBDETECT_GPIO));
qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_USB_OR_DC_GPIO]); qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_USB_OR_DC_GPIO));
qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[4]); qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, 4));
qemu_irq_lower(omap_gpio_in_get(cpu->gpio)[PALMTE_HEADPHONES_GPIO]); qemu_irq_lower(qdev_get_gpio_in(cpu->gpio, PALMTE_HEADPHONES_GPIO));
qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]); qemu_irq_lower(omap_mpuio_in_get(cpu->mpuio)[PALMTE_DC_GPIO]);
qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]); qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[6]);
qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]); qemu_irq_raise(omap_mpuio_in_get(cpu->mpuio)[7]);