OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | --- a/drivers/mtd/devices/Kconfig |
2 | +++ b/drivers/mtd/devices/Kconfig |
||
3 | @@ -130,6 +130,10 @@ config MTD_BCM47XXSFLASH |
||
4 | registered by bcma as platform devices. This enables driver for |
||
5 | serial flash memories. |
||
6 | |||
7 | +config MTD_AR2315 |
||
8 | + tristate "Atheros AR2315+ SPI Flash support" |
||
9 | + depends on SOC_AR2315 |
||
10 | + |
||
11 | config MTD_SLRAM |
||
12 | tristate "Uncached system RAM" |
||
13 | help |
||
14 | --- a/drivers/mtd/devices/Makefile |
||
15 | +++ b/drivers/mtd/devices/Makefile |
||
16 | @@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_M25P80) += m25p80.o |
||
17 | obj-$(CONFIG_MTD_MCHP23K256) += mchp23k256.o |
||
18 | obj-$(CONFIG_MTD_SPEAR_SMI) += spear_smi.o |
||
19 | obj-$(CONFIG_MTD_SST25L) += sst25l.o |
||
20 | +obj-$(CONFIG_MTD_AR2315) += ar2315.o |
||
21 | obj-$(CONFIG_MTD_BCM47XXSFLASH) += bcm47xxsflash.o |
||
22 | obj-$(CONFIG_MTD_ST_SPI_FSM) += st_spi_fsm.o |
||
23 | obj-$(CONFIG_MTD_POWERNV_FLASH) += powernv_flash.o |
||
24 | --- /dev/null |
||
25 | +++ b/drivers/mtd/devices/ar2315.c |
||
26 | @@ -0,0 +1,459 @@ |
||
27 | + |
||
28 | +/* |
||
29 | + * MTD driver for the SPI Flash Memory support on Atheros AR2315 |
||
30 | + * |
||
31 | + * Copyright (c) 2005-2006 Atheros Communications Inc. |
||
32 | + * Copyright (C) 2006-2007 FON Technology, SL. |
||
33 | + * Copyright (C) 2006-2007 Imre Kaloz <kaloz@openwrt.org> |
||
34 | + * Copyright (C) 2006-2009 Felix Fietkau <nbd@nbd.name> |
||
35 | + * Copyright (C) 2012 Alexandros C. Couloumbis <alex@ozo.com> |
||
36 | + * |
||
37 | + * This code is free software; you can redistribute it and/or modify |
||
38 | + * it under the terms of the GNU General Public License version 2 as |
||
39 | + * published by the Free Software Foundation. |
||
40 | + * |
||
41 | + */ |
||
42 | + |
||
43 | +#include <linux/kernel.h> |
||
44 | +#include <linux/module.h> |
||
45 | +#include <linux/types.h> |
||
46 | +#include <linux/errno.h> |
||
47 | +#include <linux/slab.h> |
||
48 | +#include <linux/mtd/mtd.h> |
||
49 | +#include <linux/mtd/partitions.h> |
||
50 | +#include <linux/platform_device.h> |
||
51 | +#include <linux/sched.h> |
||
52 | +#include <linux/delay.h> |
||
53 | +#include <linux/io.h> |
||
54 | +#include <linux/mutex.h> |
||
55 | + |
||
56 | +#include "ar2315_spiflash.h" |
||
57 | + |
||
58 | +#define DRIVER_NAME "ar2315-spiflash" |
||
59 | + |
||
60 | +#define busy_wait(_priv, _condition, _wait) do { \ |
||
61 | + while (_condition) { \ |
||
62 | + if (_wait > 1) \ |
||
63 | + msleep(_wait); \ |
||
64 | + else if ((_wait == 1) && need_resched()) \ |
||
65 | + schedule(); \ |
||
66 | + else \ |
||
67 | + udelay(1); \ |
||
68 | + } \ |
||
69 | +} while (0) |
||
70 | + |
||
71 | +enum { |
||
72 | + FLASH_NONE, |
||
73 | + FLASH_1MB, |
||
74 | + FLASH_2MB, |
||
75 | + FLASH_4MB, |
||
76 | + FLASH_8MB, |
||
77 | + FLASH_16MB, |
||
78 | +}; |
||
79 | + |
||
80 | +/* Flash configuration table */ |
||
81 | +struct flashconfig { |
||
82 | + u32 byte_cnt; |
||
83 | + u32 sector_cnt; |
||
84 | + u32 sector_size; |
||
85 | +}; |
||
86 | + |
||
87 | +static const struct flashconfig flashconfig_tbl[] = { |
||
88 | + [FLASH_NONE] = { 0, 0, 0}, |
||
89 | + [FLASH_1MB] = { STM_1MB_BYTE_COUNT, STM_1MB_SECTOR_COUNT, |
||
90 | + STM_1MB_SECTOR_SIZE}, |
||
91 | + [FLASH_2MB] = { STM_2MB_BYTE_COUNT, STM_2MB_SECTOR_COUNT, |
||
92 | + STM_2MB_SECTOR_SIZE}, |
||
93 | + [FLASH_4MB] = { STM_4MB_BYTE_COUNT, STM_4MB_SECTOR_COUNT, |
||
94 | + STM_4MB_SECTOR_SIZE}, |
||
95 | + [FLASH_8MB] = { STM_8MB_BYTE_COUNT, STM_8MB_SECTOR_COUNT, |
||
96 | + STM_8MB_SECTOR_SIZE}, |
||
97 | + [FLASH_16MB] = { STM_16MB_BYTE_COUNT, STM_16MB_SECTOR_COUNT, |
||
98 | + STM_16MB_SECTOR_SIZE} |
||
99 | +}; |
||
100 | + |
||
101 | +/* Mapping of generic opcodes to STM serial flash opcodes */ |
||
102 | +enum { |
||
103 | + SPI_WRITE_ENABLE, |
||
104 | + SPI_WRITE_DISABLE, |
||
105 | + SPI_RD_STATUS, |
||
106 | + SPI_WR_STATUS, |
||
107 | + SPI_RD_DATA, |
||
108 | + SPI_FAST_RD_DATA, |
||
109 | + SPI_PAGE_PROGRAM, |
||
110 | + SPI_SECTOR_ERASE, |
||
111 | + SPI_BULK_ERASE, |
||
112 | + SPI_DEEP_PWRDOWN, |
||
113 | + SPI_RD_SIG, |
||
114 | +}; |
||
115 | + |
||
116 | +struct opcodes { |
||
117 | + __u16 code; |
||
118 | + __s8 tx_cnt; |
||
119 | + __s8 rx_cnt; |
||
120 | +}; |
||
121 | + |
||
122 | +static const struct opcodes stm_opcodes[] = { |
||
123 | + [SPI_WRITE_ENABLE] = {STM_OP_WR_ENABLE, 1, 0}, |
||
124 | + [SPI_WRITE_DISABLE] = {STM_OP_WR_DISABLE, 1, 0}, |
||
125 | + [SPI_RD_STATUS] = {STM_OP_RD_STATUS, 1, 1}, |
||
126 | + [SPI_WR_STATUS] = {STM_OP_WR_STATUS, 1, 0}, |
||
127 | + [SPI_RD_DATA] = {STM_OP_RD_DATA, 4, 4}, |
||
128 | + [SPI_FAST_RD_DATA] = {STM_OP_FAST_RD_DATA, 5, 0}, |
||
129 | + [SPI_PAGE_PROGRAM] = {STM_OP_PAGE_PGRM, 8, 0}, |
||
130 | + [SPI_SECTOR_ERASE] = {STM_OP_SECTOR_ERASE, 4, 0}, |
||
131 | + [SPI_BULK_ERASE] = {STM_OP_BULK_ERASE, 1, 0}, |
||
132 | + [SPI_DEEP_PWRDOWN] = {STM_OP_DEEP_PWRDOWN, 1, 0}, |
||
133 | + [SPI_RD_SIG] = {STM_OP_RD_SIG, 4, 1}, |
||
134 | +}; |
||
135 | + |
||
136 | +/* Driver private data structure */ |
||
137 | +struct spiflash_priv { |
||
138 | + struct mtd_info mtd; |
||
139 | + void __iomem *readaddr; /* memory mapped data for read */ |
||
140 | + void __iomem *mmraddr; /* memory mapped register space */ |
||
141 | + struct mutex lock; /* serialize registers access */ |
||
142 | +}; |
||
143 | + |
||
144 | +#define to_spiflash(_mtd) container_of(_mtd, struct spiflash_priv, mtd) |
||
145 | + |
||
146 | +enum { |
||
147 | + FL_READY, |
||
148 | + FL_READING, |
||
149 | + FL_ERASING, |
||
150 | + FL_WRITING |
||
151 | +}; |
||
152 | + |
||
153 | +/*****************************************************************************/ |
||
154 | + |
||
155 | +static u32 |
||
156 | +spiflash_read_reg(struct spiflash_priv *priv, int reg) |
||
157 | +{ |
||
158 | + return ioread32(priv->mmraddr + reg); |
||
159 | +} |
||
160 | + |
||
161 | +static void |
||
162 | +spiflash_write_reg(struct spiflash_priv *priv, int reg, u32 data) |
||
163 | +{ |
||
164 | + iowrite32(data, priv->mmraddr + reg); |
||
165 | +} |
||
166 | + |
||
167 | +static u32 |
||
168 | +spiflash_wait_busy(struct spiflash_priv *priv) |
||
169 | +{ |
||
170 | + u32 reg; |
||
171 | + |
||
172 | + busy_wait(priv, (reg = spiflash_read_reg(priv, SPI_FLASH_CTL)) & |
||
173 | + SPI_CTL_BUSY, 0); |
||
174 | + return reg; |
||
175 | +} |
||
176 | + |
||
177 | +static u32 |
||
178 | +spiflash_sendcmd(struct spiflash_priv *priv, int opcode, u32 addr) |
||
179 | +{ |
||
180 | + const struct opcodes *op; |
||
181 | + u32 reg, mask; |
||
182 | + |
||
183 | + op = &stm_opcodes[opcode]; |
||
184 | + reg = spiflash_wait_busy(priv); |
||
185 | + spiflash_write_reg(priv, SPI_FLASH_OPCODE, |
||
186 | + ((u32)op->code) | (addr << 8)); |
||
187 | + |
||
188 | + reg &= ~SPI_CTL_TX_RX_CNT_MASK; |
||
189 | + reg |= SPI_CTL_START | op->tx_cnt | (op->rx_cnt << 4); |
||
190 | + |
||
191 | + spiflash_write_reg(priv, SPI_FLASH_CTL, reg); |
||
192 | + spiflash_wait_busy(priv); |
||
193 | + |
||
194 | + if (!op->rx_cnt) |
||
195 | + return 0; |
||
196 | + |
||
197 | + reg = spiflash_read_reg(priv, SPI_FLASH_DATA); |
||
198 | + |
||
199 | + switch (op->rx_cnt) { |
||
200 | + case 1: |
||
201 | + mask = 0x000000ff; |
||
202 | + break; |
||
203 | + case 2: |
||
204 | + mask = 0x0000ffff; |
||
205 | + break; |
||
206 | + case 3: |
||
207 | + mask = 0x00ffffff; |
||
208 | + break; |
||
209 | + default: |
||
210 | + mask = 0xffffffff; |
||
211 | + break; |
||
212 | + } |
||
213 | + reg &= mask; |
||
214 | + |
||
215 | + return reg; |
||
216 | +} |
||
217 | + |
||
218 | +/* |
||
219 | + * Probe SPI flash device |
||
220 | + * Function returns 0 for failure. |
||
221 | + * and flashconfig_tbl array index for success. |
||
222 | + */ |
||
223 | +static int |
||
224 | +spiflash_probe_chip(struct platform_device *pdev, struct spiflash_priv *priv) |
||
225 | +{ |
||
226 | + u32 sig = spiflash_sendcmd(priv, SPI_RD_SIG, 0); |
||
227 | + int flash_size; |
||
228 | + |
||
229 | + switch (sig) { |
||
230 | + case STM_8MBIT_SIGNATURE: |
||
231 | + flash_size = FLASH_1MB; |
||
232 | + break; |
||
233 | + case STM_16MBIT_SIGNATURE: |
||
234 | + flash_size = FLASH_2MB; |
||
235 | + break; |
||
236 | + case STM_32MBIT_SIGNATURE: |
||
237 | + flash_size = FLASH_4MB; |
||
238 | + break; |
||
239 | + case STM_64MBIT_SIGNATURE: |
||
240 | + flash_size = FLASH_8MB; |
||
241 | + break; |
||
242 | + case STM_128MBIT_SIGNATURE: |
||
243 | + flash_size = FLASH_16MB; |
||
244 | + break; |
||
245 | + default: |
||
246 | + dev_warn(&pdev->dev, "read of flash device signature failed!\n"); |
||
247 | + return 0; |
||
248 | + } |
||
249 | + |
||
250 | + return flash_size; |
||
251 | +} |
||
252 | + |
||
253 | +static void |
||
254 | +spiflash_wait_complete(struct spiflash_priv *priv, unsigned int timeout) |
||
255 | +{ |
||
256 | + busy_wait(priv, spiflash_sendcmd(priv, SPI_RD_STATUS, 0) & |
||
257 | + SPI_STATUS_WIP, timeout); |
||
258 | +} |
||
259 | + |
||
260 | +static int |
||
261 | +spiflash_erase(struct mtd_info *mtd, struct erase_info *instr) |
||
262 | +{ |
||
263 | + struct spiflash_priv *priv = to_spiflash(mtd); |
||
264 | + const struct opcodes *op; |
||
265 | + u32 temp, reg; |
||
266 | + |
||
267 | + if (instr->addr + instr->len > mtd->size) |
||
268 | + return -EINVAL; |
||
269 | + |
||
270 | + mutex_lock(&priv->lock); |
||
271 | + |
||
272 | + spiflash_sendcmd(priv, SPI_WRITE_ENABLE, 0); |
||
273 | + reg = spiflash_wait_busy(priv); |
||
274 | + |
||
275 | + op = &stm_opcodes[SPI_SECTOR_ERASE]; |
||
276 | + temp = ((u32)instr->addr << 8) | (u32)(op->code); |
||
277 | + spiflash_write_reg(priv, SPI_FLASH_OPCODE, temp); |
||
278 | + |
||
279 | + reg &= ~SPI_CTL_TX_RX_CNT_MASK; |
||
280 | + reg |= op->tx_cnt | SPI_CTL_START; |
||
281 | + spiflash_write_reg(priv, SPI_FLASH_CTL, reg); |
||
282 | + |
||
283 | + spiflash_wait_complete(priv, 20); |
||
284 | + |
||
285 | + mutex_unlock(&priv->lock); |
||
286 | + |
||
287 | + instr->state = MTD_ERASE_DONE; |
||
288 | + mtd_erase_callback(instr); |
||
289 | + |
||
290 | + return 0; |
||
291 | +} |
||
292 | + |
||
293 | +static int |
||
294 | +spiflash_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, |
||
295 | + u_char *buf) |
||
296 | +{ |
||
297 | + struct spiflash_priv *priv = to_spiflash(mtd); |
||
298 | + |
||
299 | + if (!len) |
||
300 | + return 0; |
||
301 | + |
||
302 | + if (from + len > mtd->size) |
||
303 | + return -EINVAL; |
||
304 | + |
||
305 | + *retlen = len; |
||
306 | + |
||
307 | + mutex_lock(&priv->lock); |
||
308 | + |
||
309 | + memcpy_fromio(buf, priv->readaddr + from, len); |
||
310 | + |
||
311 | + mutex_unlock(&priv->lock); |
||
312 | + |
||
313 | + return 0; |
||
314 | +} |
||
315 | + |
||
316 | +static int |
||
317 | +spiflash_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, |
||
318 | + const u8 *buf) |
||
319 | +{ |
||
320 | + struct spiflash_priv *priv = to_spiflash(mtd); |
||
321 | + u32 opcode, bytes_left; |
||
322 | + |
||
323 | + *retlen = 0; |
||
324 | + |
||
325 | + if (!len) |
||
326 | + return 0; |
||
327 | + |
||
328 | + if (to + len > mtd->size) |
||
329 | + return -EINVAL; |
||
330 | + |
||
331 | + bytes_left = len; |
||
332 | + |
||
333 | + do { |
||
334 | + u32 read_len, reg, page_offset, spi_data = 0; |
||
335 | + |
||
336 | + read_len = min(bytes_left, sizeof(u32)); |
||
337 | + |
||
338 | + /* 32-bit writes cannot span across a page boundary |
||
339 | + * (256 bytes). This types of writes require two page |
||
340 | + * program operations to handle it correctly. The STM part |
||
341 | + * will write the overflow data to the beginning of the |
||
342 | + * current page as opposed to the subsequent page. |
||
343 | + */ |
||
344 | + page_offset = (to & (STM_PAGE_SIZE - 1)) + read_len; |
||
345 | + |
||
346 | + if (page_offset > STM_PAGE_SIZE) |
||
347 | + read_len -= (page_offset - STM_PAGE_SIZE); |
||
348 | + |
||
349 | + mutex_lock(&priv->lock); |
||
350 | + |
||
351 | + spiflash_sendcmd(priv, SPI_WRITE_ENABLE, 0); |
||
352 | + spi_data = 0; |
||
353 | + switch (read_len) { |
||
354 | + case 4: |
||
355 | + spi_data |= buf[3] << 24; |
||
356 | + /* fall through */ |
||
357 | + case 3: |
||
358 | + spi_data |= buf[2] << 16; |
||
359 | + /* fall through */ |
||
360 | + case 2: |
||
361 | + spi_data |= buf[1] << 8; |
||
362 | + /* fall through */ |
||
363 | + case 1: |
||
364 | + spi_data |= buf[0] & 0xff; |
||
365 | + break; |
||
366 | + default: |
||
367 | + break; |
||
368 | + } |
||
369 | + |
||
370 | + spiflash_write_reg(priv, SPI_FLASH_DATA, spi_data); |
||
371 | + opcode = stm_opcodes[SPI_PAGE_PROGRAM].code | |
||
372 | + (to & 0x00ffffff) << 8; |
||
373 | + spiflash_write_reg(priv, SPI_FLASH_OPCODE, opcode); |
||
374 | + |
||
375 | + reg = spiflash_read_reg(priv, SPI_FLASH_CTL); |
||
376 | + reg &= ~SPI_CTL_TX_RX_CNT_MASK; |
||
377 | + reg |= (read_len + 4) | SPI_CTL_START; |
||
378 | + spiflash_write_reg(priv, SPI_FLASH_CTL, reg); |
||
379 | + |
||
380 | + spiflash_wait_complete(priv, 1); |
||
381 | + |
||
382 | + mutex_unlock(&priv->lock); |
||
383 | + |
||
384 | + bytes_left -= read_len; |
||
385 | + to += read_len; |
||
386 | + buf += read_len; |
||
387 | + |
||
388 | + *retlen += read_len; |
||
389 | + } while (bytes_left != 0); |
||
390 | + |
||
391 | + return 0; |
||
392 | +} |
||
393 | + |
||
394 | +#if defined CONFIG_MTD_REDBOOT_PARTS || CONFIG_MTD_MYLOADER_PARTS |
||
395 | +static const char * const part_probe_types[] = { |
||
396 | + "cmdlinepart", "RedBoot", "MyLoader", NULL |
||
397 | +}; |
||
398 | +#endif |
||
399 | + |
||
400 | +static int |
||
401 | +spiflash_probe(struct platform_device *pdev) |
||
402 | +{ |
||
403 | + struct spiflash_priv *priv; |
||
404 | + struct mtd_info *mtd; |
||
405 | + struct resource *res; |
||
406 | + int index; |
||
407 | + int result = 0; |
||
408 | + |
||
409 | + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); |
||
410 | + if (!priv) |
||
411 | + return -ENOMEM; |
||
412 | + |
||
413 | + mutex_init(&priv->lock); |
||
414 | + mtd = &priv->mtd; |
||
415 | + |
||
416 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
||
417 | + priv->mmraddr = devm_ioremap_resource(&pdev->dev, res); |
||
418 | + if (IS_ERR(priv->mmraddr)) { |
||
419 | + dev_warn(&pdev->dev, "failed to map flash MMR\n"); |
||
420 | + return PTR_ERR(priv->mmraddr); |
||
421 | + } |
||
422 | + |
||
423 | + index = spiflash_probe_chip(pdev, priv); |
||
424 | + if (!index) { |
||
425 | + dev_warn(&pdev->dev, "found no flash device\n"); |
||
426 | + return -ENODEV; |
||
427 | + } |
||
428 | + |
||
429 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
||
430 | + priv->readaddr = devm_ioremap_resource(&pdev->dev, res); |
||
431 | + if (IS_ERR(priv->readaddr)) { |
||
432 | + dev_warn(&pdev->dev, "failed to map flash read mem\n"); |
||
433 | + return PTR_ERR(priv->readaddr); |
||
434 | + } |
||
435 | + |
||
436 | + platform_set_drvdata(pdev, priv); |
||
437 | + mtd->name = "spiflash"; |
||
438 | + mtd->type = MTD_NORFLASH; |
||
439 | + mtd->flags = (MTD_CAP_NORFLASH|MTD_WRITEABLE); |
||
440 | + mtd->size = flashconfig_tbl[index].byte_cnt; |
||
441 | + mtd->erasesize = flashconfig_tbl[index].sector_size; |
||
442 | + mtd->writesize = 1; |
||
443 | + mtd->numeraseregions = 0; |
||
444 | + mtd->eraseregions = NULL; |
||
445 | + mtd->_erase = spiflash_erase; |
||
446 | + mtd->_read = spiflash_read; |
||
447 | + mtd->_write = spiflash_write; |
||
448 | + mtd->owner = THIS_MODULE; |
||
449 | + |
||
450 | + dev_info(&pdev->dev, "%lld Kbytes flash detected\n", mtd->size >> 10); |
||
451 | + |
||
452 | +#if defined CONFIG_MTD_REDBOOT_PARTS || CONFIG_MTD_MYLOADER_PARTS |
||
453 | + /* parse redboot partitions */ |
||
454 | + |
||
455 | + result = mtd_device_parse_register(mtd, part_probe_types, |
||
456 | + NULL, NULL, 0); |
||
457 | +#endif |
||
458 | + |
||
459 | + return result; |
||
460 | +} |
||
461 | + |
||
462 | +static int |
||
463 | +spiflash_remove(struct platform_device *pdev) |
||
464 | +{ |
||
465 | + struct spiflash_priv *priv = platform_get_drvdata(pdev); |
||
466 | + |
||
467 | + mtd_device_unregister(&priv->mtd); |
||
468 | + |
||
469 | + return 0; |
||
470 | +} |
||
471 | + |
||
472 | +static struct platform_driver spiflash_driver = { |
||
473 | + .driver.name = DRIVER_NAME, |
||
474 | + .probe = spiflash_probe, |
||
475 | + .remove = spiflash_remove, |
||
476 | +}; |
||
477 | + |
||
478 | +module_platform_driver(spiflash_driver); |
||
479 | + |
||
480 | +MODULE_LICENSE("GPL"); |
||
481 | +MODULE_AUTHOR("OpenWrt.org"); |
||
482 | +MODULE_AUTHOR("Atheros Communications Inc"); |
||
483 | +MODULE_DESCRIPTION("MTD driver for SPI Flash on Atheros AR2315+ SOC"); |
||
484 | +MODULE_ALIAS("platform:" DRIVER_NAME); |
||
485 | + |
||
486 | --- /dev/null |
||
487 | +++ b/drivers/mtd/devices/ar2315_spiflash.h |
||
488 | @@ -0,0 +1,106 @@ |
||
489 | +/* |
||
490 | + * Atheros AR2315 SPI Flash Memory support header file. |
||
491 | + * |
||
492 | + * Copyright (c) 2005, Atheros Communications Inc. |
||
493 | + * Copyright (C) 2006 FON Technology, SL. |
||
494 | + * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> |
||
495 | + * Copyright (C) 2006-2009 Felix Fietkau <nbd@nbd.name> |
||
496 | + * |
||
497 | + * This code is free software; you can redistribute it and/or modify |
||
498 | + * it under the terms of the GNU General Public License version 2 as |
||
499 | + * published by the Free Software Foundation. |
||
500 | + * |
||
501 | + */ |
||
502 | +#ifndef __AR2315_SPIFLASH_H |
||
503 | +#define __AR2315_SPIFLASH_H |
||
504 | + |
||
505 | +#define STM_PAGE_SIZE 256 |
||
506 | + |
||
507 | +#define SFI_WRITE_BUFFER_SIZE 4 |
||
508 | +#define SFI_FLASH_ADDR_MASK 0x00ffffff |
||
509 | + |
||
510 | +#define STM_8MBIT_SIGNATURE 0x13 |
||
511 | +#define STM_M25P80_BYTE_COUNT 1048576 |
||
512 | +#define STM_M25P80_SECTOR_COUNT 16 |
||
513 | +#define STM_M25P80_SECTOR_SIZE 0x10000 |
||
514 | + |
||
515 | +#define STM_16MBIT_SIGNATURE 0x14 |
||
516 | +#define STM_M25P16_BYTE_COUNT 2097152 |
||
517 | +#define STM_M25P16_SECTOR_COUNT 32 |
||
518 | +#define STM_M25P16_SECTOR_SIZE 0x10000 |
||
519 | + |
||
520 | +#define STM_32MBIT_SIGNATURE 0x15 |
||
521 | +#define STM_M25P32_BYTE_COUNT 4194304 |
||
522 | +#define STM_M25P32_SECTOR_COUNT 64 |
||
523 | +#define STM_M25P32_SECTOR_SIZE 0x10000 |
||
524 | + |
||
525 | +#define STM_64MBIT_SIGNATURE 0x16 |
||
526 | +#define STM_M25P64_BYTE_COUNT 8388608 |
||
527 | +#define STM_M25P64_SECTOR_COUNT 128 |
||
528 | +#define STM_M25P64_SECTOR_SIZE 0x10000 |
||
529 | + |
||
530 | +#define STM_128MBIT_SIGNATURE 0x17 |
||
531 | +#define STM_M25P128_BYTE_COUNT 16777216 |
||
532 | +#define STM_M25P128_SECTOR_COUNT 256 |
||
533 | +#define STM_M25P128_SECTOR_SIZE 0x10000 |
||
534 | + |
||
535 | +#define STM_1MB_BYTE_COUNT STM_M25P80_BYTE_COUNT |
||
536 | +#define STM_1MB_SECTOR_COUNT STM_M25P80_SECTOR_COUNT |
||
537 | +#define STM_1MB_SECTOR_SIZE STM_M25P80_SECTOR_SIZE |
||
538 | +#define STM_2MB_BYTE_COUNT STM_M25P16_BYTE_COUNT |
||
539 | +#define STM_2MB_SECTOR_COUNT STM_M25P16_SECTOR_COUNT |
||
540 | +#define STM_2MB_SECTOR_SIZE STM_M25P16_SECTOR_SIZE |
||
541 | +#define STM_4MB_BYTE_COUNT STM_M25P32_BYTE_COUNT |
||
542 | +#define STM_4MB_SECTOR_COUNT STM_M25P32_SECTOR_COUNT |
||
543 | +#define STM_4MB_SECTOR_SIZE STM_M25P32_SECTOR_SIZE |
||
544 | +#define STM_8MB_BYTE_COUNT STM_M25P64_BYTE_COUNT |
||
545 | +#define STM_8MB_SECTOR_COUNT STM_M25P64_SECTOR_COUNT |
||
546 | +#define STM_8MB_SECTOR_SIZE STM_M25P64_SECTOR_SIZE |
||
547 | +#define STM_16MB_BYTE_COUNT STM_M25P128_BYTE_COUNT |
||
548 | +#define STM_16MB_SECTOR_COUNT STM_M25P128_SECTOR_COUNT |
||
549 | +#define STM_16MB_SECTOR_SIZE STM_M25P128_SECTOR_SIZE |
||
550 | + |
||
551 | +/* |
||
552 | + * ST Microelectronics Opcodes for Serial Flash |
||
553 | + */ |
||
554 | + |
||
555 | +#define STM_OP_WR_ENABLE 0x06 /* Write Enable */ |
||
556 | +#define STM_OP_WR_DISABLE 0x04 /* Write Disable */ |
||
557 | +#define STM_OP_RD_STATUS 0x05 /* Read Status */ |
||
558 | +#define STM_OP_WR_STATUS 0x01 /* Write Status */ |
||
559 | +#define STM_OP_RD_DATA 0x03 /* Read Data */ |
||
560 | +#define STM_OP_FAST_RD_DATA 0x0b /* Fast Read Data */ |
||
561 | +#define STM_OP_PAGE_PGRM 0x02 /* Page Program */ |
||
562 | +#define STM_OP_SECTOR_ERASE 0xd8 /* Sector Erase */ |
||
563 | +#define STM_OP_BULK_ERASE 0xc7 /* Bulk Erase */ |
||
564 | +#define STM_OP_DEEP_PWRDOWN 0xb9 /* Deep Power-Down Mode */ |
||
565 | +#define STM_OP_RD_SIG 0xab /* Read Electronic Signature */ |
||
566 | + |
||
567 | +#define STM_STATUS_WIP 0x01 /* Write-In-Progress */ |
||
568 | +#define STM_STATUS_WEL 0x02 /* Write Enable Latch */ |
||
569 | +#define STM_STATUS_BP0 0x04 /* Block Protect 0 */ |
||
570 | +#define STM_STATUS_BP1 0x08 /* Block Protect 1 */ |
||
571 | +#define STM_STATUS_BP2 0x10 /* Block Protect 2 */ |
||
572 | +#define STM_STATUS_SRWD 0x80 /* Status Register Write Disable */ |
||
573 | + |
||
574 | +/* |
||
575 | + * SPI Flash Interface Registers |
||
576 | + */ |
||
577 | + |
||
578 | +#define SPI_FLASH_CTL 0x00 |
||
579 | +#define SPI_FLASH_OPCODE 0x04 |
||
580 | +#define SPI_FLASH_DATA 0x08 |
||
581 | + |
||
582 | +#define SPI_CTL_START 0x00000100 |
||
583 | +#define SPI_CTL_BUSY 0x00010000 |
||
584 | +#define SPI_CTL_TXCNT_MASK 0x0000000f |
||
585 | +#define SPI_CTL_RXCNT_MASK 0x000000f0 |
||
586 | +#define SPI_CTL_TX_RX_CNT_MASK 0x000000ff |
||
587 | +#define SPI_CTL_SIZE_MASK 0x00060000 |
||
588 | + |
||
589 | +#define SPI_CTL_CLK_SEL_MASK 0x03000000 |
||
590 | +#define SPI_OPCODE_MASK 0x000000ff |
||
591 | + |
||
592 | +#define SPI_STATUS_WIP STM_STATUS_WIP |
||
593 | + |
||
594 | +#endif |
||
595 | --- a/arch/mips/ath25/ar2315.c |
||
596 | +++ b/arch/mips/ath25/ar2315.c |
||
597 | @@ -220,6 +220,28 @@ static struct platform_device ar2315_gpi |
||
598 | .num_resources = ARRAY_SIZE(ar2315_gpio_res) |
||
599 | }; |
||
600 | |||
601 | +static struct resource ar2315_spiflash_res[] = { |
||
602 | + { |
||
603 | + .name = "spiflash_read", |
||
604 | + .flags = IORESOURCE_MEM, |
||
605 | + .start = AR2315_SPI_READ_BASE, |
||
606 | + .end = AR2315_SPI_READ_BASE + AR2315_SPI_READ_SIZE - 1, |
||
607 | + }, |
||
608 | + { |
||
609 | + .name = "spiflash_mmr", |
||
610 | + .flags = IORESOURCE_MEM, |
||
611 | + .start = AR2315_SPI_MMR_BASE, |
||
612 | + .end = AR2315_SPI_MMR_BASE + AR2315_SPI_MMR_SIZE - 1, |
||
613 | + }, |
||
614 | +}; |
||
615 | + |
||
616 | +static struct platform_device ar2315_spiflash = { |
||
617 | + .id = 0, |
||
618 | + .name = "ar2315-spiflash", |
||
619 | + .resource = ar2315_spiflash_res, |
||
620 | + .num_resources = ARRAY_SIZE(ar2315_spiflash_res) |
||
621 | +}; |
||
622 | + |
||
623 | void __init ar2315_init_devices(void) |
||
624 | { |
||
625 | /* Find board configuration */ |
||
626 | @@ -230,6 +252,8 @@ void __init ar2315_init_devices(void) |
||
627 | ar2315_gpio_res[1].end = ar2315_gpio_res[1].start; |
||
628 | platform_device_register(&ar2315_gpio); |
||
629 | |||
630 | + platform_device_register(&ar2315_spiflash); |
||
631 | + |
||
632 | ar2315_eth_data.macaddr = ath25_board.config->enet0_mac; |
||
633 | ath25_add_ethernet(0, AR2315_ENET0_BASE, "eth0_mii", |
||
634 | AR2315_ENET0_MII_BASE, AR2315_IRQ_ENET0, |