]>
Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
ceb720c7 CLG |
2 | /* |
3 | * ASPEED Static Memory Controller driver | |
4 | * | |
5 | * Copyright (c) 2015-2016, IBM Corporation. | |
ceb720c7 CLG |
6 | */ |
7 | ||
8 | #include <linux/bug.h> | |
9 | #include <linux/device.h> | |
10 | #include <linux/io.h> | |
11 | #include <linux/module.h> | |
12 | #include <linux/mutex.h> | |
13 | #include <linux/mtd/mtd.h> | |
14 | #include <linux/mtd/partitions.h> | |
15 | #include <linux/mtd/spi-nor.h> | |
16 | #include <linux/of.h> | |
17 | #include <linux/of_platform.h> | |
7ef0e5e1 | 18 | #include <linux/sizes.h> |
ceb720c7 CLG |
19 | #include <linux/sysfs.h> |
20 | ||
21 | #define DEVICE_NAME "aspeed-smc" | |
22 | ||
23 | /* | |
24 | * The driver only support SPI flash | |
25 | */ | |
26 | enum aspeed_smc_flash_type { | |
27 | smc_type_nor = 0, | |
28 | smc_type_nand = 1, | |
29 | smc_type_spi = 2, | |
30 | }; | |
31 | ||
32 | struct aspeed_smc_chip; | |
33 | ||
34 | struct aspeed_smc_info { | |
35 | u32 maxsize; /* maximum size of chip window */ | |
36 | u8 nce; /* number of chip enables */ | |
37 | bool hastype; /* flash type field exists in config reg */ | |
38 | u8 we0; /* shift for write enable bit for CE0 */ | |
39 | u8 ctl0; /* offset in regs of ctl for CE0 */ | |
40 | ||
41 | void (*set_4b)(struct aspeed_smc_chip *chip); | |
42 | }; | |
43 | ||
e56beebb | 44 | static void aspeed_smc_chip_set_4b_spi_2400(struct aspeed_smc_chip *chip); |
ceb720c7 CLG |
45 | static void aspeed_smc_chip_set_4b(struct aspeed_smc_chip *chip); |
46 | ||
e56beebb CLG |
47 | static const struct aspeed_smc_info fmc_2400_info = { |
48 | .maxsize = 64 * 1024 * 1024, | |
49 | .nce = 5, | |
50 | .hastype = true, | |
51 | .we0 = 16, | |
52 | .ctl0 = 0x10, | |
53 | .set_4b = aspeed_smc_chip_set_4b, | |
54 | }; | |
55 | ||
56 | static const struct aspeed_smc_info spi_2400_info = { | |
57 | .maxsize = 64 * 1024 * 1024, | |
58 | .nce = 1, | |
59 | .hastype = false, | |
60 | .we0 = 0, | |
61 | .ctl0 = 0x04, | |
62 | .set_4b = aspeed_smc_chip_set_4b_spi_2400, | |
63 | }; | |
64 | ||
ceb720c7 CLG |
65 | static const struct aspeed_smc_info fmc_2500_info = { |
66 | .maxsize = 256 * 1024 * 1024, | |
67 | .nce = 3, | |
68 | .hastype = true, | |
69 | .we0 = 16, | |
70 | .ctl0 = 0x10, | |
71 | .set_4b = aspeed_smc_chip_set_4b, | |
72 | }; | |
73 | ||
74 | static const struct aspeed_smc_info spi_2500_info = { | |
75 | .maxsize = 128 * 1024 * 1024, | |
76 | .nce = 2, | |
77 | .hastype = false, | |
78 | .we0 = 16, | |
79 | .ctl0 = 0x10, | |
80 | .set_4b = aspeed_smc_chip_set_4b, | |
81 | }; | |
82 | ||
83 | enum aspeed_smc_ctl_reg_value { | |
84 | smc_base, /* base value without mode for other commands */ | |
85 | smc_read, /* command reg for (maybe fast) reads */ | |
86 | smc_write, /* command reg for writes */ | |
87 | smc_max, | |
88 | }; | |
89 | ||
90 | struct aspeed_smc_controller; | |
91 | ||
92 | struct aspeed_smc_chip { | |
93 | int cs; | |
94 | struct aspeed_smc_controller *controller; | |
95 | void __iomem *ctl; /* control register */ | |
96 | void __iomem *ahb_base; /* base of chip window */ | |
7ef0e5e1 | 97 | u32 ahb_window_size; /* chip mapping window size */ |
ceb720c7 CLG |
98 | u32 ctl_val[smc_max]; /* control settings */ |
99 | enum aspeed_smc_flash_type type; /* what type of flash */ | |
100 | struct spi_nor nor; | |
101 | }; | |
102 | ||
103 | struct aspeed_smc_controller { | |
104 | struct device *dev; | |
105 | ||
106 | struct mutex mutex; /* controller access mutex */ | |
107 | const struct aspeed_smc_info *info; /* type info of controller */ | |
108 | void __iomem *regs; /* controller registers */ | |
109 | void __iomem *ahb_base; /* per-chip windows resource */ | |
7ef0e5e1 | 110 | u32 ahb_window_size; /* full mapping window size */ |
ceb720c7 CLG |
111 | |
112 | struct aspeed_smc_chip *chips[0]; /* pointers to attached chips */ | |
113 | }; | |
114 | ||
115 | /* | |
116 | * SPI Flash Configuration Register (AST2500 SPI) | |
117 | * or | |
118 | * Type setting Register (AST2500 FMC). | |
119 | * CE0 and CE1 can only be of type SPI. CE2 can be of type NOR but the | |
120 | * driver does not support it. | |
121 | */ | |
122 | #define CONFIG_REG 0x0 | |
123 | #define CONFIG_DISABLE_LEGACY BIT(31) /* 1 */ | |
124 | ||
125 | #define CONFIG_CE2_WRITE BIT(18) | |
126 | #define CONFIG_CE1_WRITE BIT(17) | |
127 | #define CONFIG_CE0_WRITE BIT(16) | |
128 | ||
129 | #define CONFIG_CE2_TYPE BIT(4) /* AST2500 FMC only */ | |
130 | #define CONFIG_CE1_TYPE BIT(2) /* AST2500 FMC only */ | |
131 | #define CONFIG_CE0_TYPE BIT(0) /* AST2500 FMC only */ | |
132 | ||
133 | /* | |
134 | * CE Control Register | |
135 | */ | |
136 | #define CE_CONTROL_REG 0x4 | |
137 | ||
138 | /* | |
139 | * CEx Control Register | |
140 | */ | |
141 | #define CONTROL_AAF_MODE BIT(31) | |
142 | #define CONTROL_IO_MODE_MASK GENMASK(30, 28) | |
143 | #define CONTROL_IO_DUAL_DATA BIT(29) | |
144 | #define CONTROL_IO_DUAL_ADDR_DATA (BIT(29) | BIT(28)) | |
145 | #define CONTROL_IO_QUAD_DATA BIT(30) | |
146 | #define CONTROL_IO_QUAD_ADDR_DATA (BIT(30) | BIT(28)) | |
147 | #define CONTROL_CE_INACTIVE_SHIFT 24 | |
148 | #define CONTROL_CE_INACTIVE_MASK GENMASK(27, \ | |
149 | CONTROL_CE_INACTIVE_SHIFT) | |
150 | /* 0 = 16T ... 15 = 1T T=HCLK */ | |
151 | #define CONTROL_COMMAND_SHIFT 16 | |
152 | #define CONTROL_DUMMY_COMMAND_OUT BIT(15) | |
153 | #define CONTROL_IO_DUMMY_HI BIT(14) | |
154 | #define CONTROL_IO_DUMMY_HI_SHIFT 14 | |
155 | #define CONTROL_CLK_DIV4 BIT(13) /* others */ | |
e56beebb | 156 | #define CONTROL_IO_ADDRESS_4B BIT(13) /* AST2400 SPI */ |
ceb720c7 CLG |
157 | #define CONTROL_RW_MERGE BIT(12) |
158 | #define CONTROL_IO_DUMMY_LO_SHIFT 6 | |
159 | #define CONTROL_IO_DUMMY_LO GENMASK(7, \ | |
160 | CONTROL_IO_DUMMY_LO_SHIFT) | |
161 | #define CONTROL_IO_DUMMY_MASK (CONTROL_IO_DUMMY_HI | \ | |
162 | CONTROL_IO_DUMMY_LO) | |
163 | #define CONTROL_IO_DUMMY_SET(dummy) \ | |
164 | (((((dummy) >> 2) & 0x1) << CONTROL_IO_DUMMY_HI_SHIFT) | \ | |
165 | (((dummy) & 0x3) << CONTROL_IO_DUMMY_LO_SHIFT)) | |
166 | ||
167 | #define CONTROL_CLOCK_FREQ_SEL_SHIFT 8 | |
168 | #define CONTROL_CLOCK_FREQ_SEL_MASK GENMASK(11, \ | |
169 | CONTROL_CLOCK_FREQ_SEL_SHIFT) | |
170 | #define CONTROL_LSB_FIRST BIT(5) | |
171 | #define CONTROL_CLOCK_MODE_3 BIT(4) | |
172 | #define CONTROL_IN_DUAL_DATA BIT(3) | |
173 | #define CONTROL_CE_STOP_ACTIVE_CONTROL BIT(2) | |
174 | #define CONTROL_COMMAND_MODE_MASK GENMASK(1, 0) | |
175 | #define CONTROL_COMMAND_MODE_NORMAL 0 | |
176 | #define CONTROL_COMMAND_MODE_FREAD 1 | |
177 | #define CONTROL_COMMAND_MODE_WRITE 2 | |
178 | #define CONTROL_COMMAND_MODE_USER 3 | |
179 | ||
180 | #define CONTROL_KEEP_MASK \ | |
181 | (CONTROL_AAF_MODE | CONTROL_CE_INACTIVE_MASK | CONTROL_CLK_DIV4 | \ | |
a9f127bb | 182 | CONTROL_CLOCK_FREQ_SEL_MASK | CONTROL_LSB_FIRST | CONTROL_CLOCK_MODE_3) |
ceb720c7 CLG |
183 | |
184 | /* | |
185 | * The Segment Register uses a 8MB unit to encode the start address | |
186 | * and the end address of the mapping window of a flash SPI slave : | |
187 | * | |
188 | * | byte 1 | byte 2 | byte 3 | byte 4 | | |
189 | * +--------+--------+--------+--------+ | |
190 | * | end | start | 0 | 0 | | |
191 | */ | |
192 | #define SEGMENT_ADDR_REG0 0x30 | |
193 | #define SEGMENT_ADDR_START(_r) ((((_r) >> 16) & 0xFF) << 23) | |
194 | #define SEGMENT_ADDR_END(_r) ((((_r) >> 24) & 0xFF) << 23) | |
7ef0e5e1 CLG |
195 | #define SEGMENT_ADDR_VALUE(start, end) \ |
196 | (((((start) >> 23) & 0xFF) << 16) | ((((end) >> 23) & 0xFF) << 24)) | |
197 | #define SEGMENT_ADDR_REG(controller, cs) \ | |
198 | ((controller)->regs + SEGMENT_ADDR_REG0 + (cs) * 4) | |
ceb720c7 CLG |
199 | |
200 | /* | |
201 | * In user mode all data bytes read or written to the chip decode address | |
202 | * range are transferred to or from the SPI bus. The range is treated as a | |
203 | * fifo of arbitratry 1, 2, or 4 byte width but each write has to be aligned | |
204 | * to its size. The address within the multiple 8kB range is ignored when | |
205 | * sending bytes to the SPI bus. | |
206 | * | |
207 | * On the arm architecture, as of Linux version 4.3, memcpy_fromio and | |
208 | * memcpy_toio on little endian targets use the optimized memcpy routines | |
209 | * that were designed for well behavied memory storage. These routines | |
210 | * have a stutter if the source and destination are not both word aligned, | |
211 | * once with a duplicate access to the source after aligning to the | |
212 | * destination to a word boundary, and again with a duplicate access to | |
213 | * the source when the final byte count is not word aligned. | |
214 | * | |
215 | * When writing or reading the fifo this stutter discards data or sends | |
216 | * too much data to the fifo and can not be used by this driver. | |
217 | * | |
218 | * While the low level io string routines that implement the insl family do | |
219 | * the desired accesses and memory increments, the cross architecture io | |
220 | * macros make them essentially impossible to use on a memory mapped address | |
221 | * instead of a a token from the call to iomap of an io port. | |
222 | * | |
223 | * These fifo routines use readl and friends to a constant io port and update | |
224 | * the memory buffer pointer and count via explicit code. The final updates | |
225 | * to len are optimistically suppressed. | |
226 | */ | |
f40a2725 | 227 | static int aspeed_smc_read_from_ahb(void *buf, void __iomem *src, size_t len) |
ceb720c7 CLG |
228 | { |
229 | size_t offset = 0; | |
230 | ||
231 | if (IS_ALIGNED((uintptr_t)src, sizeof(uintptr_t)) && | |
232 | IS_ALIGNED((uintptr_t)buf, sizeof(uintptr_t))) { | |
233 | ioread32_rep(src, buf, len >> 2); | |
234 | offset = len & ~0x3; | |
235 | len -= offset; | |
236 | } | |
237 | ioread8_rep(src, (u8 *)buf + offset, len); | |
238 | return 0; | |
239 | } | |
240 | ||
241 | static int aspeed_smc_write_to_ahb(void __iomem *dst, const void *buf, | |
242 | size_t len) | |
243 | { | |
244 | size_t offset = 0; | |
245 | ||
246 | if (IS_ALIGNED((uintptr_t)dst, sizeof(uintptr_t)) && | |
247 | IS_ALIGNED((uintptr_t)buf, sizeof(uintptr_t))) { | |
248 | iowrite32_rep(dst, buf, len >> 2); | |
249 | offset = len & ~0x3; | |
250 | len -= offset; | |
251 | } | |
252 | iowrite8_rep(dst, (const u8 *)buf + offset, len); | |
253 | return 0; | |
254 | } | |
255 | ||
256 | static inline u32 aspeed_smc_chip_write_bit(struct aspeed_smc_chip *chip) | |
257 | { | |
258 | return BIT(chip->controller->info->we0 + chip->cs); | |
259 | } | |
260 | ||
261 | static void aspeed_smc_chip_check_config(struct aspeed_smc_chip *chip) | |
262 | { | |
263 | struct aspeed_smc_controller *controller = chip->controller; | |
264 | u32 reg; | |
265 | ||
266 | reg = readl(controller->regs + CONFIG_REG); | |
267 | ||
268 | if (reg & aspeed_smc_chip_write_bit(chip)) | |
269 | return; | |
270 | ||
271 | dev_dbg(controller->dev, "config write is not set ! @%p: 0x%08x\n", | |
272 | controller->regs + CONFIG_REG, reg); | |
273 | reg |= aspeed_smc_chip_write_bit(chip); | |
274 | writel(reg, controller->regs + CONFIG_REG); | |
275 | } | |
276 | ||
277 | static void aspeed_smc_start_user(struct spi_nor *nor) | |
278 | { | |
279 | struct aspeed_smc_chip *chip = nor->priv; | |
280 | u32 ctl = chip->ctl_val[smc_base]; | |
281 | ||
282 | /* | |
283 | * When the chip is controlled in user mode, we need write | |
284 | * access to send the opcodes to it. So check the config. | |
285 | */ | |
286 | aspeed_smc_chip_check_config(chip); | |
287 | ||
288 | ctl |= CONTROL_COMMAND_MODE_USER | | |
289 | CONTROL_CE_STOP_ACTIVE_CONTROL; | |
290 | writel(ctl, chip->ctl); | |
291 | ||
292 | ctl &= ~CONTROL_CE_STOP_ACTIVE_CONTROL; | |
293 | writel(ctl, chip->ctl); | |
294 | } | |
295 | ||
296 | static void aspeed_smc_stop_user(struct spi_nor *nor) | |
297 | { | |
298 | struct aspeed_smc_chip *chip = nor->priv; | |
299 | ||
300 | u32 ctl = chip->ctl_val[smc_read]; | |
301 | u32 ctl2 = ctl | CONTROL_COMMAND_MODE_USER | | |
302 | CONTROL_CE_STOP_ACTIVE_CONTROL; | |
303 | ||
304 | writel(ctl2, chip->ctl); /* stop user CE control */ | |
305 | writel(ctl, chip->ctl); /* default to fread or read mode */ | |
306 | } | |
307 | ||
308 | static int aspeed_smc_prep(struct spi_nor *nor, enum spi_nor_ops ops) | |
309 | { | |
310 | struct aspeed_smc_chip *chip = nor->priv; | |
311 | ||
312 | mutex_lock(&chip->controller->mutex); | |
313 | return 0; | |
314 | } | |
315 | ||
316 | static void aspeed_smc_unprep(struct spi_nor *nor, enum spi_nor_ops ops) | |
317 | { | |
318 | struct aspeed_smc_chip *chip = nor->priv; | |
319 | ||
320 | mutex_unlock(&chip->controller->mutex); | |
321 | } | |
322 | ||
323 | static int aspeed_smc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) | |
324 | { | |
325 | struct aspeed_smc_chip *chip = nor->priv; | |
326 | ||
327 | aspeed_smc_start_user(nor); | |
328 | aspeed_smc_write_to_ahb(chip->ahb_base, &opcode, 1); | |
329 | aspeed_smc_read_from_ahb(buf, chip->ahb_base, len); | |
330 | aspeed_smc_stop_user(nor); | |
331 | return 0; | |
332 | } | |
333 | ||
334 | static int aspeed_smc_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, | |
335 | int len) | |
336 | { | |
337 | struct aspeed_smc_chip *chip = nor->priv; | |
338 | ||
339 | aspeed_smc_start_user(nor); | |
340 | aspeed_smc_write_to_ahb(chip->ahb_base, &opcode, 1); | |
341 | aspeed_smc_write_to_ahb(chip->ahb_base, buf, len); | |
342 | aspeed_smc_stop_user(nor); | |
343 | return 0; | |
344 | } | |
345 | ||
346 | static void aspeed_smc_send_cmd_addr(struct spi_nor *nor, u8 cmd, u32 addr) | |
347 | { | |
348 | struct aspeed_smc_chip *chip = nor->priv; | |
349 | __be32 temp; | |
350 | u32 cmdaddr; | |
351 | ||
352 | switch (nor->addr_width) { | |
353 | default: | |
354 | WARN_ONCE(1, "Unexpected address width %u, defaulting to 3\n", | |
355 | nor->addr_width); | |
356 | /* FALLTHROUGH */ | |
357 | case 3: | |
358 | cmdaddr = addr & 0xFFFFFF; | |
359 | cmdaddr |= cmd << 24; | |
360 | ||
361 | temp = cpu_to_be32(cmdaddr); | |
362 | aspeed_smc_write_to_ahb(chip->ahb_base, &temp, 4); | |
363 | break; | |
364 | case 4: | |
365 | temp = cpu_to_be32(addr); | |
366 | aspeed_smc_write_to_ahb(chip->ahb_base, &cmd, 1); | |
367 | aspeed_smc_write_to_ahb(chip->ahb_base, &temp, 4); | |
368 | break; | |
369 | } | |
370 | } | |
371 | ||
372 | static ssize_t aspeed_smc_read_user(struct spi_nor *nor, loff_t from, | |
373 | size_t len, u_char *read_buf) | |
374 | { | |
375 | struct aspeed_smc_chip *chip = nor->priv; | |
376 | int i; | |
377 | u8 dummy = 0xFF; | |
378 | ||
379 | aspeed_smc_start_user(nor); | |
380 | aspeed_smc_send_cmd_addr(nor, nor->read_opcode, from); | |
381 | for (i = 0; i < chip->nor.read_dummy / 8; i++) | |
382 | aspeed_smc_write_to_ahb(chip->ahb_base, &dummy, sizeof(dummy)); | |
383 | ||
384 | aspeed_smc_read_from_ahb(read_buf, chip->ahb_base, len); | |
385 | aspeed_smc_stop_user(nor); | |
386 | return len; | |
387 | } | |
388 | ||
389 | static ssize_t aspeed_smc_write_user(struct spi_nor *nor, loff_t to, | |
390 | size_t len, const u_char *write_buf) | |
391 | { | |
392 | struct aspeed_smc_chip *chip = nor->priv; | |
393 | ||
394 | aspeed_smc_start_user(nor); | |
395 | aspeed_smc_send_cmd_addr(nor, nor->program_opcode, to); | |
396 | aspeed_smc_write_to_ahb(chip->ahb_base, write_buf, len); | |
397 | aspeed_smc_stop_user(nor); | |
398 | return len; | |
399 | } | |
400 | ||
401 | static int aspeed_smc_unregister(struct aspeed_smc_controller *controller) | |
402 | { | |
403 | struct aspeed_smc_chip *chip; | |
404 | int n; | |
405 | ||
406 | for (n = 0; n < controller->info->nce; n++) { | |
407 | chip = controller->chips[n]; | |
408 | if (chip) | |
409 | mtd_device_unregister(&chip->nor.mtd); | |
410 | } | |
411 | ||
412 | return 0; | |
413 | } | |
414 | ||
415 | static int aspeed_smc_remove(struct platform_device *dev) | |
416 | { | |
417 | return aspeed_smc_unregister(platform_get_drvdata(dev)); | |
418 | } | |
419 | ||
420 | static const struct of_device_id aspeed_smc_matches[] = { | |
e56beebb CLG |
421 | { .compatible = "aspeed,ast2400-fmc", .data = &fmc_2400_info }, |
422 | { .compatible = "aspeed,ast2400-spi", .data = &spi_2400_info }, | |
ceb720c7 CLG |
423 | { .compatible = "aspeed,ast2500-fmc", .data = &fmc_2500_info }, |
424 | { .compatible = "aspeed,ast2500-spi", .data = &spi_2500_info }, | |
425 | { } | |
426 | }; | |
427 | MODULE_DEVICE_TABLE(of, aspeed_smc_matches); | |
428 | ||
429 | /* | |
430 | * Each chip has a mapping window defined by a segment address | |
431 | * register defining a start and an end address on the AHB bus. These | |
432 | * addresses can be configured to fit the chip size and offer a | |
433 | * contiguous memory region across chips. For the moment, we only | |
434 | * check that each chip segment is valid. | |
435 | */ | |
436 | static void __iomem *aspeed_smc_chip_base(struct aspeed_smc_chip *chip, | |
437 | struct resource *res) | |
438 | { | |
439 | struct aspeed_smc_controller *controller = chip->controller; | |
440 | u32 offset = 0; | |
441 | u32 reg; | |
442 | ||
443 | if (controller->info->nce > 1) { | |
7ef0e5e1 | 444 | reg = readl(SEGMENT_ADDR_REG(controller, chip->cs)); |
ceb720c7 CLG |
445 | |
446 | if (SEGMENT_ADDR_START(reg) >= SEGMENT_ADDR_END(reg)) | |
447 | return NULL; | |
448 | ||
449 | offset = SEGMENT_ADDR_START(reg) - res->start; | |
450 | } | |
451 | ||
452 | return controller->ahb_base + offset; | |
453 | } | |
454 | ||
7ef0e5e1 CLG |
455 | static u32 aspeed_smc_ahb_base_phy(struct aspeed_smc_controller *controller) |
456 | { | |
457 | u32 seg0_val = readl(SEGMENT_ADDR_REG(controller, 0)); | |
458 | ||
459 | return SEGMENT_ADDR_START(seg0_val); | |
460 | } | |
461 | ||
462 | static u32 chip_set_segment(struct aspeed_smc_chip *chip, u32 cs, u32 start, | |
463 | u32 size) | |
464 | { | |
465 | struct aspeed_smc_controller *controller = chip->controller; | |
466 | void __iomem *seg_reg; | |
467 | u32 seg_oldval, seg_newval, ahb_base_phy, end; | |
468 | ||
469 | ahb_base_phy = aspeed_smc_ahb_base_phy(controller); | |
470 | ||
471 | seg_reg = SEGMENT_ADDR_REG(controller, cs); | |
472 | seg_oldval = readl(seg_reg); | |
473 | ||
474 | /* | |
475 | * If the chip size is not specified, use the default segment | |
476 | * size, but take into account the possible overlap with the | |
477 | * previous segment | |
478 | */ | |
479 | if (!size) | |
480 | size = SEGMENT_ADDR_END(seg_oldval) - start; | |
481 | ||
482 | /* | |
483 | * The segment cannot exceed the maximum window size of the | |
484 | * controller. | |
485 | */ | |
486 | if (start + size > ahb_base_phy + controller->ahb_window_size) { | |
487 | size = ahb_base_phy + controller->ahb_window_size - start; | |
488 | dev_warn(chip->nor.dev, "CE%d window resized to %dMB", | |
489 | cs, size >> 20); | |
490 | } | |
491 | ||
492 | end = start + size; | |
493 | seg_newval = SEGMENT_ADDR_VALUE(start, end); | |
494 | writel(seg_newval, seg_reg); | |
495 | ||
496 | /* | |
497 | * Restore default value if something goes wrong. The chip | |
498 | * might have set some bogus value and we would loose access | |
499 | * to the chip. | |
500 | */ | |
501 | if (seg_newval != readl(seg_reg)) { | |
502 | dev_err(chip->nor.dev, "CE%d window invalid", cs); | |
503 | writel(seg_oldval, seg_reg); | |
504 | start = SEGMENT_ADDR_START(seg_oldval); | |
505 | end = SEGMENT_ADDR_END(seg_oldval); | |
506 | size = end - start; | |
507 | } | |
508 | ||
509 | dev_info(chip->nor.dev, "CE%d window [ 0x%.8x - 0x%.8x ] %dMB", | |
510 | cs, start, end, size >> 20); | |
511 | ||
512 | return size; | |
513 | } | |
514 | ||
515 | /* | |
516 | * The segment register defines the mapping window on the AHB bus and | |
517 | * it needs to be configured depending on the chip size. The segment | |
518 | * register of the following CE also needs to be tuned in order to | |
519 | * provide a contiguous window across multiple chips. | |
520 | * | |
521 | * This is expected to be called in increasing CE order | |
522 | */ | |
523 | static u32 aspeed_smc_chip_set_segment(struct aspeed_smc_chip *chip) | |
524 | { | |
525 | struct aspeed_smc_controller *controller = chip->controller; | |
526 | u32 ahb_base_phy, start; | |
527 | u32 size = chip->nor.mtd.size; | |
528 | ||
529 | /* | |
530 | * Each controller has a chip size limit for direct memory | |
531 | * access | |
532 | */ | |
533 | if (size > controller->info->maxsize) | |
534 | size = controller->info->maxsize; | |
535 | ||
536 | /* | |
537 | * The AST2400 SPI controller only handles one chip and does | |
538 | * not have segment registers. Let's use the chip size for the | |
539 | * AHB window. | |
540 | */ | |
541 | if (controller->info == &spi_2400_info) | |
542 | goto out; | |
543 | ||
544 | /* | |
545 | * The AST2500 SPI controller has a HW bug when the CE0 chip | |
546 | * size reaches 128MB. Enforce a size limit of 120MB to | |
547 | * prevent the controller from using bogus settings in the | |
548 | * segment register. | |
549 | */ | |
550 | if (chip->cs == 0 && controller->info == &spi_2500_info && | |
551 | size == SZ_128M) { | |
552 | size = 120 << 20; | |
553 | dev_info(chip->nor.dev, | |
554 | "CE%d window resized to %dMB (AST2500 HW quirk)", | |
555 | chip->cs, size >> 20); | |
556 | } | |
557 | ||
558 | ahb_base_phy = aspeed_smc_ahb_base_phy(controller); | |
559 | ||
560 | /* | |
561 | * As a start address for the current segment, use the default | |
562 | * start address if we are handling CE0 or use the previous | |
563 | * segment ending address | |
564 | */ | |
565 | if (chip->cs) { | |
566 | u32 prev = readl(SEGMENT_ADDR_REG(controller, chip->cs - 1)); | |
567 | ||
568 | start = SEGMENT_ADDR_END(prev); | |
569 | } else { | |
570 | start = ahb_base_phy; | |
571 | } | |
572 | ||
573 | size = chip_set_segment(chip, chip->cs, start, size); | |
574 | ||
575 | /* Update chip base address on the AHB bus */ | |
576 | chip->ahb_base = controller->ahb_base + (start - ahb_base_phy); | |
577 | ||
578 | /* | |
579 | * Now, make sure the next segment does not overlap with the | |
580 | * current one we just configured, even if there is no | |
581 | * available chip. That could break access in Command Mode. | |
582 | */ | |
583 | if (chip->cs < controller->info->nce - 1) | |
584 | chip_set_segment(chip, chip->cs + 1, start + size, 0); | |
585 | ||
586 | out: | |
587 | if (size < chip->nor.mtd.size) | |
588 | dev_warn(chip->nor.dev, | |
589 | "CE%d window too small for chip %dMB", | |
590 | chip->cs, (u32)chip->nor.mtd.size >> 20); | |
591 | ||
592 | return size; | |
593 | } | |
594 | ||
ceb720c7 CLG |
595 | static void aspeed_smc_chip_enable_write(struct aspeed_smc_chip *chip) |
596 | { | |
597 | struct aspeed_smc_controller *controller = chip->controller; | |
598 | u32 reg; | |
599 | ||
600 | reg = readl(controller->regs + CONFIG_REG); | |
601 | ||
602 | reg |= aspeed_smc_chip_write_bit(chip); | |
603 | writel(reg, controller->regs + CONFIG_REG); | |
604 | } | |
605 | ||
606 | static void aspeed_smc_chip_set_type(struct aspeed_smc_chip *chip, int type) | |
607 | { | |
608 | struct aspeed_smc_controller *controller = chip->controller; | |
609 | u32 reg; | |
610 | ||
611 | chip->type = type; | |
612 | ||
613 | reg = readl(controller->regs + CONFIG_REG); | |
614 | reg &= ~(3 << (chip->cs * 2)); | |
615 | reg |= chip->type << (chip->cs * 2); | |
616 | writel(reg, controller->regs + CONFIG_REG); | |
617 | } | |
618 | ||
619 | /* | |
811cb897 CLG |
620 | * The first chip of the AST2500 FMC flash controller is strapped by |
621 | * hardware, or autodetected, but other chips need to be set. Enforce | |
622 | * the 4B setting for all chips. | |
ceb720c7 CLG |
623 | */ |
624 | static void aspeed_smc_chip_set_4b(struct aspeed_smc_chip *chip) | |
625 | { | |
626 | struct aspeed_smc_controller *controller = chip->controller; | |
627 | u32 reg; | |
628 | ||
811cb897 CLG |
629 | reg = readl(controller->regs + CE_CONTROL_REG); |
630 | reg |= 1 << chip->cs; | |
631 | writel(reg, controller->regs + CE_CONTROL_REG); | |
ceb720c7 CLG |
632 | } |
633 | ||
e56beebb CLG |
634 | /* |
635 | * The AST2400 SPI flash controller does not have a CE Control | |
636 | * register. It uses the CE0 control register to set 4Byte mode at the | |
637 | * controller level. | |
638 | */ | |
639 | static void aspeed_smc_chip_set_4b_spi_2400(struct aspeed_smc_chip *chip) | |
640 | { | |
641 | chip->ctl_val[smc_base] |= CONTROL_IO_ADDRESS_4B; | |
642 | chip->ctl_val[smc_read] |= CONTROL_IO_ADDRESS_4B; | |
643 | } | |
644 | ||
ceb720c7 CLG |
645 | static int aspeed_smc_chip_setup_init(struct aspeed_smc_chip *chip, |
646 | struct resource *res) | |
647 | { | |
648 | struct aspeed_smc_controller *controller = chip->controller; | |
649 | const struct aspeed_smc_info *info = controller->info; | |
650 | u32 reg, base_reg; | |
651 | ||
652 | /* | |
653 | * Always turn on the write enable bit to allow opcodes to be | |
654 | * sent in user mode. | |
655 | */ | |
656 | aspeed_smc_chip_enable_write(chip); | |
657 | ||
658 | /* The driver only supports SPI type flash */ | |
659 | if (info->hastype) | |
660 | aspeed_smc_chip_set_type(chip, smc_type_spi); | |
661 | ||
662 | /* | |
663 | * Configure chip base address in memory | |
664 | */ | |
665 | chip->ahb_base = aspeed_smc_chip_base(chip, res); | |
666 | if (!chip->ahb_base) { | |
7ef0e5e1 | 667 | dev_warn(chip->nor.dev, "CE%d window closed", chip->cs); |
ceb720c7 CLG |
668 | return -EINVAL; |
669 | } | |
670 | ||
671 | /* | |
672 | * Get value of the inherited control register. U-Boot usually | |
673 | * does some timing calibration on the FMC chip, so it's good | |
674 | * to keep them. In the future, we should handle calibration | |
675 | * from Linux. | |
676 | */ | |
677 | reg = readl(chip->ctl); | |
678 | dev_dbg(controller->dev, "control register: %08x\n", reg); | |
679 | ||
680 | base_reg = reg & CONTROL_KEEP_MASK; | |
681 | if (base_reg != reg) { | |
682 | dev_dbg(controller->dev, | |
683 | "control register changed to: %08x\n", | |
684 | base_reg); | |
685 | } | |
686 | chip->ctl_val[smc_base] = base_reg; | |
687 | ||
688 | /* | |
689 | * Retain the prior value of the control register as the | |
690 | * default if it was normal access mode. Otherwise start with | |
691 | * the sanitized base value set to read mode. | |
692 | */ | |
693 | if ((reg & CONTROL_COMMAND_MODE_MASK) == | |
694 | CONTROL_COMMAND_MODE_NORMAL) | |
695 | chip->ctl_val[smc_read] = reg; | |
696 | else | |
697 | chip->ctl_val[smc_read] = chip->ctl_val[smc_base] | | |
698 | CONTROL_COMMAND_MODE_NORMAL; | |
699 | ||
700 | dev_dbg(controller->dev, "default control register: %08x\n", | |
701 | chip->ctl_val[smc_read]); | |
702 | return 0; | |
703 | } | |
704 | ||
705 | static int aspeed_smc_chip_setup_finish(struct aspeed_smc_chip *chip) | |
706 | { | |
707 | struct aspeed_smc_controller *controller = chip->controller; | |
708 | const struct aspeed_smc_info *info = controller->info; | |
709 | u32 cmd; | |
710 | ||
711 | if (chip->nor.addr_width == 4 && info->set_4b) | |
712 | info->set_4b(chip); | |
713 | ||
7ef0e5e1 CLG |
714 | /* This is for direct AHB access when using Command Mode. */ |
715 | chip->ahb_window_size = aspeed_smc_chip_set_segment(chip); | |
716 | ||
ceb720c7 CLG |
717 | /* |
718 | * base mode has not been optimized yet. use it for writes. | |
719 | */ | |
720 | chip->ctl_val[smc_write] = chip->ctl_val[smc_base] | | |
721 | chip->nor.program_opcode << CONTROL_COMMAND_SHIFT | | |
722 | CONTROL_COMMAND_MODE_WRITE; | |
723 | ||
724 | dev_dbg(controller->dev, "write control register: %08x\n", | |
725 | chip->ctl_val[smc_write]); | |
726 | ||
727 | /* | |
728 | * TODO: Adjust clocks if fast read is supported and interpret | |
729 | * SPI-NOR flags to adjust controller settings. | |
730 | */ | |
cfc5604c CP |
731 | if (chip->nor.read_proto == SNOR_PROTO_1_1_1) { |
732 | if (chip->nor.read_dummy == 0) | |
733 | cmd = CONTROL_COMMAND_MODE_NORMAL; | |
734 | else | |
735 | cmd = CONTROL_COMMAND_MODE_FREAD; | |
736 | } else { | |
ceb720c7 CLG |
737 | dev_err(chip->nor.dev, "unsupported SPI read mode\n"); |
738 | return -EINVAL; | |
739 | } | |
740 | ||
741 | chip->ctl_val[smc_read] |= cmd | | |
742 | CONTROL_IO_DUMMY_SET(chip->nor.read_dummy / 8); | |
743 | ||
744 | dev_dbg(controller->dev, "base control register: %08x\n", | |
745 | chip->ctl_val[smc_read]); | |
746 | return 0; | |
747 | } | |
748 | ||
749 | static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller, | |
750 | struct device_node *np, struct resource *r) | |
751 | { | |
cfc5604c CP |
752 | const struct spi_nor_hwcaps hwcaps = { |
753 | .mask = SNOR_HWCAPS_READ | | |
754 | SNOR_HWCAPS_READ_FAST | | |
755 | SNOR_HWCAPS_PP, | |
756 | }; | |
ceb720c7 CLG |
757 | const struct aspeed_smc_info *info = controller->info; |
758 | struct device *dev = controller->dev; | |
759 | struct device_node *child; | |
760 | unsigned int cs; | |
761 | int ret = -ENODEV; | |
762 | ||
763 | for_each_available_child_of_node(np, child) { | |
764 | struct aspeed_smc_chip *chip; | |
765 | struct spi_nor *nor; | |
766 | struct mtd_info *mtd; | |
767 | ||
768 | /* This driver does not support NAND or NOR flash devices. */ | |
769 | if (!of_device_is_compatible(child, "jedec,spi-nor")) | |
770 | continue; | |
771 | ||
772 | ret = of_property_read_u32(child, "reg", &cs); | |
773 | if (ret) { | |
774 | dev_err(dev, "Couldn't not read chip select.\n"); | |
775 | break; | |
776 | } | |
777 | ||
778 | if (cs >= info->nce) { | |
779 | dev_err(dev, "Chip select %d out of range.\n", | |
780 | cs); | |
781 | ret = -ERANGE; | |
782 | break; | |
783 | } | |
784 | ||
785 | if (controller->chips[cs]) { | |
786 | dev_err(dev, "Chip select %d already in use by %s\n", | |
787 | cs, dev_name(controller->chips[cs]->nor.dev)); | |
788 | ret = -EBUSY; | |
789 | break; | |
790 | } | |
791 | ||
792 | chip = devm_kzalloc(controller->dev, sizeof(*chip), GFP_KERNEL); | |
793 | if (!chip) { | |
794 | ret = -ENOMEM; | |
795 | break; | |
796 | } | |
797 | ||
798 | chip->controller = controller; | |
799 | chip->ctl = controller->regs + info->ctl0 + cs * 4; | |
800 | chip->cs = cs; | |
801 | ||
802 | nor = &chip->nor; | |
803 | mtd = &nor->mtd; | |
804 | ||
805 | nor->dev = dev; | |
806 | nor->priv = chip; | |
807 | spi_nor_set_flash_node(nor, child); | |
808 | nor->read = aspeed_smc_read_user; | |
809 | nor->write = aspeed_smc_write_user; | |
810 | nor->read_reg = aspeed_smc_read_reg; | |
811 | nor->write_reg = aspeed_smc_write_reg; | |
812 | nor->prepare = aspeed_smc_prep; | |
813 | nor->unprepare = aspeed_smc_unprep; | |
814 | ||
815 | ret = aspeed_smc_chip_setup_init(chip, r); | |
816 | if (ret) | |
817 | break; | |
818 | ||
819 | /* | |
cfc5604c | 820 | * TODO: Add support for Dual and Quad SPI protocols |
ceb720c7 CLG |
821 | * attach when board support is present as determined |
822 | * by of property. | |
823 | */ | |
cfc5604c | 824 | ret = spi_nor_scan(nor, NULL, &hwcaps); |
ceb720c7 CLG |
825 | if (ret) |
826 | break; | |
827 | ||
828 | ret = aspeed_smc_chip_setup_finish(chip); | |
829 | if (ret) | |
830 | break; | |
831 | ||
832 | ret = mtd_device_register(mtd, NULL, 0); | |
833 | if (ret) | |
834 | break; | |
835 | ||
836 | controller->chips[cs] = chip; | |
837 | } | |
838 | ||
839 | if (ret) | |
840 | aspeed_smc_unregister(controller); | |
841 | ||
842 | return ret; | |
843 | } | |
844 | ||
845 | static int aspeed_smc_probe(struct platform_device *pdev) | |
846 | { | |
847 | struct device_node *np = pdev->dev.of_node; | |
848 | struct device *dev = &pdev->dev; | |
849 | struct aspeed_smc_controller *controller; | |
850 | const struct of_device_id *match; | |
851 | const struct aspeed_smc_info *info; | |
852 | struct resource *res; | |
853 | int ret; | |
854 | ||
855 | match = of_match_device(aspeed_smc_matches, &pdev->dev); | |
856 | if (!match || !match->data) | |
857 | return -ENODEV; | |
858 | info = match->data; | |
859 | ||
0ed2dd03 KC |
860 | controller = devm_kzalloc(&pdev->dev, |
861 | struct_size(controller, chips, info->nce), | |
862 | GFP_KERNEL); | |
ceb720c7 CLG |
863 | if (!controller) |
864 | return -ENOMEM; | |
865 | controller->info = info; | |
866 | controller->dev = dev; | |
867 | ||
868 | mutex_init(&controller->mutex); | |
869 | platform_set_drvdata(pdev, controller); | |
870 | ||
871 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
872 | controller->regs = devm_ioremap_resource(dev, res); | |
d91f6cee | 873 | if (IS_ERR(controller->regs)) |
ceb720c7 | 874 | return PTR_ERR(controller->regs); |
ceb720c7 CLG |
875 | |
876 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | |
877 | controller->ahb_base = devm_ioremap_resource(dev, res); | |
d91f6cee | 878 | if (IS_ERR(controller->ahb_base)) |
ceb720c7 | 879 | return PTR_ERR(controller->ahb_base); |
ceb720c7 | 880 | |
7ef0e5e1 CLG |
881 | controller->ahb_window_size = resource_size(res); |
882 | ||
ceb720c7 CLG |
883 | ret = aspeed_smc_setup_flash(controller, np, res); |
884 | if (ret) | |
885 | dev_err(dev, "Aspeed SMC probe failed %d\n", ret); | |
886 | ||
887 | return ret; | |
888 | } | |
889 | ||
890 | static struct platform_driver aspeed_smc_driver = { | |
891 | .probe = aspeed_smc_probe, | |
892 | .remove = aspeed_smc_remove, | |
893 | .driver = { | |
894 | .name = DEVICE_NAME, | |
895 | .of_match_table = aspeed_smc_matches, | |
896 | } | |
897 | }; | |
898 | ||
899 | module_platform_driver(aspeed_smc_driver); | |
900 | ||
901 | MODULE_DESCRIPTION("ASPEED Static Memory Controller Driver"); | |
902 | MODULE_AUTHOR("Cedric Le Goater <clg@kaod.org>"); | |
903 | MODULE_LICENSE("GPL v2"); |