xref: /openbmc/linux/drivers/mtd/devices/sst25l.c (revision 4800cd83)
1 /*
2  * sst25l.c
3  *
4  * Driver for SST25L SPI Flash chips
5  *
6  * Copyright © 2009 Bluewater Systems Ltd
7  * Author: Andre Renaud <andre@bluewatersys.com>
8  * Author: Ryan Mallon <ryan@bluewatersys.com>
9  *
10  * Based on m25p80.c
11  *
12  * This code is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2 as
14  * published by the Free Software Foundation.
15  *
16  */
17 
18 #include <linux/init.h>
19 #include <linux/module.h>
20 #include <linux/device.h>
21 #include <linux/mutex.h>
22 #include <linux/interrupt.h>
23 #include <linux/slab.h>
24 #include <linux/sched.h>
25 
26 #include <linux/mtd/mtd.h>
27 #include <linux/mtd/partitions.h>
28 
29 #include <linux/spi/spi.h>
30 #include <linux/spi/flash.h>
31 
32 /* Erases can take up to 3 seconds! */
33 #define MAX_READY_WAIT_JIFFIES	msecs_to_jiffies(3000)
34 
35 #define SST25L_CMD_WRSR		0x01	/* Write status register */
36 #define SST25L_CMD_WRDI		0x04	/* Write disable */
37 #define SST25L_CMD_RDSR		0x05	/* Read status register */
38 #define SST25L_CMD_WREN		0x06	/* Write enable */
39 #define SST25L_CMD_READ		0x03	/* High speed read */
40 
41 #define SST25L_CMD_EWSR		0x50	/* Enable write status register */
42 #define SST25L_CMD_SECTOR_ERASE	0x20	/* Erase sector */
43 #define SST25L_CMD_READ_ID	0x90	/* Read device ID */
44 #define SST25L_CMD_AAI_PROGRAM	0xaf	/* Auto address increment */
45 
46 #define SST25L_STATUS_BUSY	(1 << 0)	/* Chip is busy */
47 #define SST25L_STATUS_WREN	(1 << 1)	/* Write enabled */
48 #define SST25L_STATUS_BP0	(1 << 2)	/* Block protection 0 */
49 #define SST25L_STATUS_BP1	(1 << 3)	/* Block protection 1 */
50 
51 struct sst25l_flash {
52 	struct spi_device	*spi;
53 	struct mutex		lock;
54 	struct mtd_info		mtd;
55 
56 	int 			partitioned;
57 };
58 
59 struct flash_info {
60 	const char		*name;
61 	uint16_t		device_id;
62 	unsigned		page_size;
63 	unsigned		nr_pages;
64 	unsigned		erase_size;
65 };
66 
67 #define to_sst25l_flash(x) container_of(x, struct sst25l_flash, mtd)
68 
69 static struct flash_info __initdata sst25l_flash_info[] = {
70 	{"sst25lf020a", 0xbf43, 256, 1024, 4096},
71 	{"sst25lf040a",	0xbf44,	256, 2048, 4096},
72 };
73 
74 static int sst25l_status(struct sst25l_flash *flash, int *status)
75 {
76 	struct spi_message m;
77 	struct spi_transfer t;
78 	unsigned char cmd_resp[2];
79 	int err;
80 
81 	spi_message_init(&m);
82 	memset(&t, 0, sizeof(struct spi_transfer));
83 
84 	cmd_resp[0] = SST25L_CMD_RDSR;
85 	cmd_resp[1] = 0xff;
86 	t.tx_buf = cmd_resp;
87 	t.rx_buf = cmd_resp;
88 	t.len = sizeof(cmd_resp);
89 	spi_message_add_tail(&t, &m);
90 	err = spi_sync(flash->spi, &m);
91 	if (err < 0)
92 		return err;
93 
94 	*status = cmd_resp[1];
95 	return 0;
96 }
97 
98 static int sst25l_write_enable(struct sst25l_flash *flash, int enable)
99 {
100 	unsigned char command[2];
101 	int status, err;
102 
103 	command[0] = enable ? SST25L_CMD_WREN : SST25L_CMD_WRDI;
104 	err = spi_write(flash->spi, command, 1);
105 	if (err)
106 		return err;
107 
108 	command[0] = SST25L_CMD_EWSR;
109 	err = spi_write(flash->spi, command, 1);
110 	if (err)
111 		return err;
112 
113 	command[0] = SST25L_CMD_WRSR;
114 	command[1] = enable ? 0 : SST25L_STATUS_BP0 | SST25L_STATUS_BP1;
115 	err = spi_write(flash->spi, command, 2);
116 	if (err)
117 		return err;
118 
119 	if (enable) {
120 		err = sst25l_status(flash, &status);
121 		if (err)
122 			return err;
123 		if (!(status & SST25L_STATUS_WREN))
124 			return -EROFS;
125 	}
126 
127 	return 0;
128 }
129 
130 static int sst25l_wait_till_ready(struct sst25l_flash *flash)
131 {
132 	unsigned long deadline;
133 	int status, err;
134 
135 	deadline = jiffies + MAX_READY_WAIT_JIFFIES;
136 	do {
137 		err = sst25l_status(flash, &status);
138 		if (err)
139 			return err;
140 		if (!(status & SST25L_STATUS_BUSY))
141 			return 0;
142 
143 		cond_resched();
144 	} while (!time_after_eq(jiffies, deadline));
145 
146 	return -ETIMEDOUT;
147 }
148 
149 static int sst25l_erase_sector(struct sst25l_flash *flash, uint32_t offset)
150 {
151 	unsigned char command[4];
152 	int err;
153 
154 	err = sst25l_write_enable(flash, 1);
155 	if (err)
156 		return err;
157 
158 	command[0] = SST25L_CMD_SECTOR_ERASE;
159 	command[1] = offset >> 16;
160 	command[2] = offset >> 8;
161 	command[3] = offset;
162 	err = spi_write(flash->spi, command, 4);
163 	if (err)
164 		return err;
165 
166 	err = sst25l_wait_till_ready(flash);
167 	if (err)
168 		return err;
169 
170 	return sst25l_write_enable(flash, 0);
171 }
172 
173 static int sst25l_erase(struct mtd_info *mtd, struct erase_info *instr)
174 {
175 	struct sst25l_flash *flash = to_sst25l_flash(mtd);
176 	uint32_t addr, end;
177 	int err;
178 
179 	/* Sanity checks */
180 	if (instr->addr + instr->len > flash->mtd.size)
181 		return -EINVAL;
182 
183 	if ((uint32_t)instr->len % mtd->erasesize)
184 		return -EINVAL;
185 
186 	if ((uint32_t)instr->addr % mtd->erasesize)
187 		return -EINVAL;
188 
189 	addr = instr->addr;
190 	end = addr + instr->len;
191 
192 	mutex_lock(&flash->lock);
193 
194 	err = sst25l_wait_till_ready(flash);
195 	if (err) {
196 		mutex_unlock(&flash->lock);
197 		return err;
198 	}
199 
200 	while (addr < end) {
201 		err = sst25l_erase_sector(flash, addr);
202 		if (err) {
203 			mutex_unlock(&flash->lock);
204 			instr->state = MTD_ERASE_FAILED;
205 			dev_err(&flash->spi->dev, "Erase failed\n");
206 			return err;
207 		}
208 
209 		addr += mtd->erasesize;
210 	}
211 
212 	mutex_unlock(&flash->lock);
213 
214 	instr->state = MTD_ERASE_DONE;
215 	mtd_erase_callback(instr);
216 	return 0;
217 }
218 
219 static int sst25l_read(struct mtd_info *mtd, loff_t from, size_t len,
220 		       size_t *retlen, unsigned char *buf)
221 {
222 	struct sst25l_flash *flash = to_sst25l_flash(mtd);
223 	struct spi_transfer transfer[2];
224 	struct spi_message message;
225 	unsigned char command[4];
226 	int ret;
227 
228 	/* Sanity checking */
229 	if (len == 0)
230 		return 0;
231 
232 	if (from + len > flash->mtd.size)
233 		return -EINVAL;
234 
235 	if (retlen)
236 		*retlen = 0;
237 
238 	spi_message_init(&message);
239 	memset(&transfer, 0, sizeof(transfer));
240 
241 	command[0] = SST25L_CMD_READ;
242 	command[1] = from >> 16;
243 	command[2] = from >> 8;
244 	command[3] = from;
245 
246 	transfer[0].tx_buf = command;
247 	transfer[0].len = sizeof(command);
248 	spi_message_add_tail(&transfer[0], &message);
249 
250 	transfer[1].rx_buf = buf;
251 	transfer[1].len = len;
252 	spi_message_add_tail(&transfer[1], &message);
253 
254 	mutex_lock(&flash->lock);
255 
256 	/* Wait for previous write/erase to complete */
257 	ret = sst25l_wait_till_ready(flash);
258 	if (ret) {
259 		mutex_unlock(&flash->lock);
260 		return ret;
261 	}
262 
263 	spi_sync(flash->spi, &message);
264 
265 	if (retlen && message.actual_length > sizeof(command))
266 		*retlen += message.actual_length - sizeof(command);
267 
268 	mutex_unlock(&flash->lock);
269 	return 0;
270 }
271 
272 static int sst25l_write(struct mtd_info *mtd, loff_t to, size_t len,
273 			size_t *retlen, const unsigned char *buf)
274 {
275 	struct sst25l_flash *flash = to_sst25l_flash(mtd);
276 	int i, j, ret, bytes, copied = 0;
277 	unsigned char command[5];
278 
279 	/* Sanity checks */
280 	if (!len)
281 		return 0;
282 
283 	if (to + len > flash->mtd.size)
284 		return -EINVAL;
285 
286 	if ((uint32_t)to % mtd->writesize)
287 		return -EINVAL;
288 
289 	mutex_lock(&flash->lock);
290 
291 	ret = sst25l_write_enable(flash, 1);
292 	if (ret)
293 		goto out;
294 
295 	for (i = 0; i < len; i += mtd->writesize) {
296 		ret = sst25l_wait_till_ready(flash);
297 		if (ret)
298 			goto out;
299 
300 		/* Write the first byte of the page */
301 		command[0] = SST25L_CMD_AAI_PROGRAM;
302 		command[1] = (to + i) >> 16;
303 		command[2] = (to + i) >> 8;
304 		command[3] = (to + i);
305 		command[4] = buf[i];
306 		ret = spi_write(flash->spi, command, 5);
307 		if (ret < 0)
308 			goto out;
309 		copied++;
310 
311 		/*
312 		 * Write the remaining bytes using auto address
313 		 * increment mode
314 		 */
315 		bytes = min_t(uint32_t, mtd->writesize, len - i);
316 		for (j = 1; j < bytes; j++, copied++) {
317 			ret = sst25l_wait_till_ready(flash);
318 			if (ret)
319 				goto out;
320 
321 			command[1] = buf[i + j];
322 			ret = spi_write(flash->spi, command, 2);
323 			if (ret)
324 				goto out;
325 		}
326 	}
327 
328 out:
329 	ret = sst25l_write_enable(flash, 0);
330 
331 	if (retlen)
332 		*retlen = copied;
333 
334 	mutex_unlock(&flash->lock);
335 	return ret;
336 }
337 
338 static struct flash_info *__devinit sst25l_match_device(struct spi_device *spi)
339 {
340 	struct flash_info *flash_info = NULL;
341 	struct spi_message m;
342 	struct spi_transfer t;
343 	unsigned char cmd_resp[6];
344 	int i, err;
345 	uint16_t id;
346 
347 	spi_message_init(&m);
348 	memset(&t, 0, sizeof(struct spi_transfer));
349 
350 	cmd_resp[0] = SST25L_CMD_READ_ID;
351 	cmd_resp[1] = 0;
352 	cmd_resp[2] = 0;
353 	cmd_resp[3] = 0;
354 	cmd_resp[4] = 0xff;
355 	cmd_resp[5] = 0xff;
356 	t.tx_buf = cmd_resp;
357 	t.rx_buf = cmd_resp;
358 	t.len = sizeof(cmd_resp);
359 	spi_message_add_tail(&t, &m);
360 	err = spi_sync(spi, &m);
361 	if (err < 0) {
362 		dev_err(&spi->dev, "error reading device id\n");
363 		return NULL;
364 	}
365 
366 	id = (cmd_resp[4] << 8) | cmd_resp[5];
367 
368 	for (i = 0; i < ARRAY_SIZE(sst25l_flash_info); i++)
369 		if (sst25l_flash_info[i].device_id == id)
370 			flash_info = &sst25l_flash_info[i];
371 
372 	if (!flash_info)
373 		dev_err(&spi->dev, "unknown id %.4x\n", id);
374 
375 	return flash_info;
376 }
377 
378 static int __devinit sst25l_probe(struct spi_device *spi)
379 {
380 	struct flash_info *flash_info;
381 	struct sst25l_flash *flash;
382 	struct flash_platform_data *data;
383 	int ret, i;
384 
385 	flash_info = sst25l_match_device(spi);
386 	if (!flash_info)
387 		return -ENODEV;
388 
389 	flash = kzalloc(sizeof(struct sst25l_flash), GFP_KERNEL);
390 	if (!flash)
391 		return -ENOMEM;
392 
393 	flash->spi = spi;
394 	mutex_init(&flash->lock);
395 	dev_set_drvdata(&spi->dev, flash);
396 
397 	data = spi->dev.platform_data;
398 	if (data && data->name)
399 		flash->mtd.name = data->name;
400 	else
401 		flash->mtd.name = dev_name(&spi->dev);
402 
403 	flash->mtd.type		= MTD_NORFLASH;
404 	flash->mtd.flags	= MTD_CAP_NORFLASH;
405 	flash->mtd.erasesize	= flash_info->erase_size;
406 	flash->mtd.writesize	= flash_info->page_size;
407 	flash->mtd.size		= flash_info->page_size * flash_info->nr_pages;
408 	flash->mtd.erase	= sst25l_erase;
409 	flash->mtd.read		= sst25l_read;
410 	flash->mtd.write 	= sst25l_write;
411 
412 	dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name,
413 		 (long long)flash->mtd.size >> 10);
414 
415 	DEBUG(MTD_DEBUG_LEVEL2,
416 	      "mtd .name = %s, .size = 0x%llx (%lldMiB) "
417 	      ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
418 	      flash->mtd.name,
419 	      (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
420 	      flash->mtd.erasesize, flash->mtd.erasesize / 1024,
421 	      flash->mtd.numeraseregions);
422 
423 	if (mtd_has_partitions()) {
424 		struct mtd_partition *parts = NULL;
425 		int nr_parts = 0;
426 
427 		if (mtd_has_cmdlinepart()) {
428 			static const char *part_probes[] =
429 				{"cmdlinepart", NULL};
430 
431 			nr_parts = parse_mtd_partitions(&flash->mtd,
432 							part_probes,
433 							&parts, 0);
434 		}
435 
436 		if (nr_parts <= 0 && data && data->parts) {
437 			parts = data->parts;
438 			nr_parts = data->nr_parts;
439 		}
440 
441 		if (nr_parts > 0) {
442 			for (i = 0; i < nr_parts; i++) {
443 				DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
444 				      "{.name = %s, .offset = 0x%llx, "
445 				      ".size = 0x%llx (%lldKiB) }\n",
446 				      i, parts[i].name,
447 				      (long long)parts[i].offset,
448 				      (long long)parts[i].size,
449 				      (long long)(parts[i].size >> 10));
450 			}
451 
452 			flash->partitioned = 1;
453 			return add_mtd_partitions(&flash->mtd,
454 						  parts, nr_parts);
455 		}
456 
457 	} else if (data && data->nr_parts) {
458 		dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
459 			 data->nr_parts, data->name);
460 	}
461 
462 	ret = add_mtd_device(&flash->mtd);
463 	if (ret == 1) {
464 		kfree(flash);
465 		dev_set_drvdata(&spi->dev, NULL);
466 		return -ENODEV;
467 	}
468 
469 	return 0;
470 }
471 
472 static int __exit sst25l_remove(struct spi_device *spi)
473 {
474 	struct sst25l_flash *flash = dev_get_drvdata(&spi->dev);
475 	int ret;
476 
477 	if (mtd_has_partitions() && flash->partitioned)
478 		ret = del_mtd_partitions(&flash->mtd);
479 	else
480 		ret = del_mtd_device(&flash->mtd);
481 	if (ret == 0)
482 		kfree(flash);
483 	return ret;
484 }
485 
486 static struct spi_driver sst25l_driver = {
487 	.driver = {
488 		.name	= "sst25l",
489 		.bus	= &spi_bus_type,
490 		.owner	= THIS_MODULE,
491 	},
492 	.probe		= sst25l_probe,
493 	.remove		= __exit_p(sst25l_remove),
494 };
495 
496 static int __init sst25l_init(void)
497 {
498 	return spi_register_driver(&sst25l_driver);
499 }
500 
501 static void __exit sst25l_exit(void)
502 {
503 	spi_unregister_driver(&sst25l_driver);
504 }
505 
506 module_init(sst25l_init);
507 module_exit(sst25l_exit);
508 
509 MODULE_DESCRIPTION("MTD SPI driver for SST25L Flash chips");
510 MODULE_AUTHOR("Andre Renaud <andre@bluewatersys.com>, "
511 	      "Ryan Mallon <ryan@bluewatersys.com>");
512 MODULE_LICENSE("GPL");
513