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 06b3207adebd..cf6e4dd22fd2 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 3cf9cc923cd2..94bf07c54a43 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 6e157a58a1d7..2c4eec2ca5a0 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 758af9ccdef0..a501d259287c 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 | } | ||
