blob: 2d460368ce5fd484d2fd954f6d4c90e06a6f6dea [file] [log] [blame]
Huang Shijiee46ecda2014-02-24 18:37:42 +08001/*
2 * Freescale QuadSPI driver.
3 *
4 * Copyright (C) 2013 Freescale Semiconductor, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/interrupt.h>
14#include <linux/errno.h>
15#include <linux/platform_device.h>
16#include <linux/sched.h>
17#include <linux/delay.h>
18#include <linux/io.h>
19#include <linux/clk.h>
20#include <linux/err.h>
21#include <linux/of.h>
22#include <linux/of_device.h>
23#include <linux/timer.h>
24#include <linux/jiffies.h>
25#include <linux/completion.h>
26#include <linux/mtd/mtd.h>
27#include <linux/mtd/partitions.h>
28#include <linux/mtd/spi-nor.h>
Han Xu392d39c2015-05-13 14:40:57 -050029#include <linux/mutex.h>
Huang Shijiee46ecda2014-02-24 18:37:42 +080030
31/* The registers */
32#define QUADSPI_MCR 0x00
33#define QUADSPI_MCR_RESERVED_SHIFT 16
34#define QUADSPI_MCR_RESERVED_MASK (0xF << QUADSPI_MCR_RESERVED_SHIFT)
35#define QUADSPI_MCR_MDIS_SHIFT 14
36#define QUADSPI_MCR_MDIS_MASK (1 << QUADSPI_MCR_MDIS_SHIFT)
37#define QUADSPI_MCR_CLR_TXF_SHIFT 11
38#define QUADSPI_MCR_CLR_TXF_MASK (1 << QUADSPI_MCR_CLR_TXF_SHIFT)
39#define QUADSPI_MCR_CLR_RXF_SHIFT 10
40#define QUADSPI_MCR_CLR_RXF_MASK (1 << QUADSPI_MCR_CLR_RXF_SHIFT)
41#define QUADSPI_MCR_DDR_EN_SHIFT 7
42#define QUADSPI_MCR_DDR_EN_MASK (1 << QUADSPI_MCR_DDR_EN_SHIFT)
43#define QUADSPI_MCR_END_CFG_SHIFT 2
44#define QUADSPI_MCR_END_CFG_MASK (3 << QUADSPI_MCR_END_CFG_SHIFT)
45#define QUADSPI_MCR_SWRSTHD_SHIFT 1
46#define QUADSPI_MCR_SWRSTHD_MASK (1 << QUADSPI_MCR_SWRSTHD_SHIFT)
47#define QUADSPI_MCR_SWRSTSD_SHIFT 0
48#define QUADSPI_MCR_SWRSTSD_MASK (1 << QUADSPI_MCR_SWRSTSD_SHIFT)
49
50#define QUADSPI_IPCR 0x08
51#define QUADSPI_IPCR_SEQID_SHIFT 24
52#define QUADSPI_IPCR_SEQID_MASK (0xF << QUADSPI_IPCR_SEQID_SHIFT)
53
54#define QUADSPI_BUF0CR 0x10
55#define QUADSPI_BUF1CR 0x14
56#define QUADSPI_BUF2CR 0x18
57#define QUADSPI_BUFXCR_INVALID_MSTRID 0xe
58
59#define QUADSPI_BUF3CR 0x1c
60#define QUADSPI_BUF3CR_ALLMST_SHIFT 31
Allen Xu4e898ce2015-01-14 00:28:56 +080061#define QUADSPI_BUF3CR_ALLMST_MASK (1 << QUADSPI_BUF3CR_ALLMST_SHIFT)
62#define QUADSPI_BUF3CR_ADATSZ_SHIFT 8
63#define QUADSPI_BUF3CR_ADATSZ_MASK (0xFF << QUADSPI_BUF3CR_ADATSZ_SHIFT)
Huang Shijiee46ecda2014-02-24 18:37:42 +080064
65#define QUADSPI_BFGENCR 0x20
66#define QUADSPI_BFGENCR_PAR_EN_SHIFT 16
67#define QUADSPI_BFGENCR_PAR_EN_MASK (1 << (QUADSPI_BFGENCR_PAR_EN_SHIFT))
68#define QUADSPI_BFGENCR_SEQID_SHIFT 12
69#define QUADSPI_BFGENCR_SEQID_MASK (0xF << QUADSPI_BFGENCR_SEQID_SHIFT)
70
71#define QUADSPI_BUF0IND 0x30
72#define QUADSPI_BUF1IND 0x34
73#define QUADSPI_BUF2IND 0x38
74#define QUADSPI_SFAR 0x100
75
76#define QUADSPI_SMPR 0x108
77#define QUADSPI_SMPR_DDRSMP_SHIFT 16
78#define QUADSPI_SMPR_DDRSMP_MASK (7 << QUADSPI_SMPR_DDRSMP_SHIFT)
79#define QUADSPI_SMPR_FSDLY_SHIFT 6
80#define QUADSPI_SMPR_FSDLY_MASK (1 << QUADSPI_SMPR_FSDLY_SHIFT)
81#define QUADSPI_SMPR_FSPHS_SHIFT 5
82#define QUADSPI_SMPR_FSPHS_MASK (1 << QUADSPI_SMPR_FSPHS_SHIFT)
83#define QUADSPI_SMPR_HSENA_SHIFT 0
84#define QUADSPI_SMPR_HSENA_MASK (1 << QUADSPI_SMPR_HSENA_SHIFT)
85
86#define QUADSPI_RBSR 0x10c
87#define QUADSPI_RBSR_RDBFL_SHIFT 8
88#define QUADSPI_RBSR_RDBFL_MASK (0x3F << QUADSPI_RBSR_RDBFL_SHIFT)
89
90#define QUADSPI_RBCT 0x110
91#define QUADSPI_RBCT_WMRK_MASK 0x1F
92#define QUADSPI_RBCT_RXBRD_SHIFT 8
93#define QUADSPI_RBCT_RXBRD_USEIPS (0x1 << QUADSPI_RBCT_RXBRD_SHIFT)
94
95#define QUADSPI_TBSR 0x150
96#define QUADSPI_TBDR 0x154
97#define QUADSPI_SR 0x15c
98#define QUADSPI_SR_IP_ACC_SHIFT 1
99#define QUADSPI_SR_IP_ACC_MASK (0x1 << QUADSPI_SR_IP_ACC_SHIFT)
100#define QUADSPI_SR_AHB_ACC_SHIFT 2
101#define QUADSPI_SR_AHB_ACC_MASK (0x1 << QUADSPI_SR_AHB_ACC_SHIFT)
102
103#define QUADSPI_FR 0x160
104#define QUADSPI_FR_TFF_MASK 0x1
105
106#define QUADSPI_SFA1AD 0x180
107#define QUADSPI_SFA2AD 0x184
108#define QUADSPI_SFB1AD 0x188
109#define QUADSPI_SFB2AD 0x18c
110#define QUADSPI_RBDR 0x200
111
112#define QUADSPI_LUTKEY 0x300
113#define QUADSPI_LUTKEY_VALUE 0x5AF05AF0
114
115#define QUADSPI_LCKCR 0x304
116#define QUADSPI_LCKER_LOCK 0x1
117#define QUADSPI_LCKER_UNLOCK 0x2
118
119#define QUADSPI_RSER 0x164
120#define QUADSPI_RSER_TFIE (0x1 << 0)
121
122#define QUADSPI_LUT_BASE 0x310
123
124/*
125 * The definition of the LUT register shows below:
126 *
127 * ---------------------------------------------------
128 * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 |
129 * ---------------------------------------------------
130 */
131#define OPRND0_SHIFT 0
132#define PAD0_SHIFT 8
133#define INSTR0_SHIFT 10
134#define OPRND1_SHIFT 16
135
136/* Instruction set for the LUT register. */
137#define LUT_STOP 0
138#define LUT_CMD 1
139#define LUT_ADDR 2
140#define LUT_DUMMY 3
141#define LUT_MODE 4
142#define LUT_MODE2 5
143#define LUT_MODE4 6
144#define LUT_READ 7
145#define LUT_WRITE 8
146#define LUT_JMP_ON_CS 9
147#define LUT_ADDR_DDR 10
148#define LUT_MODE_DDR 11
149#define LUT_MODE2_DDR 12
150#define LUT_MODE4_DDR 13
151#define LUT_READ_DDR 14
152#define LUT_WRITE_DDR 15
153#define LUT_DATA_LEARN 16
154
155/*
156 * The PAD definitions for LUT register.
157 *
158 * The pad stands for the lines number of IO[0:3].
159 * For example, the Quad read need four IO lines, so you should
160 * set LUT_PAD4 which means we use four IO lines.
161 */
162#define LUT_PAD1 0
163#define LUT_PAD2 1
164#define LUT_PAD4 2
165
166/* Oprands for the LUT register. */
167#define ADDR24BIT 0x18
168#define ADDR32BIT 0x20
169
170/* Macros for constructing the LUT register. */
171#define LUT0(ins, pad, opr) \
172 (((opr) << OPRND0_SHIFT) | ((LUT_##pad) << PAD0_SHIFT) | \
173 ((LUT_##ins) << INSTR0_SHIFT))
174
175#define LUT1(ins, pad, opr) (LUT0(ins, pad, opr) << OPRND1_SHIFT)
176
177/* other macros for LUT register. */
178#define QUADSPI_LUT(x) (QUADSPI_LUT_BASE + (x) * 4)
179#define QUADSPI_LUT_NUM 64
180
181/* SEQID -- we can have 16 seqids at most. */
182#define SEQID_QUAD_READ 0
183#define SEQID_WREN 1
184#define SEQID_WRDI 2
185#define SEQID_RDSR 3
186#define SEQID_SE 4
187#define SEQID_CHIP_ERASE 5
188#define SEQID_PP 6
189#define SEQID_RDID 7
190#define SEQID_WRSR 8
191#define SEQID_RDCR 9
192#define SEQID_EN4B 10
193#define SEQID_BRWR 11
194
Han Xu49bd7062015-08-04 10:25:22 -0500195#define QUADSPI_MIN_IOMAP SZ_4M
196
Huang Shijiee46ecda2014-02-24 18:37:42 +0800197enum fsl_qspi_devtype {
198 FSL_QUADSPI_VYBRID,
199 FSL_QUADSPI_IMX6SX,
200};
201
202struct fsl_qspi_devtype_data {
203 enum fsl_qspi_devtype devtype;
204 int rxfifo;
205 int txfifo;
Allen Xu4e898ce2015-01-14 00:28:56 +0800206 int ahb_buf_size;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800207};
208
209static struct fsl_qspi_devtype_data vybrid_data = {
210 .devtype = FSL_QUADSPI_VYBRID,
211 .rxfifo = 128,
Allen Xu4e898ce2015-01-14 00:28:56 +0800212 .txfifo = 64,
213 .ahb_buf_size = 1024
Huang Shijiee46ecda2014-02-24 18:37:42 +0800214};
215
216static struct fsl_qspi_devtype_data imx6sx_data = {
217 .devtype = FSL_QUADSPI_IMX6SX,
218 .rxfifo = 128,
Allen Xu4e898ce2015-01-14 00:28:56 +0800219 .txfifo = 512,
220 .ahb_buf_size = 1024
Huang Shijiee46ecda2014-02-24 18:37:42 +0800221};
222
223#define FSL_QSPI_MAX_CHIP 4
224struct fsl_qspi {
225 struct mtd_info mtd[FSL_QSPI_MAX_CHIP];
226 struct spi_nor nor[FSL_QSPI_MAX_CHIP];
227 void __iomem *iobase;
Han Xu49bd7062015-08-04 10:25:22 -0500228 void __iomem *ahb_addr;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800229 u32 memmap_phy;
Han Xu49bd7062015-08-04 10:25:22 -0500230 u32 memmap_offs;
231 u32 memmap_len;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800232 struct clk *clk, *clk_en;
233 struct device *dev;
234 struct completion c;
235 struct fsl_qspi_devtype_data *devtype_data;
236 u32 nor_size;
237 u32 nor_num;
238 u32 clk_rate;
239 unsigned int chip_base_addr; /* We may support two chips. */
Fabio Estevamcfe4af32015-01-13 20:14:15 -0200240 bool has_second_chip;
Han Xu392d39c2015-05-13 14:40:57 -0500241 struct mutex lock;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800242};
243
244static inline int is_vybrid_qspi(struct fsl_qspi *q)
245{
246 return q->devtype_data->devtype == FSL_QUADSPI_VYBRID;
247}
248
249static inline int is_imx6sx_qspi(struct fsl_qspi *q)
250{
251 return q->devtype_data->devtype == FSL_QUADSPI_IMX6SX;
252}
253
254/*
255 * An IC bug makes us to re-arrange the 32-bit data.
256 * The following chips, such as IMX6SLX, have fixed this bug.
257 */
258static inline u32 fsl_qspi_endian_xchg(struct fsl_qspi *q, u32 a)
259{
260 return is_vybrid_qspi(q) ? __swab32(a) : a;
261}
262
263static inline void fsl_qspi_unlock_lut(struct fsl_qspi *q)
264{
265 writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
266 writel(QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR);
267}
268
269static inline void fsl_qspi_lock_lut(struct fsl_qspi *q)
270{
271 writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
272 writel(QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR);
273}
274
275static irqreturn_t fsl_qspi_irq_handler(int irq, void *dev_id)
276{
277 struct fsl_qspi *q = dev_id;
278 u32 reg;
279
280 /* clear interrupt */
281 reg = readl(q->iobase + QUADSPI_FR);
282 writel(reg, q->iobase + QUADSPI_FR);
283
284 if (reg & QUADSPI_FR_TFF_MASK)
285 complete(&q->c);
286
287 dev_dbg(q->dev, "QUADSPI_FR : 0x%.8x:0x%.8x\n", q->chip_base_addr, reg);
288 return IRQ_HANDLED;
289}
290
291static void fsl_qspi_init_lut(struct fsl_qspi *q)
292{
Brian Norrisa965d042014-04-10 15:49:38 -0700293 void __iomem *base = q->iobase;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800294 int rxfifo = q->devtype_data->rxfifo;
295 u32 lut_base;
296 u8 cmd, addrlen, dummy;
297 int i;
298
299 fsl_qspi_unlock_lut(q);
300
301 /* Clear all the LUT table */
302 for (i = 0; i < QUADSPI_LUT_NUM; i++)
303 writel(0, base + QUADSPI_LUT_BASE + i * 4);
304
305 /* Quad Read */
306 lut_base = SEQID_QUAD_READ * 4;
307
308 if (q->nor_size <= SZ_16M) {
Brian Norris58b89a12014-04-08 19:16:49 -0700309 cmd = SPINOR_OP_READ_1_1_4;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800310 addrlen = ADDR24BIT;
311 dummy = 8;
312 } else {
313 /* use the 4-byte address */
Brian Norris58b89a12014-04-08 19:16:49 -0700314 cmd = SPINOR_OP_READ_1_1_4;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800315 addrlen = ADDR32BIT;
316 dummy = 8;
317 }
318
319 writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
320 base + QUADSPI_LUT(lut_base));
321 writel(LUT0(DUMMY, PAD1, dummy) | LUT1(READ, PAD4, rxfifo),
322 base + QUADSPI_LUT(lut_base + 1));
323
324 /* Write enable */
325 lut_base = SEQID_WREN * 4;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700326 writel(LUT0(CMD, PAD1, SPINOR_OP_WREN), base + QUADSPI_LUT(lut_base));
Huang Shijiee46ecda2014-02-24 18:37:42 +0800327
328 /* Page Program */
329 lut_base = SEQID_PP * 4;
330
331 if (q->nor_size <= SZ_16M) {
Brian Norrisb02e7f32014-04-08 18:15:31 -0700332 cmd = SPINOR_OP_PP;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800333 addrlen = ADDR24BIT;
334 } else {
335 /* use the 4-byte address */
Brian Norrisb02e7f32014-04-08 18:15:31 -0700336 cmd = SPINOR_OP_PP;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800337 addrlen = ADDR32BIT;
338 }
339
340 writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
341 base + QUADSPI_LUT(lut_base));
342 writel(LUT0(WRITE, PAD1, 0), base + QUADSPI_LUT(lut_base + 1));
343
344 /* Read Status */
345 lut_base = SEQID_RDSR * 4;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700346 writel(LUT0(CMD, PAD1, SPINOR_OP_RDSR) | LUT1(READ, PAD1, 0x1),
Huang Shijiee46ecda2014-02-24 18:37:42 +0800347 base + QUADSPI_LUT(lut_base));
348
349 /* Erase a sector */
350 lut_base = SEQID_SE * 4;
351
352 if (q->nor_size <= SZ_16M) {
Brian Norrisb02e7f32014-04-08 18:15:31 -0700353 cmd = SPINOR_OP_SE;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800354 addrlen = ADDR24BIT;
355 } else {
356 /* use the 4-byte address */
Brian Norrisb02e7f32014-04-08 18:15:31 -0700357 cmd = SPINOR_OP_SE;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800358 addrlen = ADDR32BIT;
359 }
360
361 writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
362 base + QUADSPI_LUT(lut_base));
363
364 /* Erase the whole chip */
365 lut_base = SEQID_CHIP_ERASE * 4;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700366 writel(LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE),
Huang Shijiee46ecda2014-02-24 18:37:42 +0800367 base + QUADSPI_LUT(lut_base));
368
369 /* READ ID */
370 lut_base = SEQID_RDID * 4;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700371 writel(LUT0(CMD, PAD1, SPINOR_OP_RDID) | LUT1(READ, PAD1, 0x8),
Huang Shijiee46ecda2014-02-24 18:37:42 +0800372 base + QUADSPI_LUT(lut_base));
373
374 /* Write Register */
375 lut_base = SEQID_WRSR * 4;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700376 writel(LUT0(CMD, PAD1, SPINOR_OP_WRSR) | LUT1(WRITE, PAD1, 0x2),
Huang Shijiee46ecda2014-02-24 18:37:42 +0800377 base + QUADSPI_LUT(lut_base));
378
379 /* Read Configuration Register */
380 lut_base = SEQID_RDCR * 4;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700381 writel(LUT0(CMD, PAD1, SPINOR_OP_RDCR) | LUT1(READ, PAD1, 0x1),
Huang Shijiee46ecda2014-02-24 18:37:42 +0800382 base + QUADSPI_LUT(lut_base));
383
384 /* Write disable */
385 lut_base = SEQID_WRDI * 4;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700386 writel(LUT0(CMD, PAD1, SPINOR_OP_WRDI), base + QUADSPI_LUT(lut_base));
Huang Shijiee46ecda2014-02-24 18:37:42 +0800387
388 /* Enter 4 Byte Mode (Micron) */
389 lut_base = SEQID_EN4B * 4;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700390 writel(LUT0(CMD, PAD1, SPINOR_OP_EN4B), base + QUADSPI_LUT(lut_base));
Huang Shijiee46ecda2014-02-24 18:37:42 +0800391
392 /* Enter 4 Byte Mode (Spansion) */
393 lut_base = SEQID_BRWR * 4;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700394 writel(LUT0(CMD, PAD1, SPINOR_OP_BRWR), base + QUADSPI_LUT(lut_base));
Huang Shijiee46ecda2014-02-24 18:37:42 +0800395
396 fsl_qspi_lock_lut(q);
397}
398
399/* Get the SEQID for the command */
400static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd)
401{
402 switch (cmd) {
Brian Norris58b89a12014-04-08 19:16:49 -0700403 case SPINOR_OP_READ_1_1_4:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800404 return SEQID_QUAD_READ;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700405 case SPINOR_OP_WREN:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800406 return SEQID_WREN;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700407 case SPINOR_OP_WRDI:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800408 return SEQID_WRDI;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700409 case SPINOR_OP_RDSR:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800410 return SEQID_RDSR;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700411 case SPINOR_OP_SE:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800412 return SEQID_SE;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700413 case SPINOR_OP_CHIP_ERASE:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800414 return SEQID_CHIP_ERASE;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700415 case SPINOR_OP_PP:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800416 return SEQID_PP;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700417 case SPINOR_OP_RDID:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800418 return SEQID_RDID;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700419 case SPINOR_OP_WRSR:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800420 return SEQID_WRSR;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700421 case SPINOR_OP_RDCR:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800422 return SEQID_RDCR;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700423 case SPINOR_OP_EN4B:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800424 return SEQID_EN4B;
Brian Norrisb02e7f32014-04-08 18:15:31 -0700425 case SPINOR_OP_BRWR:
Huang Shijiee46ecda2014-02-24 18:37:42 +0800426 return SEQID_BRWR;
427 default:
428 dev_err(q->dev, "Unsupported cmd 0x%.2x\n", cmd);
429 break;
430 }
431 return -EINVAL;
432}
433
434static int
435fsl_qspi_runcmd(struct fsl_qspi *q, u8 cmd, unsigned int addr, int len)
436{
Brian Norrisa965d042014-04-10 15:49:38 -0700437 void __iomem *base = q->iobase;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800438 int seqid;
439 u32 reg, reg2;
440 int err;
441
442 init_completion(&q->c);
443 dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len:%d, cmd:%.2x\n",
444 q->chip_base_addr, addr, len, cmd);
445
446 /* save the reg */
447 reg = readl(base + QUADSPI_MCR);
448
449 writel(q->memmap_phy + q->chip_base_addr + addr, base + QUADSPI_SFAR);
450 writel(QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS,
451 base + QUADSPI_RBCT);
452 writel(reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR);
453
454 do {
455 reg2 = readl(base + QUADSPI_SR);
456 if (reg2 & (QUADSPI_SR_IP_ACC_MASK | QUADSPI_SR_AHB_ACC_MASK)) {
457 udelay(1);
458 dev_dbg(q->dev, "The controller is busy, 0x%x\n", reg2);
459 continue;
460 }
461 break;
462 } while (1);
463
464 /* trigger the LUT now */
465 seqid = fsl_qspi_get_seqid(q, cmd);
466 writel((seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, base + QUADSPI_IPCR);
467
468 /* Wait for the interrupt. */
Nicholas Mc Guire219a8d12015-02-01 06:15:46 -0500469 if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000))) {
Huang Shijiee46ecda2014-02-24 18:37:42 +0800470 dev_err(q->dev,
471 "cmd 0x%.2x timeout, addr@%.8x, FR:0x%.8x, SR:0x%.8x\n",
472 cmd, addr, readl(base + QUADSPI_FR),
473 readl(base + QUADSPI_SR));
474 err = -ETIMEDOUT;
475 } else {
476 err = 0;
477 }
478
479 /* restore the MCR */
480 writel(reg, base + QUADSPI_MCR);
481
482 return err;
483}
484
485/* Read out the data from the QUADSPI_RBDR buffer registers. */
486static void fsl_qspi_read_data(struct fsl_qspi *q, int len, u8 *rxbuf)
487{
488 u32 tmp;
489 int i = 0;
490
491 while (len > 0) {
492 tmp = readl(q->iobase + QUADSPI_RBDR + i * 4);
493 tmp = fsl_qspi_endian_xchg(q, tmp);
494 dev_dbg(q->dev, "chip addr:0x%.8x, rcv:0x%.8x\n",
495 q->chip_base_addr, tmp);
496
497 if (len >= 4) {
498 *((u32 *)rxbuf) = tmp;
499 rxbuf += 4;
500 } else {
501 memcpy(rxbuf, &tmp, len);
502 break;
503 }
504
505 len -= 4;
506 i++;
507 }
508}
509
510/*
511 * If we have changed the content of the flash by writing or erasing,
512 * we need to invalidate the AHB buffer. If we do not do so, we may read out
513 * the wrong data. The spec tells us reset the AHB domain and Serial Flash
514 * domain at the same time.
515 */
516static inline void fsl_qspi_invalid(struct fsl_qspi *q)
517{
518 u32 reg;
519
520 reg = readl(q->iobase + QUADSPI_MCR);
521 reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK;
522 writel(reg, q->iobase + QUADSPI_MCR);
523
524 /*
525 * The minimum delay : 1 AHB + 2 SFCK clocks.
526 * Delay 1 us is enough.
527 */
528 udelay(1);
529
530 reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK);
531 writel(reg, q->iobase + QUADSPI_MCR);
532}
533
534static int fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor,
535 u8 opcode, unsigned int to, u32 *txbuf,
536 unsigned count, size_t *retlen)
537{
538 int ret, i, j;
539 u32 tmp;
540
541 dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len : %d\n",
542 q->chip_base_addr, to, count);
543
544 /* clear the TX FIFO. */
545 tmp = readl(q->iobase + QUADSPI_MCR);
Alexander Stein038761d2015-07-02 11:37:56 +0200546 writel(tmp | QUADSPI_MCR_CLR_TXF_MASK, q->iobase + QUADSPI_MCR);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800547
548 /* fill the TX data to the FIFO */
549 for (j = 0, i = ((count + 3) / 4); j < i; j++) {
550 tmp = fsl_qspi_endian_xchg(q, *txbuf);
551 writel(tmp, q->iobase + QUADSPI_TBDR);
552 txbuf++;
553 }
554
555 /* Trigger it */
556 ret = fsl_qspi_runcmd(q, opcode, to, count);
557
558 if (ret == 0 && retlen)
559 *retlen += count;
560
561 return ret;
562}
563
564static void fsl_qspi_set_map_addr(struct fsl_qspi *q)
565{
566 int nor_size = q->nor_size;
567 void __iomem *base = q->iobase;
568
569 writel(nor_size + q->memmap_phy, base + QUADSPI_SFA1AD);
570 writel(nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD);
571 writel(nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD);
572 writel(nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD);
573}
574
575/*
576 * There are two different ways to read out the data from the flash:
577 * the "IP Command Read" and the "AHB Command Read".
578 *
579 * The IC guy suggests we use the "AHB Command Read" which is faster
580 * then the "IP Command Read". (What's more is that there is a bug in
581 * the "IP Command Read" in the Vybrid.)
582 *
583 * After we set up the registers for the "AHB Command Read", we can use
584 * the memcpy to read the data directly. A "missed" access to the buffer
585 * causes the controller to clear the buffer, and use the sequence pointed
586 * by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash.
587 */
588static void fsl_qspi_init_abh_read(struct fsl_qspi *q)
589{
590 void __iomem *base = q->iobase;
591 int seqid;
592
593 /* AHB configuration for access buffer 0/1/2 .*/
594 writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR);
595 writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR);
596 writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR);
Allen Xu4e898ce2015-01-14 00:28:56 +0800597 /*
598 * Set ADATSZ with the maximum AHB buffer size to improve the
599 * read performance.
600 */
601 writel(QUADSPI_BUF3CR_ALLMST_MASK | ((q->devtype_data->ahb_buf_size / 8)
602 << QUADSPI_BUF3CR_ADATSZ_SHIFT), base + QUADSPI_BUF3CR);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800603
604 /* We only use the buffer3 */
605 writel(0, base + QUADSPI_BUF0IND);
606 writel(0, base + QUADSPI_BUF1IND);
607 writel(0, base + QUADSPI_BUF2IND);
608
609 /* Set the default lut sequence for AHB Read. */
610 seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode);
611 writel(seqid << QUADSPI_BFGENCR_SEQID_SHIFT,
612 q->iobase + QUADSPI_BFGENCR);
613}
614
615/* We use this function to do some basic init for spi_nor_scan(). */
616static int fsl_qspi_nor_setup(struct fsl_qspi *q)
617{
618 void __iomem *base = q->iobase;
619 u32 reg;
620 int ret;
621
622 /* the default frequency, we will change it in the future.*/
623 ret = clk_set_rate(q->clk, 66000000);
624 if (ret)
625 return ret;
626
627 /* Init the LUT table. */
628 fsl_qspi_init_lut(q);
629
630 /* Disable the module */
631 writel(QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK,
632 base + QUADSPI_MCR);
633
634 reg = readl(base + QUADSPI_SMPR);
635 writel(reg & ~(QUADSPI_SMPR_FSDLY_MASK
636 | QUADSPI_SMPR_FSPHS_MASK
637 | QUADSPI_SMPR_HSENA_MASK
638 | QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR);
639
640 /* Enable the module */
641 writel(QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK,
642 base + QUADSPI_MCR);
643
644 /* enable the interrupt */
645 writel(QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER);
646
647 return 0;
648}
649
650static int fsl_qspi_nor_setup_last(struct fsl_qspi *q)
651{
652 unsigned long rate = q->clk_rate;
653 int ret;
654
655 if (is_imx6sx_qspi(q))
656 rate *= 4;
657
658 ret = clk_set_rate(q->clk, rate);
659 if (ret)
660 return ret;
661
662 /* Init the LUT table again. */
663 fsl_qspi_init_lut(q);
664
665 /* Init for AHB read */
666 fsl_qspi_init_abh_read(q);
667
668 return 0;
669}
670
Fabian Frederick66610442015-03-16 20:20:28 +0100671static const struct of_device_id fsl_qspi_dt_ids[] = {
Huang Shijiee46ecda2014-02-24 18:37:42 +0800672 { .compatible = "fsl,vf610-qspi", .data = (void *)&vybrid_data, },
673 { .compatible = "fsl,imx6sx-qspi", .data = (void *)&imx6sx_data, },
674 { /* sentinel */ }
675};
676MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids);
677
678static void fsl_qspi_set_base_addr(struct fsl_qspi *q, struct spi_nor *nor)
679{
680 q->chip_base_addr = q->nor_size * (nor - q->nor);
681}
682
683static int fsl_qspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
684{
685 int ret;
686 struct fsl_qspi *q = nor->priv;
687
688 ret = fsl_qspi_runcmd(q, opcode, 0, len);
689 if (ret)
690 return ret;
691
692 fsl_qspi_read_data(q, len, buf);
693 return 0;
694}
695
696static int fsl_qspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
697 int write_enable)
698{
699 struct fsl_qspi *q = nor->priv;
700 int ret;
701
702 if (!buf) {
703 ret = fsl_qspi_runcmd(q, opcode, 0, 1);
704 if (ret)
705 return ret;
706
Brian Norrisb02e7f32014-04-08 18:15:31 -0700707 if (opcode == SPINOR_OP_CHIP_ERASE)
Huang Shijiee46ecda2014-02-24 18:37:42 +0800708 fsl_qspi_invalid(q);
709
710 } else if (len > 0) {
711 ret = fsl_qspi_nor_write(q, nor, opcode, 0,
712 (u32 *)buf, len, NULL);
713 } else {
714 dev_err(q->dev, "invalid cmd %d\n", opcode);
715 ret = -EINVAL;
716 }
717
718 return ret;
719}
720
721static void fsl_qspi_write(struct spi_nor *nor, loff_t to,
722 size_t len, size_t *retlen, const u_char *buf)
723{
724 struct fsl_qspi *q = nor->priv;
725
726 fsl_qspi_nor_write(q, nor, nor->program_opcode, to,
727 (u32 *)buf, len, retlen);
728
729 /* invalid the data in the AHB buffer. */
730 fsl_qspi_invalid(q);
731}
732
733static int fsl_qspi_read(struct spi_nor *nor, loff_t from,
734 size_t len, size_t *retlen, u_char *buf)
735{
736 struct fsl_qspi *q = nor->priv;
737 u8 cmd = nor->read_opcode;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800738
Han Xu49bd7062015-08-04 10:25:22 -0500739 /* if necessary,ioremap buffer before AHB read, */
740 if (!q->ahb_addr) {
741 q->memmap_offs = q->chip_base_addr + from;
742 q->memmap_len = len > QUADSPI_MIN_IOMAP ? len : QUADSPI_MIN_IOMAP;
743
744 q->ahb_addr = ioremap_nocache(
745 q->memmap_phy + q->memmap_offs,
746 q->memmap_len);
747 if (!q->ahb_addr) {
748 dev_err(q->dev, "ioremap failed\n");
749 return -ENOMEM;
750 }
751 /* ioremap if the data requested is out of range */
752 } else if (q->chip_base_addr + from < q->memmap_offs
753 || q->chip_base_addr + from + len >
754 q->memmap_offs + q->memmap_len) {
755 iounmap(q->ahb_addr);
756
757 q->memmap_offs = q->chip_base_addr + from;
758 q->memmap_len = len > QUADSPI_MIN_IOMAP ? len : QUADSPI_MIN_IOMAP;
759 q->ahb_addr = ioremap_nocache(
760 q->memmap_phy + q->memmap_offs,
761 q->memmap_len);
762 if (!q->ahb_addr) {
763 dev_err(q->dev, "ioremap failed\n");
764 return -ENOMEM;
765 }
766 }
767
768 dev_dbg(q->dev, "cmd [%x],read from 0x%p, len:%d\n",
769 cmd, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs,
770 len);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800771
Huang Shijiee46ecda2014-02-24 18:37:42 +0800772 /* Read out the data directly from the AHB buffer.*/
Han Xu49bd7062015-08-04 10:25:22 -0500773 memcpy(buf, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs,
774 len);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800775
776 *retlen += len;
777 return 0;
778}
779
780static int fsl_qspi_erase(struct spi_nor *nor, loff_t offs)
781{
782 struct fsl_qspi *q = nor->priv;
783 int ret;
784
785 dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n",
786 nor->mtd->erasesize / 1024, q->chip_base_addr, (u32)offs);
787
Huang Shijiee46ecda2014-02-24 18:37:42 +0800788 ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0);
789 if (ret)
790 return ret;
791
792 fsl_qspi_invalid(q);
793 return 0;
794}
795
796static int fsl_qspi_prep(struct spi_nor *nor, enum spi_nor_ops ops)
797{
798 struct fsl_qspi *q = nor->priv;
799 int ret;
800
Han Xu392d39c2015-05-13 14:40:57 -0500801 mutex_lock(&q->lock);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800802 ret = clk_enable(q->clk_en);
803 if (ret)
Han Xu392d39c2015-05-13 14:40:57 -0500804 goto err_mutex;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800805
806 ret = clk_enable(q->clk);
Han Xu392d39c2015-05-13 14:40:57 -0500807 if (ret)
808 goto err_clk;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800809
810 fsl_qspi_set_base_addr(q, nor);
811 return 0;
Han Xu392d39c2015-05-13 14:40:57 -0500812
813err_clk:
814 clk_disable(q->clk_en);
815err_mutex:
816 mutex_unlock(&q->lock);
817
818 return ret;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800819}
820
821static void fsl_qspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
822{
823 struct fsl_qspi *q = nor->priv;
824
825 clk_disable(q->clk);
826 clk_disable(q->clk_en);
Han Xu392d39c2015-05-13 14:40:57 -0500827 mutex_unlock(&q->lock);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800828}
829
830static int fsl_qspi_probe(struct platform_device *pdev)
831{
832 struct device_node *np = pdev->dev.of_node;
833 struct mtd_part_parser_data ppdata;
834 struct device *dev = &pdev->dev;
835 struct fsl_qspi *q;
836 struct resource *res;
837 struct spi_nor *nor;
838 struct mtd_info *mtd;
839 int ret, i = 0;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800840 const struct of_device_id *of_id =
841 of_match_device(fsl_qspi_dt_ids, &pdev->dev);
842
843 q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL);
844 if (!q)
845 return -ENOMEM;
846
847 q->nor_num = of_get_child_count(dev->of_node);
848 if (!q->nor_num || q->nor_num > FSL_QSPI_MAX_CHIP)
849 return -ENODEV;
850
851 /* find the resources */
852 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI");
853 q->iobase = devm_ioremap_resource(dev, res);
Fabio Estevamb1ab4742015-01-22 22:43:07 -0200854 if (IS_ERR(q->iobase))
855 return PTR_ERR(q->iobase);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800856
857 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
858 "QuadSPI-memory");
Han Xu49bd7062015-08-04 10:25:22 -0500859 if (!devm_request_mem_region(dev, res->start, resource_size(res),
860 res->name)) {
861 dev_err(dev, "can't request region for resource %pR\n", res);
862 return -EBUSY;
863 }
Fabio Estevamb1ab4742015-01-22 22:43:07 -0200864
Huang Shijiee46ecda2014-02-24 18:37:42 +0800865 q->memmap_phy = res->start;
866
867 /* find the clocks */
868 q->clk_en = devm_clk_get(dev, "qspi_en");
Fabio Estevamb1ab4742015-01-22 22:43:07 -0200869 if (IS_ERR(q->clk_en))
870 return PTR_ERR(q->clk_en);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800871
872 q->clk = devm_clk_get(dev, "qspi");
Fabio Estevamb1ab4742015-01-22 22:43:07 -0200873 if (IS_ERR(q->clk))
874 return PTR_ERR(q->clk);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800875
876 ret = clk_prepare_enable(q->clk_en);
877 if (ret) {
Fabio Estevamdc6525c2015-02-09 10:07:19 -0200878 dev_err(dev, "cannot enable the qspi_en clock: %d\n", ret);
Fabio Estevamb1ab4742015-01-22 22:43:07 -0200879 return ret;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800880 }
881
882 ret = clk_prepare_enable(q->clk);
883 if (ret) {
Fabio Estevamdc6525c2015-02-09 10:07:19 -0200884 dev_err(dev, "cannot enable the qspi clock: %d\n", ret);
Fabio Estevam77adc082014-10-17 17:14:01 -0300885 goto clk_failed;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800886 }
887
888 /* find the irq */
889 ret = platform_get_irq(pdev, 0);
890 if (ret < 0) {
Fabio Estevamdc6525c2015-02-09 10:07:19 -0200891 dev_err(dev, "failed to get the irq: %d\n", ret);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800892 goto irq_failed;
893 }
894
895 ret = devm_request_irq(dev, ret,
896 fsl_qspi_irq_handler, 0, pdev->name, q);
897 if (ret) {
Fabio Estevamdc6525c2015-02-09 10:07:19 -0200898 dev_err(dev, "failed to request irq: %d\n", ret);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800899 goto irq_failed;
900 }
901
902 q->dev = dev;
903 q->devtype_data = (struct fsl_qspi_devtype_data *)of_id->data;
904 platform_set_drvdata(pdev, q);
905
906 ret = fsl_qspi_nor_setup(q);
907 if (ret)
908 goto irq_failed;
909
910 if (of_get_property(np, "fsl,qspi-has-second-chip", NULL))
Fabio Estevamcfe4af32015-01-13 20:14:15 -0200911 q->has_second_chip = true;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800912
Han Xu392d39c2015-05-13 14:40:57 -0500913 mutex_init(&q->lock);
914
Huang Shijiee46ecda2014-02-24 18:37:42 +0800915 /* iterate the subnodes. */
916 for_each_available_child_of_node(dev->of_node, np) {
Huang Shijiee46ecda2014-02-24 18:37:42 +0800917 char modalias[40];
918
919 /* skip the holes */
Fabio Estevamcfe4af32015-01-13 20:14:15 -0200920 if (!q->has_second_chip)
Huang Shijiee46ecda2014-02-24 18:37:42 +0800921 i *= 2;
922
923 nor = &q->nor[i];
924 mtd = &q->mtd[i];
925
926 nor->mtd = mtd;
927 nor->dev = dev;
928 nor->priv = q;
929 mtd->priv = nor;
930
931 /* fill the hooks */
932 nor->read_reg = fsl_qspi_read_reg;
933 nor->write_reg = fsl_qspi_write_reg;
934 nor->read = fsl_qspi_read;
935 nor->write = fsl_qspi_write;
936 nor->erase = fsl_qspi_erase;
937
938 nor->prepare = fsl_qspi_prep;
939 nor->unprepare = fsl_qspi_unprep;
940
Fabio Estevamb26171e2014-10-17 15:31:08 -0300941 ret = of_modalias_node(np, modalias, sizeof(modalias));
942 if (ret < 0)
Han Xu392d39c2015-05-13 14:40:57 -0500943 goto mutex_failed;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800944
Huang Shijiee46ecda2014-02-24 18:37:42 +0800945 ret = of_property_read_u32(np, "spi-max-frequency",
946 &q->clk_rate);
947 if (ret < 0)
Han Xu392d39c2015-05-13 14:40:57 -0500948 goto mutex_failed;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800949
950 /* set the chip address for READID */
951 fsl_qspi_set_base_addr(q, nor);
952
Ben Hutchings70f3ce02014-09-29 11:47:54 +0200953 ret = spi_nor_scan(nor, modalias, SPI_NOR_QUAD);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800954 if (ret)
Han Xu392d39c2015-05-13 14:40:57 -0500955 goto mutex_failed;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800956
957 ppdata.of_node = np;
958 ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
959 if (ret)
Han Xu392d39c2015-05-13 14:40:57 -0500960 goto mutex_failed;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800961
962 /* Set the correct NOR size now. */
963 if (q->nor_size == 0) {
964 q->nor_size = mtd->size;
965
966 /* Map the SPI NOR to accessiable address */
967 fsl_qspi_set_map_addr(q);
968 }
969
970 /*
971 * The TX FIFO is 64 bytes in the Vybrid, but the Page Program
972 * may writes 265 bytes per time. The write is working in the
973 * unit of the TX FIFO, not in the unit of the SPI NOR's page
974 * size.
975 *
976 * So shrink the spi_nor->page_size if it is larger then the
977 * TX FIFO.
978 */
979 if (nor->page_size > q->devtype_data->txfifo)
980 nor->page_size = q->devtype_data->txfifo;
981
982 i++;
983 }
984
985 /* finish the rest init. */
986 ret = fsl_qspi_nor_setup_last(q);
987 if (ret)
988 goto last_init_failed;
989
990 clk_disable(q->clk);
991 clk_disable(q->clk_en);
Huang Shijiee46ecda2014-02-24 18:37:42 +0800992 return 0;
993
994last_init_failed:
Fabio Estevamcfe4af32015-01-13 20:14:15 -0200995 for (i = 0; i < q->nor_num; i++) {
996 /* skip the holes */
997 if (!q->has_second_chip)
998 i *= 2;
Huang Shijiee46ecda2014-02-24 18:37:42 +0800999 mtd_device_unregister(&q->mtd[i]);
Fabio Estevamcfe4af32015-01-13 20:14:15 -02001000 }
Han Xu392d39c2015-05-13 14:40:57 -05001001mutex_failed:
1002 mutex_destroy(&q->lock);
Huang Shijiee46ecda2014-02-24 18:37:42 +08001003irq_failed:
1004 clk_disable_unprepare(q->clk);
Fabio Estevam77adc082014-10-17 17:14:01 -03001005clk_failed:
Huang Shijiee46ecda2014-02-24 18:37:42 +08001006 clk_disable_unprepare(q->clk_en);
Huang Shijiee46ecda2014-02-24 18:37:42 +08001007 return ret;
1008}
1009
1010static int fsl_qspi_remove(struct platform_device *pdev)
1011{
1012 struct fsl_qspi *q = platform_get_drvdata(pdev);
1013 int i;
1014
Fabio Estevamcfe4af32015-01-13 20:14:15 -02001015 for (i = 0; i < q->nor_num; i++) {
1016 /* skip the holes */
1017 if (!q->has_second_chip)
1018 i *= 2;
Huang Shijiee46ecda2014-02-24 18:37:42 +08001019 mtd_device_unregister(&q->mtd[i]);
Fabio Estevamcfe4af32015-01-13 20:14:15 -02001020 }
Huang Shijiee46ecda2014-02-24 18:37:42 +08001021
1022 /* disable the hardware */
1023 writel(QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
1024 writel(0x0, q->iobase + QUADSPI_RSER);
1025
Han Xu392d39c2015-05-13 14:40:57 -05001026 mutex_destroy(&q->lock);
Huang Shijiee46ecda2014-02-24 18:37:42 +08001027 clk_unprepare(q->clk);
1028 clk_unprepare(q->clk_en);
Han Xu49bd7062015-08-04 10:25:22 -05001029
1030 if (q->ahb_addr)
1031 iounmap(q->ahb_addr);
1032
Huang Shijiee46ecda2014-02-24 18:37:42 +08001033 return 0;
1034}
1035
Allen Xu45c6a0c2015-01-13 04:56:40 +08001036static int fsl_qspi_suspend(struct platform_device *pdev, pm_message_t state)
1037{
1038 return 0;
1039}
1040
1041static int fsl_qspi_resume(struct platform_device *pdev)
1042{
1043 struct fsl_qspi *q = platform_get_drvdata(pdev);
1044
1045 fsl_qspi_nor_setup(q);
1046 fsl_qspi_set_map_addr(q);
1047 fsl_qspi_nor_setup_last(q);
1048
1049 return 0;
1050}
1051
Huang Shijiee46ecda2014-02-24 18:37:42 +08001052static struct platform_driver fsl_qspi_driver = {
1053 .driver = {
1054 .name = "fsl-quadspi",
1055 .bus = &platform_bus_type,
Huang Shijiee46ecda2014-02-24 18:37:42 +08001056 .of_match_table = fsl_qspi_dt_ids,
1057 },
1058 .probe = fsl_qspi_probe,
1059 .remove = fsl_qspi_remove,
Allen Xu45c6a0c2015-01-13 04:56:40 +08001060 .suspend = fsl_qspi_suspend,
1061 .resume = fsl_qspi_resume,
Huang Shijiee46ecda2014-02-24 18:37:42 +08001062};
1063module_platform_driver(fsl_qspi_driver);
1064
1065MODULE_DESCRIPTION("Freescale QuadSPI Controller Driver");
1066MODULE_AUTHOR("Freescale Semiconductor Inc.");
1067MODULE_LICENSE("GPL v2");