layerscape: add 64b/32b target for ls1012ardb device
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.4 / 1087-mtd-spi-nor-fsl-quadspi-add-big-endian-support.patch
1 From c58b398221d88ac0db29c3bb7522a4f48dfa102c Mon Sep 17 00:00:00 2001
2 From: Yuan Yao <yao.yuan@freescale.com>
3 Date: Tue, 17 Nov 2015 16:13:47 +0800
4 Subject: [PATCH 087/113] mtd: spi-nor: fsl-quadspi: add big-endian support
5
6 Add R/W functions for big- or little-endian registers:
7 The qSPI controller's endian is independent of the CPU core's endian.
8 So far, the qSPI have two versions for big-endian and little-endian.
9
10 Signed-off-by: Yuan Yao <yao.yuan@nxp.com>
11 Acked-by: Han xu <han.xu@freescale.com>
12 ---
13 drivers/mtd/spi-nor/fsl-quadspi.c | 157 +++++++++++++++++++++++--------------
14 1 file changed, 97 insertions(+), 60 deletions(-)
15
16 --- a/drivers/mtd/spi-nor/fsl-quadspi.c
17 +++ b/drivers/mtd/spi-nor/fsl-quadspi.c
18 @@ -275,6 +275,7 @@ struct fsl_qspi {
19 u32 clk_rate;
20 unsigned int chip_base_addr; /* We may support two chips. */
21 bool has_second_chip;
22 + bool big_endian;
23 struct mutex lock;
24 struct pm_qos_request pm_qos_req;
25 };
26 @@ -300,6 +301,28 @@ static inline int needs_wakeup_wait_mode
27 }
28
29 /*
30 + * R/W functions for big- or little-endian registers:
31 + * The qSPI controller's endian is independent of the CPU core's endian.
32 + * So far, although the CPU core is little-endian but the qSPI have two
33 + * versions for big-endian and little-endian.
34 + */
35 +static void qspi_writel(struct fsl_qspi *q, u32 val, void __iomem *addr)
36 +{
37 + if (q->big_endian)
38 + iowrite32be(val, addr);
39 + else
40 + iowrite32(val, addr);
41 +}
42 +
43 +static u32 qspi_readl(struct fsl_qspi *q, void __iomem *addr)
44 +{
45 + if (q->big_endian)
46 + return ioread32be(addr);
47 + else
48 + return ioread32(addr);
49 +}
50 +
51 +/*
52 * An IC bug makes us to re-arrange the 32-bit data.
53 * The following chips, such as IMX6SLX, have fixed this bug.
54 */
55 @@ -310,14 +333,14 @@ static inline u32 fsl_qspi_endian_xchg(s
56
57 static inline void fsl_qspi_unlock_lut(struct fsl_qspi *q)
58 {
59 - writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
60 - writel(QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR);
61 + qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
62 + qspi_writel(q, QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR);
63 }
64
65 static inline void fsl_qspi_lock_lut(struct fsl_qspi *q)
66 {
67 - writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
68 - writel(QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR);
69 + qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
70 + qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR);
71 }
72
73 static irqreturn_t fsl_qspi_irq_handler(int irq, void *dev_id)
74 @@ -326,8 +349,8 @@ static irqreturn_t fsl_qspi_irq_handler(
75 u32 reg;
76
77 /* clear interrupt */
78 - reg = readl(q->iobase + QUADSPI_FR);
79 - writel(reg, q->iobase + QUADSPI_FR);
80 + reg = qspi_readl(q, q->iobase + QUADSPI_FR);
81 + qspi_writel(q, reg, q->iobase + QUADSPI_FR);
82
83 if (reg & QUADSPI_FR_TFF_MASK)
84 complete(&q->c);
85 @@ -348,7 +371,7 @@ static void fsl_qspi_init_lut(struct fsl
86
87 /* Clear all the LUT table */
88 for (i = 0; i < QUADSPI_LUT_NUM; i++)
89 - writel(0, base + QUADSPI_LUT_BASE + i * 4);
90 + qspi_writel(q, 0, base + QUADSPI_LUT_BASE + i * 4);
91
92 /* Quad Read */
93 lut_base = SEQID_QUAD_READ * 4;
94 @@ -364,14 +387,15 @@ static void fsl_qspi_init_lut(struct fsl
95 dummy = 8;
96 }
97
98 - writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
99 + qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
100 base + QUADSPI_LUT(lut_base));
101 - writel(LUT0(DUMMY, PAD1, dummy) | LUT1(FSL_READ, PAD4, rxfifo),
102 + qspi_writel(q, LUT0(DUMMY, PAD1, dummy) | LUT1(FSL_READ, PAD4, rxfifo),
103 base + QUADSPI_LUT(lut_base + 1));
104
105 /* Write enable */
106 lut_base = SEQID_WREN * 4;
107 - writel(LUT0(CMD, PAD1, SPINOR_OP_WREN), base + QUADSPI_LUT(lut_base));
108 + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WREN),
109 + base + QUADSPI_LUT(lut_base));
110
111 /* Page Program */
112 lut_base = SEQID_PP * 4;
113 @@ -385,13 +409,15 @@ static void fsl_qspi_init_lut(struct fsl
114 addrlen = ADDR32BIT;
115 }
116
117 - writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
118 + qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
119 base + QUADSPI_LUT(lut_base));
120 - writel(LUT0(FSL_WRITE, PAD1, 0), base + QUADSPI_LUT(lut_base + 1));
121 + qspi_writel(q, LUT0(FSL_WRITE, PAD1, 0),
122 + base + QUADSPI_LUT(lut_base + 1));
123
124 /* Read Status */
125 lut_base = SEQID_RDSR * 4;
126 - writel(LUT0(CMD, PAD1, SPINOR_OP_RDSR) | LUT1(FSL_READ, PAD1, 0x1),
127 + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDSR) |
128 + LUT1(FSL_READ, PAD1, 0x1),
129 base + QUADSPI_LUT(lut_base));
130
131 /* Erase a sector */
132 @@ -400,40 +426,46 @@ static void fsl_qspi_init_lut(struct fsl
133 cmd = q->nor[0].erase_opcode;
134 addrlen = q->nor_size <= SZ_16M ? ADDR24BIT : ADDR32BIT;
135
136 - writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
137 + qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
138 base + QUADSPI_LUT(lut_base));
139
140 /* Erase the whole chip */
141 lut_base = SEQID_CHIP_ERASE * 4;
142 - writel(LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE),
143 + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE),
144 base + QUADSPI_LUT(lut_base));
145
146 /* READ ID */
147 lut_base = SEQID_RDID * 4;
148 - writel(LUT0(CMD, PAD1, SPINOR_OP_RDID) | LUT1(FSL_READ, PAD1, 0x8),
149 + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDID) |
150 + LUT1(FSL_READ, PAD1, 0x8),
151 base + QUADSPI_LUT(lut_base));
152
153 /* Write Register */
154 lut_base = SEQID_WRSR * 4;
155 - writel(LUT0(CMD, PAD1, SPINOR_OP_WRSR) | LUT1(FSL_WRITE, PAD1, 0x2),
156 + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRSR) |
157 + LUT1(FSL_WRITE, PAD1, 0x2),
158 base + QUADSPI_LUT(lut_base));
159
160 /* Read Configuration Register */
161 lut_base = SEQID_RDCR * 4;
162 - writel(LUT0(CMD, PAD1, SPINOR_OP_RDCR) | LUT1(FSL_READ, PAD1, 0x1),
163 + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDCR) |
164 + LUT1(FSL_READ, PAD1, 0x1),
165 base + QUADSPI_LUT(lut_base));
166
167 /* Write disable */
168 lut_base = SEQID_WRDI * 4;
169 - writel(LUT0(CMD, PAD1, SPINOR_OP_WRDI), base + QUADSPI_LUT(lut_base));
170 + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRDI),
171 + base + QUADSPI_LUT(lut_base));
172
173 /* Enter 4 Byte Mode (Micron) */
174 lut_base = SEQID_EN4B * 4;
175 - writel(LUT0(CMD, PAD1, SPINOR_OP_EN4B), base + QUADSPI_LUT(lut_base));
176 + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_EN4B),
177 + base + QUADSPI_LUT(lut_base));
178
179 /* Enter 4 Byte Mode (Spansion) */
180 lut_base = SEQID_BRWR * 4;
181 - writel(LUT0(CMD, PAD1, SPINOR_OP_BRWR), base + QUADSPI_LUT(lut_base));
182 + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_BRWR),
183 + base + QUADSPI_LUT(lut_base));
184
185 fsl_qspi_lock_lut(q);
186 }
187 @@ -488,15 +520,16 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 c
188 q->chip_base_addr, addr, len, cmd);
189
190 /* save the reg */
191 - reg = readl(base + QUADSPI_MCR);
192 + reg = qspi_readl(q, base + QUADSPI_MCR);
193
194 - writel(q->memmap_phy + q->chip_base_addr + addr, base + QUADSPI_SFAR);
195 - writel(QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS,
196 + qspi_writel(q, q->memmap_phy + q->chip_base_addr + addr,
197 + base + QUADSPI_SFAR);
198 + qspi_writel(q, QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS,
199 base + QUADSPI_RBCT);
200 - writel(reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR);
201 + qspi_writel(q, reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR);
202
203 do {
204 - reg2 = readl(base + QUADSPI_SR);
205 + reg2 = qspi_readl(q, base + QUADSPI_SR);
206 if (reg2 & (QUADSPI_SR_IP_ACC_MASK | QUADSPI_SR_AHB_ACC_MASK)) {
207 udelay(1);
208 dev_dbg(q->dev, "The controller is busy, 0x%x\n", reg2);
209 @@ -507,21 +540,22 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 c
210
211 /* trigger the LUT now */
212 seqid = fsl_qspi_get_seqid(q, cmd);
213 - writel((seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, base + QUADSPI_IPCR);
214 + qspi_writel(q, (seqid << QUADSPI_IPCR_SEQID_SHIFT) | len,
215 + base + QUADSPI_IPCR);
216
217 /* Wait for the interrupt. */
218 if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000))) {
219 dev_err(q->dev,
220 "cmd 0x%.2x timeout, addr@%.8x, FR:0x%.8x, SR:0x%.8x\n",
221 - cmd, addr, readl(base + QUADSPI_FR),
222 - readl(base + QUADSPI_SR));
223 + cmd, addr, qspi_readl(q, base + QUADSPI_FR),
224 + qspi_readl(q, base + QUADSPI_SR));
225 err = -ETIMEDOUT;
226 } else {
227 err = 0;
228 }
229
230 /* restore the MCR */
231 - writel(reg, base + QUADSPI_MCR);
232 + qspi_writel(q, reg, base + QUADSPI_MCR);
233
234 return err;
235 }
236 @@ -533,7 +567,7 @@ static void fsl_qspi_read_data(struct fs
237 int i = 0;
238
239 while (len > 0) {
240 - tmp = readl(q->iobase + QUADSPI_RBDR + i * 4);
241 + tmp = qspi_readl(q, q->iobase + QUADSPI_RBDR + i * 4);
242 tmp = fsl_qspi_endian_xchg(q, tmp);
243 dev_dbg(q->dev, "chip addr:0x%.8x, rcv:0x%.8x\n",
244 q->chip_base_addr, tmp);
245 @@ -561,9 +595,9 @@ static inline void fsl_qspi_invalid(stru
246 {
247 u32 reg;
248
249 - reg = readl(q->iobase + QUADSPI_MCR);
250 + reg = qspi_readl(q, q->iobase + QUADSPI_MCR);
251 reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK;
252 - writel(reg, q->iobase + QUADSPI_MCR);
253 + qspi_writel(q, reg, q->iobase + QUADSPI_MCR);
254
255 /*
256 * The minimum delay : 1 AHB + 2 SFCK clocks.
257 @@ -572,7 +606,7 @@ static inline void fsl_qspi_invalid(stru
258 udelay(1);
259
260 reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK);
261 - writel(reg, q->iobase + QUADSPI_MCR);
262 + qspi_writel(q, reg, q->iobase + QUADSPI_MCR);
263 }
264
265 static int fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor,
266 @@ -586,20 +620,20 @@ static int fsl_qspi_nor_write(struct fsl
267 q->chip_base_addr, to, count);
268
269 /* clear the TX FIFO. */
270 - tmp = readl(q->iobase + QUADSPI_MCR);
271 - writel(tmp | QUADSPI_MCR_CLR_TXF_MASK, q->iobase + QUADSPI_MCR);
272 + tmp = qspi_readl(q, q->iobase + QUADSPI_MCR);
273 + qspi_writel(q, tmp | QUADSPI_MCR_CLR_TXF_MASK, q->iobase + QUADSPI_MCR);
274
275 /* fill the TX data to the FIFO */
276 for (j = 0, i = ((count + 3) / 4); j < i; j++) {
277 tmp = fsl_qspi_endian_xchg(q, *txbuf);
278 - writel(tmp, q->iobase + QUADSPI_TBDR);
279 + qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR);
280 txbuf++;
281 }
282
283 /* fill the TXFIFO upto 16 bytes for i.MX7d */
284 if (needs_fill_txfifo(q))
285 for (; i < 4; i++)
286 - writel(tmp, q->iobase + QUADSPI_TBDR);
287 + qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR);
288
289 /* Trigger it */
290 ret = fsl_qspi_runcmd(q, opcode, to, count);
291 @@ -615,10 +649,10 @@ static void fsl_qspi_set_map_addr(struct
292 int nor_size = q->nor_size;
293 void __iomem *base = q->iobase;
294
295 - writel(nor_size + q->memmap_phy, base + QUADSPI_SFA1AD);
296 - writel(nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD);
297 - writel(nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD);
298 - writel(nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD);
299 + qspi_writel(q, nor_size + q->memmap_phy, base + QUADSPI_SFA1AD);
300 + qspi_writel(q, nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD);
301 + qspi_writel(q, nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD);
302 + qspi_writel(q, nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD);
303 }
304
305 /*
306 @@ -640,24 +674,26 @@ static void fsl_qspi_init_abh_read(struc
307 int seqid;
308
309 /* AHB configuration for access buffer 0/1/2 .*/
310 - writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR);
311 - writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR);
312 - writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR);
313 + qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR);
314 + qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR);
315 + qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR);
316 /*
317 * Set ADATSZ with the maximum AHB buffer size to improve the
318 * read performance.
319 */
320 - writel(QUADSPI_BUF3CR_ALLMST_MASK | ((q->devtype_data->ahb_buf_size / 8)
321 - << QUADSPI_BUF3CR_ADATSZ_SHIFT), base + QUADSPI_BUF3CR);
322 + qspi_writel(q, QUADSPI_BUF3CR_ALLMST_MASK |
323 + ((q->devtype_data->ahb_buf_size / 8)
324 + << QUADSPI_BUF3CR_ADATSZ_SHIFT),
325 + base + QUADSPI_BUF3CR);
326
327 /* We only use the buffer3 */
328 - writel(0, base + QUADSPI_BUF0IND);
329 - writel(0, base + QUADSPI_BUF1IND);
330 - writel(0, base + QUADSPI_BUF2IND);
331 + qspi_writel(q, 0, base + QUADSPI_BUF0IND);
332 + qspi_writel(q, 0, base + QUADSPI_BUF1IND);
333 + qspi_writel(q, 0, base + QUADSPI_BUF2IND);
334
335 /* Set the default lut sequence for AHB Read. */
336 seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode);
337 - writel(seqid << QUADSPI_BFGENCR_SEQID_SHIFT,
338 + qspi_writel(q, seqid << QUADSPI_BFGENCR_SEQID_SHIFT,
339 q->iobase + QUADSPI_BFGENCR);
340 }
341
342 @@ -713,7 +749,7 @@ static int fsl_qspi_nor_setup(struct fsl
343 return ret;
344
345 /* Reset the module */
346 - writel(QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK,
347 + qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK,
348 base + QUADSPI_MCR);
349 udelay(1);
350
351 @@ -721,24 +757,24 @@ static int fsl_qspi_nor_setup(struct fsl
352 fsl_qspi_init_lut(q);
353
354 /* Disable the module */
355 - writel(QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK,
356 + qspi_writel(q, QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK,
357 base + QUADSPI_MCR);
358
359 - reg = readl(base + QUADSPI_SMPR);
360 - writel(reg & ~(QUADSPI_SMPR_FSDLY_MASK
361 + reg = qspi_readl(q, base + QUADSPI_SMPR);
362 + qspi_writel(q, reg & ~(QUADSPI_SMPR_FSDLY_MASK
363 | QUADSPI_SMPR_FSPHS_MASK
364 | QUADSPI_SMPR_HSENA_MASK
365 | QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR);
366
367 /* Enable the module */
368 - writel(QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK,
369 + qspi_writel(q, QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK,
370 base + QUADSPI_MCR);
371
372 /* clear all interrupt status */
373 - writel(0xffffffff, q->iobase + QUADSPI_FR);
374 + qspi_writel(q, 0xffffffff, q->iobase + QUADSPI_FR);
375
376 /* enable the interrupt */
377 - writel(QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER);
378 + qspi_writel(q, QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER);
379
380 return 0;
381 }
382 @@ -954,6 +990,7 @@ static int fsl_qspi_probe(struct platfor
383 if (IS_ERR(q->iobase))
384 return PTR_ERR(q->iobase);
385
386 + q->big_endian = of_property_read_bool(np, "big-endian");
387 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
388 "QuadSPI-memory");
389 if (!devm_request_mem_region(dev, res->start, resource_size(res),
390 @@ -1101,8 +1138,8 @@ static int fsl_qspi_remove(struct platfo
391 }
392
393 /* disable the hardware */
394 - writel(QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
395 - writel(0x0, q->iobase + QUADSPI_RSER);
396 + qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
397 + qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER);
398
399 mutex_destroy(&q->lock);
400