realtek: Add GPIO support for RTL930X and RTL931X
[openwrt/staging/chunkeey.git] / target / linux / realtek / patches-5.10 / 320-gpio-add-support-for-RTL930X-and-RTL931X.patch
1 --- a/drivers/gpio/gpio-realtek-otto.c
2 +++ b/drivers/gpio/gpio-realtek-otto.c
3 @@ -55,9 +55,12 @@
4 struct realtek_gpio_ctrl {
5 struct gpio_chip gc;
6 void __iomem *base;
7 + void __iomem *cpumap_base;
8 raw_spinlock_t lock;
9 u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
10 u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
11 + unsigned int (*port_offset_u8)(unsigned int port);
12 + unsigned int (*port_offset_u16)(unsigned int port);
13 };
14
15 /* Expand with more flags as devices with other quirks are added */
16 @@ -69,6 +72,16 @@ enum realtek_gpio_flags {
17 * line the IRQ handler was assigned to, causing uncaught interrupts.
18 */
19 GPIO_INTERRUPTS_DISABLED = BIT(0),
20 + /*
21 + * Port order is reversed, meaning DCBA register layout for 1-bit
22 + * fields, and [BA, DC] for 2-bit fields.
23 + */
24 + GPIO_PORTS_REVERSED = BIT(1),
25 + /*
26 + * Interrupts can be enabled per cpu. This requires a secondary IO
27 + * range, where the per-cpu enable masks are located.
28 + */
29 + GPIO_INTERRUPTS_PER_CPU = BIT(2),
30 };
31
32 static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
33 @@ -86,21 +99,50 @@ static struct realtek_gpio_ctrl *irq_dat
34 * port. The two interrupt mask registers store two bits per GPIO, so use u16
35 * values.
36 */
37 +static unsigned int realtek_gpio_port_offset_u8(unsigned int port)
38 +{
39 + return port;
40 +}
41 +
42 +static unsigned int realtek_gpio_port_offset_u16(unsigned int port)
43 +{
44 + return 2 * port;
45 +}
46 +
47 +/*
48 + * Reversed port order register access
49 + *
50 + * For registers with one bit per GPIO, all ports are stored as u8-s in one
51 + * register in reversed order. The two interrupt mask registers store two bits
52 + * per GPIO, so use u16 values. The first register contains ports 1 and 0, the
53 + * second ports 3 and 2.
54 + */
55 +static unsigned int realtek_gpio_port_offset_u8_rev(unsigned int port)
56 +{
57 + return 3 - port;
58 +}
59 +
60 +static unsigned int realtek_gpio_port_offset_u16_rev(unsigned int port)
61 +{
62 + return 2 * (port ^ 1);
63 +}
64 +
65 static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl,
66 unsigned int port, u16 irq_type, u16 irq_mask)
67 {
68 - iowrite16(irq_type & irq_mask, ctrl->base + REALTEK_GPIO_REG_IMR + 2 * port);
69 + iowrite16(irq_type & irq_mask,
70 + ctrl->base + REALTEK_GPIO_REG_IMR + ctrl->port_offset_u16(port));
71 }
72
73 static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl,
74 unsigned int port, u8 mask)
75 {
76 - iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + port);
77 + iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
78 }
79
80 static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port)
81 {
82 - return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + port);
83 + return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
84 }
85
86 /* Set the rising and falling edge mask bits for a GPIO port pin */
87 @@ -222,6 +264,12 @@ static int realtek_gpio_irq_init(struct
88 for (port = 0; (port * 8) < gc->ngpio; port++) {
89 realtek_gpio_write_imr(ctrl, port, 0, 0);
90 realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
91 +
92 + if (ctrl->cpumap_base) {
93 + /* Default CPU affinity to the first CPU */
94 + iowrite8(GENMASK(7, 0),
95 + ctrl->cpumap_base + ctrl->port_offset_u8(port));
96 + }
97 }
98
99 return 0;
100 @@ -246,6 +294,13 @@ static const struct of_device_id realtek
101 {
102 .compatible = "realtek,rtl8390-gpio",
103 },
104 + {
105 + .compatible = "realtek,rtl9300-gpio",
106 + .data = (void *)(GPIO_PORTS_REVERSED | GPIO_INTERRUPTS_PER_CPU)
107 + },
108 + {
109 + .compatible = "realtek,rtl9310-gpio",
110 + },
111 {}
112 };
113 MODULE_DEVICE_TABLE(of, realtek_gpio_of_match);
114 @@ -253,12 +308,14 @@ MODULE_DEVICE_TABLE(of, realtek_gpio_of_
115 static int realtek_gpio_probe(struct platform_device *pdev)
116 {
117 struct device *dev = &pdev->dev;
118 + unsigned long bgpio_flags;
119 unsigned int dev_flags;
120 struct gpio_irq_chip *girq;
121 struct realtek_gpio_ctrl *ctrl;
122 u32 ngpios;
123 int err, irq;
124
125 + pr_info("%s probing RTL GPIO\n", __func__);
126 ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
127 if (!ctrl)
128 return -ENOMEM;
129 @@ -280,10 +337,21 @@ static int realtek_gpio_probe(struct pla
130
131 raw_spin_lock_init(&ctrl->lock);
132
133 + if (dev_flags & GPIO_PORTS_REVERSED) {
134 + bgpio_flags = 0;
135 + ctrl->port_offset_u8 = realtek_gpio_port_offset_u8_rev;
136 + ctrl->port_offset_u16 = realtek_gpio_port_offset_u16_rev;
137 + }
138 + else {
139 + bgpio_flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
140 + ctrl->port_offset_u8 = realtek_gpio_port_offset_u8;
141 + ctrl->port_offset_u16 = realtek_gpio_port_offset_u16;
142 + }
143 +
144 err = bgpio_init(&ctrl->gc, dev, 4,
145 ctrl->base + REALTEK_GPIO_REG_DATA, NULL, NULL,
146 ctrl->base + REALTEK_GPIO_REG_DIR, NULL,
147 - BGPIOF_BIG_ENDIAN_BYTE_ORDER);
148 + bgpio_flags);
149 if (err) {
150 dev_err(dev, "unable to init generic GPIO");
151 return err;
152 @@ -308,6 +376,13 @@ static int realtek_gpio_probe(struct pla
153 girq->init_hw = realtek_gpio_irq_init;
154 }
155
156 + if (dev_flags & GPIO_INTERRUPTS_PER_CPU) {
157 + ctrl->cpumap_base = devm_platform_ioremap_resource(pdev, 1);
158 + if (IS_ERR(ctrl->cpumap_base))
159 + return dev_err_probe(dev, PTR_ERR(ctrl->cpumap_base),
160 + "IRQ CPU map registers not defined");
161 + }
162 +
163 return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
164 }
165