xref: /openbmc/linux/drivers/mtd/devices/sst25l.c (revision a0386bba)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * sst25l.c
4  *
5  * Driver for SST25L SPI Flash chips
6  *
7  * Copyright © 2009 Bluewater Systems Ltd
8  * Author: Andre Renaud <andre@bluewatersys.com>
9  * Author: Ryan Mallon
10  *
11  * Based on m25p80.c
12  */
13 
14 #include <linux/module.h>
15 #include <linux/device.h>
16 #include <linux/mutex.h>
17 #include <linux/interrupt.h>
18 #include <linux/slab.h>
19 #include <linux/sched.h>
20 
21 #include <linux/mtd/mtd.h>
22 #include <linux/mtd/partitions.h>
23 
24 #include <linux/spi/spi.h>
25 #include <linux/spi/flash.h>
26 
27 /* Erases can take up to 3 seconds! */
28 #define MAX_READY_WAIT_JIFFIES	msecs_to_jiffies(3000)
29 
30 #define SST25L_CMD_WRSR		0x01	/* Write status register */
31 #define SST25L_CMD_WRDI		0x04	/* Write disable */
32 #define SST25L_CMD_RDSR		0x05	/* Read status register */
33 #define SST25L_CMD_WREN		0x06	/* Write enable */
34 #define SST25L_CMD_READ		0x03	/* High speed read */
35 
36 #define SST25L_CMD_EWSR		0x50	/* Enable write status register */
37 #define SST25L_CMD_SECTOR_ERASE	0x20	/* Erase sector */
38 #define SST25L_CMD_READ_ID	0x90	/* Read device ID */
39 #define SST25L_CMD_AAI_PROGRAM	0xaf	/* Auto address increment */
40 
41 #define SST25L_STATUS_BUSY	(1 << 0)	/* Chip is busy */
42 #define SST25L_STATUS_WREN	(1 << 1)	/* Write enabled */
43 #define SST25L_STATUS_BP0	(1 << 2)	/* Block protection 0 */
44 #define SST25L_STATUS_BP1	(1 << 3)	/* Block protection 1 */
45 
46 struct sst25l_flash {
47 	struct spi_device	*spi;
48 	struct mutex		lock;
49 	struct mtd_info		mtd;
50 };
51 
52 struct flash_info {
53 	const char		*name;
54 	uint16_t		device_id;
55 	unsigned		page_size;
56 	unsigned		nr_pages;
57 	unsigned		erase_size;
58 };
59 
60 #define to_sst25l_flash(x) container_of(x, struct sst25l_flash, mtd)
61 
62 static struct flash_info sst25l_flash_info[] = {
63 	{"sst25lf020a", 0xbf43, 256, 1024, 4096},
64 	{"sst25lf040a",	0xbf44,	256, 2048, 4096},
65 };
66 
sst25l_status(struct sst25l_flash * flash,int * status)67 static int sst25l_status(struct sst25l_flash *flash, int *status)
68 {
69 	struct spi_message m;
70 	struct spi_transfer t;
71 	unsigned char cmd_resp[2];
72 	int err;
73 
74 	spi_message_init(&m);
75 	memset(&t, 0, sizeof(struct spi_transfer));
76 
77 	cmd_resp[0] = SST25L_CMD_RDSR;
78 	cmd_resp[1] = 0xff;
79 	t.tx_buf = cmd_resp;
80 	t.rx_buf = cmd_resp;
81 	t.len = sizeof(cmd_resp);
82 	spi_message_add_tail(&t, &m);
83 	err = spi_sync(flash->spi, &m);
84 	if (err < 0)
85 		return err;
86 
87 	*status = cmd_resp[1];
88 	return 0;
89 }
90 
sst25l_write_enable(struct sst25l_flash * flash,int enable)91 static int sst25l_write_enable(struct sst25l_flash *flash, int enable)
92 {
93 	unsigned char command[2];
94 	int status, err;
95 
96 	command[0] = enable ? SST25L_CMD_WREN : SST25L_CMD_WRDI;
97 	err = spi_write(flash->spi, command, 1);
98 	if (err)
99 		return err;
100 
101 	command[0] = SST25L_CMD_EWSR;
102 	err = spi_write(flash->spi, command, 1);
103 	if (err)
104 		return err;
105 
106 	command[0] = SST25L_CMD_WRSR;
107 	command[1] = enable ? 0 : SST25L_STATUS_BP0 | SST25L_STATUS_BP1;
108 	err = spi_write(flash->spi, command, 2);
109 	if (err)
110 		return err;
111 
112 	if (enable) {
113 		err = sst25l_status(flash, &status);
114 		if (err)
115 			return err;
116 		if (!(status & SST25L_STATUS_WREN))
117 			return -EROFS;
118 	}
119 
120 	return 0;
121 }
122 
sst25l_wait_till_ready(struct sst25l_flash * flash)123 static int sst25l_wait_till_ready(struct sst25l_flash *flash)
124 {
125 	unsigned long deadline;
126 	int status, err;
127 
128 	deadline = jiffies + MAX_READY_WAIT_JIFFIES;
129 	do {
130 		err = sst25l_status(flash, &status);
131 		if (err)
132 			return err;
133 		if (!(status & SST25L_STATUS_BUSY))
134 			return 0;
135 
136 		cond_resched();
137 	} while (!time_after_eq(jiffies, deadline));
138 
139 	return -ETIMEDOUT;
140 }
141 
sst25l_erase_sector(struct sst25l_flash * flash,uint32_t offset)142 static int sst25l_erase_sector(struct sst25l_flash *flash, uint32_t offset)
143 {
144 	unsigned char command[4];
145 	int err;
146 
147 	err = sst25l_write_enable(flash, 1);
148 	if (err)
149 		return err;
150 
151 	command[0] = SST25L_CMD_SECTOR_ERASE;
152 	command[1] = offset >> 16;
153 	command[2] = offset >> 8;
154 	command[3] = offset;
155 	err = spi_write(flash->spi, command, 4);
156 	if (err)
157 		return err;
158 
159 	err = sst25l_wait_till_ready(flash);
160 	if (err)
161 		return err;
162 
163 	return sst25l_write_enable(flash, 0);
164 }
165 
sst25l_erase(struct mtd_info * mtd,struct erase_info * instr)166 static int sst25l_erase(struct mtd_info *mtd, struct erase_info *instr)
167 {
168 	struct sst25l_flash *flash = to_sst25l_flash(mtd);
169 	uint32_t addr, end;
170 	int err;
171 
172 	/* Sanity checks */
173 	if ((uint32_t)instr->len % mtd->erasesize)
174 		return -EINVAL;
175 
176 	if ((uint32_t)instr->addr % mtd->erasesize)
177 		return -EINVAL;
178 
179 	addr = instr->addr;
180 	end = addr + instr->len;
181 
182 	mutex_lock(&flash->lock);
183 
184 	err = sst25l_wait_till_ready(flash);
185 	if (err) {
186 		mutex_unlock(&flash->lock);
187 		return err;
188 	}
189 
190 	while (addr < end) {
191 		err = sst25l_erase_sector(flash, addr);
192 		if (err) {
193 			mutex_unlock(&flash->lock);
194 			dev_err(&flash->spi->dev, "Erase failed\n");
195 			return err;
196 		}
197 
198 		addr += mtd->erasesize;
199 	}
200 
201 	mutex_unlock(&flash->lock);
202 
203 	return 0;
204 }
205 
sst25l_read(struct mtd_info * mtd,loff_t from,size_t len,size_t * retlen,unsigned char * buf)206 static int sst25l_read(struct mtd_info *mtd, loff_t from, size_t len,
207 		       size_t *retlen, unsigned char *buf)
208 {
209 	struct sst25l_flash *flash = to_sst25l_flash(mtd);
210 	struct spi_transfer transfer[2];
211 	struct spi_message message;
212 	unsigned char command[4];
213 	int ret;
214 
215 	spi_message_init(&message);
216 	memset(&transfer, 0, sizeof(transfer));
217 
218 	command[0] = SST25L_CMD_READ;
219 	command[1] = from >> 16;
220 	command[2] = from >> 8;
221 	command[3] = from;
222 
223 	transfer[0].tx_buf = command;
224 	transfer[0].len = sizeof(command);
225 	spi_message_add_tail(&transfer[0], &message);
226 
227 	transfer[1].rx_buf = buf;
228 	transfer[1].len = len;
229 	spi_message_add_tail(&transfer[1], &message);
230 
231 	mutex_lock(&flash->lock);
232 
233 	/* Wait for previous write/erase to complete */
234 	ret = sst25l_wait_till_ready(flash);
235 	if (ret) {
236 		mutex_unlock(&flash->lock);
237 		return ret;
238 	}
239 
240 	spi_sync(flash->spi, &message);
241 
242 	if (retlen && message.actual_length > sizeof(command))
243 		*retlen += message.actual_length - sizeof(command);
244 
245 	mutex_unlock(&flash->lock);
246 	return 0;
247 }
248 
sst25l_write(struct mtd_info * mtd,loff_t to,size_t len,size_t * retlen,const unsigned char * buf)249 static int sst25l_write(struct mtd_info *mtd, loff_t to, size_t len,
250 			size_t *retlen, const unsigned char *buf)
251 {
252 	struct sst25l_flash *flash = to_sst25l_flash(mtd);
253 	int i, j, ret, bytes, copied = 0;
254 	unsigned char command[5];
255 
256 	if ((uint32_t)to % mtd->writesize)
257 		return -EINVAL;
258 
259 	mutex_lock(&flash->lock);
260 
261 	ret = sst25l_write_enable(flash, 1);
262 	if (ret)
263 		goto out;
264 
265 	for (i = 0; i < len; i += mtd->writesize) {
266 		ret = sst25l_wait_till_ready(flash);
267 		if (ret)
268 			goto out;
269 
270 		/* Write the first byte of the page */
271 		command[0] = SST25L_CMD_AAI_PROGRAM;
272 		command[1] = (to + i) >> 16;
273 		command[2] = (to + i) >> 8;
274 		command[3] = (to + i);
275 		command[4] = buf[i];
276 		ret = spi_write(flash->spi, command, 5);
277 		if (ret < 0)
278 			goto out;
279 		copied++;
280 
281 		/*
282 		 * Write the remaining bytes using auto address
283 		 * increment mode
284 		 */
285 		bytes = min_t(uint32_t, mtd->writesize, len - i);
286 		for (j = 1; j < bytes; j++, copied++) {
287 			ret = sst25l_wait_till_ready(flash);
288 			if (ret)
289 				goto out;
290 
291 			command[1] = buf[i + j];
292 			ret = spi_write(flash->spi, command, 2);
293 			if (ret)
294 				goto out;
295 		}
296 	}
297 
298 out:
299 	ret = sst25l_write_enable(flash, 0);
300 
301 	if (retlen)
302 		*retlen = copied;
303 
304 	mutex_unlock(&flash->lock);
305 	return ret;
306 }
307 
sst25l_match_device(struct spi_device * spi)308 static struct flash_info *sst25l_match_device(struct spi_device *spi)
309 {
310 	struct flash_info *flash_info = NULL;
311 	struct spi_message m;
312 	struct spi_transfer t;
313 	unsigned char cmd_resp[6];
314 	int i, err;
315 	uint16_t id;
316 
317 	spi_message_init(&m);
318 	memset(&t, 0, sizeof(struct spi_transfer));
319 
320 	cmd_resp[0] = SST25L_CMD_READ_ID;
321 	cmd_resp[1] = 0;
322 	cmd_resp[2] = 0;
323 	cmd_resp[3] = 0;
324 	cmd_resp[4] = 0xff;
325 	cmd_resp[5] = 0xff;
326 	t.tx_buf = cmd_resp;
327 	t.rx_buf = cmd_resp;
328 	t.len = sizeof(cmd_resp);
329 	spi_message_add_tail(&t, &m);
330 	err = spi_sync(spi, &m);
331 	if (err < 0) {
332 		dev_err(&spi->dev, "error reading device id\n");
333 		return NULL;
334 	}
335 
336 	id = (cmd_resp[4] << 8) | cmd_resp[5];
337 
338 	for (i = 0; i < ARRAY_SIZE(sst25l_flash_info); i++)
339 		if (sst25l_flash_info[i].device_id == id)
340 			flash_info = &sst25l_flash_info[i];
341 
342 	if (!flash_info)
343 		dev_err(&spi->dev, "unknown id %.4x\n", id);
344 
345 	return flash_info;
346 }
347 
sst25l_probe(struct spi_device * spi)348 static int sst25l_probe(struct spi_device *spi)
349 {
350 	struct flash_info *flash_info;
351 	struct sst25l_flash *flash;
352 	struct flash_platform_data *data;
353 	int ret;
354 
355 	flash_info = sst25l_match_device(spi);
356 	if (!flash_info)
357 		return -ENODEV;
358 
359 	flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL);
360 	if (!flash)
361 		return -ENOMEM;
362 
363 	flash->spi = spi;
364 	mutex_init(&flash->lock);
365 	spi_set_drvdata(spi, flash);
366 
367 	data = dev_get_platdata(&spi->dev);
368 	if (data && data->name)
369 		flash->mtd.name = data->name;
370 
371 	flash->mtd.dev.parent   = &spi->dev;
372 	flash->mtd.type		= MTD_NORFLASH;
373 	flash->mtd.flags	= MTD_CAP_NORFLASH;
374 	flash->mtd.erasesize	= flash_info->erase_size;
375 	flash->mtd.writesize	= flash_info->page_size;
376 	flash->mtd.writebufsize	= flash_info->page_size;
377 	flash->mtd.size		= flash_info->page_size * flash_info->nr_pages;
378 	flash->mtd._erase	= sst25l_erase;
379 	flash->mtd._read		= sst25l_read;
380 	flash->mtd._write 	= sst25l_write;
381 
382 	dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name,
383 		 (long long)flash->mtd.size >> 10);
384 
385 	pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) "
386 	      ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
387 	      flash->mtd.name,
388 	      (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
389 	      flash->mtd.erasesize, flash->mtd.erasesize / 1024,
390 	      flash->mtd.numeraseregions);
391 
392 
393 	ret = mtd_device_register(&flash->mtd, data ? data->parts : NULL,
394 				  data ? data->nr_parts : 0);
395 	if (ret)
396 		return -ENODEV;
397 
398 	return 0;
399 }
400 
sst25l_remove(struct spi_device * spi)401 static void sst25l_remove(struct spi_device *spi)
402 {
403 	struct sst25l_flash *flash = spi_get_drvdata(spi);
404 
405 	WARN_ON(mtd_device_unregister(&flash->mtd));
406 }
407 
408 static struct spi_driver sst25l_driver = {
409 	.driver = {
410 		.name	= "sst25l",
411 	},
412 	.probe		= sst25l_probe,
413 	.remove		= sst25l_remove,
414 };
415 
416 module_spi_driver(sst25l_driver);
417 
418 MODULE_DESCRIPTION("MTD SPI driver for SST25L Flash chips");
419 MODULE_AUTHOR("Andre Renaud <andre@bluewatersys.com>, "
420 	      "Ryan Mallon");
421 MODULE_LICENSE("GPL");
422