bcm53xx: backport spi-nor changes and update bcm53xxspiflash
[openwrt/openwrt.git] / target / linux / bcm53xx / files / drivers / mtd / spi-nor / bcm53xxspiflash.c
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
8 static const char * const probes[] = { "bcm47xxpart", NULL };
9
10 struct bcm53xxsf {
11 struct spi_device *spi;
12 struct mtd_info mtd;
13 struct spi_nor nor;
14 };
15
16 /**************************************************
17 * spi-nor API
18 **************************************************/
19
20 static int bcm53xxspiflash_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
21 int len)
22 {
23 struct bcm53xxsf *b53sf = nor->priv;
24
25 return spi_write_then_read(b53sf->spi, &opcode, 1, buf, len);
26 }
27
28 static int bcm53xxspiflash_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
29 int len, int write_enable)
30 {
31 struct bcm53xxsf *b53sf = nor->priv;
32 u8 *cmd = kzalloc(len + 1, GFP_KERNEL);
33 int err;
34
35 if (!cmd)
36 return -ENOMEM;
37
38 cmd[0] = opcode;
39 memcpy(&cmd[1], buf, len);
40 err = spi_write(b53sf->spi, cmd, len + 1);
41
42 kfree(cmd);
43
44 return err;
45 }
46
47 static int bcm53xxspiflash_read(struct spi_nor *nor, loff_t from, size_t len,
48 size_t *retlen, u_char *buf)
49 {
50 struct bcm53xxsf *b53sf = nor->priv;
51 struct spi_message m;
52 struct spi_transfer t[2] = { { 0 }, { 0 } };
53 unsigned char cmd[5];
54 int cmd_len = 0;
55 int err;
56
57 spi_message_init(&m);
58
59 cmd[cmd_len++] = SPINOR_OP_READ;
60 if (b53sf->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;
65
66 t[0].tx_buf = cmd;
67 t[0].len = cmd_len;
68 spi_message_add_tail(&t[0], &m);
69
70 t[1].rx_buf = buf;
71 t[1].len = len;
72 spi_message_add_tail(&t[1], &m);
73
74 err = spi_sync(b53sf->spi, &m);
75 if (err)
76 return err;
77
78 if (retlen && m.actual_length > cmd_len)
79 *retlen = m.actual_length - cmd_len;
80
81 return 0;
82 }
83
84 static void bcm53xxspiflash_write(struct spi_nor *nor, loff_t to, size_t len,
85 size_t *retlen, const u_char *buf)
86 {
87 struct bcm53xxsf *b53sf = nor->priv;
88 struct spi_message m;
89 struct spi_transfer t = { 0 };
90 u8 *cmd = kzalloc(len + 5, GFP_KERNEL);
91 int cmd_len = 0;
92 int err;
93
94 if (!cmd)
95 return;
96
97 spi_message_init(&m);
98
99 cmd[cmd_len++] = nor->program_opcode;
100 if (b53sf->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);
106
107 t.tx_buf = cmd;
108 t.len = cmd_len + len;
109 spi_message_add_tail(&t, &m);
110
111 err = spi_sync(b53sf->spi, &m);
112 if (err)
113 goto out;
114
115 if (retlen && m.actual_length > cmd_len)
116 *retlen += m.actual_length - cmd_len;
117
118 out:
119 kfree(cmd);
120 }
121
122 static int bcm53xxspiflash_erase(struct spi_nor *nor, loff_t offs)
123 {
124 struct bcm53xxsf *b53sf = nor->priv;
125 unsigned char cmd[5];
126 int i;
127
128 i = 0;
129 cmd[i++] = nor->erase_opcode;
130 if (b53sf->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);
135
136 return spi_write(b53sf->spi, cmd, i);
137 }
138
139 static const char *bcm53xxspiflash_chip_name(struct spi_nor *nor)
140 {
141 struct bcm53xxsf *b53sf = nor->priv;
142 struct device *dev = &b53sf->spi->dev;
143 unsigned char cmd[4];
144 unsigned char resp[2];
145 int err;
146
147 /* SST and Winbond/NexFlash specific command */
148 cmd[0] = 0x90; /* Read Manufacturer / Device ID */
149 cmd[1] = 0;
150 cmd[2] = 0;
151 cmd[3] = 0;
152 err = spi_write_then_read(b53sf->spi, cmd, 4, resp, 2);
153 if (err < 0) {
154 dev_err(dev, "error reading SPI flash id\n");
155 return ERR_PTR(-EBUSY);
156 }
157 switch (resp[0]) {
158 case 0xef: /* Winbond/NexFlash */
159 switch (resp[1]) {
160 case 0x17:
161 return "w25q128";
162 }
163 dev_err(dev, "Unknown Winbond/NexFlash flash: %02X %02X\n",
164 resp[0], resp[1]);
165 return NULL;
166 }
167
168 /* TODO: Try more ID commands */
169
170 return NULL;
171 }
172
173 /**************************************************
174 * SPI driver
175 **************************************************/
176
177 static int bcm53xxspiflash_probe(struct spi_device *spi)
178 {
179 struct bcm53xxsf *b53sf;
180 struct spi_nor *nor;
181 int err;
182
183 b53sf = devm_kzalloc(&spi->dev, sizeof(*b53sf), GFP_KERNEL);
184 if (!b53sf)
185 return -ENOMEM;
186 spi_set_drvdata(spi, b53sf);
187
188 nor = &b53sf->nor;
189 b53sf->spi = spi;
190 b53sf->mtd.priv = &b53sf->nor;
191
192 nor->mtd = &b53sf->mtd;
193 nor->dev = &spi->dev;
194 nor->read_reg = bcm53xxspiflash_read_reg;
195 nor->write_reg = bcm53xxspiflash_write_reg;
196 nor->read = bcm53xxspiflash_read;
197 nor->write = bcm53xxspiflash_write;
198 nor->erase = bcm53xxspiflash_erase;
199 nor->priv = b53sf;
200
201 err = spi_nor_scan(&b53sf->nor, bcm53xxspiflash_chip_name(nor),
202 SPI_NOR_NORMAL);
203 if (err)
204 return err;
205
206 err = mtd_device_parse_register(&b53sf->mtd, probes, NULL, NULL, 0);
207 if (err)
208 return err;
209
210 return 0;
211 }
212
213 static int bcm53xxspiflash_remove(struct spi_device *spi)
214 {
215 return 0;
216 }
217
218 static struct spi_driver bcm53xxspiflash_driver = {
219 .driver = {
220 .name = "bcm53xxspiflash",
221 .owner = THIS_MODULE,
222 },
223 .probe = bcm53xxspiflash_probe,
224 .remove = bcm53xxspiflash_remove,
225 };
226
227 module_spi_driver(bcm53xxspiflash_driver);