Merge tag 'staging-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[linux-2.6-microblaze.git] / drivers / iio / common / st_sensors / st_sensors_spi.c
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 = (struct st_sensors_platform_data *)dev->platform_data;
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 (%d)\n",
105                         (int)PTR_ERR(sdata->regmap));
106                 return PTR_ERR(sdata->regmap);
107         }
108
109         spi_set_drvdata(spi, indio_dev);
110
111         indio_dev->dev.parent = &spi->dev;
112         indio_dev->name = spi->modalias;
113
114         sdata->dev = &spi->dev;
115         sdata->irq = spi->irq;
116
117         return 0;
118 }
119 EXPORT_SYMBOL(st_sensors_spi_configure);
120
121 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
122 MODULE_DESCRIPTION("STMicroelectronics ST-sensors spi driver");
123 MODULE_LICENSE("GPL v2");