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