Commit d57ef3a6a2eeb88df47e892c66692e3f59722ffe

Authored by Rafał Miłecki
Committed by John W. Linville
1 parent 01e17dacd4

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
... ... @@ -48,7 +48,7 @@
48 48  
49 49 config BCMA_SFLASH
50 50 bool
51   - depends on BCMA_DRIVER_MIPS && BROKEN
  51 + depends on BCMA_DRIVER_MIPS
52 52 default y
53 53  
54 54 config BCMA_NFLASH
drivers/bcma/bcma_private.h
... ... @@ -54,6 +54,7 @@
54 54 #ifdef CONFIG_BCMA_SFLASH
55 55 /* driver_chipcommon_sflash.c */
56 56 int bcma_sflash_init(struct bcma_drv_cc *cc);
  57 +extern struct platform_device bcma_sflash_dev;
57 58 #else
58 59 static inline int bcma_sflash_init(struct bcma_drv_cc *cc)
59 60 {
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 }
... ... @@ -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];
include/linux/bcma/bcma_regs.h
... ... @@ -85,5 +85,7 @@
85 85 * (2 ZettaBytes), high 32 bits
86 86 */
87 87  
  88 +#define BCMA_SFLASH 0x1c000000
  89 +
88 90 #endif /* LINUX_BCMA_REGS_H_ */