1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * STMicroelectronics sensors spi library driver
4  *
5  * Copyright 2012-2013 STMicroelectronics Inc.
6  *
7  * Denis Ciocca <denis.ciocca@st.com>
8  */
9 
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/slab.h>
13 #include <linux/iio/iio.h>
14 #include <linux/property.h>
15 #include <linux/regmap.h>
16 
17 #include <linux/iio/common/st_sensors_spi.h>
18 #include "st_sensors_core.h"
19 
20 #define ST_SENSORS_SPI_MULTIREAD	0xc0
21 
22 static const struct regmap_config st_sensors_spi_regmap_config = {
23 	.reg_bits = 8,
24 	.val_bits = 8,
25 };
26 
27 static const struct regmap_config st_sensors_spi_regmap_multiread_bit_config = {
28 	.reg_bits = 8,
29 	.val_bits = 8,
30 	.read_flag_mask = ST_SENSORS_SPI_MULTIREAD,
31 };
32 
33 /*
34  * st_sensors_is_spi_3_wire() - check if SPI 3-wire mode has been selected
35  * @spi: spi device reference.
36  *
37  * Return: true if SPI 3-wire mode is selected, false otherwise.
38  */
39 static bool st_sensors_is_spi_3_wire(struct spi_device *spi)
40 {
41 	struct st_sensors_platform_data *pdata;
42 	struct device *dev = &spi->dev;
43 
44 	if (device_property_read_bool(dev, "spi-3wire"))
45 		return true;
46 
47 	pdata = dev_get_platdata(dev);
48 	if (pdata && pdata->spi_3wire)
49 		return true;
50 
51 	return false;
52 }
53 
54 /*
55  * st_sensors_configure_spi_3_wire() - configure SPI 3-wire if needed
56  * @spi: spi device reference.
57  * @settings: sensor specific settings reference.
58  *
59  * Return: 0 on success, else a negative error code.
60  */
61 static int st_sensors_configure_spi_3_wire(struct spi_device *spi,
62 					   struct st_sensor_settings *settings)
63 {
64 	if (settings->sim.addr) {
65 		u8 buffer[] = {
66 			settings->sim.addr,
67 			settings->sim.value
68 		};
69 
70 		return spi_write(spi, buffer, 2);
71 	}
72 
73 	return 0;
74 }
75 
76 /*
77  * st_sensors_spi_configure() - configure SPI interface
78  * @indio_dev: IIO device reference.
79  * @spi: spi device reference.
80  *
81  * Return: 0 on success, else a negative error code.
82  */
83 int st_sensors_spi_configure(struct iio_dev *indio_dev,
84 			     struct spi_device *spi)
85 {
86 	struct st_sensor_data *sdata = iio_priv(indio_dev);
87 	const struct regmap_config *config;
88 	int err;
89 
90 	if (st_sensors_is_spi_3_wire(spi)) {
91 		err = st_sensors_configure_spi_3_wire(spi,
92 						      sdata->sensor_settings);
93 		if (err < 0)
94 			return err;
95 	}
96 
97 	if (sdata->sensor_settings->multi_read_bit)
98 		config = &st_sensors_spi_regmap_multiread_bit_config;
99 	else
100 		config = &st_sensors_spi_regmap_config;
101 
102 	sdata->regmap = devm_regmap_init_spi(spi, config);
103 	if (IS_ERR(sdata->regmap)) {
104 		dev_err(&spi->dev, "Failed to register spi regmap (%ld)\n",
105 			PTR_ERR(sdata->regmap));
106 		return PTR_ERR(sdata->regmap);
107 	}
108 
109 	spi_set_drvdata(spi, indio_dev);
110 
111 	indio_dev->name = spi->modalias;
112 
113 	sdata->dev = &spi->dev;
114 	sdata->irq = spi->irq;
115 
116 	return 0;
117 }
118 EXPORT_SYMBOL(st_sensors_spi_configure);
119 
120 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
121 MODULE_DESCRIPTION("STMicroelectronics ST-sensors spi driver");
122 MODULE_LICENSE("GPL v2");
123