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