1 #include <linux/module.h>
2 #include <linux/delay.h>
3 #include <linux/spi/spi.h>
4 #include <linux/mtd/spi-nor.h>
5 #include <linux/mtd/mtd.h>
6 #include <linux/mtd/cfi.h>
7 #include <linux/mtd/partitions.h>
9 static const char * const probes
[] = { "ofpart", "bcm47xxpart", NULL
};
12 struct spi_device
*spi
;
16 /**************************************************
18 **************************************************/
20 static int bcm53xxspiflash_read_reg(struct spi_nor
*nor
, u8 opcode
, u8
*buf
,
23 struct bcm53xxsf
*b53sf
= nor
->priv
;
25 return spi_write_then_read(b53sf
->spi
, &opcode
, 1, buf
, len
);
28 static int bcm53xxspiflash_write_reg(struct spi_nor
*nor
, u8 opcode
, u8
*buf
,
31 struct bcm53xxsf
*b53sf
= nor
->priv
;
32 u8
*cmd
= kzalloc(len
+ 1, GFP_KERNEL
);
39 memcpy(&cmd
[1], buf
, len
);
40 err
= spi_write(b53sf
->spi
, cmd
, len
+ 1);
47 static int bcm53xxspiflash_read(struct spi_nor
*nor
, loff_t from
, size_t len
,
48 size_t *retlen
, u_char
*buf
)
50 struct bcm53xxsf
*b53sf
= nor
->priv
;
52 struct spi_transfer t
[2] = { { 0 }, { 0 } };
59 cmd
[cmd_len
++] = SPINOR_OP_READ
;
60 if (nor
->mtd
.size
> 0x1000000)
61 cmd
[cmd_len
++] = (from
& 0xFF000000) >> 24;
62 cmd
[cmd_len
++] = (from
& 0x00FF0000) >> 16;
63 cmd
[cmd_len
++] = (from
& 0x0000FF00) >> 8;
64 cmd
[cmd_len
++] = (from
& 0x000000FF) >> 0;
68 spi_message_add_tail(&t
[0], &m
);
72 spi_message_add_tail(&t
[1], &m
);
74 err
= spi_sync(b53sf
->spi
, &m
);
78 if (retlen
&& m
.actual_length
> cmd_len
)
79 *retlen
= m
.actual_length
- cmd_len
;
84 static void bcm53xxspiflash_write(struct spi_nor
*nor
, loff_t to
, size_t len
,
85 size_t *retlen
, const u_char
*buf
)
87 struct bcm53xxsf
*b53sf
= nor
->priv
;
89 struct spi_transfer t
= { 0 };
90 u8
*cmd
= kzalloc(len
+ 5, GFP_KERNEL
);
99 cmd
[cmd_len
++] = nor
->program_opcode
;
100 if (nor
->mtd
.size
> 0x1000000)
101 cmd
[cmd_len
++] = (to
& 0xFF000000) >> 24;
102 cmd
[cmd_len
++] = (to
& 0x00FF0000) >> 16;
103 cmd
[cmd_len
++] = (to
& 0x0000FF00) >> 8;
104 cmd
[cmd_len
++] = (to
& 0x000000FF) >> 0;
105 memcpy(&cmd
[cmd_len
], buf
, len
);
108 t
.len
= cmd_len
+ len
;
109 spi_message_add_tail(&t
, &m
);
111 err
= spi_sync(b53sf
->spi
, &m
);
115 if (retlen
&& m
.actual_length
> cmd_len
)
116 *retlen
+= m
.actual_length
- cmd_len
;
122 static int bcm53xxspiflash_erase(struct spi_nor
*nor
, loff_t offs
)
124 struct bcm53xxsf
*b53sf
= nor
->priv
;
125 unsigned char cmd
[5];
129 cmd
[i
++] = nor
->erase_opcode
;
130 if (nor
->mtd
.size
> 0x1000000)
131 cmd
[i
++] = (offs
& 0xFF000000) >> 24;
132 cmd
[i
++] = ((offs
& 0x00FF0000) >> 16);
133 cmd
[i
++] = ((offs
& 0x0000FF00) >> 8);
134 cmd
[i
++] = ((offs
& 0x000000FF) >> 0);
136 return spi_write(b53sf
->spi
, cmd
, i
);
139 static const char *bcm53xxspiflash_chip_name(struct spi_nor
*nor
)
141 struct bcm53xxsf
*b53sf
= nor
->priv
;
142 struct device
*dev
= &b53sf
->spi
->dev
;
143 unsigned char cmd
[4];
144 unsigned char resp
[2];
147 /* SST and Winbond/NexFlash specific command */
148 cmd
[0] = 0x90; /* Read Manufacturer / Device ID */
152 err
= spi_write_then_read(b53sf
->spi
, cmd
, 4, resp
, 2);
154 dev_err(dev
, "error reading SPI flash id\n");
155 return ERR_PTR(-EBUSY
);
158 case 0xef: /* Winbond/NexFlash */
163 dev_err(dev
, "Unknown Winbond/NexFlash flash: %02X %02X\n",
168 /* TODO: Try more ID commands */
173 /**************************************************
175 **************************************************/
177 static int bcm53xxspiflash_probe(struct spi_device
*spi
)
179 struct mtd_part_parser_data parser_data
= {};
180 struct bcm53xxsf
*b53sf
;
184 b53sf
= devm_kzalloc(&spi
->dev
, sizeof(*b53sf
), GFP_KERNEL
);
187 spi_set_drvdata(spi
, b53sf
);
192 nor
->dev
= &spi
->dev
;
193 nor
->read_reg
= bcm53xxspiflash_read_reg
;
194 nor
->write_reg
= bcm53xxspiflash_write_reg
;
195 nor
->read
= bcm53xxspiflash_read
;
196 nor
->write
= bcm53xxspiflash_write
;
197 nor
->erase
= bcm53xxspiflash_erase
;
200 err
= spi_nor_scan(&b53sf
->nor
, bcm53xxspiflash_chip_name(nor
),
205 parser_data
.of_node
= spi
->master
->dev
.parent
->of_node
;
206 err
= mtd_device_parse_register(&nor
->mtd
, probes
, &parser_data
,
214 static int bcm53xxspiflash_remove(struct spi_device
*spi
)
219 static struct spi_driver bcm53xxspiflash_driver
= {
221 .name
= "bcm53xxspiflash",
222 .owner
= THIS_MODULE
,
224 .probe
= bcm53xxspiflash_probe
,
225 .remove
= bcm53xxspiflash_remove
,
228 module_spi_driver(bcm53xxspiflash_driver
);