1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ADXL313 3-Axis Digital Accelerometer |
4 | * |
5 | * Copyright (c) 2021 Lucas Stankus <lucas.p.stankus@gmail.com> |
6 | * |
7 | * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL313.pdf |
8 | */ |
9 | |
10 | #include <linux/mod_devicetable.h> |
11 | #include <linux/module.h> |
12 | #include <linux/regmap.h> |
13 | #include <linux/spi/spi.h> |
14 | #include <linux/property.h> |
15 | |
16 | #include "adxl313.h" |
17 | |
18 | static const struct regmap_config adxl31x_spi_regmap_config[] = { |
19 | [ADXL312] = { |
20 | .reg_bits = 8, |
21 | .val_bits = 8, |
22 | .rd_table = &adxl312_readable_regs_table, |
23 | .wr_table = &adxl312_writable_regs_table, |
24 | .max_register = 0x39, |
25 | /* Setting bits 7 and 6 enables multiple-byte read */ |
26 | .read_flag_mask = BIT(7) | BIT(6), |
27 | }, |
28 | [ADXL313] = { |
29 | .reg_bits = 8, |
30 | .val_bits = 8, |
31 | .rd_table = &adxl313_readable_regs_table, |
32 | .wr_table = &adxl313_writable_regs_table, |
33 | .max_register = 0x39, |
34 | /* Setting bits 7 and 6 enables multiple-byte read */ |
35 | .read_flag_mask = BIT(7) | BIT(6), |
36 | }, |
37 | [ADXL314] = { |
38 | .reg_bits = 8, |
39 | .val_bits = 8, |
40 | .rd_table = &adxl314_readable_regs_table, |
41 | .wr_table = &adxl314_writable_regs_table, |
42 | .max_register = 0x39, |
43 | /* Setting bits 7 and 6 enables multiple-byte read */ |
44 | .read_flag_mask = BIT(7) | BIT(6), |
45 | }, |
46 | }; |
47 | |
48 | static int adxl313_spi_setup(struct device *dev, struct regmap *regmap) |
49 | { |
50 | struct spi_device *spi = container_of(dev, struct spi_device, dev); |
51 | int ret; |
52 | |
53 | if (spi->mode & SPI_3WIRE) { |
54 | ret = regmap_write(map: regmap, ADXL313_REG_DATA_FORMAT, |
55 | ADXL313_SPI_3WIRE); |
56 | if (ret) |
57 | return ret; |
58 | } |
59 | |
60 | return regmap_update_bits(map: regmap, ADXL313_REG_POWER_CTL, |
61 | ADXL313_I2C_DISABLE, ADXL313_I2C_DISABLE); |
62 | } |
63 | |
64 | static int adxl313_spi_probe(struct spi_device *spi) |
65 | { |
66 | const struct adxl313_chip_info *chip_data; |
67 | struct regmap *regmap; |
68 | int ret; |
69 | |
70 | spi->mode |= SPI_MODE_3; |
71 | ret = spi_setup(spi); |
72 | if (ret) |
73 | return ret; |
74 | |
75 | /* |
76 | * Retrieves device specific data as a pointer to a |
77 | * adxl313_chip_info structure |
78 | */ |
79 | chip_data = device_get_match_data(dev: &spi->dev); |
80 | if (!chip_data) |
81 | chip_data = (const struct adxl313_chip_info *)spi_get_device_id(sdev: spi)->driver_data; |
82 | |
83 | regmap = devm_regmap_init_spi(spi, |
84 | &adxl31x_spi_regmap_config[chip_data->type]); |
85 | |
86 | if (IS_ERR(ptr: regmap)) { |
87 | dev_err(&spi->dev, "Error initializing spi regmap: %ld\n" , |
88 | PTR_ERR(regmap)); |
89 | return PTR_ERR(ptr: regmap); |
90 | } |
91 | |
92 | return adxl313_core_probe(dev: &spi->dev, regmap, |
93 | chip_info: chip_data, setup: &adxl313_spi_setup); |
94 | } |
95 | |
96 | static const struct spi_device_id adxl313_spi_id[] = { |
97 | { .name = "adxl312" , .driver_data = (kernel_ulong_t)&adxl31x_chip_info[ADXL312] }, |
98 | { .name = "adxl313" , .driver_data = (kernel_ulong_t)&adxl31x_chip_info[ADXL313] }, |
99 | { .name = "adxl314" , .driver_data = (kernel_ulong_t)&adxl31x_chip_info[ADXL314] }, |
100 | { } |
101 | }; |
102 | |
103 | MODULE_DEVICE_TABLE(spi, adxl313_spi_id); |
104 | |
105 | static const struct of_device_id adxl313_of_match[] = { |
106 | { .compatible = "adi,adxl312" , .data = &adxl31x_chip_info[ADXL312] }, |
107 | { .compatible = "adi,adxl313" , .data = &adxl31x_chip_info[ADXL313] }, |
108 | { .compatible = "adi,adxl314" , .data = &adxl31x_chip_info[ADXL314] }, |
109 | { } |
110 | }; |
111 | |
112 | MODULE_DEVICE_TABLE(of, adxl313_of_match); |
113 | |
114 | static struct spi_driver adxl313_spi_driver = { |
115 | .driver = { |
116 | .name = "adxl313_spi" , |
117 | .of_match_table = adxl313_of_match, |
118 | }, |
119 | .probe = adxl313_spi_probe, |
120 | .id_table = adxl313_spi_id, |
121 | }; |
122 | |
123 | module_spi_driver(adxl313_spi_driver); |
124 | |
125 | MODULE_AUTHOR("Lucas Stankus <lucas.p.stankus@gmail.com>" ); |
126 | MODULE_DESCRIPTION("ADXL313 3-Axis Digital Accelerometer SPI driver" ); |
127 | MODULE_LICENSE("GPL v2" ); |
128 | MODULE_IMPORT_NS(IIO_ADXL313); |
129 | |