brintos

brintos / linux-shallow public Read only

0
0
Text · 12.8 KiB · 595ceb9 Raw
532 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Driver for most of the SPI EEPROMs, such as Atmel AT25 models4 * and Cypress FRAMs FM25 models.5 *6 * Copyright (C) 2006 David Brownell7 */8 9#include <linux/bits.h>10#include <linux/delay.h>11#include <linux/device.h>12#include <linux/kernel.h>13#include <linux/module.h>14#include <linux/property.h>15#include <linux/sched.h>16#include <linux/slab.h>17 18#include <linux/spi/eeprom.h>19#include <linux/spi/spi.h>20 21#include <linux/nvmem-provider.h>22 23/*24 * NOTE: this is an *EEPROM* driver. The vagaries of product naming25 * mean that some AT25 products are EEPROMs, and others are FLASH.26 * Handle FLASH chips with the drivers/mtd/devices/m25p80.c driver,27 * not this one!28 *29 * EEPROMs that can be used with this driver include, for example:30 *   AT25M02, AT25128B31 */32 33#define	FM25_SN_LEN	8		/* serial number length */34#define EE_MAXADDRLEN	3		/* 24 bit addresses, up to 2 MBytes */35 36struct at25_data {37	struct spi_eeprom	chip;38	struct spi_device	*spi;39	struct mutex		lock;40	unsigned		addrlen;41	struct nvmem_config	nvmem_config;42	struct nvmem_device	*nvmem;43	u8 sernum[FM25_SN_LEN];44	u8 command[EE_MAXADDRLEN + 1];45};46 47#define	AT25_WREN	0x06		/* latch the write enable */48#define	AT25_WRDI	0x04		/* reset the write enable */49#define	AT25_RDSR	0x05		/* read status register */50#define	AT25_WRSR	0x01		/* write status register */51#define	AT25_READ	0x03		/* read byte(s) */52#define	AT25_WRITE	0x02		/* write byte(s)/sector */53#define	FM25_SLEEP	0xb9		/* enter sleep mode */54#define	FM25_RDID	0x9f		/* read device ID */55#define	FM25_RDSN	0xc3		/* read S/N */56 57#define	AT25_SR_nRDY	0x01		/* nRDY = write-in-progress */58#define	AT25_SR_WEN	0x02		/* write enable (latched) */59#define	AT25_SR_BP0	0x04		/* BP for software writeprotect */60#define	AT25_SR_BP1	0x0861#define	AT25_SR_WPEN	0x80		/* writeprotect enable */62 63#define	AT25_INSTR_BIT3	0x08		/* additional address bit in instr */64 65#define	FM25_ID_LEN	9		/* ID length */66 67/*68 * Specs often allow 5ms for a page write, sometimes 20ms;69 * it's important to recover from write timeouts.70 */71#define	EE_TIMEOUT	2572 73/*-------------------------------------------------------------------------*/74 75#define	io_limit	PAGE_SIZE	/* bytes */76 77static int at25_ee_read(void *priv, unsigned int offset,78			void *val, size_t count)79{80	struct at25_data *at25 = priv;81	char *buf = val;82	size_t max_chunk = spi_max_transfer_size(at25->spi);83	unsigned int msg_offset = offset;84	size_t bytes_left = count;85	size_t segment;86	u8			*cp;87	ssize_t			status;88	struct spi_transfer	t[2];89	struct spi_message	m;90	u8			instr;91 92	if (unlikely(offset >= at25->chip.byte_len))93		return -EINVAL;94	if ((offset + count) > at25->chip.byte_len)95		count = at25->chip.byte_len - offset;96	if (unlikely(!count))97		return -EINVAL;98 99	do {100		segment = min(bytes_left, max_chunk);101		cp = at25->command;102 103		instr = AT25_READ;104		if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)105			if (msg_offset >= BIT(at25->addrlen * 8))106				instr |= AT25_INSTR_BIT3;107 108		mutex_lock(&at25->lock);109 110		*cp++ = instr;111 112		/* 8/16/24-bit address is written MSB first */113		switch (at25->addrlen) {114		default:	/* case 3 */115			*cp++ = msg_offset >> 16;116			fallthrough;117		case 2:118			*cp++ = msg_offset >> 8;119			fallthrough;120		case 1:121		case 0:	/* can't happen: for better code generation */122			*cp++ = msg_offset >> 0;123		}124 125		spi_message_init(&m);126		memset(t, 0, sizeof(t));127 128		t[0].tx_buf = at25->command;129		t[0].len = at25->addrlen + 1;130		spi_message_add_tail(&t[0], &m);131 132		t[1].rx_buf = buf;133		t[1].len = segment;134		spi_message_add_tail(&t[1], &m);135 136		status = spi_sync(at25->spi, &m);137 138		mutex_unlock(&at25->lock);139 140		if (status)141			return status;142 143		msg_offset += segment;144		buf += segment;145		bytes_left -= segment;146	} while (bytes_left > 0);147 148	dev_dbg(&at25->spi->dev, "read %zu bytes at %d\n",149		count, offset);150	return 0;151}152 153/* Read extra registers as ID or serial number */154static int fm25_aux_read(struct at25_data *at25, u8 *buf, uint8_t command,155			 int len)156{157	int status;158	struct spi_transfer t[2];159	struct spi_message m;160 161	spi_message_init(&m);162	memset(t, 0, sizeof(t));163 164	t[0].tx_buf = at25->command;165	t[0].len = 1;166	spi_message_add_tail(&t[0], &m);167 168	t[1].rx_buf = buf;169	t[1].len = len;170	spi_message_add_tail(&t[1], &m);171 172	mutex_lock(&at25->lock);173 174	at25->command[0] = command;175 176	status = spi_sync(at25->spi, &m);177	dev_dbg(&at25->spi->dev, "read %d aux bytes --> %d\n", len, status);178 179	mutex_unlock(&at25->lock);180	return status;181}182 183static ssize_t sernum_show(struct device *dev, struct device_attribute *attr, char *buf)184{185	struct at25_data *at25;186 187	at25 = dev_get_drvdata(dev);188	return sysfs_emit(buf, "%*ph\n", (int)sizeof(at25->sernum), at25->sernum);189}190static DEVICE_ATTR_RO(sernum);191 192static struct attribute *sernum_attrs[] = {193	&dev_attr_sernum.attr,194	NULL,195};196ATTRIBUTE_GROUPS(sernum);197 198static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count)199{200	struct at25_data *at25 = priv;201	size_t maxsz = spi_max_transfer_size(at25->spi);202	const char *buf = val;203	int			status = 0;204	unsigned		buf_size;205	u8			*bounce;206 207	if (unlikely(off >= at25->chip.byte_len))208		return -EFBIG;209	if ((off + count) > at25->chip.byte_len)210		count = at25->chip.byte_len - off;211	if (unlikely(!count))212		return -EINVAL;213 214	/* Temp buffer starts with command and address */215	buf_size = at25->chip.page_size;216	if (buf_size > io_limit)217		buf_size = io_limit;218	bounce = kmalloc(buf_size + at25->addrlen + 1, GFP_KERNEL);219	if (!bounce)220		return -ENOMEM;221 222	/*223	 * For write, rollover is within the page ... so we write at224	 * most one page, then manually roll over to the next page.225	 */226	mutex_lock(&at25->lock);227	do {228		unsigned long	timeout, retries;229		unsigned	segment;230		unsigned	offset = off;231		u8		*cp = bounce;232		int		sr;233		u8		instr;234 235		*cp = AT25_WREN;236		status = spi_write(at25->spi, cp, 1);237		if (status < 0) {238			dev_dbg(&at25->spi->dev, "WREN --> %d\n", status);239			break;240		}241 242		instr = AT25_WRITE;243		if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)244			if (offset >= BIT(at25->addrlen * 8))245				instr |= AT25_INSTR_BIT3;246		*cp++ = instr;247 248		/* 8/16/24-bit address is written MSB first */249		switch (at25->addrlen) {250		default:	/* case 3 */251			*cp++ = offset >> 16;252			fallthrough;253		case 2:254			*cp++ = offset >> 8;255			fallthrough;256		case 1:257		case 0:	/* can't happen: for better code generation */258			*cp++ = offset >> 0;259		}260 261		/* Write as much of a page as we can */262		segment = buf_size - (offset % buf_size);263		if (segment > count)264			segment = count;265		if (segment > maxsz)266			segment = maxsz;267		memcpy(cp, buf, segment);268		status = spi_write(at25->spi, bounce,269				segment + at25->addrlen + 1);270		dev_dbg(&at25->spi->dev, "write %u bytes at %u --> %d\n",271			segment, offset, status);272		if (status < 0)273			break;274 275		/*276		 * REVISIT this should detect (or prevent) failed writes277		 * to read-only sections of the EEPROM...278		 */279 280		/* Wait for non-busy status */281		timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT);282		retries = 0;283		do {284 285			sr = spi_w8r8(at25->spi, AT25_RDSR);286			if (sr < 0 || (sr & AT25_SR_nRDY)) {287				dev_dbg(&at25->spi->dev,288					"rdsr --> %d (%02x)\n", sr, sr);289				/* at HZ=100, this is sloooow */290				msleep(1);291				continue;292			}293			if (!(sr & AT25_SR_nRDY))294				break;295		} while (retries++ < 3 || time_before_eq(jiffies, timeout));296 297		if ((sr < 0) || (sr & AT25_SR_nRDY)) {298			dev_err(&at25->spi->dev,299				"write %u bytes offset %u, timeout after %u msecs\n",300				segment, offset,301				jiffies_to_msecs(jiffies -302					(timeout - EE_TIMEOUT)));303			status = -ETIMEDOUT;304			break;305		}306 307		off += segment;308		buf += segment;309		count -= segment;310 311	} while (count > 0);312 313	mutex_unlock(&at25->lock);314 315	kfree(bounce);316	return status;317}318 319/*-------------------------------------------------------------------------*/320 321static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)322{323	u32 val;324	int err;325 326	strscpy(chip->name, "at25", sizeof(chip->name));327 328	err = device_property_read_u32(dev, "size", &val);329	if (err)330		err = device_property_read_u32(dev, "at25,byte-len", &val);331	if (err) {332		dev_err(dev, "Error: missing \"size\" property\n");333		return err;334	}335	chip->byte_len = val;336 337	err = device_property_read_u32(dev, "pagesize", &val);338	if (err)339		err = device_property_read_u32(dev, "at25,page-size", &val);340	if (err) {341		dev_err(dev, "Error: missing \"pagesize\" property\n");342		return err;343	}344	chip->page_size = val;345 346	err = device_property_read_u32(dev, "address-width", &val);347	if (err) {348		err = device_property_read_u32(dev, "at25,addr-mode", &val);349		if (err) {350			dev_err(dev, "Error: missing \"address-width\" property\n");351			return err;352		}353		chip->flags = (u16)val;354	} else {355		switch (val) {356		case 9:357			chip->flags |= EE_INSTR_BIT3_IS_ADDR;358			fallthrough;359		case 8:360			chip->flags |= EE_ADDR1;361			break;362		case 16:363			chip->flags |= EE_ADDR2;364			break;365		case 24:366			chip->flags |= EE_ADDR3;367			break;368		default:369			dev_err(dev,370				"Error: bad \"address-width\" property: %u\n",371				val);372			return -ENODEV;373		}374		if (device_property_present(dev, "read-only"))375			chip->flags |= EE_READONLY;376	}377	return 0;378}379 380static int at25_fram_to_chip(struct device *dev, struct spi_eeprom *chip)381{382	struct at25_data *at25 = container_of(chip, struct at25_data, chip);383	u8 sernum[FM25_SN_LEN];384	u8 id[FM25_ID_LEN];385	int i;386 387	strscpy(chip->name, "fm25", sizeof(chip->name));388 389	/* Get ID of chip */390	fm25_aux_read(at25, id, FM25_RDID, FM25_ID_LEN);391	if (id[6] != 0xc2) {392		dev_err(dev, "Error: no Cypress FRAM (id %02x)\n", id[6]);393		return -ENODEV;394	}395	/* Set size found in ID */396	if (id[7] < 0x21 || id[7] > 0x26) {397		dev_err(dev, "Error: unsupported size (id %02x)\n", id[7]);398		return -ENODEV;399	}400 401	chip->byte_len = BIT(id[7] - 0x21 + 4) * 1024;402	if (chip->byte_len > 64 * 1024)403		chip->flags |= EE_ADDR3;404	else405		chip->flags |= EE_ADDR2;406 407	if (id[8]) {408		fm25_aux_read(at25, sernum, FM25_RDSN, FM25_SN_LEN);409		/* Swap byte order */410		for (i = 0; i < FM25_SN_LEN; i++)411			at25->sernum[i] = sernum[FM25_SN_LEN - 1 - i];412	}413 414	chip->page_size = PAGE_SIZE;415	return 0;416}417 418static const struct of_device_id at25_of_match[] = {419	{ .compatible = "atmel,at25" },420	{ .compatible = "cypress,fm25" },421	{ }422};423MODULE_DEVICE_TABLE(of, at25_of_match);424 425static const struct spi_device_id at25_spi_ids[] = {426	{ .name = "at25" },427	{ .name = "fm25" },428	{ }429};430MODULE_DEVICE_TABLE(spi, at25_spi_ids);431 432static int at25_probe(struct spi_device *spi)433{434	struct at25_data	*at25 = NULL;435	int			err;436	int			sr;437	struct spi_eeprom *pdata;438	bool is_fram;439 440	/*441	 * Ping the chip ... the status register is pretty portable,442	 * unlike probing manufacturer IDs. We do expect that system443	 * firmware didn't write it in the past few milliseconds!444	 */445	sr = spi_w8r8(spi, AT25_RDSR);446	if (sr < 0 || sr & AT25_SR_nRDY) {447		dev_dbg(&spi->dev, "rdsr --> %d (%02x)\n", sr, sr);448		return -ENXIO;449	}450 451	at25 = devm_kzalloc(&spi->dev, sizeof(*at25), GFP_KERNEL);452	if (!at25)453		return -ENOMEM;454 455	mutex_init(&at25->lock);456	at25->spi = spi;457	spi_set_drvdata(spi, at25);458 459	is_fram = fwnode_device_is_compatible(dev_fwnode(&spi->dev), "cypress,fm25");460 461	/* Chip description */462	pdata = dev_get_platdata(&spi->dev);463	if (pdata) {464		at25->chip = *pdata;465	} else {466		if (is_fram)467			err = at25_fram_to_chip(&spi->dev, &at25->chip);468		else469			err = at25_fw_to_chip(&spi->dev, &at25->chip);470		if (err)471			return err;472	}473 474	/* For now we only support 8/16/24 bit addressing */475	if (at25->chip.flags & EE_ADDR1)476		at25->addrlen = 1;477	else if (at25->chip.flags & EE_ADDR2)478		at25->addrlen = 2;479	else if (at25->chip.flags & EE_ADDR3)480		at25->addrlen = 3;481	else {482		dev_dbg(&spi->dev, "unsupported address type\n");483		return -EINVAL;484	}485 486	at25->nvmem_config.type = is_fram ? NVMEM_TYPE_FRAM : NVMEM_TYPE_EEPROM;487	at25->nvmem_config.name = dev_name(&spi->dev);488	at25->nvmem_config.dev = &spi->dev;489	at25->nvmem_config.read_only = at25->chip.flags & EE_READONLY;490	at25->nvmem_config.root_only = true;491	at25->nvmem_config.owner = THIS_MODULE;492	at25->nvmem_config.compat = true;493	at25->nvmem_config.base_dev = &spi->dev;494	at25->nvmem_config.reg_read = at25_ee_read;495	at25->nvmem_config.reg_write = at25_ee_write;496	at25->nvmem_config.priv = at25;497	at25->nvmem_config.stride = 1;498	at25->nvmem_config.word_size = 1;499	at25->nvmem_config.size = at25->chip.byte_len;500 501	at25->nvmem = devm_nvmem_register(&spi->dev, &at25->nvmem_config);502	if (IS_ERR(at25->nvmem))503		return PTR_ERR(at25->nvmem);504 505	dev_info(&spi->dev, "%d %s %s %s%s, pagesize %u\n",506		 (at25->chip.byte_len < 1024) ?507			at25->chip.byte_len : (at25->chip.byte_len / 1024),508		 (at25->chip.byte_len < 1024) ? "Byte" : "KByte",509		 at25->chip.name, is_fram ? "fram" : "eeprom",510		 (at25->chip.flags & EE_READONLY) ? " (readonly)" : "",511		 at25->chip.page_size);512	return 0;513}514 515/*-------------------------------------------------------------------------*/516 517static struct spi_driver at25_driver = {518	.driver = {519		.name		= "at25",520		.of_match_table = at25_of_match,521		.dev_groups	= sernum_groups,522	},523	.probe		= at25_probe,524	.id_table	= at25_spi_ids,525};526 527module_spi_driver(at25_driver);528 529MODULE_DESCRIPTION("Driver for most SPI EEPROMs");530MODULE_AUTHOR("David Brownell");531MODULE_LICENSE("GPL");532