Commit d57ef3a6a2eeb88df47e892c66692e3f59722ffe
Committed by
John W. Linville
1 parent
01e17dacd4
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
bcma: detect and register serial flash device
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Showing 6 changed files with 146 additions and 4 deletions Side-by-side Diff
drivers/bcma/Kconfig
drivers/bcma/bcma_private.h
drivers/bcma/driver_chipcommon_sflash.c
... | ... | @@ -5,16 +5,133 @@ |
5 | 5 | * Licensed under the GNU/GPL. See COPYING for details. |
6 | 6 | */ |
7 | 7 | |
8 | +#include <linux/platform_device.h> | |
8 | 9 | #include <linux/bcma/bcma.h> |
9 | -#include <linux/bcma/bcma_driver_chipcommon.h> | |
10 | -#include <linux/delay.h> | |
11 | 10 | |
12 | 11 | #include "bcma_private.h" |
13 | 12 | |
13 | +static struct resource bcma_sflash_resource = { | |
14 | + .name = "bcma_sflash", | |
15 | + .start = BCMA_SFLASH, | |
16 | + .end = 0, | |
17 | + .flags = IORESOURCE_MEM | IORESOURCE_READONLY, | |
18 | +}; | |
19 | + | |
20 | +struct platform_device bcma_sflash_dev = { | |
21 | + .name = "bcma_sflash", | |
22 | + .resource = &bcma_sflash_resource, | |
23 | + .num_resources = 1, | |
24 | +}; | |
25 | + | |
26 | +struct bcma_sflash_tbl_e { | |
27 | + char *name; | |
28 | + u32 id; | |
29 | + u32 blocksize; | |
30 | + u16 numblocks; | |
31 | +}; | |
32 | + | |
33 | +static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { | |
34 | + { "", 0x14, 0x10000, 32, }, | |
35 | + { 0 }, | |
36 | +}; | |
37 | + | |
38 | +static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { | |
39 | + { 0 }, | |
40 | +}; | |
41 | + | |
42 | +static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { | |
43 | + { 0 }, | |
44 | +}; | |
45 | + | |
46 | +static void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode) | |
47 | +{ | |
48 | + int i; | |
49 | + bcma_cc_write32(cc, BCMA_CC_FLASHCTL, | |
50 | + BCMA_CC_FLASHCTL_START | opcode); | |
51 | + for (i = 0; i < 1000; i++) { | |
52 | + if (!(bcma_cc_read32(cc, BCMA_CC_FLASHCTL) & | |
53 | + BCMA_CC_FLASHCTL_BUSY)) | |
54 | + return; | |
55 | + cpu_relax(); | |
56 | + } | |
57 | + bcma_err(cc->core->bus, "SFLASH control command failed (timeout)!\n"); | |
58 | +} | |
59 | + | |
14 | 60 | /* Initialize serial flash access */ |
15 | 61 | int bcma_sflash_init(struct bcma_drv_cc *cc) |
16 | 62 | { |
17 | - bcma_err(cc->core->bus, "Serial flash support is broken\n"); | |
63 | + struct bcma_bus *bus = cc->core->bus; | |
64 | + struct bcma_sflash *sflash = &cc->sflash; | |
65 | + struct bcma_sflash_tbl_e *e; | |
66 | + u32 id, id2; | |
67 | + | |
68 | + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { | |
69 | + case BCMA_CC_FLASHT_STSER: | |
70 | + bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_DP); | |
71 | + | |
72 | + bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 0); | |
73 | + bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES); | |
74 | + id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA); | |
75 | + | |
76 | + bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 1); | |
77 | + bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES); | |
78 | + id2 = bcma_cc_read32(cc, BCMA_CC_FLASHDATA); | |
79 | + | |
80 | + switch (id) { | |
81 | + case 0xbf: | |
82 | + for (e = bcma_sflash_sst_tbl; e->name; e++) { | |
83 | + if (e->id == id2) | |
84 | + break; | |
85 | + } | |
86 | + break; | |
87 | + default: | |
88 | + for (e = bcma_sflash_st_tbl; e->name; e++) { | |
89 | + if (e->id == id) | |
90 | + break; | |
91 | + } | |
92 | + break; | |
93 | + } | |
94 | + if (!e->name) { | |
95 | + bcma_err(bus, "Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", id, id2); | |
96 | + return -ENOTSUPP; | |
97 | + } | |
98 | + | |
99 | + break; | |
100 | + case BCMA_CC_FLASHT_ATSER: | |
101 | + bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS); | |
102 | + id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA) & 0x3c; | |
103 | + | |
104 | + for (e = bcma_sflash_at_tbl; e->name; e++) { | |
105 | + if (e->id == id) | |
106 | + break; | |
107 | + } | |
108 | + if (!e->name) { | |
109 | + bcma_err(bus, "Unsupported Atmel serial flash (id: 0x%X)\n", id); | |
110 | + return -ENOTSUPP; | |
111 | + } | |
112 | + | |
113 | + break; | |
114 | + default: | |
115 | + bcma_err(bus, "Unsupported flash type\n"); | |
116 | + return -ENOTSUPP; | |
117 | + } | |
118 | + | |
119 | + sflash->window = BCMA_SFLASH; | |
120 | + sflash->blocksize = e->blocksize; | |
121 | + sflash->numblocks = e->numblocks; | |
122 | + sflash->size = sflash->blocksize * sflash->numblocks; | |
123 | + sflash->present = true; | |
124 | + | |
125 | + bcma_info(bus, "Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n", | |
126 | + e->name, sflash->size / 1024, sflash->blocksize, | |
127 | + sflash->numblocks); | |
128 | + | |
129 | + /* Prepare platform device, but don't register it yet. It's too early, | |
130 | + * malloc (required by device_private_init) is not available yet. */ | |
131 | + bcma_sflash_dev.resource[0].end = bcma_sflash_dev.resource[0].start + | |
132 | + sflash->size; | |
133 | + bcma_sflash_dev.dev.platform_data = sflash; | |
134 | + | |
18 | 135 | return 0; |
19 | 136 | } |
drivers/bcma/main.c
... | ... | @@ -7,6 +7,7 @@ |
7 | 7 | |
8 | 8 | #include "bcma_private.h" |
9 | 9 | #include <linux/module.h> |
10 | +#include <linux/platform_device.h> | |
10 | 11 | #include <linux/bcma/bcma.h> |
11 | 12 | #include <linux/slab.h> |
12 | 13 | |
... | ... | @@ -135,6 +136,14 @@ |
135 | 136 | core->dev_registered = true; |
136 | 137 | dev_id++; |
137 | 138 | } |
139 | + | |
140 | +#ifdef CONFIG_BCMA_SFLASH | |
141 | + if (bus->drv_cc.sflash.present) { | |
142 | + err = platform_device_register(&bcma_sflash_dev); | |
143 | + if (err) | |
144 | + bcma_err(bus, "Error registering serial flash\n"); | |
145 | + } | |
146 | +#endif | |
138 | 147 | |
139 | 148 | return 0; |
140 | 149 | } |
include/linux/bcma/bcma_driver_chipcommon.h
... | ... | @@ -509,6 +509,16 @@ |
509 | 509 | u32 window_size; |
510 | 510 | }; |
511 | 511 | |
512 | +#ifdef CONFIG_BCMA_SFLASH | |
513 | +struct bcma_sflash { | |
514 | + bool present; | |
515 | + u32 window; | |
516 | + u32 blocksize; | |
517 | + u16 numblocks; | |
518 | + u32 size; | |
519 | +}; | |
520 | +#endif | |
521 | + | |
512 | 522 | struct bcma_serial_port { |
513 | 523 | void *regs; |
514 | 524 | unsigned long clockspeed; |
... | ... | @@ -529,6 +539,9 @@ |
529 | 539 | struct bcma_chipcommon_pmu pmu; |
530 | 540 | #ifdef CONFIG_BCMA_DRIVER_MIPS |
531 | 541 | struct bcma_pflash pflash; |
542 | +#ifdef CONFIG_BCMA_SFLASH | |
543 | + struct bcma_sflash sflash; | |
544 | +#endif | |
532 | 545 | |
533 | 546 | int nr_serial_ports; |
534 | 547 | struct bcma_serial_port serial_ports[4]; |