File Index
Files and directories
Sign in
FILE

tps6594-spi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/mfd/tps6594-spi.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * SPI access driver for the following TI PMICs:
  4 *  - LP8764
  5 *  - TPS65224
  6 *  - TPS652G1
  7 *  - TPS6593
  8 *  - TPS6594
  9 *
 10 * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
 11 */
 12
 13#include <linux/crc8.h>
 14#include <linux/module.h>
 15#include <linux/mod_devicetable.h>
 16#include <linux/of_device.h>
 17#include <linux/regmap.h>
 18#include <linux/spi/spi.h>
 19
 20#include <linux/mfd/tps6594.h>
 21
 22#define TPS6594_SPI_PAGE_SHIFT	5
 23#define TPS6594_SPI_READ_BIT	BIT(4)
 24
 25static bool enable_crc;
 26module_param(enable_crc, bool, 0444);
 27MODULE_PARM_DESC(enable_crc, "Enable CRC feature for SPI interface");
 28
 29DECLARE_CRC8_TABLE(tps6594_spi_crc_table);
 30
 31static int tps6594_spi_reg_read(void *context, unsigned int reg, unsigned int *val)
 32{
 33	struct spi_device *spi = context;
 34	struct tps6594 *tps = spi_get_drvdata(spi);
 35	u8 buf[4] = { 0 };
 36	size_t count_rx = 1;
 37	int ret;
 38
 39	buf[0] = reg;
 40	buf[1] = TPS6594_REG_TO_PAGE(reg) << TPS6594_SPI_PAGE_SHIFT | TPS6594_SPI_READ_BIT;
 41
 42	if (tps->use_crc)
 43		count_rx++;
 44
 45	ret = spi_write_then_read(spi, buf, 2, buf + 2, count_rx);
 46	if (ret < 0)
 47		return ret;
 48
 49	if (tps->use_crc && buf[3] != crc8(tps6594_spi_crc_table, buf, 3, CRC8_INIT_VALUE))
 50		return -EIO;
 51
 52	*val = buf[2];
 53
 54	return 0;
 55}
 56
 57static int tps6594_spi_reg_write(void *context, unsigned int reg, unsigned int val)
 58{
 59	struct spi_device *spi = context;
 60	struct tps6594 *tps = spi_get_drvdata(spi);
 61	u8 buf[4] = { 0 };
 62	size_t count = 3;
 63
 64	buf[0] = reg;
 65	buf[1] = TPS6594_REG_TO_PAGE(reg) << TPS6594_SPI_PAGE_SHIFT;
 66	buf[2] = val;
 67
 68	if (tps->use_crc)
 69		buf[3] = crc8(tps6594_spi_crc_table, buf, count++, CRC8_INIT_VALUE);
 70
 71	return spi_write(spi, buf, count);
 72}
 73
 74static struct regmap_config tps6594_spi_regmap_config = {
 75	.reg_bits = 16,
 76	.val_bits = 8,
 77	.max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
 78	.volatile_table = &tps6594_volatile_table,
 79	.reg_read = tps6594_spi_reg_read,
 80	.reg_write = tps6594_spi_reg_write,
 81	.use_single_read = true,
 82	.use_single_write = true,
 83};
 84
 85static const struct of_device_id tps6594_spi_of_match_table[] = {
 86	{ .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
 87	{ .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
 88	{ .compatible = "ti,lp8764-q1",  .data = (void *)LP8764,  },
 89	{ .compatible = "ti,tps65224-q1", .data = (void *)TPS65224, },
 90	{ .compatible = "ti,tps652g1", .data = (void *)TPS652G1, },
 91	{}
 92};
 93MODULE_DEVICE_TABLE(of, tps6594_spi_of_match_table);
 94
 95static int tps6594_spi_probe(struct spi_device *spi)
 96{
 97	struct device *dev = &spi->dev;
 98	struct tps6594 *tps;
 99	const struct of_device_id *match;
100
101	tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL);
102	if (!tps)
103		return -ENOMEM;
104
105	spi_set_drvdata(spi, tps);
106
107	tps->dev = dev;
108	tps->reg = spi_get_chipselect(spi, 0);
109	tps->irq = spi->irq;
110
111	match = of_match_device(tps6594_spi_of_match_table, dev);
112	if (!match)
113		return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n");
114	tps->chip_id = (unsigned long)match->data;
115
116	if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1)
117		tps6594_spi_regmap_config.volatile_table = &tps65224_volatile_table;
118
119	tps->regmap = devm_regmap_init(dev, NULL, spi, &tps6594_spi_regmap_config);
120	if (IS_ERR(tps->regmap))
121		return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
122
123	crc8_populate_msb(tps6594_spi_crc_table, TPS6594_CRC8_POLYNOMIAL);
124
125	return tps6594_device_init(tps, enable_crc);
126}
127
128static struct spi_driver tps6594_spi_driver = {
129	.driver	= {
130		.name = "tps6594",
131		.of_match_table = tps6594_spi_of_match_table,
132	},
133	.probe = tps6594_spi_probe,
134};
135module_spi_driver(tps6594_spi_driver);
136
137MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
138MODULE_DESCRIPTION("SPI Interface Driver for TPS65224, TPS6594/3, and LP8764");
139MODULE_LICENSE("GPL");
~/ Read-only file preview.