summaryrefslogtreecommitdiffstats
path: root/hw/arm/spitz.c
diff options
context:
space:
mode:
authorPeter Maydell2020-07-03 17:59:45 +0200
committerPeter Maydell2020-07-03 17:59:45 +0200
commiteb2dc887a4c71d9e4efd0861fcf7094d0df9df99 (patch)
tree59b31f04ffa9dedd4376dffec56880150b2cbd63 /hw/arm/spitz.c
parenthw/misc/max111x: Create header file for documentation, TYPE_ macros (diff)
downloadqemu-eb2dc887a4c71d9e4efd0861fcf7094d0df9df99.tar.gz
qemu-eb2dc887a4c71d9e4efd0861fcf7094d0df9df99.tar.xz
qemu-eb2dc887a4c71d9e4efd0861fcf7094d0df9df99.zip
hw/arm/spitz: Encapsulate misc GPIO handling in a device
Currently we have a free-floating set of IRQs and a function spitz_out_switch() which handle some miscellaneous GPIO lines for the spitz board. Encapsulate this behaviour in a simple QOM device. At this point we can finally remove the 'max1111' global, because the ADC battery-temperature value is now handled by the misc-gpio device writing the value to its outbound "adc-temp" GPIO, which the board code wires up to the appropriate inbound GPIO line on the max1111. This commit also fixes Coverity issue CID 1421913 (which pointed out that the 'outsignals' in spitz_scoop_gpio_setup() were leaked), because it removes the use of the qemu_allocate_irqs() API from this code entirely. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20200628142429.17111-13-peter.maydell@linaro.org
Diffstat (limited to 'hw/arm/spitz.c')
-rw-r--r--hw/arm/spitz.c131
1 files changed, 88 insertions, 43 deletions
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index 1400a56729..bab9968cce 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -51,6 +51,7 @@ typedef struct {
DeviceState *max1111;
DeviceState *scp0;
DeviceState *scp1;
+ DeviceState *misc_gpio;
} SpitzMachineState;
#define TYPE_SPITZ_MACHINE "spitz-common"
@@ -658,8 +659,6 @@ static void spitz_lcdtg_realize(SSISlave *ssi, Error **errp)
#define SPITZ_GPIO_MAX1111_CS 20
#define SPITZ_GPIO_TP_INT 11
-static DeviceState *max1111;
-
/* "Demux" the signal based on current chipselect */
typedef struct {
SSISlave ssidev;
@@ -695,18 +694,6 @@ static void corgi_ssp_gpio_cs(void *opaque, int line, int level)
#define SPITZ_BATTERY_VOLT 0xd0 /* About 4.0V */
#define SPITZ_CHARGEON_ACIN 0x80 /* About 5.0V */
-static void spitz_adc_temp_on(void *opaque, int line, int level)
-{
- int batt_temp;
-
- if (!max1111)
- return;
-
- batt_temp = level ? SPITZ_BATTERY_TEMP : 0;
-
- qemu_set_irq(qdev_get_gpio_in(max1111, MAX1111_BATT_TEMP), batt_temp);
-}
-
static void corgi_ssp_realize(SSISlave *d, Error **errp)
{
DeviceState *dev = DEVICE(d);
@@ -734,7 +721,6 @@ static void spitz_ssp_attach(SpitzMachineState *sms)
bus = qdev_get_child_bus(sms->mux, "ssi2");
sms->max1111 = qdev_new(TYPE_MAX_1111);
- max1111 = sms->max1111;
qdev_prop_set_uint8(sms->max1111, "input1" /* BATT_VOLT */,
SPITZ_BATTERY_VOLT);
qdev_prop_set_uint8(sms->max1111, "input2" /* BATT_TEMP */, 0);
@@ -810,27 +796,66 @@ static void spitz_akita_i2c_setup(PXA2xxState *cpu)
/* Other peripherals */
-static void spitz_out_switch(void *opaque, int line, int level)
+/*
+ * Encapsulation of some miscellaneous GPIO line behaviour for the Spitz boards.
+ *
+ * QEMU interface:
+ * + named GPIO inputs "green-led", "orange-led", "charging", "discharging":
+ * these currently just print messages that the line has been signalled
+ * + named GPIO input "adc-temp-on": set to cause the battery-temperature
+ * value to be passed to the max111x ADC
+ * + named GPIO output "adc-temp": the ADC value, to be wired up to the max111x
+ */
+#define TYPE_SPITZ_MISC_GPIO "spitz-misc-gpio"
+#define SPITZ_MISC_GPIO(obj) \
+ OBJECT_CHECK(SpitzMiscGPIOState, (obj), TYPE_SPITZ_MISC_GPIO)
+
+typedef struct SpitzMiscGPIOState {
+ SysBusDevice parent_obj;
+
+ qemu_irq adc_value;
+} SpitzMiscGPIOState;
+
+static void spitz_misc_charging(void *opaque, int n, int level)
{
- switch (line) {
- case 0:
- zaurus_printf("Charging %s.\n", level ? "off" : "on");
- break;
- case 1:
- zaurus_printf("Discharging %s.\n", level ? "on" : "off");
- break;
- case 2:
- zaurus_printf("Green LED %s.\n", level ? "on" : "off");
- break;
- case 3:
- zaurus_printf("Orange LED %s.\n", level ? "on" : "off");
- break;
- case 6:
- spitz_adc_temp_on(opaque, line, level);
- break;
- default:
- g_assert_not_reached();
- }
+ zaurus_printf("Charging %s.\n", level ? "off" : "on");
+}
+
+static void spitz_misc_discharging(void *opaque, int n, int level)
+{
+ zaurus_printf("Discharging %s.\n", level ? "off" : "on");
+}
+
+static void spitz_misc_green_led(void *opaque, int n, int level)
+{
+ zaurus_printf("Green LED %s.\n", level ? "off" : "on");
+}
+
+static void spitz_misc_orange_led(void *opaque, int n, int level)
+{
+ zaurus_printf("Orange LED %s.\n", level ? "off" : "on");
+}
+
+static void spitz_misc_adc_temp(void *opaque, int n, int level)
+{
+ SpitzMiscGPIOState *s = SPITZ_MISC_GPIO(opaque);
+ int batt_temp = level ? SPITZ_BATTERY_TEMP : 0;
+
+ qemu_set_irq(s->adc_value, batt_temp);
+}
+
+static void spitz_misc_gpio_init(Object *obj)
+{
+ SpitzMiscGPIOState *s = SPITZ_MISC_GPIO(obj);
+ DeviceState *dev = DEVICE(obj);
+
+ qdev_init_gpio_in_named(dev, spitz_misc_charging, "charging", 1);
+ qdev_init_gpio_in_named(dev, spitz_misc_discharging, "discharging", 1);
+ qdev_init_gpio_in_named(dev, spitz_misc_green_led, "green-led", 1);
+ qdev_init_gpio_in_named(dev, spitz_misc_orange_led, "orange-led", 1);
+ qdev_init_gpio_in_named(dev, spitz_misc_adc_temp, "adc-temp-on", 1);
+
+ qdev_init_gpio_out_named(dev, &s->adc_value, "adc-temp", 1);
}
#define SPITZ_SCP_LED_GREEN 1
@@ -850,12 +875,22 @@ static void spitz_out_switch(void *opaque, int line, int level)
static void spitz_scoop_gpio_setup(SpitzMachineState *sms)
{
- qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, sms->mpu, 8);
-
- qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_CHRG_ON, outsignals[0]);
- qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_JK_B, outsignals[1]);
- qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_LED_GREEN, outsignals[2]);
- qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]);
+ DeviceState *miscdev = sysbus_create_simple(TYPE_SPITZ_MISC_GPIO, -1, NULL);
+
+ sms->misc_gpio = miscdev;
+
+ qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_CHRG_ON,
+ qdev_get_gpio_in_named(miscdev, "charging", 0));
+ qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_JK_B,
+ qdev_get_gpio_in_named(miscdev, "discharging", 0));
+ qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_LED_GREEN,
+ qdev_get_gpio_in_named(miscdev, "green-led", 0));
+ qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_LED_ORANGE,
+ qdev_get_gpio_in_named(miscdev, "orange-led", 0));
+ qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_ADC_TEMP_ON,
+ qdev_get_gpio_in_named(miscdev, "adc-temp-on", 0));
+ qdev_connect_gpio_out_named(miscdev, "adc-temp", 0,
+ qdev_get_gpio_in(sms->max1111, MAX1111_BATT_TEMP));
if (sms->scp1) {
qdev_connect_gpio_out(sms->scp1, SPITZ_SCP2_BACKLIGHT_CONT,
@@ -863,8 +898,6 @@ static void spitz_scoop_gpio_setup(SpitzMachineState *sms)
qdev_connect_gpio_out(sms->scp1, SPITZ_SCP2_BACKLIGHT_ON,
qdev_get_gpio_in_named(sms->lcdtg, "bl_power", 0));
}
-
- qdev_connect_gpio_out(sms->scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
}
#define SPITZ_GPIO_HSYNC 22
@@ -1217,12 +1250,24 @@ static const TypeInfo spitz_lcdtg_info = {
.class_init = spitz_lcdtg_class_init,
};
+static const TypeInfo spitz_misc_gpio_info = {
+ .name = TYPE_SPITZ_MISC_GPIO,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SpitzMiscGPIOState),
+ .instance_init = spitz_misc_gpio_init,
+ /*
+ * No class_init required: device has no internal state so does not
+ * need to set up reset or vmstate, and does not have a realize method.
+ */
+};
+
static void spitz_register_types(void)
{
type_register_static(&corgi_ssp_info);
type_register_static(&spitz_lcdtg_info);
type_register_static(&spitz_keyboard_info);
type_register_static(&sl_nand_info);
+ type_register_static(&spitz_misc_gpio_info);
}
type_init(spitz_register_types)