2 * Broadcom specific AMBA
3 * ChipCommon serial flash interface
5 * Licensed under the GNU/GPL. See COPYING for details.
8 #include <linux/platform_device.h>
9 #include <linux/bcma/bcma.h>
11 #include "bcma_private.h"
13 static struct resource bcma_sflash_resource
= {
14 .name
= "bcma_sflash",
17 .flags
= IORESOURCE_MEM
| IORESOURCE_READONLY
,
20 struct platform_device bcma_sflash_dev
= {
21 .name
= "bcma_sflash",
22 .resource
= &bcma_sflash_resource
,
26 struct bcma_sflash_tbl_e
{
33 static struct bcma_sflash_tbl_e bcma_sflash_st_tbl
[] = {
34 { "", 0x14, 0x10000, 32, },
38 static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl
[] = {
42 static struct bcma_sflash_tbl_e bcma_sflash_at_tbl
[] = {
46 static void bcma_sflash_cmd(struct bcma_drv_cc
*cc
, u32 opcode
)
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
))
57 bcma_err(cc
->core
->bus
, "SFLASH control command failed (timeout)!\n");
60 /* Initialize serial flash access */
61 int bcma_sflash_init(struct bcma_drv_cc
*cc
)
63 struct bcma_bus
*bus
= cc
->core
->bus
;
64 struct bcma_sflash
*sflash
= &cc
->sflash
;
65 struct bcma_sflash_tbl_e
*e
;
68 switch (cc
->capabilities
& BCMA_CC_CAP_FLASHT
) {
69 case BCMA_CC_FLASHT_STSER
:
70 bcma_sflash_cmd(cc
, BCMA_CC_FLASHCTL_ST_DP
);
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
);
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
);
82 for (e
= bcma_sflash_sst_tbl
; e
->name
; e
++) {
88 for (e
= bcma_sflash_st_tbl
; e
->name
; e
++) {
95 bcma_err(bus
, "Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", id
, id2
);
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;
104 for (e
= bcma_sflash_at_tbl
; e
->name
; e
++) {
109 bcma_err(bus
, "Unsupported Atmel serial flash (id: 0x%X)\n", id
);
115 bcma_err(bus
, "Unsupported flash type\n");
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;
125 bcma_info(bus
, "Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n",
126 e
->name
, sflash
->size
/ 1024, sflash
->blocksize
,
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
+
133 bcma_sflash_dev
.dev
.platform_data
= sflash
;