Skip to content

Commit d30ea7f

Browse files
committed
WIP
1 parent 7b44f07 commit d30ea7f

23 files changed

+942
-54
lines changed

hw/arm/amazfit.c

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,50 @@
44
#include "hw/arm/stm32l467_soc.h"
55
#include "hw/boards.h"
66
#include "hw/i2c/i2c.h"
7+
#include "hw/irq.h"
78
#include "hw/loader.h"
89
#include "hw/qdev-properties.h"
910
#include "hw/ssi/ssi.h"
1011
#include "qapi/error.h"
12+
#include "ui/console.h"
1113

12-
// static uint32_t readu32(hwaddr addr) {
13-
// uint32_t ret;
14-
// ARMCPU *cpu = ARM_CPU(first_cpu);
15-
// cpu_memory_rw_debug(cpu, addr, &ret, 4, false);
16-
//
17-
// return ret;
18-
//}
14+
static uint32_t readu32(hwaddr addr)
15+
{
16+
uint32_t ret;
17+
ARMCPU *cpu = ARM_CPU(first_cpu);
18+
cpu_memory_rw_debug(cpu, addr, &ret, 4, false);
19+
20+
return ret;
21+
}
22+
qemu_irq buttonIrq;
23+
qemu_irq buttonExtiIrq;
24+
qemu_irq touchIrq;
25+
qemu_irq touchExtiIrq;
26+
void amazfit_key_event(void *opaque, int keycode)
27+
{
28+
bool pressed = (keycode & 0x80) == 0;
29+
printf("KEY: %d | 0x%x\n", keycode & 0x7F, keycode & 0x80);
30+
31+
switch (keycode & 0x7F) {
32+
case 31: /* S */
33+
// LOW = pressed, HIGH = unpressed
34+
qemu_set_irq(buttonIrq, !pressed);
35+
qemu_set_irq(buttonExtiIrq, !pressed);
36+
break;
37+
38+
default:
39+
return;
40+
}
41+
}
42+
43+
static void amazfit_mouse_event(void *opaque, int dx, int dy, int dz,
44+
int buttons_state)
45+
{
46+
printf("mouse %d, %d, %d | %d\n", dx, dy, dz, buttons_state);
47+
48+
qemu_set_irq(touchIrq, buttons_state);
49+
qemu_set_irq(touchExtiIrq, buttons_state);
50+
}
1951

