1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
From 2fc26b1b6377156e07c6c9ce934c58f634fcd21b Mon Sep 17 00:00:00 2001
From: Kuldeep Singh <kuldeep.singh@nxp.com>
Date: Wed, 1 Apr 2020 14:51:37 +0800
Subject: [PATCH] LF-18-3 spi: fsl-qspi: Allocate AHB memory dynamically for
imx platforms
LS platforms doesn't require dynamic allocaltion of AHB memory. So, let's
define a quirk which allocates AHB memory dynamically only for imx
platforms.
Fixes: c70adc97("spi: spi-fsl-qspi: dynamically alloc AHB memory for QSPI")
Signed-off-by: Kuldeep Singh <kuldeep.singh@nxp.com>
[rebase]
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
drivers/spi/spi-fsl-qspi.c | 71 +++++++++++++++++++++++++++++++++++-----------
1 file changed, 55 insertions(+), 16 deletions(-)
--- a/drivers/spi/spi-fsl-qspi.c
+++ b/drivers/spi/spi-fsl-qspi.c
@@ -197,6 +197,12 @@
*/
#define QUADSPI_QUIRK_USE_TDH_SETTING BIT(5)
+/*
+ * Use flash size for imx platforms and not for LS platforms. Define a
+ * quirk which enables it only on imx platforms.
+ */
+#define QUADSPI_QUIRK_USE_FLASH_SIZE BIT(6)
+
#define QUADSPI_MIN_IOMAP SZ_4M
struct fsl_qspi_devtype_data {
@@ -213,7 +219,7 @@ static const struct fsl_qspi_devtype_dat
.txfifo = SZ_64,
.invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID,
.ahb_buf_size = SZ_1K,
- .quirks = QUADSPI_QUIRK_SWAP_ENDIAN,
+ .quirks = QUADSPI_QUIRK_SWAP_ENDIAN | QUADSPI_QUIRK_USE_FLASH_SIZE,
.little_endian = true,
};
@@ -222,7 +228,8 @@ static const struct fsl_qspi_devtype_dat
.txfifo = SZ_512,
.invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID,
.ahb_buf_size = SZ_1K,
- .quirks = QUADSPI_QUIRK_4X_INT_CLK | QUADSPI_QUIRK_TKT245618,
+ .quirks = QUADSPI_QUIRK_4X_INT_CLK | QUADSPI_QUIRK_TKT245618 |
+ QUADSPI_QUIRK_USE_FLASH_SIZE,
.little_endian = true,
};
@@ -232,7 +239,7 @@ static const struct fsl_qspi_devtype_dat
.invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID,
.ahb_buf_size = SZ_1K,
.quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK |
- QUADSPI_QUIRK_USE_TDH_SETTING,
+ QUADSPI_QUIRK_USE_TDH_SETTING | QUADSPI_QUIRK_USE_FLASH_SIZE,
.little_endian = true,
};
@@ -242,7 +249,7 @@ static const struct fsl_qspi_devtype_dat
.invalid_mstrid = QUADSPI_BUFXCR_INVALID_MSTRID,
.ahb_buf_size = SZ_1K,
.quirks = QUADSPI_QUIRK_TKT253890 | QUADSPI_QUIRK_4X_INT_CLK |
- QUADSPI_QUIRK_USE_TDH_SETTING,
+ QUADSPI_QUIRK_USE_TDH_SETTING | QUADSPI_QUIRK_USE_FLASH_SIZE,
.little_endian = true,
};
@@ -310,6 +317,11 @@ static inline int needs_tdh_setting(stru
return q->devtype_data->quirks & QUADSPI_QUIRK_USE_TDH_SETTING;
}
+static inline int needs_flash_size(struct fsl_qspi *q)
+{
+ return q->devtype_data->quirks & QUADSPI_QUIRK_USE_FLASH_SIZE;
+}
+
/*
* An IC bug makes it necessary to rearrange the 32-bit data.
* Later chips, such as IMX6SLX, have fixed this bug.
@@ -556,6 +568,14 @@ static void fsl_qspi_select_mem(struct f
static int fsl_qspi_read_ahb(struct fsl_qspi *q, const struct spi_mem_op *op)
{
+ if (!needs_flash_size(q)) {
+ u32 size = q->devtype_data->ahb_buf_size;
+ memcpy_fromio(op->data.buf.in,
+ q->ahb_addr + q->selected * size,
+ op->data.nbytes);
+ return 0;
+ }
+
u32 start = op->addr.val + q->selected * q->memmap_phy_size / 4;
u32 len = op->data.nbytes;
@@ -674,6 +694,7 @@ static int fsl_qspi_exec_op(struct spi_m
u32 addr_offset = 0;
int err = 0;
int invalid_mstrid = q->devtype_data->invalid_mstrid;
+ u32 size = q->devtype_data->ahb_buf_size;
mutex_lock(&q->lock);
@@ -686,8 +707,11 @@ static int fsl_qspi_exec_op(struct spi_m
if (needs_amba_base_offset(q))
addr_offset = q->memmap_phy;
+ if (needs_flash_size(q))
+ size = q->memmap_phy_size / 4;
+
qspi_writel(q,
- q->selected * q->memmap_phy_size / 4 + addr_offset,
+ q->selected * size + addr_offset,
base + QUADSPI_SFAR);
qspi_writel(q, qspi_readl(q, base + QUADSPI_MCR) |
@@ -751,6 +775,7 @@ static int fsl_qspi_default_setup(struct
void __iomem *base = q->iobase;
u32 reg, addr_offset = 0;
int ret;
+ u32 size = q->devtype_data->ahb_buf_size;
/* disable and unprepare clock to avoid glitch pass to controller */
fsl_qspi_clk_disable_unprep(q);
@@ -805,19 +830,22 @@ static int fsl_qspi_default_setup(struct
addr_offset = q->memmap_phy;
/*
- * In HW there can be a maximum of four chips on two buses with
- * two chip selects on each bus. We use four chip selects in SW
- * to differentiate between the four chips.
- * We divide the total memory region size equally for each chip
- * and set SFA1AD, SFA2AD, SFB1AD, SFB2AD accordingly.
+ * In HW there can be a maximum of four chips on two buses with two
+ * chip selects on each bus. We use four chip selects in SW to
+ * differentiate between the four chips. We divide the total memory
+ * region/ahb_buf_size size equally for each chip and set SFA1AD,
+ * SFA2AD, SFB1AD, SFB2AD accordingly.
*/
- qspi_writel(q, q->memmap_phy_size / 4 + addr_offset,
+ if (needs_flash_size(q))
+ size = q->memmap_phy_size / 4;
+
+ qspi_writel(q, size + addr_offset,
base + QUADSPI_SFA1AD);
- qspi_writel(q, q->memmap_phy_size / 4 * 2 + addr_offset,
+ qspi_writel(q, size * 2 + addr_offset,
base + QUADSPI_SFA2AD);
- qspi_writel(q, q->memmap_phy_size / 4 * 3 + addr_offset,
+ qspi_writel(q, size * 3 + addr_offset,
base + QUADSPI_SFB1AD);
- qspi_writel(q, q->memmap_phy_size / 4 * 4 + addr_offset,
+ qspi_writel(q, size * 4 + addr_offset,
base + QUADSPI_SFB2AD);
q->selected = -1;
@@ -904,6 +932,15 @@ static int fsl_qspi_probe(struct platfor
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"QuadSPI-memory");
+
+ if (!needs_flash_size(q)) {
+ q->ahb_addr = devm_ioremap_resource(dev, res);
+ if (IS_ERR(q->ahb_addr)) {
+ ret = PTR_ERR(q->ahb_addr);
+ goto err_put_ctrl;
+ }
+ }
+
q->memmap_phy = res->start;
q->memmap_phy_size = resource_size(res);
@@ -979,8 +1016,10 @@ static int fsl_qspi_remove(struct platfo
mutex_destroy(&q->lock);
- if (q->ahb_addr)
- iounmap(q->ahb_addr);
+ if (needs_flash_size(q)) {
+ if (q->ahb_addr)
+ iounmap(q->ahb_addr);
+ }
return 0;
}
|