1 // SPDX-License-Identifier: GPL-2.0
3 * SPI access driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs
5 * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
8 #include <linux/crc8.h>
9 #include <linux/module.h>
10 #include <linux/mod_devicetable.h>
11 #include <linux/of_device.h>
12 #include <linux/regmap.h>
13 #include <linux/spi/spi.h>
15 #include <linux/mfd/tps6594.h>
17 #define TPS6594_SPI_PAGE_SHIFT 5
18 #define TPS6594_SPI_READ_BIT BIT(4)
20 static bool enable_crc
;
21 module_param(enable_crc
, bool, 0444);
22 MODULE_PARM_DESC(enable_crc
, "Enable CRC feature for SPI interface");
24 DECLARE_CRC8_TABLE(tps6594_spi_crc_table
);
26 static int tps6594_spi_reg_read(void *context
, unsigned int reg
, unsigned int *val
)
28 struct spi_device
*spi
= context
;
29 struct tps6594
*tps
= spi_get_drvdata(spi
);
35 buf
[1] = TPS6594_REG_TO_PAGE(reg
) << TPS6594_SPI_PAGE_SHIFT
| TPS6594_SPI_READ_BIT
;
40 ret
= spi_write_then_read(spi
, buf
, 2, buf
+ 2, count_rx
);
44 if (tps
->use_crc
&& buf
[3] != crc8(tps6594_spi_crc_table
, buf
, 3, CRC8_INIT_VALUE
))
52 static int tps6594_spi_reg_write(void *context
, unsigned int reg
, unsigned int val
)
54 struct spi_device
*spi
= context
;
55 struct tps6594
*tps
= spi_get_drvdata(spi
);
60 buf
[1] = TPS6594_REG_TO_PAGE(reg
) << TPS6594_SPI_PAGE_SHIFT
;
64 buf
[3] = crc8(tps6594_spi_crc_table
, buf
, count
++, CRC8_INIT_VALUE
);
66 return spi_write(spi
, buf
, count
);
69 static struct regmap_config tps6594_spi_regmap_config
= {
72 .max_register
= TPS6594_REG_DWD_FAIL_CNT_REG
,
73 .volatile_table
= &tps6594_volatile_table
,
74 .reg_read
= tps6594_spi_reg_read
,
75 .reg_write
= tps6594_spi_reg_write
,
76 .use_single_read
= true,
77 .use_single_write
= true,
80 static const struct of_device_id tps6594_spi_of_match_table
[] = {
81 { .compatible
= "ti,tps6594-q1", .data
= (void *)TPS6594
, },
82 { .compatible
= "ti,tps6593-q1", .data
= (void *)TPS6593
, },
83 { .compatible
= "ti,lp8764-q1", .data
= (void *)LP8764
, },
84 { .compatible
= "ti,tps65224-q1", .data
= (void *)TPS65224
, },
87 MODULE_DEVICE_TABLE(of
, tps6594_spi_of_match_table
);
89 static int tps6594_spi_probe(struct spi_device
*spi
)
91 struct device
*dev
= &spi
->dev
;
93 const struct of_device_id
*match
;
95 tps
= devm_kzalloc(dev
, sizeof(*tps
), GFP_KERNEL
);
99 spi_set_drvdata(spi
, tps
);
102 tps
->reg
= spi_get_chipselect(spi
, 0);
105 match
= of_match_device(tps6594_spi_of_match_table
, dev
);
107 return dev_err_probe(dev
, -EINVAL
, "Failed to find matching chip ID\n");
108 tps
->chip_id
= (unsigned long)match
->data
;
110 if (tps
->chip_id
== TPS65224
)
111 tps6594_spi_regmap_config
.volatile_table
= &tps65224_volatile_table
;
113 tps
->regmap
= devm_regmap_init(dev
, NULL
, spi
, &tps6594_spi_regmap_config
);
114 if (IS_ERR(tps
->regmap
))
115 return dev_err_probe(dev
, PTR_ERR(tps
->regmap
), "Failed to init regmap\n");
117 crc8_populate_msb(tps6594_spi_crc_table
, TPS6594_CRC8_POLYNOMIAL
);
119 return tps6594_device_init(tps
, enable_crc
);
122 static struct spi_driver tps6594_spi_driver
= {
125 .of_match_table
= tps6594_spi_of_match_table
,
127 .probe
= tps6594_spi_probe
,
129 module_spi_driver(tps6594_spi_driver
);
131 MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
132 MODULE_DESCRIPTION("SPI Interface Driver for TPS65224, TPS6594/3, and LP8764");
133 MODULE_LICENSE("GPL");