brintos

brintos / linux-shallow public Read only

0
0
Text · 13.3 KiB · e2221be Raw
567 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Driver for 93xx46 EEPROMs4 *5 * (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de>6 */7 8#include <linux/array_size.h>9#include <linux/bits.h>10#include <linux/delay.h>11#include <linux/device.h>12#include <linux/gpio/consumer.h>13#include <linux/kstrtox.h>14#include <linux/log2.h>15#include <linux/mod_devicetable.h>16#include <linux/module.h>17#include <linux/mutex.h>18#include <linux/property.h>19#include <linux/slab.h>20#include <linux/spi/spi.h>21#include <linux/string_choices.h>22 23#include <linux/nvmem-provider.h>24 25struct eeprom_93xx46_platform_data {26	unsigned char	flags;27#define EE_ADDR8	0x01		/*  8 bit addr. cfg */28#define EE_ADDR16	0x02		/* 16 bit addr. cfg */29#define EE_READONLY	0x08		/* forbid writing */30#define EE_SIZE1K	0x10		/* 1 kb of data, that is a 93xx46 */31#define EE_SIZE2K	0x20		/* 2 kb of data, that is a 93xx56 */32#define EE_SIZE4K	0x40		/* 4 kb of data, that is a 93xx66 */33 34	unsigned int	quirks;35/* Single word read transfers only; no sequential read. */36#define EEPROM_93XX46_QUIRK_SINGLE_WORD_READ		(1 << 0)37/* Instructions such as EWEN are (addrlen + 2) in length. */38#define EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH		(1 << 1)39/* Add extra cycle after address during a read */40#define EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE		BIT(2)41 42	struct gpio_desc *select;43};44 45#define OP_START	0x446#define OP_WRITE	(OP_START | 0x1)47#define OP_READ		(OP_START | 0x2)48#define ADDR_EWDS	0x0049#define ADDR_ERAL	0x2050#define ADDR_EWEN	0x3051 52struct eeprom_93xx46_devtype_data {53	unsigned int quirks;54	unsigned char flags;55};56 57static const struct eeprom_93xx46_devtype_data at93c46_data = {58	.flags = EE_SIZE1K,59};60 61static const struct eeprom_93xx46_devtype_data at93c56_data = {62	.flags = EE_SIZE2K,63};64 65static const struct eeprom_93xx46_devtype_data at93c66_data = {66	.flags = EE_SIZE4K,67};68 69static const struct eeprom_93xx46_devtype_data atmel_at93c46d_data = {70	.flags = EE_SIZE1K,71	.quirks = EEPROM_93XX46_QUIRK_SINGLE_WORD_READ |72		  EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH,73};74 75static const struct eeprom_93xx46_devtype_data microchip_93lc46b_data = {76	.flags = EE_SIZE1K,77	.quirks = EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE,78};79 80struct eeprom_93xx46_dev {81	struct spi_device *spi;82	struct eeprom_93xx46_platform_data *pdata;83	struct mutex lock;84	struct nvmem_config nvmem_config;85	struct nvmem_device *nvmem;86	int addrlen;87	int size;88};89 90static inline bool has_quirk_single_word_read(struct eeprom_93xx46_dev *edev)91{92	return edev->pdata->quirks & EEPROM_93XX46_QUIRK_SINGLE_WORD_READ;93}94 95static inline bool has_quirk_instruction_length(struct eeprom_93xx46_dev *edev)96{97	return edev->pdata->quirks & EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH;98}99 100static inline bool has_quirk_extra_read_cycle(struct eeprom_93xx46_dev *edev)101{102	return edev->pdata->quirks & EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE;103}104 105static int eeprom_93xx46_read(void *priv, unsigned int off,106			      void *val, size_t count)107{108	struct eeprom_93xx46_dev *edev = priv;109	char *buf = val;110	int err = 0;111	int bits;112 113	if (unlikely(off >= edev->size))114		return 0;115	if ((off + count) > edev->size)116		count = edev->size - off;117	if (unlikely(!count))118		return count;119 120	mutex_lock(&edev->lock);121 122	gpiod_set_value_cansleep(edev->pdata->select, 1);123 124	/* The opcode in front of the address is three bits. */125	bits = edev->addrlen + 3;126 127	while (count) {128		struct spi_message m;129		struct spi_transfer t[2] = {};130		u16 cmd_addr = OP_READ << edev->addrlen;131		size_t nbytes = count;132 133		if (edev->pdata->flags & EE_ADDR8) {134			cmd_addr |= off;135			if (has_quirk_single_word_read(edev))136				nbytes = 1;137		} else {138			cmd_addr |= (off >> 1);139			if (has_quirk_single_word_read(edev))140				nbytes = 2;141		}142 143		dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n",144			cmd_addr, edev->spi->max_speed_hz);145 146		if (has_quirk_extra_read_cycle(edev)) {147			cmd_addr <<= 1;148			bits += 1;149		}150 151		t[0].tx_buf = (char *)&cmd_addr;152		t[0].len = 2;153		t[0].bits_per_word = bits;154 155		t[1].rx_buf = buf;156		t[1].len = count;157		t[1].bits_per_word = 8;158 159		spi_message_init_with_transfers(&m, t, ARRAY_SIZE(t));160 161		err = spi_sync(edev->spi, &m);162		/* have to wait at least Tcsl ns */163		ndelay(250);164 165		if (err) {166			dev_err(&edev->spi->dev, "read %zu bytes at %u: err. %d\n",167				nbytes, off, err);168			break;169		}170 171		buf += nbytes;172		off += nbytes;173		count -= nbytes;174	}175 176	gpiod_set_value_cansleep(edev->pdata->select, 0);177 178	mutex_unlock(&edev->lock);179 180	return err;181}182 183static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)184{185	struct spi_message m;186	struct spi_transfer t = {};187	int bits, ret;188	u16 cmd_addr;189 190	/* The opcode in front of the address is three bits. */191	bits = edev->addrlen + 3;192 193	cmd_addr = OP_START << edev->addrlen;194	if (edev->pdata->flags & EE_ADDR8)195		cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS) << 1;196	else197		cmd_addr |= (is_on ? ADDR_EWEN : ADDR_EWDS);198 199	if (has_quirk_instruction_length(edev)) {200		cmd_addr <<= 2;201		bits += 2;202	}203 204	dev_dbg(&edev->spi->dev, "ew %s cmd 0x%04x, %d bits\n",205		str_enable_disable(is_on), cmd_addr, bits);206 207	t.tx_buf = &cmd_addr;208	t.len = 2;209	t.bits_per_word = bits;210 211	spi_message_init_with_transfers(&m, &t, 1);212 213	mutex_lock(&edev->lock);214 215	gpiod_set_value_cansleep(edev->pdata->select, 1);216 217	ret = spi_sync(edev->spi, &m);218	/* have to wait at least Tcsl ns */219	ndelay(250);220	if (ret)221		dev_err(&edev->spi->dev, "erase/write %s error %d\n",222			str_enable_disable(is_on), ret);223 224	gpiod_set_value_cansleep(edev->pdata->select, 0);225 226	mutex_unlock(&edev->lock);227	return ret;228}229 230static ssize_t231eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,232			 const char *buf, unsigned off)233{234	struct spi_message m;235	struct spi_transfer t[2] = {};236	int bits, data_len, ret;237	u16 cmd_addr;238 239	if (unlikely(off >= edev->size))240		return -EINVAL;241 242	/* The opcode in front of the address is three bits. */243	bits = edev->addrlen + 3;244 245	cmd_addr = OP_WRITE << edev->addrlen;246 247	if (edev->pdata->flags & EE_ADDR8) {248		cmd_addr |= off;249		data_len = 1;250	} else {251		cmd_addr |= (off >> 1);252		data_len = 2;253	}254 255	dev_dbg(&edev->spi->dev, "write cmd 0x%x\n", cmd_addr);256 257	t[0].tx_buf = (char *)&cmd_addr;258	t[0].len = 2;259	t[0].bits_per_word = bits;260 261	t[1].tx_buf = buf;262	t[1].len = data_len;263	t[1].bits_per_word = 8;264 265	spi_message_init_with_transfers(&m, t, ARRAY_SIZE(t));266 267	ret = spi_sync(edev->spi, &m);268	/* have to wait program cycle time Twc ms */269	mdelay(6);270	return ret;271}272 273static int eeprom_93xx46_write(void *priv, unsigned int off,274				   void *val, size_t count)275{276	struct eeprom_93xx46_dev *edev = priv;277	char *buf = val;278	int ret, step = 1;279	unsigned int i;280 281	if (unlikely(off >= edev->size))282		return -EFBIG;283	if ((off + count) > edev->size)284		count = edev->size - off;285	if (unlikely(!count))286		return count;287 288	/* only write even number of bytes on 16-bit devices */289	if (edev->pdata->flags & EE_ADDR16) {290		step = 2;291		count &= ~1;292	}293 294	/* erase/write enable */295	ret = eeprom_93xx46_ew(edev, 1);296	if (ret)297		return ret;298 299	mutex_lock(&edev->lock);300 301	gpiod_set_value_cansleep(edev->pdata->select, 1);302 303	for (i = 0; i < count; i += step) {304		ret = eeprom_93xx46_write_word(edev, &buf[i], off + i);305		if (ret) {306			dev_err(&edev->spi->dev, "write failed at %u: %d\n", off + i, ret);307			break;308		}309	}310 311	gpiod_set_value_cansleep(edev->pdata->select, 0);312 313	mutex_unlock(&edev->lock);314 315	/* erase/write disable */316	eeprom_93xx46_ew(edev, 0);317	return ret;318}319 320static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev)321{322	struct spi_message m;323	struct spi_transfer t = {};324	int bits, ret;325	u16 cmd_addr;326 327	/* The opcode in front of the address is three bits. */328	bits = edev->addrlen + 3;329 330	cmd_addr = OP_START << edev->addrlen;331	if (edev->pdata->flags & EE_ADDR8)332		cmd_addr |= ADDR_ERAL << 1;333	else334		cmd_addr |= ADDR_ERAL;335 336	if (has_quirk_instruction_length(edev)) {337		cmd_addr <<= 2;338		bits += 2;339	}340 341	dev_dbg(&edev->spi->dev, "eral cmd 0x%04x, %d bits\n", cmd_addr, bits);342 343	t.tx_buf = &cmd_addr;344	t.len = 2;345	t.bits_per_word = bits;346 347	spi_message_init_with_transfers(&m, &t, 1);348 349	mutex_lock(&edev->lock);350 351	gpiod_set_value_cansleep(edev->pdata->select, 1);352 353	ret = spi_sync(edev->spi, &m);354	if (ret)355		dev_err(&edev->spi->dev, "erase error %d\n", ret);356	/* have to wait erase cycle time Tec ms */357	mdelay(6);358 359	gpiod_set_value_cansleep(edev->pdata->select, 0);360 361	mutex_unlock(&edev->lock);362	return ret;363}364 365static ssize_t erase_store(struct device *dev, struct device_attribute *attr,366			   const char *buf, size_t count)367{368	struct eeprom_93xx46_dev *edev = dev_get_drvdata(dev);369	bool erase;370	int ret;371 372	ret = kstrtobool(buf, &erase);373	if (ret)374		return ret;375 376	if (erase) {377		ret = eeprom_93xx46_ew(edev, 1);378		if (ret)379			return ret;380		ret = eeprom_93xx46_eral(edev);381		if (ret)382			return ret;383		ret = eeprom_93xx46_ew(edev, 0);384		if (ret)385			return ret;386	}387	return count;388}389static DEVICE_ATTR_WO(erase);390 391static const struct of_device_id eeprom_93xx46_of_table[] = {392	{ .compatible = "eeprom-93xx46", .data = &at93c46_data, },393	{ .compatible = "atmel,at93c46", .data = &at93c46_data, },394	{ .compatible = "atmel,at93c46d", .data = &atmel_at93c46d_data, },395	{ .compatible = "atmel,at93c56", .data = &at93c56_data, },396	{ .compatible = "atmel,at93c66", .data = &at93c66_data, },397	{ .compatible = "microchip,93lc46b", .data = &microchip_93lc46b_data, },398	{}399};400MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table);401 402static const struct spi_device_id eeprom_93xx46_spi_ids[] = {403	{ .name = "eeprom-93xx46",404	  .driver_data = (kernel_ulong_t)&at93c46_data, },405	{ .name = "at93c46",406	  .driver_data = (kernel_ulong_t)&at93c46_data, },407	{ .name = "at93c46d",408	  .driver_data = (kernel_ulong_t)&atmel_at93c46d_data, },409	{ .name = "at93c56",410	  .driver_data = (kernel_ulong_t)&at93c56_data, },411	{ .name = "at93c66",412	  .driver_data = (kernel_ulong_t)&at93c66_data, },413	{ .name = "93lc46b",414	  .driver_data = (kernel_ulong_t)&microchip_93lc46b_data, },415	{}416};417MODULE_DEVICE_TABLE(spi, eeprom_93xx46_spi_ids);418 419static int eeprom_93xx46_probe_fw(struct device *dev)420{421	const struct eeprom_93xx46_devtype_data *data;422	struct eeprom_93xx46_platform_data *pd;423	u32 tmp;424	int ret;425 426	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);427	if (!pd)428		return -ENOMEM;429 430	ret = device_property_read_u32(dev, "data-size", &tmp);431	if (ret < 0) {432		dev_err(dev, "data-size property not found\n");433		return ret;434	}435 436	if (tmp == 8) {437		pd->flags |= EE_ADDR8;438	} else if (tmp == 16) {439		pd->flags |= EE_ADDR16;440	} else {441		dev_err(dev, "invalid data-size (%d)\n", tmp);442		return -EINVAL;443	}444 445	if (device_property_read_bool(dev, "read-only"))446		pd->flags |= EE_READONLY;447 448	pd->select = devm_gpiod_get_optional(dev, "select", GPIOD_OUT_LOW);449	if (IS_ERR(pd->select))450		return PTR_ERR(pd->select);451	gpiod_set_consumer_name(pd->select, "93xx46 EEPROMs OE");452 453	data = spi_get_device_match_data(to_spi_device(dev));454	if (data) {455		pd->quirks = data->quirks;456		pd->flags |= data->flags;457	}458 459	dev->platform_data = pd;460 461	return 0;462}463 464static int eeprom_93xx46_probe(struct spi_device *spi)465{466	struct eeprom_93xx46_platform_data *pd;467	struct eeprom_93xx46_dev *edev;468	struct device *dev = &spi->dev;469	int err;470 471	err = eeprom_93xx46_probe_fw(dev);472	if (err < 0)473		return err;474 475	pd = spi->dev.platform_data;476	if (!pd) {477		dev_err(&spi->dev, "missing platform data\n");478		return -ENODEV;479	}480 481	edev = devm_kzalloc(&spi->dev, sizeof(*edev), GFP_KERNEL);482	if (!edev)483		return -ENOMEM;484 485	if (pd->flags & EE_SIZE1K)486		edev->size = 128;487	else if (pd->flags & EE_SIZE2K)488		edev->size = 256;489	else if (pd->flags & EE_SIZE4K)490		edev->size = 512;491	else {492		dev_err(&spi->dev, "unspecified size\n");493		return -EINVAL;494	}495 496	if (pd->flags & EE_ADDR8)497		edev->addrlen = ilog2(edev->size);498	else if (pd->flags & EE_ADDR16)499		edev->addrlen = ilog2(edev->size) - 1;500	else {501		dev_err(&spi->dev, "unspecified address type\n");502		return -EINVAL;503	}504 505	mutex_init(&edev->lock);506 507	edev->spi = spi;508	edev->pdata = pd;509 510	edev->nvmem_config.type = NVMEM_TYPE_EEPROM;511	edev->nvmem_config.name = dev_name(&spi->dev);512	edev->nvmem_config.dev = &spi->dev;513	edev->nvmem_config.read_only = pd->flags & EE_READONLY;514	edev->nvmem_config.root_only = true;515	edev->nvmem_config.owner = THIS_MODULE;516	edev->nvmem_config.compat = true;517	edev->nvmem_config.base_dev = &spi->dev;518	edev->nvmem_config.reg_read = eeprom_93xx46_read;519	edev->nvmem_config.reg_write = eeprom_93xx46_write;520	edev->nvmem_config.priv = edev;521	edev->nvmem_config.stride = 4;522	edev->nvmem_config.word_size = 1;523	edev->nvmem_config.size = edev->size;524 525	edev->nvmem = devm_nvmem_register(&spi->dev, &edev->nvmem_config);526	if (IS_ERR(edev->nvmem))527		return PTR_ERR(edev->nvmem);528 529	dev_info(&spi->dev, "%d-bit eeprom containing %d bytes %s\n",530		(pd->flags & EE_ADDR8) ? 8 : 16,531		edev->size,532		(pd->flags & EE_READONLY) ? "(readonly)" : "");533 534	if (!(pd->flags & EE_READONLY)) {535		if (device_create_file(&spi->dev, &dev_attr_erase))536			dev_err(&spi->dev, "can't create erase interface\n");537	}538 539	spi_set_drvdata(spi, edev);540	return 0;541}542 543static void eeprom_93xx46_remove(struct spi_device *spi)544{545	struct eeprom_93xx46_dev *edev = spi_get_drvdata(spi);546 547	if (!(edev->pdata->flags & EE_READONLY))548		device_remove_file(&spi->dev, &dev_attr_erase);549}550 551static struct spi_driver eeprom_93xx46_driver = {552	.driver = {553		.name	= "93xx46",554		.of_match_table = eeprom_93xx46_of_table,555	},556	.probe		= eeprom_93xx46_probe,557	.remove		= eeprom_93xx46_remove,558	.id_table	= eeprom_93xx46_spi_ids,559};560 561module_spi_driver(eeprom_93xx46_driver);562 563MODULE_LICENSE("GPL");564MODULE_DESCRIPTION("Driver for 93xx46 EEPROMs");565MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");566MODULE_ALIAS("spi:93xx46");567