317-gpio-realtek-otto-switch-to-32-bit-I-O.patch 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. From ee0175b3b44288c74d5292c2a9c2c154f6c0317e Mon Sep 17 00:00:00 2001
  2. From: Sander Vanheule <[email protected]>
  3. Date: Sun, 7 Aug 2022 21:21:15 +0200
  4. Subject: [PATCH] gpio: realtek-otto: switch to 32-bit I/O
  5. By using 16-bit I/O on the GPIO peripheral, which is apparently not safe
  6. on MIPS, the IMR can end up containing garbage. This then results in
  7. interrupt triggers for lines that don't have an interrupt handler
  8. associated. The irq_desc lookup fails, and the ISR will not be cleared,
  9. keeping the CPU busy until reboot, or until another IMR operation
  10. restores the correct value. This situation appears to happen very
  11. rarely, for < 0.5% of IMR writes.
  12. Instead of using 8-bit or 16-bit I/O operations on the 32-bit memory
  13. mapped peripheral registers, switch to using 32-bit I/O only, operating
  14. on the entire bank for all single bit line settings. For 2-bit line
  15. settings, with 16-bit port values, stick to manual (un)packing.
  16. This issue has been seen on RTL8382M (HPE 1920-16G), RTL8391M (Netgear
  17. GS728TP v2), and RTL8393M (D-Link DGS-1210-52 F3, Zyxel GS1900-48).
  18. Reported-by: Luiz Angelo Daros de Luca <[email protected]> # DGS-1210-52
  19. Reported-by: Birger Koblitz <[email protected]> # GS728TP
  20. Reported-by: Jan Hoffmann <[email protected]> # 1920-16G
  21. Fixes: 0d82fb1127fb ("gpio: Add Realtek Otto GPIO support")
  22. Signed-off-by: Sander Vanheule <[email protected]>
  23. Cc: Paul Cercueil <[email protected]>
  24. Reviewed-by: Linus Walleij <[email protected]>
  25. Signed-off-by: Bartosz Golaszewski <[email protected]>
  26. Update patch for missing upstream changes:
  27. - commit a01a40e33499 ("gpio: realtek-otto: Make the irqchip immutable")
  28. Signed-off-by: Sander Vanheule <[email protected]>
  29. ---
  30. drivers/gpio/gpio-realtek-otto.c | 166 ++++++++++++++++---------------
  31. 1 file changed, 85 insertions(+), 81 deletions(-)
  32. --- a/drivers/gpio/gpio-realtek-otto.c
  33. +++ b/drivers/gpio/gpio-realtek-otto.c
  34. @@ -46,10 +46,20 @@
  35. * @lock: Lock for accessing the IRQ registers and values
  36. * @intr_mask: Mask for interrupts lines
  37. * @intr_type: Interrupt type selection
  38. + * @bank_read: Read a bank setting as a single 32-bit value
  39. + * @bank_write: Write a bank setting as a single 32-bit value
  40. + * @imr_line_pos: Bit shift of an IRQ line's IMR value.
  41. + *
  42. + * The DIR, DATA, and ISR registers consist of four 8-bit port values, packed
  43. + * into a single 32-bit register. Use @bank_read (@bank_write) to get (assign)
  44. + * a value from (to) these registers. The IMR register consists of four 16-bit
  45. + * port values, packed into two 32-bit registers. Use @imr_line_pos to get the
  46. + * bit shift of the 2-bit field for a line's IMR settings. Shifts larger than
  47. + * 32 overflow into the second register.
  48. *
  49. * Because the interrupt mask register (IMR) combines the function of IRQ type
  50. * selection and masking, two extra values are stored. @intr_mask is used to
  51. - * mask/unmask the interrupts for a GPIO port, and @intr_type is used to store
  52. + * mask/unmask the interrupts for a GPIO line, and @intr_type is used to store
  53. * the selected interrupt types. The logical AND of these values is written to
  54. * IMR on changes.
  55. */
  56. @@ -59,10 +69,11 @@ struct realtek_gpio_ctrl {
  57. void __iomem *cpumask_base;
  58. struct cpumask cpu_irq_maskable;
  59. raw_spinlock_t lock;
  60. - u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
  61. - u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
  62. - unsigned int (*port_offset_u8)(unsigned int port);
  63. - unsigned int (*port_offset_u16)(unsigned int port);
  64. + u8 intr_mask[REALTEK_GPIO_MAX];
  65. + u8 intr_type[REALTEK_GPIO_MAX];
  66. + u32 (*bank_read)(void __iomem *reg);
  67. + void (*bank_write)(void __iomem *reg, u32 value);
  68. + unsigned int (*line_imr_pos)(unsigned int line);
  69. };
  70. /* Expand with more flags as devices with other quirks are added */
  71. @@ -101,14 +112,22 @@ static struct realtek_gpio_ctrl *irq_dat
  72. * port. The two interrupt mask registers store two bits per GPIO, so use u16
  73. * values.
  74. */
  75. -static unsigned int realtek_gpio_port_offset_u8(unsigned int port)
  76. +static u32 realtek_gpio_bank_read_swapped(void __iomem *reg)
  77. +{
  78. + return ioread32be(reg);
  79. +}
  80. +
  81. +static void realtek_gpio_bank_write_swapped(void __iomem *reg, u32 value)
  82. {
  83. - return port;
  84. + iowrite32be(value, reg);
  85. }
  86. -static unsigned int realtek_gpio_port_offset_u16(unsigned int port)
  87. +static unsigned int realtek_gpio_line_imr_pos_swapped(unsigned int line)
  88. {
  89. - return 2 * port;
  90. + unsigned int port_pin = line % 8;
  91. + unsigned int port = line / 8;
  92. +
  93. + return 2 * (8 * (port ^ 1) + port_pin);
  94. }
  95. /*
  96. @@ -119,64 +138,65 @@ static unsigned int realtek_gpio_port_of
  97. * per GPIO, so use u16 values. The first register contains ports 1 and 0, the
  98. * second ports 3 and 2.
  99. */
  100. -static unsigned int realtek_gpio_port_offset_u8_rev(unsigned int port)
  101. +static u32 realtek_gpio_bank_read(void __iomem *reg)
  102. {
  103. - return 3 - port;
  104. + return ioread32(reg);
  105. }
  106. -static unsigned int realtek_gpio_port_offset_u16_rev(unsigned int port)
  107. +static void realtek_gpio_bank_write(void __iomem *reg, u32 value)
  108. {
  109. - return 2 * (port ^ 1);
  110. + iowrite32(value, reg);
  111. }
  112. -static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl,
  113. - unsigned int port, u16 irq_type, u16 irq_mask)
  114. +static unsigned int realtek_gpio_line_imr_pos(unsigned int line)
  115. {
  116. - iowrite16(irq_type & irq_mask,
  117. - ctrl->base + REALTEK_GPIO_REG_IMR + ctrl->port_offset_u16(port));
  118. + return 2 * line;
  119. }
  120. -static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl,
  121. - unsigned int port, u8 mask)
  122. +static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl, u32 mask)
  123. {
  124. - iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
  125. + ctrl->bank_write(ctrl->base + REALTEK_GPIO_REG_ISR, mask);
  126. }
  127. -static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port)
  128. +static u32 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl)
  129. {
  130. - return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
  131. + return ctrl->bank_read(ctrl->base + REALTEK_GPIO_REG_ISR);
  132. }
  133. -/* Set the rising and falling edge mask bits for a GPIO port pin */
  134. -static u16 realtek_gpio_imr_bits(unsigned int pin, u16 value)
  135. +/* Set the rising and falling edge mask bits for a GPIO pin */
  136. +static void realtek_gpio_update_line_imr(struct realtek_gpio_ctrl *ctrl, unsigned int line)
  137. {
  138. - return (value & REALTEK_GPIO_IMR_LINE_MASK) << 2 * pin;
  139. + void __iomem *reg = ctrl->base + REALTEK_GPIO_REG_IMR;
  140. + unsigned int line_shift = ctrl->line_imr_pos(line);
  141. + unsigned int shift = line_shift % 32;
  142. + u32 irq_type = ctrl->intr_type[line];
  143. + u32 irq_mask = ctrl->intr_mask[line];
  144. + u32 reg_val;
  145. +
  146. + reg += 4 * (line_shift / 32);
  147. + reg_val = ioread32(reg);
  148. + reg_val &= ~(REALTEK_GPIO_IMR_LINE_MASK << shift);
  149. + reg_val |= (irq_type & irq_mask & REALTEK_GPIO_IMR_LINE_MASK) << shift;
  150. + iowrite32(reg_val, reg);
  151. }
  152. static void realtek_gpio_irq_ack(struct irq_data *data)
  153. {
  154. struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
  155. irq_hw_number_t line = irqd_to_hwirq(data);
  156. - unsigned int port = line / 8;
  157. - unsigned int port_pin = line % 8;
  158. - realtek_gpio_clear_isr(ctrl, port, BIT(port_pin));
  159. + realtek_gpio_clear_isr(ctrl, BIT(line));
  160. }
  161. static void realtek_gpio_irq_unmask(struct irq_data *data)
  162. {
  163. struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
  164. unsigned int line = irqd_to_hwirq(data);
  165. - unsigned int port = line / 8;
  166. - unsigned int port_pin = line % 8;
  167. unsigned long flags;
  168. - u16 m;
  169. raw_spin_lock_irqsave(&ctrl->lock, flags);
  170. - m = ctrl->intr_mask[port];
  171. - m |= realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
  172. - ctrl->intr_mask[port] = m;
  173. - realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
  174. + ctrl->intr_mask[line] = REALTEK_GPIO_IMR_LINE_MASK;
  175. + realtek_gpio_update_line_imr(ctrl, line);
  176. raw_spin_unlock_irqrestore(&ctrl->lock, flags);
  177. }
  178. @@ -184,16 +204,11 @@ static void realtek_gpio_irq_mask(struct
  179. {
  180. struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
  181. unsigned int line = irqd_to_hwirq(data);
  182. - unsigned int port = line / 8;
  183. - unsigned int port_pin = line % 8;
  184. unsigned long flags;
  185. - u16 m;
  186. raw_spin_lock_irqsave(&ctrl->lock, flags);
  187. - m = ctrl->intr_mask[port];
  188. - m &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
  189. - ctrl->intr_mask[port] = m;
  190. - realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
  191. + ctrl->intr_mask[line] = 0;
  192. + realtek_gpio_update_line_imr(ctrl, line);
  193. raw_spin_unlock_irqrestore(&ctrl->lock, flags);
  194. }
  195. @@ -201,10 +216,8 @@ static int realtek_gpio_irq_set_type(str
  196. {
  197. struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
  198. unsigned int line = irqd_to_hwirq(data);
  199. - unsigned int port = line / 8;
  200. - unsigned int port_pin = line % 8;
  201. unsigned long flags;
  202. - u16 type, t;
  203. + u8 type;
  204. switch (flow_type & IRQ_TYPE_SENSE_MASK) {
  205. case IRQ_TYPE_EDGE_FALLING:
  206. @@ -223,11 +236,8 @@ static int realtek_gpio_irq_set_type(str
  207. irq_set_handler_locked(data, handle_edge_irq);
  208. raw_spin_lock_irqsave(&ctrl->lock, flags);
  209. - t = ctrl->intr_type[port];
  210. - t &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
  211. - t |= realtek_gpio_imr_bits(port_pin, type);
  212. - ctrl->intr_type[port] = t;
  213. - realtek_gpio_write_imr(ctrl, port, t, ctrl->intr_mask[port]);
  214. + ctrl->intr_type[line] = type;
  215. + realtek_gpio_update_line_imr(ctrl, line);
  216. raw_spin_unlock_irqrestore(&ctrl->lock, flags);
  217. return 0;
  218. @@ -238,28 +248,21 @@ static void realtek_gpio_irq_handler(str
  219. struct gpio_chip *gc = irq_desc_get_handler_data(desc);
  220. struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
  221. struct irq_chip *irq_chip = irq_desc_get_chip(desc);
  222. - unsigned int lines_done;
  223. - unsigned int port_pin_count;
  224. unsigned long status;
  225. int offset;
  226. chained_irq_enter(irq_chip, desc);
  227. - for (lines_done = 0; lines_done < gc->ngpio; lines_done += 8) {
  228. - status = realtek_gpio_read_isr(ctrl, lines_done / 8);
  229. - port_pin_count = min(gc->ngpio - lines_done, 8U);
  230. - for_each_set_bit(offset, &status, port_pin_count)
  231. - generic_handle_domain_irq(gc->irq.domain, offset + lines_done);
  232. - }
  233. + status = realtek_gpio_read_isr(ctrl);
  234. + for_each_set_bit(offset, &status, gc->ngpio)
  235. + generic_handle_domain_irq(gc->irq.domain, offset);
  236. chained_irq_exit(irq_chip, desc);
  237. }
  238. -static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl,
  239. - unsigned int port, int cpu)
  240. +static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl, int cpu)
  241. {
  242. - return ctrl->cpumask_base + ctrl->port_offset_u8(port) +
  243. - REALTEK_GPIO_PORTS_PER_BANK * cpu;
  244. + return ctrl->cpumask_base + REALTEK_GPIO_PORTS_PER_BANK * cpu;
  245. }
  246. static int realtek_gpio_irq_set_affinity(struct irq_data *data,
  247. @@ -267,12 +270,10 @@ static int realtek_gpio_irq_set_affinity
  248. {
  249. struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
  250. unsigned int line = irqd_to_hwirq(data);
  251. - unsigned int port = line / 8;
  252. - unsigned int port_pin = line % 8;
  253. void __iomem *irq_cpu_mask;
  254. unsigned long flags;
  255. int cpu;
  256. - u8 v;
  257. + u32 v;
  258. if (!ctrl->cpumask_base)
  259. return -ENXIO;
  260. @@ -280,15 +281,15 @@ static int realtek_gpio_irq_set_affinity
  261. raw_spin_lock_irqsave(&ctrl->lock, flags);
  262. for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
  263. - irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
  264. - v = ioread8(irq_cpu_mask);
  265. + irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, cpu);
  266. + v = ctrl->bank_read(irq_cpu_mask);
  267. if (cpumask_test_cpu(cpu, dest))
  268. - v |= BIT(port_pin);
  269. + v |= BIT(line);
  270. else
  271. - v &= ~BIT(port_pin);
  272. + v &= ~BIT(line);
  273. - iowrite8(v, irq_cpu_mask);
  274. + ctrl->bank_write(irq_cpu_mask, v);
  275. }
  276. raw_spin_unlock_irqrestore(&ctrl->lock, flags);
  277. @@ -302,22 +303,23 @@ static int realtek_gpio_irq_init(struct
  278. {
  279. struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
  280. void __iomem *irq_cpu_mask;
  281. - unsigned int port;
  282. + u32 mask_all = GENMASK(gc->ngpio - 1, 0);
  283. + unsigned int line;
  284. int cpu;
  285. - for (port = 0; (port * 8) < gc->ngpio; port++) {
  286. - realtek_gpio_write_imr(ctrl, port, 0, 0);
  287. - realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
  288. -
  289. - /*
  290. - * Uniprocessor builds assume a mask always contains one CPU,
  291. - * so only start the loop if we have at least one maskable CPU.
  292. - */
  293. - if(!cpumask_empty(&ctrl->cpu_irq_maskable)) {
  294. - for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
  295. - irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
  296. - iowrite8(GENMASK(7, 0), irq_cpu_mask);
  297. - }
  298. + for (line = 0; line < gc->ngpio; line++)
  299. + realtek_gpio_update_line_imr(ctrl, line);
  300. +
  301. + realtek_gpio_clear_isr(ctrl, mask_all);
  302. +
  303. + /*
  304. + * Uniprocessor builds assume a mask always contains one CPU,
  305. + * so only start the loop if we have at least one maskable CPU.
  306. + */
  307. + if(!cpumask_empty(&ctrl->cpu_irq_maskable)) {
  308. + for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
  309. + irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, cpu);
  310. + ctrl->bank_write(irq_cpu_mask, mask_all);
  311. }
  312. }
  313. @@ -390,12 +392,14 @@ static int realtek_gpio_probe(struct pla
  314. if (dev_flags & GPIO_PORTS_REVERSED) {
  315. bgpio_flags = 0;
  316. - ctrl->port_offset_u8 = realtek_gpio_port_offset_u8_rev;
  317. - ctrl->port_offset_u16 = realtek_gpio_port_offset_u16_rev;
  318. + ctrl->bank_read = realtek_gpio_bank_read;
  319. + ctrl->bank_write = realtek_gpio_bank_write;
  320. + ctrl->line_imr_pos = realtek_gpio_line_imr_pos;
  321. } else {
  322. bgpio_flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
  323. - ctrl->port_offset_u8 = realtek_gpio_port_offset_u8;
  324. - ctrl->port_offset_u16 = realtek_gpio_port_offset_u16;
  325. + ctrl->bank_read = realtek_gpio_bank_read_swapped;
  326. + ctrl->bank_write = realtek_gpio_bank_write_swapped;
  327. + ctrl->line_imr_pos = realtek_gpio_line_imr_pos_swapped;
  328. }
  329. err = bgpio_init(&ctrl->gc, dev, 4,