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