1*cf09b7a0SBartosz Golaszewski // SPDX-License-Identifier: GPL-2.0-or-later 2*cf09b7a0SBartosz Golaszewski /* 3*cf09b7a0SBartosz Golaszewski * Driver for most of the SPI EEPROMs, such as Atmel AT25 models 4*cf09b7a0SBartosz Golaszewski * and Cypress FRAMs FM25 models. 5*cf09b7a0SBartosz Golaszewski * 6*cf09b7a0SBartosz Golaszewski * Copyright (C) 2006 David Brownell 7*cf09b7a0SBartosz Golaszewski */ 8*cf09b7a0SBartosz Golaszewski 9*cf09b7a0SBartosz Golaszewski #include <linux/bits.h> 10*cf09b7a0SBartosz Golaszewski #include <linux/cleanup.h> 11*cf09b7a0SBartosz Golaszewski #include <linux/delay.h> 12*cf09b7a0SBartosz Golaszewski #include <linux/device.h> 13*cf09b7a0SBartosz Golaszewski #include <linux/iopoll.h> 14*cf09b7a0SBartosz Golaszewski #include <linux/kernel.h> 15*cf09b7a0SBartosz Golaszewski #include <linux/module.h> 16*cf09b7a0SBartosz Golaszewski #include <linux/property.h> 17*cf09b7a0SBartosz Golaszewski #include <linux/sched.h> 18*cf09b7a0SBartosz Golaszewski #include <linux/slab.h> 19*cf09b7a0SBartosz Golaszewski 20*cf09b7a0SBartosz Golaszewski #include <linux/spi/eeprom.h> 21*cf09b7a0SBartosz Golaszewski #include <linux/spi/spi.h> 22*cf09b7a0SBartosz Golaszewski #include <linux/spi/spi-mem.h> 23*cf09b7a0SBartosz Golaszewski 24*cf09b7a0SBartosz Golaszewski #include <linux/nvmem-provider.h> 25*cf09b7a0SBartosz Golaszewski 26*cf09b7a0SBartosz Golaszewski /* 27*cf09b7a0SBartosz Golaszewski * NOTE: this is an *EEPROM* driver. The vagaries of product naming 28*cf09b7a0SBartosz Golaszewski * mean that some AT25 products are EEPROMs, and others are FLASH. 29*cf09b7a0SBartosz Golaszewski * Handle FLASH chips with the drivers/mtd/devices/m25p80.c driver, 30*cf09b7a0SBartosz Golaszewski * not this one! 31*cf09b7a0SBartosz Golaszewski * 32*cf09b7a0SBartosz Golaszewski * EEPROMs that can be used with this driver include, for example: 33*cf09b7a0SBartosz Golaszewski * AT25M02, AT25128B 34*cf09b7a0SBartosz Golaszewski */ 35*cf09b7a0SBartosz Golaszewski 36*cf09b7a0SBartosz Golaszewski #define FM25_SN_LEN 8 /* serial number length */ 37*cf09b7a0SBartosz Golaszewski #define FM25_MAX_ID_LEN 9 /* ID length */ 38*cf09b7a0SBartosz Golaszewski #define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */ 39*cf09b7a0SBartosz Golaszewski 40*cf09b7a0SBartosz Golaszewski struct at25_data { 41*cf09b7a0SBartosz Golaszewski struct spi_eeprom chip; 42*cf09b7a0SBartosz Golaszewski struct spi_mem *spimem; 43*cf09b7a0SBartosz Golaszewski struct mutex lock; 44*cf09b7a0SBartosz Golaszewski unsigned addrlen; 45*cf09b7a0SBartosz Golaszewski struct nvmem_config nvmem_config; 46*cf09b7a0SBartosz Golaszewski struct nvmem_device *nvmem; 47*cf09b7a0SBartosz Golaszewski u8 sernum[FM25_SN_LEN]; 48*cf09b7a0SBartosz Golaszewski u8 id[FM25_MAX_ID_LEN]; 49*cf09b7a0SBartosz Golaszewski u8 id_len; 50*cf09b7a0SBartosz Golaszewski }; 51*cf09b7a0SBartosz Golaszewski 52*cf09b7a0SBartosz Golaszewski #define AT25_WREN 0x06 /* latch the write enable */ 53*cf09b7a0SBartosz Golaszewski #define AT25_WRDI 0x04 /* reset the write enable */ 54*cf09b7a0SBartosz Golaszewski #define AT25_RDSR 0x05 /* read status register */ 55*cf09b7a0SBartosz Golaszewski #define AT25_WRSR 0x01 /* write status register */ 56*cf09b7a0SBartosz Golaszewski #define AT25_READ 0x03 /* read byte(s) */ 57*cf09b7a0SBartosz Golaszewski #define AT25_WRITE 0x02 /* write byte(s)/sector */ 58*cf09b7a0SBartosz Golaszewski #define FM25_SLEEP 0xb9 /* enter sleep mode */ 59*cf09b7a0SBartosz Golaszewski #define FM25_RDID 0x9f /* read device ID */ 60*cf09b7a0SBartosz Golaszewski #define FM25_RDSN 0xc3 /* read S/N */ 61*cf09b7a0SBartosz Golaszewski 62*cf09b7a0SBartosz Golaszewski #define AT25_SR_nRDY 0x01 /* nRDY = write-in-progress */ 63*cf09b7a0SBartosz Golaszewski #define AT25_SR_WEN 0x02 /* write enable (latched) */ 64*cf09b7a0SBartosz Golaszewski #define AT25_SR_BP0 0x04 /* BP for software writeprotect */ 65*cf09b7a0SBartosz Golaszewski #define AT25_SR_BP1 0x08 66*cf09b7a0SBartosz Golaszewski #define AT25_SR_WPEN 0x80 /* writeprotect enable */ 67*cf09b7a0SBartosz Golaszewski 68*cf09b7a0SBartosz Golaszewski #define AT25_INSTR_BIT3 0x08 /* additional address bit in instr */ 69*cf09b7a0SBartosz Golaszewski 70*cf09b7a0SBartosz Golaszewski /* 71*cf09b7a0SBartosz Golaszewski * Specs often allow 5ms for a page write, sometimes 20ms; 72*cf09b7a0SBartosz Golaszewski * it's important to recover from write timeouts. 73*cf09b7a0SBartosz Golaszewski */ 74*cf09b7a0SBartosz Golaszewski #define EE_TIMEOUT 25 75*cf09b7a0SBartosz Golaszewski 76*cf09b7a0SBartosz Golaszewski /*-------------------------------------------------------------------------*/ 77*cf09b7a0SBartosz Golaszewski 78*cf09b7a0SBartosz Golaszewski #define io_limit PAGE_SIZE /* bytes */ 79*cf09b7a0SBartosz Golaszewski 80*cf09b7a0SBartosz Golaszewski /* Handle the address MSB as part of instruction byte */ 81*cf09b7a0SBartosz Golaszewski static u8 at25_instr(struct at25_data *at25, u8 instr, unsigned int off) 82*cf09b7a0SBartosz Golaszewski { 83*cf09b7a0SBartosz Golaszewski if (!(at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)) 84*cf09b7a0SBartosz Golaszewski return instr; 85*cf09b7a0SBartosz Golaszewski if (off < BIT(at25->addrlen * 8)) 86*cf09b7a0SBartosz Golaszewski return instr; 87*cf09b7a0SBartosz Golaszewski return instr | AT25_INSTR_BIT3; 88*cf09b7a0SBartosz Golaszewski } 89*cf09b7a0SBartosz Golaszewski 90*cf09b7a0SBartosz Golaszewski static int at25_ee_read(void *priv, unsigned int offset, 91*cf09b7a0SBartosz Golaszewski void *val, size_t count) 92*cf09b7a0SBartosz Golaszewski { 93*cf09b7a0SBartosz Golaszewski u8 *bounce __free(kfree) = kmalloc(min(count, io_limit), GFP_KERNEL); 94*cf09b7a0SBartosz Golaszewski struct at25_data *at25 = priv; 95*cf09b7a0SBartosz Golaszewski char *buf = val; 96*cf09b7a0SBartosz Golaszewski unsigned int msg_offset = offset; 97*cf09b7a0SBartosz Golaszewski size_t bytes_left = count; 98*cf09b7a0SBartosz Golaszewski size_t segment; 99*cf09b7a0SBartosz Golaszewski int status; 100*cf09b7a0SBartosz Golaszewski 101*cf09b7a0SBartosz Golaszewski if (!bounce) 102*cf09b7a0SBartosz Golaszewski return -ENOMEM; 103*cf09b7a0SBartosz Golaszewski 104*cf09b7a0SBartosz Golaszewski if (unlikely(offset >= at25->chip.byte_len)) 105*cf09b7a0SBartosz Golaszewski return -EINVAL; 106*cf09b7a0SBartosz Golaszewski if ((offset + count) > at25->chip.byte_len) 107*cf09b7a0SBartosz Golaszewski count = at25->chip.byte_len - offset; 108*cf09b7a0SBartosz Golaszewski if (unlikely(!count)) 109*cf09b7a0SBartosz Golaszewski return -EINVAL; 110*cf09b7a0SBartosz Golaszewski 111*cf09b7a0SBartosz Golaszewski do { 112*cf09b7a0SBartosz Golaszewski struct spi_mem_op op; 113*cf09b7a0SBartosz Golaszewski 114*cf09b7a0SBartosz Golaszewski segment = min(bytes_left, io_limit); 115*cf09b7a0SBartosz Golaszewski 116*cf09b7a0SBartosz Golaszewski op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(at25_instr(at25, AT25_READ, 117*cf09b7a0SBartosz Golaszewski msg_offset), 1), 118*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_ADDR(at25->addrlen, msg_offset, 1), 119*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_NO_DUMMY, 120*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_DATA_IN(segment, bounce, 1)); 121*cf09b7a0SBartosz Golaszewski 122*cf09b7a0SBartosz Golaszewski status = spi_mem_adjust_op_size(at25->spimem, &op); 123*cf09b7a0SBartosz Golaszewski if (status) 124*cf09b7a0SBartosz Golaszewski return status; 125*cf09b7a0SBartosz Golaszewski segment = op.data.nbytes; 126*cf09b7a0SBartosz Golaszewski 127*cf09b7a0SBartosz Golaszewski mutex_lock(&at25->lock); 128*cf09b7a0SBartosz Golaszewski status = spi_mem_exec_op(at25->spimem, &op); 129*cf09b7a0SBartosz Golaszewski mutex_unlock(&at25->lock); 130*cf09b7a0SBartosz Golaszewski if (status) 131*cf09b7a0SBartosz Golaszewski return status; 132*cf09b7a0SBartosz Golaszewski memcpy(buf, bounce, segment); 133*cf09b7a0SBartosz Golaszewski 134*cf09b7a0SBartosz Golaszewski msg_offset += segment; 135*cf09b7a0SBartosz Golaszewski buf += segment; 136*cf09b7a0SBartosz Golaszewski bytes_left -= segment; 137*cf09b7a0SBartosz Golaszewski } while (bytes_left > 0); 138*cf09b7a0SBartosz Golaszewski 139*cf09b7a0SBartosz Golaszewski dev_dbg(&at25->spimem->spi->dev, "read %zu bytes at %d\n", 140*cf09b7a0SBartosz Golaszewski count, offset); 141*cf09b7a0SBartosz Golaszewski return 0; 142*cf09b7a0SBartosz Golaszewski } 143*cf09b7a0SBartosz Golaszewski 144*cf09b7a0SBartosz Golaszewski /* 145*cf09b7a0SBartosz Golaszewski * Read extra registers as ID or serial number 146*cf09b7a0SBartosz Golaszewski * 147*cf09b7a0SBartosz Golaszewski * Allow for the callers to provide @buf on stack (not necessary DMA-capable) 148*cf09b7a0SBartosz Golaszewski * by allocating a bounce buffer internally. 149*cf09b7a0SBartosz Golaszewski */ 150*cf09b7a0SBartosz Golaszewski static int fm25_aux_read(struct at25_data *at25, u8 *buf, uint8_t command, 151*cf09b7a0SBartosz Golaszewski int len) 152*cf09b7a0SBartosz Golaszewski { 153*cf09b7a0SBartosz Golaszewski u8 *bounce __free(kfree) = kmalloc(len, GFP_KERNEL); 154*cf09b7a0SBartosz Golaszewski struct spi_mem_op op; 155*cf09b7a0SBartosz Golaszewski int status; 156*cf09b7a0SBartosz Golaszewski 157*cf09b7a0SBartosz Golaszewski if (!bounce) 158*cf09b7a0SBartosz Golaszewski return -ENOMEM; 159*cf09b7a0SBartosz Golaszewski 160*cf09b7a0SBartosz Golaszewski op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(command, 1), 161*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_NO_ADDR, 162*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_NO_DUMMY, 163*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_DATA_IN(len, bounce, 1)); 164*cf09b7a0SBartosz Golaszewski 165*cf09b7a0SBartosz Golaszewski status = spi_mem_exec_op(at25->spimem, &op); 166*cf09b7a0SBartosz Golaszewski dev_dbg(&at25->spimem->spi->dev, "read %d aux bytes --> %d\n", len, status); 167*cf09b7a0SBartosz Golaszewski if (status) 168*cf09b7a0SBartosz Golaszewski return status; 169*cf09b7a0SBartosz Golaszewski 170*cf09b7a0SBartosz Golaszewski memcpy(buf, bounce, len); 171*cf09b7a0SBartosz Golaszewski 172*cf09b7a0SBartosz Golaszewski return 0; 173*cf09b7a0SBartosz Golaszewski } 174*cf09b7a0SBartosz Golaszewski 175*cf09b7a0SBartosz Golaszewski static ssize_t sernum_show(struct device *dev, struct device_attribute *attr, char *buf) 176*cf09b7a0SBartosz Golaszewski { 177*cf09b7a0SBartosz Golaszewski struct at25_data *at25; 178*cf09b7a0SBartosz Golaszewski 179*cf09b7a0SBartosz Golaszewski at25 = dev_get_drvdata(dev); 180*cf09b7a0SBartosz Golaszewski return sysfs_emit(buf, "%*ph\n", (int)sizeof(at25->sernum), at25->sernum); 181*cf09b7a0SBartosz Golaszewski } 182*cf09b7a0SBartosz Golaszewski static DEVICE_ATTR_RO(sernum); 183*cf09b7a0SBartosz Golaszewski 184*cf09b7a0SBartosz Golaszewski static ssize_t jedec_id_show(struct device *dev, struct device_attribute *attr, char *buf) 185*cf09b7a0SBartosz Golaszewski { 186*cf09b7a0SBartosz Golaszewski struct at25_data *at25; 187*cf09b7a0SBartosz Golaszewski 188*cf09b7a0SBartosz Golaszewski at25 = dev_get_drvdata(dev); 189*cf09b7a0SBartosz Golaszewski 190*cf09b7a0SBartosz Golaszewski if (!at25->id_len) 191*cf09b7a0SBartosz Golaszewski return -EOPNOTSUPP; 192*cf09b7a0SBartosz Golaszewski 193*cf09b7a0SBartosz Golaszewski return sysfs_emit(buf, "%*phN\n", at25->id_len, at25->id); 194*cf09b7a0SBartosz Golaszewski } 195*cf09b7a0SBartosz Golaszewski static DEVICE_ATTR_RO(jedec_id); 196*cf09b7a0SBartosz Golaszewski 197*cf09b7a0SBartosz Golaszewski static struct attribute *at25_attrs[] = { 198*cf09b7a0SBartosz Golaszewski &dev_attr_sernum.attr, 199*cf09b7a0SBartosz Golaszewski &dev_attr_jedec_id.attr, 200*cf09b7a0SBartosz Golaszewski NULL, 201*cf09b7a0SBartosz Golaszewski }; 202*cf09b7a0SBartosz Golaszewski ATTRIBUTE_GROUPS(at25); 203*cf09b7a0SBartosz Golaszewski 204*cf09b7a0SBartosz Golaszewski /* 205*cf09b7a0SBartosz Golaszewski * Poll Read Status Register with timeout 206*cf09b7a0SBartosz Golaszewski * 207*cf09b7a0SBartosz Golaszewski * Return: 208*cf09b7a0SBartosz Golaszewski * 0, if the chip is ready 209*cf09b7a0SBartosz Golaszewski * [positive] Status Register value as-is, if the chip is busy 210*cf09b7a0SBartosz Golaszewski * [negative] error code in case of read failure 211*cf09b7a0SBartosz Golaszewski */ 212*cf09b7a0SBartosz Golaszewski static int at25_wait_ready(struct at25_data *at25) 213*cf09b7a0SBartosz Golaszewski { 214*cf09b7a0SBartosz Golaszewski u8 *bounce __free(kfree) = kmalloc(1, GFP_KERNEL); 215*cf09b7a0SBartosz Golaszewski struct spi_mem_op op; 216*cf09b7a0SBartosz Golaszewski int status; 217*cf09b7a0SBartosz Golaszewski 218*cf09b7a0SBartosz Golaszewski if (!bounce) 219*cf09b7a0SBartosz Golaszewski return -ENOMEM; 220*cf09b7a0SBartosz Golaszewski 221*cf09b7a0SBartosz Golaszewski op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(AT25_RDSR, 1), 222*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_NO_ADDR, 223*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_NO_DUMMY, 224*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_DATA_IN(1, bounce, 1)); 225*cf09b7a0SBartosz Golaszewski 226*cf09b7a0SBartosz Golaszewski read_poll_timeout(spi_mem_exec_op, status, 227*cf09b7a0SBartosz Golaszewski status || !(bounce[0] & AT25_SR_nRDY), false, 228*cf09b7a0SBartosz Golaszewski USEC_PER_MSEC, USEC_PER_MSEC * EE_TIMEOUT, 229*cf09b7a0SBartosz Golaszewski at25->spimem, &op); 230*cf09b7a0SBartosz Golaszewski if (status < 0) 231*cf09b7a0SBartosz Golaszewski return status; 232*cf09b7a0SBartosz Golaszewski if (!(bounce[0] & AT25_SR_nRDY)) 233*cf09b7a0SBartosz Golaszewski return 0; 234*cf09b7a0SBartosz Golaszewski 235*cf09b7a0SBartosz Golaszewski return bounce[0]; 236*cf09b7a0SBartosz Golaszewski } 237*cf09b7a0SBartosz Golaszewski 238*cf09b7a0SBartosz Golaszewski static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count) 239*cf09b7a0SBartosz Golaszewski { 240*cf09b7a0SBartosz Golaszewski u8 *bounce __free(kfree) = kmalloc(min(count, io_limit), GFP_KERNEL); 241*cf09b7a0SBartosz Golaszewski struct at25_data *at25 = priv; 242*cf09b7a0SBartosz Golaszewski const char *buf = val; 243*cf09b7a0SBartosz Golaszewski unsigned int buf_size; 244*cf09b7a0SBartosz Golaszewski int status; 245*cf09b7a0SBartosz Golaszewski 246*cf09b7a0SBartosz Golaszewski if (unlikely(off >= at25->chip.byte_len)) 247*cf09b7a0SBartosz Golaszewski return -EFBIG; 248*cf09b7a0SBartosz Golaszewski if ((off + count) > at25->chip.byte_len) 249*cf09b7a0SBartosz Golaszewski count = at25->chip.byte_len - off; 250*cf09b7a0SBartosz Golaszewski if (unlikely(!count)) 251*cf09b7a0SBartosz Golaszewski return -EINVAL; 252*cf09b7a0SBartosz Golaszewski 253*cf09b7a0SBartosz Golaszewski buf_size = at25->chip.page_size; 254*cf09b7a0SBartosz Golaszewski 255*cf09b7a0SBartosz Golaszewski if (!bounce) 256*cf09b7a0SBartosz Golaszewski return -ENOMEM; 257*cf09b7a0SBartosz Golaszewski 258*cf09b7a0SBartosz Golaszewski /* 259*cf09b7a0SBartosz Golaszewski * For write, rollover is within the page ... so we write at 260*cf09b7a0SBartosz Golaszewski * most one page, then manually roll over to the next page. 261*cf09b7a0SBartosz Golaszewski */ 262*cf09b7a0SBartosz Golaszewski guard(mutex)(&at25->lock); 263*cf09b7a0SBartosz Golaszewski do { 264*cf09b7a0SBartosz Golaszewski struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(AT25_WREN, 1), 265*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_NO_ADDR, 266*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_NO_DUMMY, 267*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_NO_DATA); 268*cf09b7a0SBartosz Golaszewski unsigned int segment; 269*cf09b7a0SBartosz Golaszewski 270*cf09b7a0SBartosz Golaszewski status = spi_mem_exec_op(at25->spimem, &op); 271*cf09b7a0SBartosz Golaszewski if (status < 0) { 272*cf09b7a0SBartosz Golaszewski dev_dbg(&at25->spimem->spi->dev, "WREN --> %d\n", status); 273*cf09b7a0SBartosz Golaszewski return status; 274*cf09b7a0SBartosz Golaszewski } 275*cf09b7a0SBartosz Golaszewski 276*cf09b7a0SBartosz Golaszewski /* Write as much of a page as we can */ 277*cf09b7a0SBartosz Golaszewski segment = buf_size - (off % buf_size); 278*cf09b7a0SBartosz Golaszewski if (segment > count) 279*cf09b7a0SBartosz Golaszewski segment = count; 280*cf09b7a0SBartosz Golaszewski if (segment > io_limit) 281*cf09b7a0SBartosz Golaszewski segment = io_limit; 282*cf09b7a0SBartosz Golaszewski 283*cf09b7a0SBartosz Golaszewski op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(at25_instr(at25, AT25_WRITE, off), 284*cf09b7a0SBartosz Golaszewski 1), 285*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_ADDR(at25->addrlen, off, 1), 286*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_NO_DUMMY, 287*cf09b7a0SBartosz Golaszewski SPI_MEM_OP_DATA_OUT(segment, bounce, 1)); 288*cf09b7a0SBartosz Golaszewski 289*cf09b7a0SBartosz Golaszewski status = spi_mem_adjust_op_size(at25->spimem, &op); 290*cf09b7a0SBartosz Golaszewski if (status) 291*cf09b7a0SBartosz Golaszewski return status; 292*cf09b7a0SBartosz Golaszewski segment = op.data.nbytes; 293*cf09b7a0SBartosz Golaszewski 294*cf09b7a0SBartosz Golaszewski memcpy(bounce, buf, segment); 295*cf09b7a0SBartosz Golaszewski 296*cf09b7a0SBartosz Golaszewski status = spi_mem_exec_op(at25->spimem, &op); 297*cf09b7a0SBartosz Golaszewski dev_dbg(&at25->spimem->spi->dev, "write %u bytes at %u --> %d\n", 298*cf09b7a0SBartosz Golaszewski segment, off, status); 299*cf09b7a0SBartosz Golaszewski if (status) 300*cf09b7a0SBartosz Golaszewski return status; 301*cf09b7a0SBartosz Golaszewski 302*cf09b7a0SBartosz Golaszewski /* 303*cf09b7a0SBartosz Golaszewski * REVISIT this should detect (or prevent) failed writes 304*cf09b7a0SBartosz Golaszewski * to read-only sections of the EEPROM... 305*cf09b7a0SBartosz Golaszewski */ 306*cf09b7a0SBartosz Golaszewski 307*cf09b7a0SBartosz Golaszewski status = at25_wait_ready(at25); 308*cf09b7a0SBartosz Golaszewski if (status < 0) { 309*cf09b7a0SBartosz Golaszewski dev_err_probe(&at25->spimem->spi->dev, status, 310*cf09b7a0SBartosz Golaszewski "Read Status Redister command failed\n"); 311*cf09b7a0SBartosz Golaszewski return status; 312*cf09b7a0SBartosz Golaszewski } 313*cf09b7a0SBartosz Golaszewski if (status) { 314*cf09b7a0SBartosz Golaszewski dev_dbg(&at25->spimem->spi->dev, 315*cf09b7a0SBartosz Golaszewski "Status %02x\n", status); 316*cf09b7a0SBartosz Golaszewski dev_err(&at25->spimem->spi->dev, 317*cf09b7a0SBartosz Golaszewski "write %u bytes offset %u, timeout after %u msecs\n", 318*cf09b7a0SBartosz Golaszewski segment, off, EE_TIMEOUT); 319*cf09b7a0SBartosz Golaszewski return -ETIMEDOUT; 320*cf09b7a0SBartosz Golaszewski } 321*cf09b7a0SBartosz Golaszewski 322*cf09b7a0SBartosz Golaszewski off += segment; 323*cf09b7a0SBartosz Golaszewski buf += segment; 324*cf09b7a0SBartosz Golaszewski count -= segment; 325*cf09b7a0SBartosz Golaszewski 326*cf09b7a0SBartosz Golaszewski } while (count > 0); 327*cf09b7a0SBartosz Golaszewski 328*cf09b7a0SBartosz Golaszewski return status; 329*cf09b7a0SBartosz Golaszewski } 330*cf09b7a0SBartosz Golaszewski 331*cf09b7a0SBartosz Golaszewski /*-------------------------------------------------------------------------*/ 332*cf09b7a0SBartosz Golaszewski 333*cf09b7a0SBartosz Golaszewski static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip) 334*cf09b7a0SBartosz Golaszewski { 335*cf09b7a0SBartosz Golaszewski u32 val; 336*cf09b7a0SBartosz Golaszewski int err; 337*cf09b7a0SBartosz Golaszewski 338*cf09b7a0SBartosz Golaszewski strscpy(chip->name, "at25", sizeof(chip->name)); 339*cf09b7a0SBartosz Golaszewski 340*cf09b7a0SBartosz Golaszewski err = device_property_read_u32(dev, "size", &val); 341*cf09b7a0SBartosz Golaszewski if (err) 342*cf09b7a0SBartosz Golaszewski err = device_property_read_u32(dev, "at25,byte-len", &val); 343*cf09b7a0SBartosz Golaszewski if (err) { 344*cf09b7a0SBartosz Golaszewski dev_err(dev, "Error: missing \"size\" property\n"); 345*cf09b7a0SBartosz Golaszewski return err; 346*cf09b7a0SBartosz Golaszewski } 347*cf09b7a0SBartosz Golaszewski chip->byte_len = val; 348*cf09b7a0SBartosz Golaszewski 349*cf09b7a0SBartosz Golaszewski err = device_property_read_u32(dev, "pagesize", &val); 350*cf09b7a0SBartosz Golaszewski if (err) 351*cf09b7a0SBartosz Golaszewski err = device_property_read_u32(dev, "at25,page-size", &val); 352*cf09b7a0SBartosz Golaszewski if (err) { 353*cf09b7a0SBartosz Golaszewski dev_err(dev, "Error: missing \"pagesize\" property\n"); 354*cf09b7a0SBartosz Golaszewski return err; 355*cf09b7a0SBartosz Golaszewski } 356*cf09b7a0SBartosz Golaszewski chip->page_size = val; 357*cf09b7a0SBartosz Golaszewski 358*cf09b7a0SBartosz Golaszewski err = device_property_read_u32(dev, "address-width", &val); 359*cf09b7a0SBartosz Golaszewski if (err) { 360*cf09b7a0SBartosz Golaszewski err = device_property_read_u32(dev, "at25,addr-mode", &val); 361*cf09b7a0SBartosz Golaszewski if (err) { 362*cf09b7a0SBartosz Golaszewski dev_err(dev, "Error: missing \"address-width\" property\n"); 363*cf09b7a0SBartosz Golaszewski return err; 364*cf09b7a0SBartosz Golaszewski } 365*cf09b7a0SBartosz Golaszewski chip->flags = (u16)val; 366*cf09b7a0SBartosz Golaszewski } else { 367*cf09b7a0SBartosz Golaszewski switch (val) { 368*cf09b7a0SBartosz Golaszewski case 9: 369*cf09b7a0SBartosz Golaszewski chip->flags |= EE_INSTR_BIT3_IS_ADDR; 370*cf09b7a0SBartosz Golaszewski fallthrough; 371*cf09b7a0SBartosz Golaszewski case 8: 372*cf09b7a0SBartosz Golaszewski chip->flags |= EE_ADDR1; 373*cf09b7a0SBartosz Golaszewski break; 374*cf09b7a0SBartosz Golaszewski case 16: 375*cf09b7a0SBartosz Golaszewski chip->flags |= EE_ADDR2; 376*cf09b7a0SBartosz Golaszewski break; 377*cf09b7a0SBartosz Golaszewski case 24: 378*cf09b7a0SBartosz Golaszewski chip->flags |= EE_ADDR3; 379*cf09b7a0SBartosz Golaszewski break; 380*cf09b7a0SBartosz Golaszewski default: 381*cf09b7a0SBartosz Golaszewski dev_err(dev, 382*cf09b7a0SBartosz Golaszewski "Error: bad \"address-width\" property: %u\n", 383*cf09b7a0SBartosz Golaszewski val); 384*cf09b7a0SBartosz Golaszewski return -ENODEV; 385*cf09b7a0SBartosz Golaszewski } 386*cf09b7a0SBartosz Golaszewski if (device_property_present(dev, "read-only")) 387*cf09b7a0SBartosz Golaszewski chip->flags |= EE_READONLY; 388*cf09b7a0SBartosz Golaszewski } 389*cf09b7a0SBartosz Golaszewski return 0; 390*cf09b7a0SBartosz Golaszewski } 391*cf09b7a0SBartosz Golaszewski 392*cf09b7a0SBartosz Golaszewski static int at25_fram_to_chip(struct device *dev, struct spi_eeprom *chip) 393*cf09b7a0SBartosz Golaszewski { 394*cf09b7a0SBartosz Golaszewski struct at25_data *at25 = container_of(chip, struct at25_data, chip); 395*cf09b7a0SBartosz Golaszewski u8 sernum[FM25_SN_LEN]; 396*cf09b7a0SBartosz Golaszewski u8 id[FM25_MAX_ID_LEN]; 397*cf09b7a0SBartosz Golaszewski u32 val; 398*cf09b7a0SBartosz Golaszewski int i; 399*cf09b7a0SBartosz Golaszewski 400*cf09b7a0SBartosz Golaszewski strscpy(chip->name, "fm25", sizeof(chip->name)); 401*cf09b7a0SBartosz Golaszewski 402*cf09b7a0SBartosz Golaszewski if (!device_property_read_u32(dev, "size", &val)) { 403*cf09b7a0SBartosz Golaszewski chip->byte_len = val; 404*cf09b7a0SBartosz Golaszewski } else { 405*cf09b7a0SBartosz Golaszewski /* Get ID of chip */ 406*cf09b7a0SBartosz Golaszewski fm25_aux_read(at25, id, FM25_RDID, FM25_MAX_ID_LEN); 407*cf09b7a0SBartosz Golaszewski 408*cf09b7a0SBartosz Golaszewski /* Store the unprocessed ID for exposing via sysfs */ 409*cf09b7a0SBartosz Golaszewski memcpy(at25->id, id, FM25_MAX_ID_LEN); 410*cf09b7a0SBartosz Golaszewski at25->id_len = FM25_MAX_ID_LEN; 411*cf09b7a0SBartosz Golaszewski 412*cf09b7a0SBartosz Golaszewski /* There are inside-out FRAM variations, detect them and reverse the ID bytes */ 413*cf09b7a0SBartosz Golaszewski if (id[6] == 0x7f && id[2] == 0xc2) 414*cf09b7a0SBartosz Golaszewski for (i = 0; i < ARRAY_SIZE(id) / 2; i++) { 415*cf09b7a0SBartosz Golaszewski u8 tmp = id[i]; 416*cf09b7a0SBartosz Golaszewski int j = ARRAY_SIZE(id) - i - 1; 417*cf09b7a0SBartosz Golaszewski 418*cf09b7a0SBartosz Golaszewski id[i] = id[j]; 419*cf09b7a0SBartosz Golaszewski id[j] = tmp; 420*cf09b7a0SBartosz Golaszewski } 421*cf09b7a0SBartosz Golaszewski 422*cf09b7a0SBartosz Golaszewski if (id[6] == 0xc2) { 423*cf09b7a0SBartosz Golaszewski at25->id_len = 9; 424*cf09b7a0SBartosz Golaszewski switch (id[7]) { 425*cf09b7a0SBartosz Golaszewski case 0x21 ... 0x26: 426*cf09b7a0SBartosz Golaszewski chip->byte_len = BIT(id[7] - 0x21 + 4) * 1024; 427*cf09b7a0SBartosz Golaszewski break; 428*cf09b7a0SBartosz Golaszewski case 0x2a ... 0x30: 429*cf09b7a0SBartosz Golaszewski /* CY15B102QN ... CY15B116QN */ 430*cf09b7a0SBartosz Golaszewski chip->byte_len = BIT(((id[7] >> 1) & 0xf) + 13); 431*cf09b7a0SBartosz Golaszewski break; 432*cf09b7a0SBartosz Golaszewski default: 433*cf09b7a0SBartosz Golaszewski dev_err(dev, "Error: unsupported size (id %02x)\n", id[7]); 434*cf09b7a0SBartosz Golaszewski return -ENODEV; 435*cf09b7a0SBartosz Golaszewski } 436*cf09b7a0SBartosz Golaszewski } else if (id[2] == 0x82 && id[3] == 0x06) { 437*cf09b7a0SBartosz Golaszewski at25->id_len = 8; 438*cf09b7a0SBartosz Golaszewski switch (id[1]) { 439*cf09b7a0SBartosz Golaszewski case 0x51 ... 0x54: 440*cf09b7a0SBartosz Golaszewski /* CY15B102QSN ... CY15B204QSN */ 441*cf09b7a0SBartosz Golaszewski chip->byte_len = BIT(((id[0] >> 3) & 0x1F) + 9); 442*cf09b7a0SBartosz Golaszewski break; 443*cf09b7a0SBartosz Golaszewski default: 444*cf09b7a0SBartosz Golaszewski dev_err(dev, "Error: unsupported product id %02x\n", id[1]); 445*cf09b7a0SBartosz Golaszewski return -ENODEV; 446*cf09b7a0SBartosz Golaszewski } 447*cf09b7a0SBartosz Golaszewski } else { 448*cf09b7a0SBartosz Golaszewski dev_err(dev, "Error: unrecognized JEDEC ID format: %*ph\n", 449*cf09b7a0SBartosz Golaszewski FM25_MAX_ID_LEN, id); 450*cf09b7a0SBartosz Golaszewski return -ENODEV; 451*cf09b7a0SBartosz Golaszewski } 452*cf09b7a0SBartosz Golaszewski 453*cf09b7a0SBartosz Golaszewski fm25_aux_read(at25, sernum, FM25_RDSN, FM25_SN_LEN); 454*cf09b7a0SBartosz Golaszewski /* Swap byte order */ 455*cf09b7a0SBartosz Golaszewski for (i = 0; i < FM25_SN_LEN; i++) 456*cf09b7a0SBartosz Golaszewski at25->sernum[i] = sernum[FM25_SN_LEN - 1 - i]; 457*cf09b7a0SBartosz Golaszewski } 458*cf09b7a0SBartosz Golaszewski 459*cf09b7a0SBartosz Golaszewski if (chip->byte_len > 64 * 1024) 460*cf09b7a0SBartosz Golaszewski chip->flags |= EE_ADDR3; 461*cf09b7a0SBartosz Golaszewski else 462*cf09b7a0SBartosz Golaszewski chip->flags |= EE_ADDR2; 463*cf09b7a0SBartosz Golaszewski 464*cf09b7a0SBartosz Golaszewski chip->page_size = PAGE_SIZE; 465*cf09b7a0SBartosz Golaszewski return 0; 466*cf09b7a0SBartosz Golaszewski } 467*cf09b7a0SBartosz Golaszewski 468*cf09b7a0SBartosz Golaszewski static const struct of_device_id at25_of_match[] = { 469*cf09b7a0SBartosz Golaszewski { .compatible = "atmel,at25" }, 470*cf09b7a0SBartosz Golaszewski { .compatible = "cypress,fm25" }, 471*cf09b7a0SBartosz Golaszewski { } 472*cf09b7a0SBartosz Golaszewski }; 473*cf09b7a0SBartosz Golaszewski MODULE_DEVICE_TABLE(of, at25_of_match); 474*cf09b7a0SBartosz Golaszewski 475*cf09b7a0SBartosz Golaszewski static const struct spi_device_id at25_spi_ids[] = { 476*cf09b7a0SBartosz Golaszewski { .name = "at25" }, 477*cf09b7a0SBartosz Golaszewski { .name = "fm25" }, 478*cf09b7a0SBartosz Golaszewski { } 479*cf09b7a0SBartosz Golaszewski }; 480*cf09b7a0SBartosz Golaszewski MODULE_DEVICE_TABLE(spi, at25_spi_ids); 481*cf09b7a0SBartosz Golaszewski 482*cf09b7a0SBartosz Golaszewski static int at25_probe(struct spi_mem *mem) 483*cf09b7a0SBartosz Golaszewski { 484*cf09b7a0SBartosz Golaszewski struct spi_device *spi = mem->spi; 485*cf09b7a0SBartosz Golaszewski struct spi_eeprom *pdata; 486*cf09b7a0SBartosz Golaszewski struct at25_data *at25; 487*cf09b7a0SBartosz Golaszewski bool is_fram; 488*cf09b7a0SBartosz Golaszewski int err; 489*cf09b7a0SBartosz Golaszewski 490*cf09b7a0SBartosz Golaszewski at25 = devm_kzalloc(&spi->dev, sizeof(*at25), GFP_KERNEL); 491*cf09b7a0SBartosz Golaszewski if (!at25) 492*cf09b7a0SBartosz Golaszewski return -ENOMEM; 493*cf09b7a0SBartosz Golaszewski 494*cf09b7a0SBartosz Golaszewski at25->spimem = mem; 495*cf09b7a0SBartosz Golaszewski 496*cf09b7a0SBartosz Golaszewski /* 497*cf09b7a0SBartosz Golaszewski * Ping the chip ... the status register is pretty portable, 498*cf09b7a0SBartosz Golaszewski * unlike probing manufacturer IDs. 499*cf09b7a0SBartosz Golaszewski */ 500*cf09b7a0SBartosz Golaszewski err = at25_wait_ready(at25); 501*cf09b7a0SBartosz Golaszewski if (err < 0) 502*cf09b7a0SBartosz Golaszewski return dev_err_probe(&spi->dev, err, "Read Status Register command failed\n"); 503*cf09b7a0SBartosz Golaszewski if (err) { 504*cf09b7a0SBartosz Golaszewski dev_err(&spi->dev, "Not ready (%02x)\n", err); 505*cf09b7a0SBartosz Golaszewski return -ENXIO; 506*cf09b7a0SBartosz Golaszewski } 507*cf09b7a0SBartosz Golaszewski 508*cf09b7a0SBartosz Golaszewski mutex_init(&at25->lock); 509*cf09b7a0SBartosz Golaszewski spi_set_drvdata(spi, at25); 510*cf09b7a0SBartosz Golaszewski 511*cf09b7a0SBartosz Golaszewski is_fram = fwnode_device_is_compatible(dev_fwnode(&spi->dev), "cypress,fm25"); 512*cf09b7a0SBartosz Golaszewski 513*cf09b7a0SBartosz Golaszewski /* Chip description */ 514*cf09b7a0SBartosz Golaszewski pdata = dev_get_platdata(&spi->dev); 515*cf09b7a0SBartosz Golaszewski if (pdata) { 516*cf09b7a0SBartosz Golaszewski at25->chip = *pdata; 517*cf09b7a0SBartosz Golaszewski } else { 518*cf09b7a0SBartosz Golaszewski if (is_fram) 519*cf09b7a0SBartosz Golaszewski err = at25_fram_to_chip(&spi->dev, &at25->chip); 520*cf09b7a0SBartosz Golaszewski else 521*cf09b7a0SBartosz Golaszewski err = at25_fw_to_chip(&spi->dev, &at25->chip); 522*cf09b7a0SBartosz Golaszewski if (err) 523*cf09b7a0SBartosz Golaszewski return err; 524*cf09b7a0SBartosz Golaszewski } 525*cf09b7a0SBartosz Golaszewski 526*cf09b7a0SBartosz Golaszewski /* For now we only support 8/16/24 bit addressing */ 527*cf09b7a0SBartosz Golaszewski if (at25->chip.flags & EE_ADDR1) 528*cf09b7a0SBartosz Golaszewski at25->addrlen = 1; 529*cf09b7a0SBartosz Golaszewski else if (at25->chip.flags & EE_ADDR2) 530*cf09b7a0SBartosz Golaszewski at25->addrlen = 2; 531*cf09b7a0SBartosz Golaszewski else if (at25->chip.flags & EE_ADDR3) 532*cf09b7a0SBartosz Golaszewski at25->addrlen = 3; 533*cf09b7a0SBartosz Golaszewski else { 534*cf09b7a0SBartosz Golaszewski dev_dbg(&spi->dev, "unsupported address type\n"); 535*cf09b7a0SBartosz Golaszewski return -EINVAL; 536*cf09b7a0SBartosz Golaszewski } 537*cf09b7a0SBartosz Golaszewski 538*cf09b7a0SBartosz Golaszewski at25->nvmem_config.type = is_fram ? NVMEM_TYPE_FRAM : NVMEM_TYPE_EEPROM; 539*cf09b7a0SBartosz Golaszewski at25->nvmem_config.name = dev_name(&spi->dev); 540*cf09b7a0SBartosz Golaszewski at25->nvmem_config.dev = &spi->dev; 541*cf09b7a0SBartosz Golaszewski at25->nvmem_config.read_only = at25->chip.flags & EE_READONLY; 542*cf09b7a0SBartosz Golaszewski at25->nvmem_config.root_only = true; 543*cf09b7a0SBartosz Golaszewski at25->nvmem_config.owner = THIS_MODULE; 544*cf09b7a0SBartosz Golaszewski at25->nvmem_config.compat = true; 545*cf09b7a0SBartosz Golaszewski at25->nvmem_config.base_dev = &spi->dev; 546*cf09b7a0SBartosz Golaszewski at25->nvmem_config.reg_read = at25_ee_read; 547*cf09b7a0SBartosz Golaszewski at25->nvmem_config.reg_write = at25_ee_write; 548*cf09b7a0SBartosz Golaszewski at25->nvmem_config.priv = at25; 549*cf09b7a0SBartosz Golaszewski at25->nvmem_config.stride = 1; 550*cf09b7a0SBartosz Golaszewski at25->nvmem_config.word_size = 1; 551*cf09b7a0SBartosz Golaszewski at25->nvmem_config.size = at25->chip.byte_len; 552*cf09b7a0SBartosz Golaszewski 553*cf09b7a0SBartosz Golaszewski at25->nvmem = devm_nvmem_register(&spi->dev, &at25->nvmem_config); 554*cf09b7a0SBartosz Golaszewski if (IS_ERR(at25->nvmem)) 555*cf09b7a0SBartosz Golaszewski return PTR_ERR(at25->nvmem); 556*cf09b7a0SBartosz Golaszewski 557*cf09b7a0SBartosz Golaszewski dev_info(&spi->dev, "%d %s %s %s%s, pagesize %u\n", 558*cf09b7a0SBartosz Golaszewski (at25->chip.byte_len < 1024) ? 559*cf09b7a0SBartosz Golaszewski at25->chip.byte_len : (at25->chip.byte_len / 1024), 560*cf09b7a0SBartosz Golaszewski (at25->chip.byte_len < 1024) ? "Byte" : "KByte", 561*cf09b7a0SBartosz Golaszewski at25->chip.name, is_fram ? "fram" : "eeprom", 562*cf09b7a0SBartosz Golaszewski (at25->chip.flags & EE_READONLY) ? " (readonly)" : "", 563*cf09b7a0SBartosz Golaszewski at25->chip.page_size); 564*cf09b7a0SBartosz Golaszewski return 0; 565*cf09b7a0SBartosz Golaszewski } 566*cf09b7a0SBartosz Golaszewski 567*cf09b7a0SBartosz Golaszewski /*-------------------------------------------------------------------------*/ 568*cf09b7a0SBartosz Golaszewski 569*cf09b7a0SBartosz Golaszewski static struct spi_mem_driver at25_driver = { 570*cf09b7a0SBartosz Golaszewski .spidrv = { 571*cf09b7a0SBartosz Golaszewski .driver = { 572*cf09b7a0SBartosz Golaszewski .name = "at25", 573*cf09b7a0SBartosz Golaszewski .of_match_table = at25_of_match, 574*cf09b7a0SBartosz Golaszewski .dev_groups = at25_groups, 575*cf09b7a0SBartosz Golaszewski }, 576*cf09b7a0SBartosz Golaszewski .id_table = at25_spi_ids, 577*cf09b7a0SBartosz Golaszewski }, 578*cf09b7a0SBartosz Golaszewski .probe = at25_probe, 579*cf09b7a0SBartosz Golaszewski }; 580*cf09b7a0SBartosz Golaszewski 581*cf09b7a0SBartosz Golaszewski module_spi_mem_driver(at25_driver); 582*cf09b7a0SBartosz Golaszewski 583*cf09b7a0SBartosz Golaszewski MODULE_DESCRIPTION("Driver for most SPI EEPROMs"); 584*cf09b7a0SBartosz Golaszewski MODULE_AUTHOR("David Brownell"); 585*cf09b7a0SBartosz Golaszewski MODULE_LICENSE("GPL"); 586