8f353514388850b73663bb9961703ecf73ef9375
[openwrt/staging/svanheule.git] /
1 From 512c5be35223d9baa2629efa1084cf5210eaee80 Mon Sep 17 00:00:00 2001
2 From: Sander Vanheule <sander@svanheule.net>
3 Date: Sat, 9 Apr 2022 21:55:47 +0200
4 Subject: [PATCH 2/6] gpio: realtek-otto: Support reversed port layouts
5
6 The GPIO port layout on the RTL930x SoC series is reversed compared to
7 the RTL838x and RTL839x SoC series. Add new port offset calculator
8 functions to ensure the correct order is used when reading port IRQ
9 data, and ensure bgpio uses the right byte ordering.
10
11 Signed-off-by: Sander Vanheule <sander@svanheule.net>
12 Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
13 ---
14 drivers/gpio/gpio-realtek-otto.c | 55 +++++++++++++++++++++++++++++---
15 1 file changed, 51 insertions(+), 4 deletions(-)
16
17 --- a/drivers/gpio/gpio-realtek-otto.c
18 +++ b/drivers/gpio/gpio-realtek-otto.c
19 @@ -58,6 +58,8 @@ struct realtek_gpio_ctrl {
20 raw_spinlock_t lock;
21 u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
22 u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
23 + unsigned int (*port_offset_u8)(unsigned int port);
24 + unsigned int (*port_offset_u16)(unsigned int port);
25 };
26
27 /* Expand with more flags as devices with other quirks are added */
28 @@ -69,6 +71,11 @@ enum realtek_gpio_flags {
29 * line the IRQ handler was assigned to, causing uncaught interrupts.
30 */
31 GPIO_INTERRUPTS_DISABLED = BIT(0),
32 + /*
33 + * Port order is reversed, meaning DCBA register layout for 1-bit
34 + * fields, and [BA, DC] for 2-bit fields.
35 + */
36 + GPIO_PORTS_REVERSED = BIT(1),
37 };
38
39 static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
40 @@ -86,21 +93,50 @@ static struct realtek_gpio_ctrl *irq_dat
41 * port. The two interrupt mask registers store two bits per GPIO, so use u16
42 * values.
43 */
44 +static unsigned int realtek_gpio_port_offset_u8(unsigned int port)
45 +{
46 + return port;
47 +}
48 +
49 +static unsigned int realtek_gpio_port_offset_u16(unsigned int port)
50 +{
51 + return 2 * port;
52 +}
53 +
54 +/*
55 + * Reversed port order register access
56 + *
57 + * For registers with one bit per GPIO, all ports are stored as u8-s in one
58 + * register in reversed order. The two interrupt mask registers store two bits
59 + * per GPIO, so use u16 values. The first register contains ports 1 and 0, the
60 + * second ports 3 and 2.
61 + */
62 +static unsigned int realtek_gpio_port_offset_u8_rev(unsigned int port)
63 +{
64 + return 3 - port;
65 +}
66 +
67 +static unsigned int realtek_gpio_port_offset_u16_rev(unsigned int port)
68 +{
69 + return 2 * (port ^ 1);
70 +}
71 +
72 static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl,
73 unsigned int port, u16 irq_type, u16 irq_mask)
74 {
75 - iowrite16(irq_type & irq_mask, ctrl->base + REALTEK_GPIO_REG_IMR + 2 * port);
76 + iowrite16(irq_type & irq_mask,
77 + ctrl->base + REALTEK_GPIO_REG_IMR + ctrl->port_offset_u16(port));
78 }
79
80 static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl,
81 unsigned int port, u8 mask)
82 {
83 - iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + port);
84 + iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
85 }
86
87 static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port)
88 {
89 - return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + port);
90 + return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
91 }
92
93 /* Set the rising and falling edge mask bits for a GPIO port pin */
94 @@ -253,6 +289,7 @@ MODULE_DEVICE_TABLE(of, realtek_gpio_of_
95 static int realtek_gpio_probe(struct platform_device *pdev)
96 {
97 struct device *dev = &pdev->dev;
98 + unsigned long bgpio_flags;
99 unsigned int dev_flags;
100 struct gpio_irq_chip *girq;
101 struct realtek_gpio_ctrl *ctrl;
102 @@ -280,10 +317,20 @@ static int realtek_gpio_probe(struct pla
103
104 raw_spin_lock_init(&ctrl->lock);
105
106 + if (dev_flags & GPIO_PORTS_REVERSED) {
107 + bgpio_flags = 0;
108 + ctrl->port_offset_u8 = realtek_gpio_port_offset_u8_rev;
109 + ctrl->port_offset_u16 = realtek_gpio_port_offset_u16_rev;
110 + } else {
111 + bgpio_flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
112 + ctrl->port_offset_u8 = realtek_gpio_port_offset_u8;
113 + ctrl->port_offset_u16 = realtek_gpio_port_offset_u16;
114 + }
115 +
116 err = bgpio_init(&ctrl->gc, dev, 4,
117 ctrl->base + REALTEK_GPIO_REG_DATA, NULL, NULL,
118 ctrl->base + REALTEK_GPIO_REG_DIR, NULL,
119 - BGPIOF_BIG_ENDIAN_BYTE_ORDER);
120 + bgpio_flags);
121 if (err) {
122 dev_err(dev, "unable to init generic GPIO");
123 return err;