bcm27xx: add support for linux v5.15
[openwrt/staging/chunkeey.git] / target / linux / bcm27xx / patches-5.15 / 950-0437-drm-vc4-Fix-dsi0-interrupt-support.patch
1 From 8f32ff08609bb5e7fd4fb38fe7518891e0e22f45 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Wed, 10 Feb 2021 18:46:22 +0000
4 Subject: [PATCH] drm/vc4: Fix dsi0 interrupt support.
5
6 DSI0 seemingly had very little or no testing as a load of
7 the register mappings were incorrect/missing, so host
8 transfers always timed out due to enabling/checking incorrect
9 bits in the interrupt enable and status registers.
10
11 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
12 ---
13 drivers/gpu/drm/vc4/vc4_dsi.c | 111 ++++++++++++++++++++++++++--------
14 1 file changed, 85 insertions(+), 26 deletions(-)
15
16 --- a/drivers/gpu/drm/vc4/vc4_dsi.c
17 +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
18 @@ -181,8 +181,50 @@
19
20 #define DSI0_TXPKT_PIX_FIFO 0x20 /* AKA PIX_FIFO */
21
22 -#define DSI0_INT_STAT 0x24
23 -#define DSI0_INT_EN 0x28
24 +#define DSI0_INT_STAT 0x24
25 +#define DSI0_INT_EN 0x28
26 +# define DSI0_INT_FIFO_ERR BIT(25)
27 +# define DSI0_INT_CMDC_DONE_MASK VC4_MASK(24, 23)
28 +# define DSI0_INT_CMDC_DONE_SHIFT 23
29 +# define DSI0_INT_CMDC_DONE_NO_REPEAT 1
30 +# define DSI0_INT_CMDC_DONE_REPEAT 3
31 +# define DSI0_INT_PHY_DIR_RTF BIT(22)
32 +# define DSI0_INT_PHY_D1_ULPS BIT(21)
33 +# define DSI0_INT_PHY_D1_STOP BIT(20)
34 +# define DSI0_INT_PHY_RXLPDT BIT(19)
35 +# define DSI0_INT_PHY_RXTRIG BIT(18)
36 +# define DSI0_INT_PHY_D0_ULPS BIT(17)
37 +# define DSI0_INT_PHY_D0_LPDT BIT(16)
38 +# define DSI0_INT_PHY_D0_FTR BIT(15)
39 +# define DSI0_INT_PHY_D0_STOP BIT(14)
40 +/* Signaled when the clock lane enters the given state. */
41 +# define DSI0_INT_PHY_CLK_ULPS BIT(13)
42 +# define DSI0_INT_PHY_CLK_HS BIT(12)
43 +# define DSI0_INT_PHY_CLK_FTR BIT(11)
44 +/* Signaled on timeouts */
45 +# define DSI0_INT_PR_TO BIT(10)
46 +# define DSI0_INT_TA_TO BIT(9)
47 +# define DSI0_INT_LPRX_TO BIT(8)
48 +# define DSI0_INT_HSTX_TO BIT(7)
49 +/* Contention on a line when trying to drive the line low */
50 +# define DSI0_INT_ERR_CONT_LP1 BIT(6)
51 +# define DSI0_INT_ERR_CONT_LP0 BIT(5)
52 +/* Control error: incorrect line state sequence on data lane 0. */
53 +# define DSI0_INT_ERR_CONTROL BIT(4)
54 +# define DSI0_INT_ERR_SYNC_ESC BIT(3)
55 +# define DSI0_INT_RX2_PKT BIT(2)
56 +# define DSI0_INT_RX1_PKT BIT(1)
57 +# define DSI0_INT_CMD_PKT BIT(0)
58 +
59 +#define DSI0_INTERRUPTS_ALWAYS_ENABLED (DSI0_INT_ERR_SYNC_ESC | \
60 + DSI0_INT_ERR_CONTROL | \
61 + DSI0_INT_ERR_CONT_LP0 | \
62 + DSI0_INT_ERR_CONT_LP1 | \
63 + DSI0_INT_HSTX_TO | \
64 + DSI0_INT_LPRX_TO | \
65 + DSI0_INT_TA_TO | \
66 + DSI0_INT_PR_TO)
67 +
68 # define DSI1_INT_PHY_D3_ULPS BIT(30)
69 # define DSI1_INT_PHY_D3_STOP BIT(29)
70 # define DSI1_INT_PHY_D2_ULPS BIT(28)
71 @@ -894,6 +936,9 @@ static void vc4_dsi_encoder_enable(struc
72
73 DSI_PORT_WRITE(PHY_AFEC0, afec0);
74
75 + /* AFEC reset hold time */
76 + mdelay(1);
77 +
78 DSI_PORT_WRITE(PHY_AFEC1,
79 VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE1) |
80 VC4_SET_FIELD(6, DSI0_PHY_AFEC1_IDR_DLANE0) |
81 @@ -1060,12 +1105,9 @@ static void vc4_dsi_encoder_enable(struc
82 DSI_PORT_WRITE(CTRL, DSI_PORT_READ(CTRL) | DSI1_CTRL_EN);
83
84 /* Bring AFE out of reset. */
85 - if (dsi->variant->port == 0) {
86 - } else {
87 - DSI_PORT_WRITE(PHY_AFEC0,
88 - DSI_PORT_READ(PHY_AFEC0) &
89 - ~DSI1_PHY_AFEC0_RESET);
90 - }
91 + DSI_PORT_WRITE(PHY_AFEC0,
92 + DSI_PORT_READ(PHY_AFEC0) &
93 + ~DSI_PORT_BIT(PHY_AFEC0_RESET));
94
95 vc4_dsi_ulps(dsi, false);
96
97 @@ -1184,13 +1226,28 @@ static ssize_t vc4_dsi_host_transfer(str
98 /* Enable the appropriate interrupt for the transfer completion. */
99 dsi->xfer_result = 0;
100 reinit_completion(&dsi->xfer_completion);
101 - DSI_PORT_WRITE(INT_STAT, DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF);
102 - if (msg->rx_len) {
103 - DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED |
104 - DSI1_INT_PHY_DIR_RTF));
105 + if (dsi->variant->port == 0) {
106 + DSI_PORT_WRITE(INT_STAT,
107 + DSI0_INT_CMDC_DONE_MASK | DSI1_INT_PHY_DIR_RTF);
108 + if (msg->rx_len) {
109 + DSI_PORT_WRITE(INT_EN, (DSI0_INTERRUPTS_ALWAYS_ENABLED |
110 + DSI0_INT_PHY_DIR_RTF));
111 + } else {
112 + DSI_PORT_WRITE(INT_EN,
113 + (DSI0_INTERRUPTS_ALWAYS_ENABLED |
114 + VC4_SET_FIELD(DSI0_INT_CMDC_DONE_NO_REPEAT,
115 + DSI0_INT_CMDC_DONE)));
116 + }
117 } else {
118 - DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED |
119 - DSI1_INT_TXPKT1_DONE));
120 + DSI_PORT_WRITE(INT_STAT,
121 + DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF);
122 + if (msg->rx_len) {
123 + DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED |
124 + DSI1_INT_PHY_DIR_RTF));
125 + } else {
126 + DSI_PORT_WRITE(INT_EN, (DSI1_INTERRUPTS_ALWAYS_ENABLED |
127 + DSI1_INT_TXPKT1_DONE));
128 + }
129 }
130
131 /* Send the packet. */
132 @@ -1207,7 +1264,7 @@ static ssize_t vc4_dsi_host_transfer(str
133 ret = dsi->xfer_result;
134 }
135
136 - DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED);
137 + DSI_PORT_WRITE(INT_EN, DSI_PORT_BIT(INTERRUPTS_ALWAYS_ENABLED));
138
139 if (ret)
140 goto reset_fifo_and_return;
141 @@ -1253,7 +1310,7 @@ reset_fifo_and_return:
142 DSI_PORT_BIT(CTRL_RESET_FIFOS));
143
144 DSI_PORT_WRITE(TXPKT1C, 0);
145 - DSI_PORT_WRITE(INT_EN, DSI1_INTERRUPTS_ALWAYS_ENABLED);
146 + DSI_PORT_WRITE(INT_EN, DSI_PORT_BIT(INTERRUPTS_ALWAYS_ENABLED));
147 return ret;
148 }
149
150 @@ -1390,26 +1447,28 @@ static irqreturn_t vc4_dsi_irq_handler(i
151 DSI_PORT_WRITE(INT_STAT, stat);
152
153 dsi_handle_error(dsi, &ret, stat,
154 - DSI1_INT_ERR_SYNC_ESC, "LPDT sync");
155 + DSI_PORT_BIT(INT_ERR_SYNC_ESC), "LPDT sync");
156 dsi_handle_error(dsi, &ret, stat,
157 - DSI1_INT_ERR_CONTROL, "data lane 0 sequence");
158 + DSI_PORT_BIT(INT_ERR_CONTROL), "data lane 0 sequence");
159 dsi_handle_error(dsi, &ret, stat,
160 - DSI1_INT_ERR_CONT_LP0, "LP0 contention");
161 + DSI_PORT_BIT(INT_ERR_CONT_LP0), "LP0 contention");
162 dsi_handle_error(dsi, &ret, stat,
163 - DSI1_INT_ERR_CONT_LP1, "LP1 contention");
164 + DSI_PORT_BIT(INT_ERR_CONT_LP1), "LP1 contention");
165 dsi_handle_error(dsi, &ret, stat,
166 - DSI1_INT_HSTX_TO, "HSTX timeout");
167 + DSI_PORT_BIT(INT_HSTX_TO), "HSTX timeout");
168 dsi_handle_error(dsi, &ret, stat,
169 - DSI1_INT_LPRX_TO, "LPRX timeout");
170 + DSI_PORT_BIT(INT_LPRX_TO), "LPRX timeout");
171 dsi_handle_error(dsi, &ret, stat,
172 - DSI1_INT_TA_TO, "turnaround timeout");
173 + DSI_PORT_BIT(INT_TA_TO), "turnaround timeout");
174 dsi_handle_error(dsi, &ret, stat,
175 - DSI1_INT_PR_TO, "peripheral reset timeout");
176 + DSI_PORT_BIT(INT_PR_TO), "peripheral reset timeout");
177
178 - if (stat & (DSI1_INT_TXPKT1_DONE | DSI1_INT_PHY_DIR_RTF)) {
179 + if (stat & ((dsi->variant->port ? DSI1_INT_TXPKT1_DONE :
180 + DSI0_INT_CMDC_DONE_MASK) |
181 + DSI_PORT_BIT(INT_PHY_DIR_RTF))) {
182 complete(&dsi->xfer_completion);
183 ret = IRQ_HANDLED;
184 - } else if (stat & DSI1_INT_HSTX_TO) {
185 + } else if (stat & DSI_PORT_BIT(INT_HSTX_TO)) {
186 complete(&dsi->xfer_completion);
187 dsi->xfer_result = -ETIMEDOUT;
188 ret = IRQ_HANDLED;