GPIO interrupts working!

This commit is contained in:
Martijn de Vos committed 2022-07-26 21:36:20 +02:00
1 parent 9f3e33e3cf
commit d6d52a81af
7 files changed
+108 -7

No files matched your search

+8 -1
View File
@@ -549,6 +549,12 @@ static void ipod_touch_machine_init(MachineState *machine)
IPodTouchSYSICState *sysic_state = IPOD_TOUCH_SYSIC(dev);
nms->sysic = (IPodTouchSYSICState *) g_malloc0(sizeof(struct IPodTouchSYSICState));
memory_region_add_subregion(sysmem, SYSIC_MEM_BASE, &sysic_state->iomem);
SysBusDevice *busdev = SYS_BUS_DEVICE(dev);
for(int grp = 0; grp < GPIO_NUMINTGROUPS; grp++) {
sysbus_connect_irq(busdev, grp, s5l8900_get_irq(nms, S5L8900_GPIO_IRQS[grp]));
}
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8900_GPIO_G4_IRQ));
dev = exynos4210_uart_create(UART0_MEM_BASE, 256, 0, serial_hd(0), nms->irq[0][24]);
if (!dev) {
@@ -596,8 +602,9 @@ static void ipod_touch_machine_init(MachineState *machine)
dev = qdev_new("ipodtouch.lcd");
IPodTouchLCDState *lcd_state = IPOD_TOUCH_LCD(dev);
lcd_state->sysmem = sysmem;
lcd_state->sysic = sysic_state;
nms->lcd_state = lcd_state;
SysBusDevice *busdev = SYS_BUS_DEVICE(dev);
busdev = SYS_BUS_DEVICE(dev);
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8900_LCD_IRQ));
memory_region_add_subregion(sysmem, DISPLAY_MEM_BASE, &lcd_state->iomem);
sysbus_realize(busdev, &error_fatal);
+6
View File
@@ -228,6 +228,12 @@ static const GraphicHwOps s5l8900_gfx_ops = {
static void ipod_touch_lcd_mouse_event(void *opaque, int x, int y, int z, int buttons_state)
{
//printf("CLICKY %d %d %d %d\n", x, y, z, buttons_state);
IPodTouchLCDState *lcd = (IPodTouchLCDState *) opaque;
if(buttons_state) {
// mouse press
lcd->sysic->gpio_int_status[4] |= (1 << 27);
qemu_irq_raise(lcd->sysic->gpio_irqs[4]);
}
}
static void s5l8900_lcd_realize(DeviceState *dev, Error **errp)
+1 -1
View File
@@ -3,7 +3,7 @@
static uint32_t ipod_touch_multitouch_transfer(SSIPeripheral *dev, uint32_t value)
{
IPodTouchMultitouchState *s = IPOD_TOUCH_MULTITOUCH(dev);
//printf("Got value: %d\n", value);
printf("<MULTITOUCH> Got value: %d\n", value);
return value;
}
+65 -4
View File
@@ -10,12 +10,36 @@ static uint64_t ipod_touch_sysic_read(void *opaque, hwaddr addr, unsigned size)
case POWER_ID:
//return (3 << 24); //for older iboots
return (2 << 0x18);
case 0x7a:
case 0x7c:
return 1;
case POWER_SETSTATE:
case POWER_STATE:
return s->power_state;
case 0x7a:
case 0x7c:
return 1;
case GPIO_INTLEVEL ... (GPIO_INTLEVEL + GPIO_NUMINTGROUPS * 4):
{
fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
uint8_t group = (addr - GPIO_INTLEVEL) / 4;
return s->gpio_int_level[group];
}
case GPIO_INTSTAT ... (GPIO_INTSTAT + GPIO_NUMINTGROUPS * 4):
{
fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
uint8_t group = (addr - GPIO_INTSTAT) / 4;
return s->gpio_int_status[group];
}
case GPIO_INTEN ... (GPIO_INTEN + GPIO_NUMINTGROUPS * 4):
{
fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
uint8_t group = (addr - GPIO_INTEN) / 4;
return s->gpio_int_enabled[group];
}
case GPIO_INTTYPE ... (GPIO_INTTYPE + GPIO_NUMINTGROUPS * 4):
{
fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
uint8_t group = (addr - GPIO_INTTYPE) / 4;
return s->gpio_int_type[group];
}
default:
break;
}
@@ -36,6 +60,41 @@ static void ipod_touch_sysic_write(void *opaque, hwaddr addr, uint64_t val, unsi
case POWER_OFFCTRL:
s->power_state = val;
break;
case GPIO_INTLEVEL ... (GPIO_INTLEVEL + GPIO_NUMINTGROUPS * 4):
{
fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, val, addr);
uint8_t group = (addr - GPIO_INTLEVEL) / 4;
printf("Writing 0x%08x to group %d (lvl) offset 0x%08x\n", val, group, addr);
break;
}
case GPIO_INTSTAT ... (GPIO_INTSTAT + GPIO_NUMINTGROUPS * 4):
{
fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, val, addr);
uint8_t group = (addr - GPIO_INTSTAT) / 4;
// acknowledge the interrupts and clear the corresponding bits
printf("GPIO INT stat before clearing: 0x%08x\n", s->gpio_int_status[group]);
s->gpio_int_status[group] = s->gpio_int_status[group] & ~val;
printf("GPIO INT stat after clearing: 0x%08x\n", s->gpio_int_status[group]);
qemu_irq_lower(s->gpio_irqs[group]);
break;
}
case GPIO_INTEN ... (GPIO_INTEN + GPIO_NUMINTGROUPS * 4):
{
fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, val, addr);
uint8_t group = (addr - GPIO_INTEN) / 4;
s->gpio_int_enabled[group] = val;
break;
}
case GPIO_INTTYPE ... (GPIO_INTTYPE + GPIO_NUMINTGROUPS * 4):
{
fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, val, addr);
uint8_t group = (addr - GPIO_INTTYPE) / 4;
s->gpio_int_type[group] = val;
break;
}
default:
break;
}
@@ -55,7 +114,9 @@ static void ipod_touch_sysic_init(Object *obj)
memory_region_init_io(&s->iomem, obj, &ipod_touch_sysic_ops, s, TYPE_IPOD_TOUCH_SYSIC, 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
for(int grp = 0; grp < GPIO_NUMINTGROUPS; grp++) {
sysbus_init_irq(sbd, &s->gpio_irqs[grp]);
}
}
static void ipod_touch_sysic_class_init(ObjectClass *klass, void *data)
+11
View File
@@ -76,6 +76,17 @@
#define S5L8900_TVOUT_SDO_IRQ 0x1E
#define S5L8900_TVOUT_MIXER_IRQ 0x26
// GPIO interrupts
#define S5L8900_GPIO_G0_IRQ 0x21
#define S5L8900_GPIO_G1_IRQ 0x20
#define S5L8900_GPIO_G2_IRQ 0x1F
#define S5L8900_GPIO_G3_IRQ 0x03
#define S5L8900_GPIO_G4_IRQ 0x02
#define S5L8900_GPIO_G5_IRQ 0x01
#define S5L8900_GPIO_G6_IRQ 0x00
const int S5L8900_GPIO_IRQS[7] = { S5L8900_GPIO_G0_IRQ, S5L8900_GPIO_G1_IRQ, S5L8900_GPIO_G2_IRQ, S5L8900_GPIO_G3_IRQ, S5L8900_GPIO_G4_IRQ, S5L8900_GPIO_G5_IRQ, S5L8900_GPIO_G6_IRQ };
typedef struct {
MachineClass parent;
} IPodTouchMachineClass;
+2
View File
@@ -6,6 +6,7 @@
#include "qemu/timer.h"
#include "hw/sysbus.h"
#include "hw/irq.h"
#include "hw/arm/ipod_touch_sysic.h"
#define TYPE_IPOD_TOUCH_LCD "ipodtouch.lcd"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchLCDState, IPOD_TOUCH_LCD)
@@ -16,6 +17,7 @@ typedef struct IPodTouchLCDState
MemoryRegion *sysmem;
MemoryRegion iomem;
QemuConsole *con;
IPodTouchSYSICState *sysic;
int invalidate;
MemoryRegionSection fbsection;
qemu_irq irq;
+15 -1
View File
@@ -18,11 +18,25 @@ OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchSYSICState, IPOD_TOUCH_SYSIC)
#define POWER_ID_ADM 0x10
// the GPIO IC is part of the system controller
#define GPIO_INTLEVEL 0x80
#define GPIO_INTSTAT 0xA0
#define GPIO_INTEN 0xC0
#define GPIO_INTTYPE 0xE0
#define GPIO_NUMINTGROUPS 7
typedef struct IPodTouchSYSICState {
SysBusDevice parent_obj;
MemoryRegion iomem;
qemu_irq irq;
qemu_irq gpio_irqs[GPIO_NUMINTGROUPS];
uint32_t power_state;
// GPIO
uint32_t gpio_int_level[GPIO_NUMINTGROUPS];
uint32_t gpio_int_status[GPIO_NUMINTGROUPS];
uint32_t gpio_int_enabled[GPIO_NUMINTGROUPS];
uint32_t gpio_int_type[GPIO_NUMINTGROUPS];
} IPodTouchSYSICState;
#endif