2052
static void bip_init(MachineState *machine)
2153
{
@@ -26,6 +58,18 @@ static void bip_init(MachineState *machine)
2658
SSIBus *spi_bus = (SSIBus *)qdev_get_child_bus(&dev->spi[2], "ssi"); // SPI3
2759
DeviceState *display = ssi_create_peripheral(spi_bus, "jdi-lpm013m126c");
2860

61+
qemu_irq cs_line = qdev_get_gpio_in_named(display, SSI_GPIO_CS, 0);
62+
qdev_connect_gpio_out(dev->gpio['G' - 'A'], 12, cs_line);
63+
64+
buttonIrq = qdev_get_gpio_in(dev->gpio['A' - 'A'], 0);
65+
buttonExtiIrq = qdev_get_gpio_in(dev->exti, 0);
66+
qemu_add_kbd_event_handler(amazfit_key_event, NULL);
67+
68+
69+
touchIrq = qdev_get_gpio_in(dev->gpio['B' - 'B'], 3);
70+
touchExtiIrq = qdev_get_gpio_in(dev->exti, 3);
71+
qemu_add_mouse_event_handler(amazfit_mouse_event, NULL, 1, "amazfit-mouse");
72+
2973
/* --- QSPI Flash --------------------------------------------- */
3074
SSIBus *qspi = (SSIBus *)qdev_get_child_bus(&dev->qspi, "qspi");
3175
DeviceState *qspi_flash = qdev_new("w25q64fw");

hw/arm/it7259.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,66 @@
1212
typedef struct {
1313
I2CSlave parent_obj;
1414

15+
int state;
16+
uint8_t buffer;
17+
int reserved;
18+
uint8_t rw;
19+
uint8_t reg;
1520
} IT7259State;
1621

1722
static int it7259_event(I2CSlave *i2c, enum i2c_event event)
1823
{
1924
IT7259State *s = IT7259(i2c);
2025

26+
switch (event) {
27+
case I2C_START_SEND:
28+
printf("[IT7259] START SEND\n", event);
29+
break;
30+
default:
31+
case I2C_FINISH:
32+
case I2C_START_RECV:
33+
printf("[IT7259] event %d\n", event);
34+
break;
35+
}
36+
2137
return 0;
2238
}
2339

2440
static uint8_t it7259_rx(I2CSlave *i2c)
2541
{
2642
IT7259State *s = IT7259(i2c);
2743

44+
assert(s->state == 2);
45+
s->state = 0;
46+
switch (s->reg) {
47+
case 0x32:
48+
return 0x59; // Device ID 2
49+
case 0x33:
50+
return 0x72; // Device ID 1
51+
}
52+
2853
return 0;
2954
}
3055

3156
static int it7259_tx(I2CSlave *i2c, uint8_t data)
3257
{
3358
IT7259State *s = IT7259(i2c);
34-
printf("I2C: 0x%02X\n", data);
59+
60+
if (s->state == 0) {
61+
s->reserved = data & 0b1111;
62+
s->buffer = (data >> 4)& 0b111;
63+
s->rw = data>>7;
64+
assert(s->reserved == 0b0000);
65+
assert(s->buffer == 0b111);
66+
assert(s->rw == 0b0);
67+
s->state++;
68+
} else if(s->state == 1) {
69+
s->reg = data;
70+
s->state++;
71+
}
72+
73+
printf("[IT7259] cmd: 0x%02X\n", data);
74+
3575

3676
return 0;
3777
}

hw/arm/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ arm_ss.add(files('stm32l476_qspi.c'))
7171
arm_ss.add(files('stm32l476_gpio.c'))
7272
arm_ss.add(files('stm32l476_syscfg.c'))
7373
arm_ss.add(files('stm32l476_i2c.c'))
74+
arm_ss.add(files('stm32l476_exti.c'))
7475
arm_ss.add(files('it7259.c'))
7576

7677

hw/arm/stm32l467_soc.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "exec/address-spaces.h"
55
#include "hw/arm/armv7m.h"
66
#include "hw/arm/boot.h"
7+
#include "hw/arm/stm32l476_exti.h"
78
#include "hw/arm/stm32l476_gpio.h"
89
#include "hw/boards.h"
910
#include "hw/loader.h"
@@ -163,6 +164,16 @@
163164
#define QSPI_R_BASE (0xA0001000UL)
164165

165166
enum {
167+
EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */
168+
EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
169+
EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */
170+
EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
171+
EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
172+
173+
EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */
174+
175+
EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */
176+
166177
DMA2_Channel1_IRQn = 56, /*!< DMA2 Channel 1 global Interrupt */
167178
DMA2_Channel2_IRQn = 57, /*!< DMA2 Channel 2 global Interrupt */
168179
DMA2_Channel3_IRQn = 58, /*!< DMA2 Channel 3 global Interrupt */
@@ -273,7 +284,6 @@ static void stm32l467_soc_realize(DeviceState *dev_soc, Error **errp)
273284
sysbus_mmio_map(SYS_BUS_DEVICE(s->gpio[i]), 0, gpio_desc[i].addr);
274285
}
275286

276-
create_unimplemented_layer("EXTI", EXTI_BASE, 0x400);
277287
create_unimplemented_layer("QUADSPI", QSPI_R_BASE, 0x400);
278288

279289
memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32L467.flash",
@@ -374,6 +384,20 @@ static void stm32l467_soc_realize(DeviceState *dev_soc, Error **errp)
374384
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[1]), 0, I2C2_BASE);
375385
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[2]), 0, I2C3_BASE);
376386

