diff options
author | Rafał Miłecki <zajec5@gmail.com> | 2012-08-10 15:23:53 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-08-21 16:05:52 -0400 |
commit | d57ef3a6a2eeb88df47e892c66692e3f59722ffe (patch) | |
tree | db2f260a55ce24cfed110cb6281674a5fbcb0a86 | |
parent | 01e17dacd47101ad7d33152bbfbbd4394352d2e6 (diff) |
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>
-rw-r--r-- | drivers/bcma/Kconfig | 2 | ||||
-rw-r--r-- | drivers/bcma/bcma_private.h | 1 | ||||
-rw-r--r-- | drivers/bcma/driver_chipcommon_sflash.c | 123 | ||||
-rw-r--r-- | drivers/bcma/main.c | 9 | ||||
-rw-r--r-- | include/linux/bcma/bcma_driver_chipcommon.h | 13 | ||||
-rw-r--r-- | include/linux/bcma/bcma_regs.h | 2 |
6 files changed, 146 insertions, 4 deletions
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig index 06b3207adeb..cf6e4dd22fd 100644 --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig | |||
@@ -48,7 +48,7 @@ config BCMA_DRIVER_MIPS | |||
48 | 48 | ||
49 | config BCMA_SFLASH | 49 | config BCMA_SFLASH |
50 | bool | 50 | bool |
51 | depends on BCMA_DRIVER_MIPS && BROKEN | 51 | depends on BCMA_DRIVER_MIPS |
52 | default y | 52 | default y |
53 | 53 | ||
54 | config BCMA_NFLASH | 54 | config BCMA_NFLASH |
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 3cf9cc923cd..94bf07c54a4 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
@@ -54,6 +54,7 @@ u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc); | |||
54 | #ifdef CONFIG_BCMA_SFLASH | 54 | #ifdef CONFIG_BCMA_SFLASH |
55 | /* driver_chipcommon_sflash.c */ | 55 | /* driver_chipcommon_sflash.c */ |
56 | int bcma_sflash_init(struct bcma_drv_cc *cc); | 56 | int bcma_sflash_init(struct bcma_drv_cc *cc); |
57 | extern struct platform_device bcma_sflash_dev; | ||
57 | #else | 58 | #else |
58 | static inline int bcma_sflash_init(struct bcma_drv_cc *cc) | 59 | static inline int bcma_sflash_init(struct bcma_drv_cc *cc) |
59 | { | 60 | { |
diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c index 6e157a58a1d..2c4eec2ca5a 100644 --- a/drivers/bcma/driver_chipcommon_sflash.c +++ b/drivers/bcma/driver_chipcommon_sflash.c | |||
@@ -5,15 +5,132 @@ | |||
5 | * Licensed under the GNU/GPL. See COPYING for details. | 5 | * Licensed under the GNU/GPL. See COPYING for details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/platform_device.h> | ||
8 | #include <linux/bcma/bcma.h> | 9 | #include <linux/bcma/bcma.h> |
9 | #include <linux/bcma/bcma_driver_chipcommon.h> | ||
10 | #include <linux/delay.h> | ||
11 | 10 | ||
12 | #include "bcma_private.h" | 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 | /* Initialize serial flash access */ | 60 | /* Initialize serial flash access */ |
15 | int bcma_sflash_init(struct bcma_drv_cc *cc) | 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 | return 0; | 135 | return 0; |
19 | } | 136 | } |
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 758af9ccdef..a501d259287 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -7,6 +7,7 @@ | |||
7 | 7 | ||
8 | #include "bcma_private.h" | 8 | #include "bcma_private.h" |
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/platform_device.h> | ||
10 | #include <linux/bcma/bcma.h> | 11 | #include <linux/bcma/bcma.h> |
11 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
12 | 13 | ||
@@ -136,6 +137,14 @@ static int bcma_register_cores(struct bcma_bus *bus) | |||
136 | dev_id++; | 137 | dev_id++; |
137 | } | 138 | } |
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 | ||
147 | |||
139 | return 0; | 148 | return 0; |
140 | } | 149 | } |
141 | 150 | ||
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index fcb06fb284e..bed89694c5f 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
@@ -509,6 +509,16 @@ struct bcma_pflash { | |||
509 | u32 window_size; | 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 | struct bcma_serial_port { | 522 | struct bcma_serial_port { |
513 | void *regs; | 523 | void *regs; |
514 | unsigned long clockspeed; | 524 | unsigned long clockspeed; |
@@ -529,6 +539,9 @@ struct bcma_drv_cc { | |||
529 | struct bcma_chipcommon_pmu pmu; | 539 | struct bcma_chipcommon_pmu pmu; |
530 | #ifdef CONFIG_BCMA_DRIVER_MIPS | 540 | #ifdef CONFIG_BCMA_DRIVER_MIPS |
531 | struct bcma_pflash pflash; | 541 | struct bcma_pflash pflash; |
542 | #ifdef CONFIG_BCMA_SFLASH | ||
543 | struct bcma_sflash sflash; | ||
544 | #endif | ||
532 | 545 | ||
533 | int nr_serial_ports; | 546 | int nr_serial_ports; |
534 | struct bcma_serial_port serial_ports[4]; | 547 | struct bcma_serial_port serial_ports[4]; |
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h index a393e82bf7b..6c9cb93ae3d 100644 --- a/include/linux/bcma/bcma_regs.h +++ b/include/linux/bcma/bcma_regs.h | |||
@@ -85,4 +85,6 @@ | |||
85 | * (2 ZettaBytes), high 32 bits | 85 | * (2 ZettaBytes), high 32 bits |
86 | */ | 86 | */ |
87 | 87 | ||
88 | #define BCMA_SFLASH 0x1c000000 | ||
89 | |||
88 | #endif /* LINUX_BCMA_REGS_H_ */ | 90 | #endif /* LINUX_BCMA_REGS_H_ */ |