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