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;
17 /**************************************************
19 **************************************************/
21 static int bcm53xxspiflash_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
24 struct bcm53xxsf *b53sf = nor->priv;
26 return spi_write_then_read(b53sf->spi, &opcode, 1, buf, len);
29 static int bcm53xxspiflash_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
30 int len, int write_enable)
32 struct bcm53xxsf *b53sf = nor->priv;
33 u8 *cmd = kzalloc(len + 1, GFP_KERNEL);
40 memcpy(&cmd[1], buf, len);
41 err = spi_write(b53sf->spi, cmd, len + 1);
48 static int bcm53xxspiflash_read(struct spi_nor *nor, loff_t from, size_t len,
49 size_t *retlen, u_char *buf)
51 struct bcm53xxsf *b53sf = nor->priv;
53 struct spi_transfer t[2] = { { 0 }, { 0 } };
60 cmd[cmd_len++] = SPINOR_OP_READ;
61 if (b53sf->mtd.size > 0x1000000)
62 cmd[cmd_len++] = (from & 0xFF000000) >> 24;
63 cmd[cmd_len++] = (from & 0x00FF0000) >> 16;
64 cmd[cmd_len++] = (from & 0x0000FF00) >> 8;
65 cmd[cmd_len++] = (from & 0x000000FF) >> 0;
69 spi_message_add_tail(&t[0], &m);
73 spi_message_add_tail(&t[1], &m);
75 err = spi_sync(b53sf->spi, &m);
79 if (retlen && m.actual_length > cmd_len)
80 *retlen = m.actual_length - cmd_len;
85 static void bcm53xxspiflash_write(struct spi_nor *nor, loff_t to, size_t len,
86 size_t *retlen, const u_char *buf)
88 struct bcm53xxsf *b53sf = nor->priv;
90 struct spi_transfer t = { 0 };
91 u8 *cmd = kzalloc(len + 5, GFP_KERNEL);
100 cmd[cmd_len++] = nor->program_opcode;
101 if (b53sf->mtd.size > 0x1000000)
102 cmd[cmd_len++] = (to & 0xFF000000) >> 24;
103 cmd[cmd_len++] = (to & 0x00FF0000) >> 16;
104 cmd[cmd_len++] = (to & 0x0000FF00) >> 8;
105 cmd[cmd_len++] = (to & 0x000000FF) >> 0;
106 memcpy(&cmd[cmd_len], buf, len);
109 t.len = cmd_len + len;
110 spi_message_add_tail(&t, &m);
112 err = spi_sync(b53sf->spi, &m);
116 if (retlen && m.actual_length > cmd_len)
117 *retlen += m.actual_length - cmd_len;
123 static int bcm53xxspiflash_erase(struct spi_nor *nor, loff_t offs)
125 struct bcm53xxsf *b53sf = nor->priv;
126 unsigned char cmd[5];
130 cmd[i++] = nor->erase_opcode;
131 if (b53sf->mtd.size > 0x1000000)
132 cmd[i++] = (offs & 0xFF000000) >> 24;
133 cmd[i++] = ((offs & 0x00FF0000) >> 16);
134 cmd[i++] = ((offs & 0x0000FF00) >> 8);
135 cmd[i++] = ((offs & 0x000000FF) >> 0);
137 return spi_write(b53sf->spi, cmd, i);
140 static const char *bcm53xxspiflash_chip_name(struct spi_nor *nor)
142 struct bcm53xxsf *b53sf = nor->priv;
143 struct device *dev = &b53sf->spi->dev;
144 unsigned char cmd[4];
145 unsigned char resp[2];
148 /* SST and Winbond/NexFlash specific command */
149 cmd[0] = 0x90; /* Read Manufacturer / Device ID */
153 err = spi_write_then_read(b53sf->spi, cmd, 4, resp, 2);
155 dev_err(dev, "error reading SPI flash id\n");
156 return ERR_PTR(-EBUSY);
159 case 0xef: /* Winbond/NexFlash */
164 dev_err(dev, "Unknown Winbond/NexFlash flash: %02X %02X\n",
169 /* TODO: Try more ID commands */
174 /**************************************************
176 **************************************************/
178 static int bcm53xxspiflash_probe(struct spi_device *spi)
180 struct mtd_part_parser_data parser_data = {};
181 struct bcm53xxsf *b53sf;
185 b53sf = devm_kzalloc(&spi->dev, sizeof(*b53sf), GFP_KERNEL);
188 spi_set_drvdata(spi, b53sf);
192 b53sf->mtd.priv = &b53sf->nor;
194 nor->mtd = &b53sf->mtd;
195 nor->dev = &spi->dev;
196 nor->read_reg = bcm53xxspiflash_read_reg;
197 nor->write_reg = bcm53xxspiflash_write_reg;
198 nor->read = bcm53xxspiflash_read;
199 nor->write = bcm53xxspiflash_write;
200 nor->erase = bcm53xxspiflash_erase;
203 err = spi_nor_scan(&b53sf->nor, bcm53xxspiflash_chip_name(nor),
208 parser_data.of_node = spi->master->dev.parent->of_node;
209 err = mtd_device_parse_register(&b53sf->mtd, probes, &parser_data,
217 static int bcm53xxspiflash_remove(struct spi_device *spi)
222 static struct spi_driver bcm53xxspiflash_driver = {
224 .name = "bcm53xxspiflash",
225 .owner = THIS_MODULE,
227 .probe = bcm53xxspiflash_probe,
228 .remove = bcm53xxspiflash_remove,
231 module_spi_driver(bcm53xxspiflash_driver);