[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 07/57] hw/misc/pca9552: Add generic PCA955xClass, parent of TYPE_P
From: |
Peter Maydell |
Subject: |
[PULL 07/57] hw/misc/pca9552: Add generic PCA955xClass, parent of TYPE_PCA9552 |
Date: |
Fri, 26 Jun 2020 16:13:34 +0100 |
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
Extract the code common to the PCA955x family in PCA955xClass,
keeping the PCA9552 specific parts into pca9552_class_init().
Remove the 'TODO' comment added in commit 5141d4158cf.
Suggested-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Tested-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20200623072723.6324-5-f4bug@amsat.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
include/hw/misc/pca9552.h | 6 ++--
hw/misc/pca9552.c | 66 ++++++++++++++++++++++++++++-----------
2 files changed, 51 insertions(+), 21 deletions(-)
diff --git a/include/hw/misc/pca9552.h b/include/hw/misc/pca9552.h
index db527595a38..90843b03b8a 100644
--- a/include/hw/misc/pca9552.h
+++ b/include/hw/misc/pca9552.h
@@ -12,9 +12,11 @@
#include "hw/i2c/i2c.h"
#define TYPE_PCA9552 "pca9552"
-#define PCA955X(obj) OBJECT_CHECK(PCA955xState, (obj), TYPE_PCA9552)
+#define TYPE_PCA955X "pca955x"
+#define PCA955X(obj) OBJECT_CHECK(PCA955xState, (obj), TYPE_PCA955X)
#define PCA955X_NR_REGS 10
+#define PCA955X_PIN_COUNT_MAX 16
typedef struct PCA955xState {
/*< private >*/
@@ -25,8 +27,6 @@ typedef struct PCA955xState {
uint8_t pointer;
uint8_t regs[PCA955X_NR_REGS];
- uint8_t max_reg;
- uint8_t pin_count;
} PCA955xState;
#endif
diff --git a/hw/misc/pca9552.c b/hw/misc/pca9552.c
index 5681ff3b22d..4de57dbe2e2 100644
--- a/hw/misc/pca9552.c
+++ b/hw/misc/pca9552.c
@@ -4,6 +4,7 @@
* https://www.nxp.com/docs/en/application-note/AN264.pdf
*
* Copyright (c) 2017-2018, IBM Corporation.
+ * Copyright (c) 2020 Philippe Mathieu-Daudé
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* later. See the COPYING file in the top-level directory.
@@ -18,6 +19,20 @@
#include "qapi/error.h"
#include "qapi/visitor.h"
+typedef struct PCA955xClass {
+ /*< private >*/
+ I2CSlaveClass parent_class;
+ /*< public >*/
+
+ uint8_t pin_count;
+ uint8_t max_reg;
+} PCA955xClass;
+
+#define PCA955X_CLASS(klass) \
+ OBJECT_CLASS_CHECK(PCA955xClass, (klass), TYPE_PCA955X)
+#define PCA955X_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(PCA955xClass, (obj), TYPE_PCA955X)
+
#define PCA9552_LED_ON 0x0
#define PCA9552_LED_OFF 0x1
#define PCA9552_LED_PWM0 0x2
@@ -35,9 +50,10 @@ static uint8_t pca955x_pin_get_config(PCA955xState *s, int
pin)
static void pca955x_update_pin_input(PCA955xState *s)
{
+ PCA955xClass *k = PCA955X_GET_CLASS(s);
int i;
- for (i = 0; i < s->pin_count; i++) {
+ for (i = 0; i < k->pin_count; i++) {
uint8_t input_reg = PCA9552_INPUT0 + (i / 8);
uint8_t input_shift = (i % 8);
uint8_t config = pca955x_pin_get_config(s, i);
@@ -112,10 +128,12 @@ static void pca955x_write(PCA955xState *s, uint8_t reg,
uint8_t data)
*/
static void pca955x_autoinc(PCA955xState *s)
{
+ PCA955xClass *k = PCA955X_GET_CLASS(s);
+
if (s->pointer != 0xFF && s->pointer & PCA9552_AUTOINC) {
uint8_t reg = s->pointer & 0xf;
- reg = (reg + 1) % (s->max_reg + 1);
+ reg = (reg + 1) % (k->max_reg + 1);
s->pointer = reg | PCA9552_AUTOINC;
}
}
@@ -176,6 +194,7 @@ static int pca955x_event(I2CSlave *i2c, enum i2c_event
event)
static void pca955x_get_led(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
+ PCA955xClass *k = PCA955X_GET_CLASS(obj);
PCA955xState *s = PCA955X(obj);
int led, rc, reg;
uint8_t state;
@@ -185,7 +204,7 @@ static void pca955x_get_led(Object *obj, Visitor *v, const
char *name,
error_setg(errp, "%s: error reading %s", __func__, name);
return;
}
- if (led < 0 || led > s->pin_count) {
+ if (led < 0 || led > k->pin_count) {
error_setg(errp, "%s invalid led %s", __func__, name);
return;
}
@@ -212,6 +231,7 @@ static inline uint8_t pca955x_ledsel(uint8_t oldval, int
led_num, int state)
static void pca955x_set_led(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
+ PCA955xClass *k = PCA955X_GET_CLASS(obj);
PCA955xState *s = PCA955X(obj);
Error *local_err = NULL;
int led, rc, reg, val;
@@ -228,7 +248,7 @@ static void pca955x_set_led(Object *obj, Visitor *v, const
char *name,
error_setg(errp, "%s: error reading %s", __func__, name);
return;
}
- if (led < 0 || led > s->pin_count) {
+ if (led < 0 || led > k->pin_count) {
error_setg(errp, "%s invalid led %s", __func__, name);
return;
}
@@ -283,17 +303,11 @@ static void pca9552_reset(DeviceState *dev)
static void pca955x_initfn(Object *obj)
{
- PCA955xState *s = PCA955X(obj);
+ PCA955xClass *k = PCA955X_GET_CLASS(obj);
int led;
- /* If support for the other PCA955X devices are implemented, these
- * constant values might be part of class structure describing the
- * PCA955X device
- */
- s->max_reg = PCA9552_LS3;
- s->pin_count = 16;
-
- for (led = 0; led < s->pin_count; led++) {
+ assert(k->pin_count <= PCA955X_PIN_COUNT_MAX);
+ for (led = 0; led < k->pin_count; led++) {
char *name;
name = g_strdup_printf("led%d", led);
@@ -303,28 +317,44 @@ static void pca955x_initfn(Object *obj)
}
}
-static void pca9552_class_init(ObjectClass *klass, void *data)
+static void pca955x_class_init(ObjectClass *klass, void *data)
{
- DeviceClass *dc = DEVICE_CLASS(klass);
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
k->event = pca955x_event;
k->recv = pca955x_recv;
k->send = pca955x_send;
+}
+
+static const TypeInfo pca955x_info = {
+ .name = TYPE_PCA955X,
+ .parent = TYPE_I2C_SLAVE,
+ .instance_init = pca955x_initfn,
+ .instance_size = sizeof(PCA955xState),
+ .class_init = pca955x_class_init,
+ .abstract = true,
+};
+
+static void pca9552_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ PCA955xClass *pc = PCA955X_CLASS(oc);
+
dc->reset = pca9552_reset;
dc->vmsd = &pca9552_vmstate;
+ pc->max_reg = PCA9552_LS3;
+ pc->pin_count = 16;
}
static const TypeInfo pca9552_info = {
.name = TYPE_PCA9552,
- .parent = TYPE_I2C_SLAVE,
- .instance_init = pca955x_initfn,
- .instance_size = sizeof(PCA955xState),
+ .parent = TYPE_PCA955X,
.class_init = pca9552_class_init,
};
static void pca955x_register_types(void)
{
+ type_register_static(&pca955x_info);
type_register_static(&pca9552_info);
}
--
2.20.1
- [PULL 00/57] target-arm queue, Peter Maydell, 2020/06/26
- [PULL 01/57] hw/arm/aspeed: Remove extraneous MemoryRegion object owner, Peter Maydell, 2020/06/26
- [PULL 02/57] hw/arm/aspeed: Rename AspeedBoardState as AspeedMachineState, Peter Maydell, 2020/06/26
- [PULL 03/57] hw/arm/aspeed: QOM'ify AspeedMachineState, Peter Maydell, 2020/06/26
- [PULL 05/57] hw/misc/pca9552: Rename 'nr_leds' as 'pin_count', Peter Maydell, 2020/06/26
- [PULL 04/57] hw/i2c/core: Add i2c_try_create_slave() and i2c_realize_and_unref(), Peter Maydell, 2020/06/26
- [PULL 06/57] hw/misc/pca9552: Rename generic code as pca955x, Peter Maydell, 2020/06/26
- [PULL 09/57] hw/misc/pca9552: Trace GPIO High/Low events, Peter Maydell, 2020/06/26
- [PULL 07/57] hw/misc/pca9552: Add generic PCA955xClass, parent of TYPE_PCA9552,
Peter Maydell <=
- [PULL 08/57] hw/misc/pca9552: Add a 'description' property for debugging purpose, Peter Maydell, 2020/06/26
- [PULL 12/57] hw/misc/pca9552: Model qdev output GPIOs, Peter Maydell, 2020/06/26
- [PULL 10/57] hw/arm/aspeed: Describe each PCA9552 device, Peter Maydell, 2020/06/26
- [PULL 11/57] hw/misc/pca9552: Trace GPIO change events, Peter Maydell, 2020/06/26
- [PULL 15/57] target/arm: Add support for MTE to SCTLR_ELx, Peter Maydell, 2020/06/26
- [PULL 14/57] target/arm: Improve masking of SCR RES0 bits, Peter Maydell, 2020/06/26
- [PULL 16/57] target/arm: Add support for MTE to HCR_EL2 and SCR_EL3, Peter Maydell, 2020/06/26
- [PULL 13/57] target/arm: Add isar tests for mte, Peter Maydell, 2020/06/26
- [PULL 17/57] target/arm: Rename DISAS_UPDATE to DISAS_UPDATE_EXIT, Peter Maydell, 2020/06/26
- [PULL 21/57] target/arm: Implement the IRG instruction, Peter Maydell, 2020/06/26