xref: /linux/drivers/mtd/devices/mchp48l640.c (revision 1b30456150e57a79e300b82eb2efac40c25a162e)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Driver for Microchip 48L640 64 Kb SPI Serial EERAM
4  *
5  * Copyright Heiko Schocher <hs@denx.de>
6  *
7  * datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/20006055B.pdf
8  *
9  * we set continuous mode but reading/writing more bytes than
10  * pagesize seems to bring chip into state where readden values
11  * are wrong ... no idea why.
12  *
13  */
14 #include <linux/delay.h>
15 #include <linux/device.h>
16 #include <linux/jiffies.h>
17 #include <linux/module.h>
18 #include <linux/mtd/mtd.h>
19 #include <linux/mtd/partitions.h>
20 #include <linux/mutex.h>
21 #include <linux/sched.h>
22 #include <linux/sizes.h>
23 #include <linux/spi/flash.h>
24 #include <linux/spi/spi.h>
25 #include <linux/of.h>
26 
27 struct mchp48_caps {
28 	unsigned int size;
29 	unsigned int page_size;
30 	bool auto_disable_wel;
31 };
32 
33 struct mchp48l640_flash {
34 	struct spi_device	*spi;
35 	struct mutex		lock;
36 	struct mtd_info		mtd;
37 	const struct mchp48_caps	*caps;
38 };
39 
40 #define MCHP48L640_CMD_WREN		0x06
41 #define MCHP48L640_CMD_WRDI		0x04
42 #define MCHP48L640_CMD_WRITE		0x02
43 #define MCHP48L640_CMD_READ		0x03
44 #define MCHP48L640_CMD_WRSR		0x01
45 #define MCHP48L640_CMD_RDSR		0x05
46 
47 #define MCHP48L640_STATUS_RDY		0x01
48 #define MCHP48L640_STATUS_WEL		0x02
49 #define MCHP48L640_STATUS_BP0		0x04
50 #define MCHP48L640_STATUS_BP1		0x08
51 #define MCHP48L640_STATUS_SWM		0x10
52 #define MCHP48L640_STATUS_PRO		0x20
53 #define MCHP48L640_STATUS_ASE		0x40
54 
55 #define MCHP48L640_TIMEOUT		100
56 
57 #define MAX_CMD_SIZE			0x10
58 
59 #define to_mchp48l640_flash(x) container_of(x, struct mchp48l640_flash, mtd)
60 
61 static int mchp48l640_mkcmd(struct mchp48l640_flash *flash, u8 cmd, loff_t addr, char *buf)
62 {
63 	buf[0] = cmd;
64 	buf[1] = addr >> 8;
65 	buf[2] = addr;
66 
67 	return 3;
68 }
69 
70 static int mchp48l640_read_status(struct mchp48l640_flash *flash, int *status)
71 {
72 	unsigned char cmd[2];
73 	int ret;
74 
75 	cmd[0] = MCHP48L640_CMD_RDSR;
76 	cmd[1] = 0x00;
77 	mutex_lock(&flash->lock);
78 	ret = spi_write_then_read(flash->spi, &cmd[0], 1, &cmd[1], 1);
79 	mutex_unlock(&flash->lock);
80 	if (!ret)
81 		*status = cmd[1];
82 	dev_dbg(&flash->spi->dev, "read status ret: %d status: %x", ret, *status);
83 
84 	return ret;
85 }
86 
87 static int mchp48l640_waitforbit(struct mchp48l640_flash *flash, int bit, bool set)
88 {
89 	int ret, status;
90 	unsigned long deadline;
91 
92 	deadline = jiffies + msecs_to_jiffies(MCHP48L640_TIMEOUT);
93 	do {
94 		ret = mchp48l640_read_status(flash, &status);
95 		dev_dbg(&flash->spi->dev, "read status ret: %d bit: %x %sset status: %x",
96 			ret, bit, (set ? "" : "not"), status);
97 		if (ret)
98 			return ret;
99 
100 		if (set) {
101 			if ((status & bit) == bit)
102 				return 0;
103 		} else {
104 			if ((status & bit) == 0)
105 				return 0;
106 		}
107 
108 		usleep_range(1000, 2000);
109 	} while (!time_after_eq(jiffies, deadline));
110 
111 	dev_err(&flash->spi->dev, "Timeout waiting for bit %x %s set in status register.",
112 		bit, (set ? "" : "not"));
113 	return -ETIMEDOUT;
114 }
115 
116 static int mchp48l640_write_prepare(struct mchp48l640_flash *flash, bool enable)
117 {
118 	unsigned char cmd[2];
119 	int ret;
120 
121 	if (enable)
122 		cmd[0] = MCHP48L640_CMD_WREN;
123 	else
124 		cmd[0] = MCHP48L640_CMD_WRDI;
125 
126 	mutex_lock(&flash->lock);
127 	ret = spi_write(flash->spi, cmd, 1);
128 	mutex_unlock(&flash->lock);
129 
130 	if (ret)
131 		dev_err(&flash->spi->dev, "write %sable failed ret: %d",
132 			(enable ? "en" : "dis"), ret);
133 
134 	dev_dbg(&flash->spi->dev, "write %sable success ret: %d",
135 		(enable ? "en" : "dis"), ret);
136 	if (enable)
137 		return mchp48l640_waitforbit(flash, MCHP48L640_STATUS_WEL, true);
138 
139 	return ret;
140 }
141 
142 static int mchp48l640_set_mode(struct mchp48l640_flash *flash)
143 {
144 	unsigned char cmd[2];
145 	int ret;
146 
147 	ret = mchp48l640_write_prepare(flash, true);
148 	if (ret)
149 		return ret;
150 
151 	cmd[0] = MCHP48L640_CMD_WRSR;
152 	cmd[1] = MCHP48L640_STATUS_PRO;
153 
154 	mutex_lock(&flash->lock);
155 	ret = spi_write(flash->spi, cmd, 2);
156 	mutex_unlock(&flash->lock);
157 	if (ret)
158 		dev_err(&flash->spi->dev, "Could not set continuous mode ret: %d", ret);
159 
160 	return mchp48l640_waitforbit(flash, MCHP48L640_STATUS_PRO, true);
161 }
162 
163 static int mchp48l640_wait_rdy(struct mchp48l640_flash *flash)
164 {
165 	return mchp48l640_waitforbit(flash, MCHP48L640_STATUS_RDY, false);
166 };
167 
168 static int mchp48l640_write_page(struct mtd_info *mtd, loff_t to, size_t len,
169 			    size_t *retlen, const unsigned char *buf)
170 {
171 	struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd);
172 	unsigned char *cmd;
173 	int ret;
174 	int cmdlen;
175 
176 	cmd = kmalloc((3 + len), GFP_KERNEL | GFP_DMA);
177 	if (!cmd)
178 		return -ENOMEM;
179 
180 	ret = mchp48l640_wait_rdy(flash);
181 	if (ret)
182 		goto fail;
183 
184 	ret = mchp48l640_write_prepare(flash, true);
185 	if (ret)
186 		goto fail;
187 
188 	mutex_lock(&flash->lock);
189 	cmdlen = mchp48l640_mkcmd(flash, MCHP48L640_CMD_WRITE, to, cmd);
190 	memcpy(&cmd[cmdlen], buf, len);
191 	ret = spi_write(flash->spi, cmd, cmdlen + len);
192 	mutex_unlock(&flash->lock);
193 	if (!ret)
194 		*retlen += len;
195 	else
196 		goto fail;
197 
198 	if (flash->caps->auto_disable_wel) {
199 		ret = mchp48l640_waitforbit(flash, MCHP48L640_STATUS_WEL, false);
200 		if (ret)
201 			goto fail;
202 	} else {
203 		ret = mchp48l640_write_prepare(flash, false);
204 		if (ret)
205 			goto fail;
206 	}
207 
208 	kfree(cmd);
209 	return 0;
210 fail:
211 	kfree(cmd);
212 	dev_err(&flash->spi->dev, "write fail with: %d", ret);
213 	return ret;
214 };
215 
216 static int mchp48l640_write(struct mtd_info *mtd, loff_t to, size_t len,
217 			    size_t *retlen, const unsigned char *buf)
218 {
219 	struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd);
220 	int ret;
221 	size_t wlen = 0;
222 	loff_t woff = to;
223 	size_t ws;
224 	size_t page_sz = flash->caps->page_size;
225 
226 	/*
227 	 * we set PRO bit (page rollover), but writing length > page size
228 	 * does result in total chaos, so write in 32 byte chunks.
229 	 */
230 	while (wlen < len) {
231 		ws = min((len - wlen), page_sz);
232 		ret = mchp48l640_write_page(mtd, woff, ws, retlen, &buf[wlen]);
233 		if (ret)
234 			return ret;
235 		wlen += ws;
236 		woff += ws;
237 	}
238 
239 	return 0;
240 }
241 
242 static int mchp48l640_read_page(struct mtd_info *mtd, loff_t from, size_t len,
243 			   size_t *retlen, unsigned char *buf)
244 {
245 	struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd);
246 	unsigned char *cmd;
247 	int ret;
248 	int cmdlen;
249 
250 	cmd = kmalloc((3 + len), GFP_KERNEL | GFP_DMA);
251 	if (!cmd)
252 		return -ENOMEM;
253 
254 	ret = mchp48l640_wait_rdy(flash);
255 	if (ret)
256 		goto fail;
257 
258 	mutex_lock(&flash->lock);
259 	cmdlen = mchp48l640_mkcmd(flash, MCHP48L640_CMD_READ, from, cmd);
260 	ret = spi_write_then_read(flash->spi, cmd, cmdlen, buf, len);
261 	mutex_unlock(&flash->lock);
262 	if (!ret)
263 		*retlen += len;
264 
265 	kfree(cmd);
266 	return ret;
267 
268 fail:
269 	kfree(cmd);
270 	dev_err(&flash->spi->dev, "read fail with: %d", ret);
271 	return ret;
272 }
273 
274 static int mchp48l640_read(struct mtd_info *mtd, loff_t from, size_t len,
275 			   size_t *retlen, unsigned char *buf)
276 {
277 	struct mchp48l640_flash *flash = to_mchp48l640_flash(mtd);
278 	int ret;
279 	size_t wlen = 0;
280 	loff_t woff = from;
281 	size_t ws;
282 	size_t page_sz = flash->caps->page_size;
283 
284 	/*
285 	 * we set PRO bit (page rollover), but if read length > page size
286 	 * does result in total chaos in result ...
287 	 */
288 	while (wlen < len) {
289 		ws = min((len - wlen), page_sz);
290 		ret = mchp48l640_read_page(mtd, woff, ws, retlen, &buf[wlen]);
291 		if (ret)
292 			return ret;
293 		wlen += ws;
294 		woff += ws;
295 	}
296 
297 	return 0;
298 };
299 
300 static const struct mchp48_caps mchp48l640_caps = {
301 	.size = SZ_8K,
302 	.page_size = 32,
303 	.auto_disable_wel = true,
304 };
305 
306 static const struct mchp48_caps mb85rs128ty_caps = {
307 	.size = SZ_16K,
308 	.page_size = 256,
309 	.auto_disable_wel = false,
310 };
311 
312 static int mchp48l640_probe(struct spi_device *spi)
313 {
314 	struct mchp48l640_flash *flash;
315 	struct flash_platform_data *data;
316 	int err;
317 	int status;
318 
319 	flash = devm_kzalloc(&spi->dev, sizeof(*flash), GFP_KERNEL);
320 	if (!flash)
321 		return -ENOMEM;
322 
323 	flash->spi = spi;
324 	mutex_init(&flash->lock);
325 	spi_set_drvdata(spi, flash);
326 
327 	err = mchp48l640_read_status(flash, &status);
328 	if (err)
329 		return err;
330 
331 	err = mchp48l640_set_mode(flash);
332 	if (err)
333 		return err;
334 
335 	data = dev_get_platdata(&spi->dev);
336 
337 	flash->caps = of_device_get_match_data(&spi->dev);
338 	if (!flash->caps)
339 		flash->caps = &mchp48l640_caps;
340 
341 	mtd_set_of_node(&flash->mtd, spi->dev.of_node);
342 	flash->mtd.dev.parent	= &spi->dev;
343 	flash->mtd.type		= MTD_RAM;
344 	flash->mtd.flags	= MTD_CAP_RAM;
345 	flash->mtd.writesize	= flash->caps->page_size;
346 	flash->mtd.size		= flash->caps->size;
347 	flash->mtd._read	= mchp48l640_read;
348 	flash->mtd._write	= mchp48l640_write;
349 
350 	err = mtd_device_register(&flash->mtd, data ? data->parts : NULL,
351 				  data ? data->nr_parts : 0);
352 	if (err)
353 		return err;
354 
355 	return 0;
356 }
357 
358 static void mchp48l640_remove(struct spi_device *spi)
359 {
360 	struct mchp48l640_flash *flash = spi_get_drvdata(spi);
361 
362 	WARN_ON(mtd_device_unregister(&flash->mtd));
363 }
364 
365 static const struct of_device_id mchp48l640_of_table[] = {
366 	{
367 		.compatible = "microchip,48l640",
368 		.data = &mchp48l640_caps,
369 	},
370 	{
371 		.compatible = "fujitsu,mb85rs128ty",
372 		.data = &mb85rs128ty_caps,
373 	},
374 	{}
375 };
376 MODULE_DEVICE_TABLE(of, mchp48l640_of_table);
377 
378 static const struct spi_device_id mchp48l640_spi_ids[] = {
379 	{
380 		.name = "48l640",
381 		.driver_data = (kernel_ulong_t)&mchp48l640_caps,
382 	},
383 	{
384 		.name = "mb85rs128ty",
385 		.driver_data = (kernel_ulong_t)&mb85rs128ty_caps,
386 	},
387 	{}
388 };
389 MODULE_DEVICE_TABLE(spi, mchp48l640_spi_ids);
390 
391 static struct spi_driver mchp48l640_driver = {
392 	.driver = {
393 		.name	= "mchp48l640",
394 		.of_match_table = mchp48l640_of_table,
395 	},
396 	.probe		= mchp48l640_probe,
397 	.remove		= mchp48l640_remove,
398 	.id_table	= mchp48l640_spi_ids,
399 };
400 
401 module_spi_driver(mchp48l640_driver);
402 
403 MODULE_DESCRIPTION("MTD SPI driver for Microchip 48l640 EERAM chips");
404 MODULE_AUTHOR("Heiko Schocher <hs@denx.de>");
405 MODULE_LICENSE("GPL v2");
406 MODULE_ALIAS("spi:mchp48l640");
407