387+
s->exti = qdev_new(TYPE_STM32L476_EXTI);
388+
if (!sysbus_realize(SYS_BUS_DEVICE(s->exti), errp)) {
389+
return;
390+
}
391+
busdev = SYS_BUS_DEVICE(s->exti);
392+
sysbus_mmio_map(busdev, 0, EXTI_BASE);
393+
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, EXTI0_IRQn));
394+
sysbus_connect_irq(busdev, 1, qdev_get_gpio_in(armv7m, EXTI1_IRQn));
395+
sysbus_connect_irq(busdev, 2, qdev_get_gpio_in(armv7m, EXTI2_IRQn));
396+
sysbus_connect_irq(busdev, 3, qdev_get_gpio_in(armv7m, EXTI3_IRQn));
397+
sysbus_connect_irq(busdev, 4, qdev_get_gpio_in(armv7m, EXTI4_IRQn));
398+
sysbus_connect_irq(busdev, 5, qdev_get_gpio_in(armv7m, EXTI9_5_IRQn));
399+
sysbus_connect_irq(busdev, 6, qdev_get_gpio_in(armv7m, EXTI15_10_IRQn));
400+
377401
system_clock_scale = 1000;
378402
}
379403

hw/arm/stm32l476_TEMPLATE.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#include "qemu/osdep.h"
2+
#include "exec/address-spaces.h"
3+
#include "hw/arm/boot.h"
4+
#include "hw/arm/stm32l476_rcc.h"
5+
#include "hw/sysbus.h"
6+
#include "qemu/log.h"
7+
#include "sysemu/sysemu.h"
8+
9+
static void stm32l476_rcc_reset(DeviceState *dev)
10+
{
11+
STM32L476RccState *s = STM32L476_RCC(dev);
12+
}
13+
14+
static uint64_t stm32l476_rcc_read(void *opaque, hwaddr offset,
15+
unsigned int size)
16+
{
17+
STM32L476RccState *s = opaque;
18+
19+
switch (offset) {
20+
default:
21+
qemu_log_mask(LOG_UNIMP,
22+
"%s: unimplemented device read "
23+
"(size %d, offset 0x%" HWADDR_PRIx ")\n",
24+
__func__, size, offset);
25+
break;
26+
}
27+
return 0;
28+
}
29+
30+
static void stm32l476_rcc_write(void *opaque, hwaddr offset, uint64_t val64,
31+
unsigned int size)
32+
{
33+
STM32L476RccState *s = opaque;
34+
35+
switch (offset) {
36+
default:
37+
qemu_log_mask(LOG_UNIMP,
38+
"%s: unimplemented device write "
39+
"(size %d, value 0x%" PRIx64 ", offset 0x%" HWADDR_PRIx
40+
")\n",
41+
__func__, size, val64, offset);
42+
break;
43+
}
44+
}
45+
46+
static const MemoryRegionOps stm32l476_rcc_ops = {
47+
.read = stm32l476_rcc_read,
48+
.write = stm32l476_rcc_write,
49+
.endianness = DEVICE_NATIVE_ENDIAN,
50+
};
51+
52+
static void stm32l476_rcc_init(Object *obj)
53+
{
54+
STM32L476RccState *s = STM32L476_RCC(obj);
55+
56+
memory_region_init_io(&s->mmio, obj, &stm32l476_rcc_ops, s,
57+
TYPE_STM32L476_RCC, 0x400);
58+
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
59+
}
60+
61+
static void stm32l476_rcc_class_init(ObjectClass *klass, void *data)
62+
{
63+
DeviceClass *dc = DEVICE_CLASS(klass);
64+
65+
dc->reset = stm32l476_rcc_reset;
66+
}
67+
68+
static const TypeInfo stm32l476_rcc_info = {
69+
.name = TYPE_STM32L476_RCC,
70+
.parent = TYPE_SYS_BUS_DEVICE,
71+
.instance_size = sizeof(STM32L476RccState),
72+
.instance_init = stm32l476_rcc_init,
73+
.class_init = stm32l476_rcc_class_init,
74+
};
75+
76+
static void stm32l476_rcc_register_types(void)
77+
{
78+
type_register_static(&stm32l476_rcc_info);
79+
}
80+
81+
type_init(stm32l476_rcc_register_types)

0 commit comments

Comments
 (0)