Revision 54e17933
b/hw/nseries.c | ||
---|---|---|
45 | 45 |
uint32_t (*txrx)(void *opaque, uint32_t value, int len); |
46 | 46 |
uWireSlave *chip; |
47 | 47 |
} ts; |
48 |
i2c_bus *i2c; |
|
49 | 48 |
|
50 | 49 |
int keymap[0x80]; |
51 | 50 |
DeviceState *kbd; |
... | ... | |
194 | 193 |
{ |
195 | 194 |
DeviceState *dev; |
196 | 195 |
qemu_irq tmp_irq = qdev_get_gpio_in(s->cpu->gpio, N8X0_TMP105_GPIO); |
197 |
|
|
198 |
/* Attach the CPU on one end of our I2C bus. */ |
|
199 |
s->i2c = omap_i2c_bus(s->cpu->i2c[0]); |
|
196 |
i2c_bus *i2c = omap_i2c_bus(s->cpu->i2c[0]); |
|
200 | 197 |
|
201 | 198 |
/* Attach a menelaus PM chip */ |
202 |
dev = i2c_create_slave(s->i2c, "twl92230", N8X0_MENELAUS_ADDR);
|
|
199 |
dev = i2c_create_slave(i2c, "twl92230", N8X0_MENELAUS_ADDR); |
|
203 | 200 |
qdev_connect_gpio_out(dev, 3, |
204 | 201 |
qdev_get_gpio_in(s->cpu->ih[0], |
205 | 202 |
OMAP_INT_24XX_SYS_NIRQ)); |
... | ... | |
207 | 204 |
qemu_system_powerdown = qdev_get_gpio_in(dev, 3); |
208 | 205 |
|
209 | 206 |
/* Attach a TMP105 PM chip (A0 wired to ground) */ |
210 |
dev = i2c_create_slave(s->i2c, "tmp105", N8X0_TMP105_ADDR);
|
|
207 |
dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR); |
|
211 | 208 |
qdev_connect_gpio_out(dev, 0, tmp_irq); |
212 | 209 |
} |
213 | 210 |
|
... | ... | |
391 | 388 |
|
392 | 389 |
/* Attach the LM8322 keyboard to the I2C bus, |
393 | 390 |
* should happen in n8x0_i2c_setup and s->kbd be initialised here. */ |
394 |
s->kbd = i2c_create_slave(s->i2c, "lm8323", N810_LM8323_ADDR); |
|
391 |
s->kbd = i2c_create_slave(omap_i2c_bus(s->cpu->i2c[0]), |
|
392 |
"lm8323", N810_LM8323_ADDR); |
|
395 | 393 |
qdev_connect_gpio_out(s->kbd, 0, kbd_irq); |
396 | 394 |
} |
397 | 395 |
|
b/hw/omap.h | ||
---|---|---|
764 | 764 |
void omap_mmc_enable(struct omap_mmc_s *s, int enable); |
765 | 765 |
|
766 | 766 |
/* omap_i2c.c */ |
767 |
struct omap_i2c_s; |
|
768 |
struct omap_i2c_s *omap_i2c_init(MemoryRegion *sysmem, |
|
769 |
target_phys_addr_t base, |
|
770 |
qemu_irq irq, |
|
771 |
qemu_irq *dma, |
|
772 |
omap_clk clk); |
|
773 |
struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta, |
|
774 |
qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk); |
|
775 |
void omap_i2c_reset(struct omap_i2c_s *s); |
|
776 |
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s); |
|
767 |
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c); |
|
777 | 768 |
|
778 | 769 |
# define cpu_is_omap310(cpu) (cpu->mpu_model == omap310) |
779 | 770 |
# define cpu_is_omap1510(cpu) (cpu->mpu_model == omap1510) |
... | ... | |
867 | 858 |
|
868 | 859 |
struct omap_pwl_s *pwl; |
869 | 860 |
struct omap_pwt_s *pwt; |
870 |
struct omap_i2c_s *i2c[2];
|
|
861 |
DeviceState *i2c[2];
|
|
871 | 862 |
|
872 | 863 |
struct omap_rtc_s *rtc; |
873 | 864 |
|
b/hw/omap1.c | ||
---|---|---|
3694 | 3694 |
omap_uwire_reset(mpu->microwire); |
3695 | 3695 |
omap_pwl_reset(mpu->pwl); |
3696 | 3696 |
omap_pwt_reset(mpu->pwt); |
3697 |
omap_i2c_reset(mpu->i2c[0]); |
|
3698 | 3697 |
omap_rtc_reset(mpu->rtc); |
3699 | 3698 |
omap_mcbsp_reset(mpu->mcbsp1); |
3700 | 3699 |
omap_mcbsp_reset(mpu->mcbsp2); |
... | ... | |
3993 | 3992 |
s->pwt = omap_pwt_init(system_memory, 0xfffb6000, |
3994 | 3993 |
omap_findclk(s, "armxor_ck")); |
3995 | 3994 |
|
3996 |
s->i2c[0] = omap_i2c_init(system_memory, 0xfffb3800, |
|
3997 |
qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C), |
|
3998 |
&s->drq[OMAP_DMA_I2C_RX], omap_findclk(s, "mpuper_ck")); |
|
3995 |
s->i2c[0] = qdev_create(NULL, "omap_i2c"); |
|
3996 |
qdev_prop_set_uint8(s->i2c[0], "revision", 0x11); |
|
3997 |
qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "mpuper_ck")); |
|
3998 |
qdev_init_nofail(s->i2c[0]); |
|
3999 |
busdev = sysbus_from_qdev(s->i2c[0]); |
|
4000 |
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C)); |
|
4001 |
sysbus_connect_irq(busdev, 1, s->drq[OMAP_DMA_I2C_TX]); |
|
4002 |
sysbus_connect_irq(busdev, 2, s->drq[OMAP_DMA_I2C_RX]); |
|
4003 |
sysbus_mmio_map(busdev, 0, 0xfffb3800); |
|
3999 | 4004 |
|
4000 | 4005 |
s->rtc = omap_rtc_init(system_memory, 0xfffb4800, |
4001 | 4006 |
qdev_get_gpio_in(s->ih[1], OMAP_INT_RTC_TIMER), |
b/hw/omap2.c | ||
---|---|---|
2222 | 2222 |
omap_mmc_reset(mpu->mmc); |
2223 | 2223 |
omap_mcspi_reset(mpu->mcspi[0]); |
2224 | 2224 |
omap_mcspi_reset(mpu->mcspi[1]); |
2225 |
omap_i2c_reset(mpu->i2c[0]); |
|
2226 |
omap_i2c_reset(mpu->i2c[1]); |
|
2227 | 2225 |
cpu_state_reset(mpu->env); |
2228 | 2226 |
} |
2229 | 2227 |
|
... | ... | |
2395 | 2393 |
omap_findclk(s, "clk32-kHz"), |
2396 | 2394 |
omap_findclk(s, "core_l4_iclk")); |
2397 | 2395 |
|
2398 |
s->i2c[0] = omap2_i2c_init(omap_l4tao(s->l4, 5), |
|
2399 |
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ), |
|
2400 |
&s->drq[OMAP24XX_DMA_I2C1_TX], |
|
2401 |
omap_findclk(s, "i2c1.fclk"), |
|
2402 |
omap_findclk(s, "i2c1.iclk")); |
|
2403 |
s->i2c[1] = omap2_i2c_init(omap_l4tao(s->l4, 6), |
|
2404 |
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ), |
|
2405 |
&s->drq[OMAP24XX_DMA_I2C2_TX], |
|
2406 |
omap_findclk(s, "i2c2.fclk"), |
|
2407 |
omap_findclk(s, "i2c2.iclk")); |
|
2396 |
s->i2c[0] = qdev_create(NULL, "omap_i2c"); |
|
2397 |
qdev_prop_set_uint8(s->i2c[0], "revision", 0x34); |
|
2398 |
qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk")); |
|
2399 |
qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk")); |
|
2400 |
qdev_init_nofail(s->i2c[0]); |
|
2401 |
busdev = sysbus_from_qdev(s->i2c[0]); |
|
2402 |
sysbus_connect_irq(busdev, 0, |
|
2403 |
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ)); |
|
2404 |
sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C1_TX]); |
|
2405 |
sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C1_RX]); |
|
2406 |
sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 5), 0)); |
|
2407 |
|
|
2408 |
s->i2c[1] = qdev_create(NULL, "omap_i2c"); |
|
2409 |
qdev_prop_set_uint8(s->i2c[1], "revision", 0x34); |
|
2410 |
qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk")); |
|
2411 |
qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk")); |
|
2412 |
qdev_init_nofail(s->i2c[1]); |
|
2413 |
busdev = sysbus_from_qdev(s->i2c[1]); |
|
2414 |
sysbus_connect_irq(busdev, 0, |
|
2415 |
qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ)); |
|
2416 |
sysbus_connect_irq(busdev, 1, s->drq[OMAP24XX_DMA_I2C2_TX]); |
|
2417 |
sysbus_connect_irq(busdev, 2, s->drq[OMAP24XX_DMA_I2C2_RX]); |
|
2418 |
sysbus_mmio_map(busdev, 0, omap_l4_region_base(omap_l4tao(s->l4, 6), 0)); |
|
2408 | 2419 |
|
2409 | 2420 |
s->gpio = qdev_create(NULL, "omap2-gpio"); |
2410 | 2421 |
qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model); |
b/hw/omap_i2c.c | ||
---|---|---|
19 | 19 |
#include "hw.h" |
20 | 20 |
#include "i2c.h" |
21 | 21 |
#include "omap.h" |
22 |
#include "sysbus.h" |
|
22 | 23 |
|
23 |
struct omap_i2c_s { |
|
24 |
|
|
25 |
typedef struct OMAPI2CState { |
|
26 |
SysBusDevice busdev; |
|
24 | 27 |
MemoryRegion iomem; |
25 | 28 |
qemu_irq irq; |
26 | 29 |
qemu_irq drq[2]; |
27 | 30 |
i2c_bus *bus; |
28 | 31 |
|
29 | 32 |
uint8_t revision; |
33 |
void *iclk; |
|
34 |
void *fclk; |
|
35 |
|
|
30 | 36 |
uint8_t mask; |
31 | 37 |
uint16_t stat; |
32 | 38 |
uint16_t dma; |
... | ... | |
40 | 46 |
uint8_t divider; |
41 | 47 |
uint8_t times[2]; |
42 | 48 |
uint16_t test; |
43 |
}; |
|
49 |
} OMAPI2CState;
|
|
44 | 50 |
|
45 | 51 |
#define OMAP2_INTR_REV 0x34 |
46 | 52 |
#define OMAP2_GC_REV 0x34 |
47 | 53 |
|
48 |
static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
|
|
54 |
static void omap_i2c_interrupts_update(OMAPI2CState *s)
|
|
49 | 55 |
{ |
50 | 56 |
qemu_set_irq(s->irq, s->stat & s->mask); |
51 | 57 |
if ((s->dma >> 15) & 1) /* RDMA_EN */ |
... | ... | |
54 | 60 |
qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */ |
55 | 61 |
} |
56 | 62 |
|
57 |
static void omap_i2c_fifo_run(struct omap_i2c_s *s)
|
|
63 |
static void omap_i2c_fifo_run(OMAPI2CState *s)
|
|
58 | 64 |
{ |
59 | 65 |
int ack = 1; |
60 | 66 |
|
... | ... | |
122 | 128 |
s->control &= ~(1 << 1); /* STP */ |
123 | 129 |
} |
124 | 130 |
|
125 |
void omap_i2c_reset(struct omap_i2c_s *s)
|
|
131 |
static void omap_i2c_reset(DeviceState *dev)
|
|
126 | 132 |
{ |
133 |
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, |
|
134 |
sysbus_from_qdev(dev)); |
|
127 | 135 |
s->mask = 0; |
128 | 136 |
s->stat = 0; |
129 | 137 |
s->dma = 0; |
... | ... | |
143 | 151 |
|
144 | 152 |
static uint32_t omap_i2c_read(void *opaque, target_phys_addr_t addr) |
145 | 153 |
{ |
146 |
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
|
|
154 |
OMAPI2CState *s = opaque;
|
|
147 | 155 |
int offset = addr & OMAP_MPUI_REG_MASK; |
148 | 156 |
uint16_t ret; |
149 | 157 |
|
... | ... | |
243 | 251 |
static void omap_i2c_write(void *opaque, target_phys_addr_t addr, |
244 | 252 |
uint32_t value) |
245 | 253 |
{ |
246 |
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
|
|
254 |
OMAPI2CState *s = opaque;
|
|
247 | 255 |
int offset = addr & OMAP_MPUI_REG_MASK; |
248 | 256 |
int nack; |
249 | 257 |
|
... | ... | |
309 | 317 |
} |
310 | 318 |
|
311 | 319 |
if (value & 2) |
312 |
omap_i2c_reset(s);
|
|
320 |
omap_i2c_reset(&s->busdev.qdev);
|
|
313 | 321 |
break; |
314 | 322 |
|
315 | 323 |
case 0x24: /* I2C_CON */ |
316 | 324 |
s->control = value & 0xcf87; |
317 | 325 |
if (~value & (1 << 15)) { /* I2C_EN */ |
318 | 326 |
if (s->revision < OMAP2_INTR_REV) |
319 |
omap_i2c_reset(s);
|
|
327 |
omap_i2c_reset(&s->busdev.qdev);
|
|
320 | 328 |
break; |
321 | 329 |
} |
322 | 330 |
if ((value & (1 << 15)) && !(value & (1 << 10))) { /* MST */ |
... | ... | |
385 | 393 |
static void omap_i2c_writeb(void *opaque, target_phys_addr_t addr, |
386 | 394 |
uint32_t value) |
387 | 395 |
{ |
388 |
struct omap_i2c_s *s = (struct omap_i2c_s *) opaque;
|
|
396 |
OMAPI2CState *s = opaque;
|
|
389 | 397 |
int offset = addr & OMAP_MPUI_REG_MASK; |
390 | 398 |
|
391 | 399 |
switch (offset) { |
... | ... | |
426 | 434 |
.endianness = DEVICE_NATIVE_ENDIAN, |
427 | 435 |
}; |
428 | 436 |
|
429 |
struct omap_i2c_s *omap_i2c_init(MemoryRegion *sysmem, |
|
430 |
target_phys_addr_t base, |
|
431 |
qemu_irq irq, |
|
432 |
qemu_irq *dma, |
|
433 |
omap_clk clk) |
|
437 |
static int omap_i2c_init(SysBusDevice *dev) |
|
434 | 438 |
{ |
435 |
struct omap_i2c_s *s = (struct omap_i2c_s *) |
|
436 |
g_malloc0(sizeof(struct omap_i2c_s)); |
|
437 |
|
|
438 |
/* TODO: set a value greater or equal to real hardware */ |
|
439 |
s->revision = 0x11; |
|
440 |
s->irq = irq; |
|
441 |
s->drq[0] = dma[0]; |
|
442 |
s->drq[1] = dma[1]; |
|
443 |
s->bus = i2c_init_bus(NULL, "i2c"); |
|
444 |
omap_i2c_reset(s); |
|
439 |
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, dev); |
|
445 | 440 |
|
446 |
memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c", 0x800); |
|
447 |
memory_region_add_subregion(sysmem, base, &s->iomem); |
|
448 |
|
|
449 |
return s; |
|
441 |
if (!s->fclk) { |
|
442 |
hw_error("omap_i2c: fclk not connected\n"); |
|
443 |
} |
|
444 |
if (s->revision >= OMAP2_INTR_REV && !s->iclk) { |
|
445 |
/* Note that OMAP1 doesn't have a separate interface clock */ |
|
446 |
hw_error("omap_i2c: iclk not connected\n"); |
|
447 |
} |
|
448 |
sysbus_init_irq(dev, &s->irq); |
|
449 |
sysbus_init_irq(dev, &s->drq[0]); |
|
450 |
sysbus_init_irq(dev, &s->drq[1]); |
|
451 |
memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c", |
|
452 |
(s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000); |
|
453 |
sysbus_init_mmio(dev, &s->iomem); |
|
454 |
s->bus = i2c_init_bus(&dev->qdev, NULL); |
|
455 |
return 0; |
|
450 | 456 |
} |
451 | 457 |
|
452 |
struct omap_i2c_s *omap2_i2c_init(struct omap_target_agent_s *ta, |
|
453 |
qemu_irq irq, qemu_irq *dma, omap_clk fclk, omap_clk iclk) |
|
454 |
{ |
|
455 |
struct omap_i2c_s *s = (struct omap_i2c_s *) |
|
456 |
g_malloc0(sizeof(struct omap_i2c_s)); |
|
458 |
static Property omap_i2c_properties[] = { |
|
459 |
DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0), |
|
460 |
DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk), |
|
461 |
DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk), |
|
462 |
DEFINE_PROP_END_OF_LIST(), |
|
463 |
}; |
|
457 | 464 |
|
458 |
s->revision = 0x34; |
|
459 |
s->irq = irq; |
|
460 |
s->drq[0] = dma[0]; |
|
461 |
s->drq[1] = dma[1]; |
|
462 |
s->bus = i2c_init_bus(NULL, "i2c"); |
|
463 |
omap_i2c_reset(s); |
|
465 |
static void omap_i2c_class_init(ObjectClass *klass, void *data) |
|
466 |
{ |
|
467 |
DeviceClass *dc = DEVICE_CLASS(klass); |
|
468 |
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); |
|
469 |
k->init = omap_i2c_init; |
|
470 |
dc->props = omap_i2c_properties; |
|
471 |
dc->reset = omap_i2c_reset; |
|
472 |
} |
|
464 | 473 |
|
465 |
memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap2.i2c", |
|
466 |
omap_l4_region_size(ta, 0)); |
|
467 |
omap_l4_attach(ta, 0, &s->iomem); |
|
474 |
static TypeInfo omap_i2c_info = { |
|
475 |
.name = "omap_i2c", |
|
476 |
.parent = TYPE_SYS_BUS_DEVICE, |
|
477 |
.instance_size = sizeof(OMAPI2CState), |
|
478 |
.class_init = omap_i2c_class_init, |
|
479 |
}; |
|
468 | 480 |
|
469 |
return s; |
|
481 |
static void omap_i2c_register_types(void) |
|
482 |
{ |
|
483 |
type_register_static(&omap_i2c_info); |
|
470 | 484 |
} |
471 | 485 |
|
472 |
i2c_bus *omap_i2c_bus(struct omap_i2c_s *s)
|
|
486 |
i2c_bus *omap_i2c_bus(DeviceState *omap_i2c)
|
|
473 | 487 |
{ |
488 |
OMAPI2CState *s = FROM_SYSBUS(OMAPI2CState, sysbus_from_qdev(omap_i2c)); |
|
474 | 489 |
return s->bus; |
475 | 490 |
} |
491 |
|
|
492 |
type_init(omap_i2c_register_types) |
Also available in: Unified diff