1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * API bus driver for ADT7316/7/8 ADT7516/7/9 digital temperature |
4 | * sensor, ADC and DAC |
5 | * |
6 | * Copyright 2010 Analog Devices Inc. |
7 | */ |
8 | |
9 | #include <linux/device.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> |
12 | #include <linux/interrupt.h> |
13 | #include <linux/spi/spi.h> |
14 | |
15 | #include "adt7316.h" |
16 | |
17 | #define ADT7316_SPI_MAX_FREQ_HZ 5000000 |
18 | #define ADT7316_SPI_CMD_READ 0x91 |
19 | #define ADT7316_SPI_CMD_WRITE 0x90 |
20 | |
21 | /* |
22 | * adt7316 register access by SPI |
23 | */ |
24 | |
25 | static int adt7316_spi_multi_read(void *client, u8 reg, u8 count, u8 *data) |
26 | { |
27 | struct spi_device *spi_dev = client; |
28 | u8 cmd[2]; |
29 | int ret; |
30 | |
31 | if (count > ADT7316_REG_MAX_ADDR) |
32 | count = ADT7316_REG_MAX_ADDR; |
33 | |
34 | cmd[0] = ADT7316_SPI_CMD_WRITE; |
35 | cmd[1] = reg; |
36 | |
37 | ret = spi_write(spi: spi_dev, buf: cmd, len: 2); |
38 | if (ret < 0) { |
39 | dev_err(&spi_dev->dev, "SPI fail to select reg\n" ); |
40 | return ret; |
41 | } |
42 | |
43 | cmd[0] = ADT7316_SPI_CMD_READ; |
44 | |
45 | ret = spi_write_then_read(spi: spi_dev, txbuf: cmd, n_tx: 1, rxbuf: data, n_rx: count); |
46 | if (ret < 0) { |
47 | dev_err(&spi_dev->dev, "SPI read data error\n" ); |
48 | return ret; |
49 | } |
50 | |
51 | return 0; |
52 | } |
53 | |
54 | static int adt7316_spi_multi_write(void *client, u8 reg, u8 count, u8 *data) |
55 | { |
56 | struct spi_device *spi_dev = client; |
57 | u8 buf[ADT7316_REG_MAX_ADDR + 2]; |
58 | int i, ret; |
59 | |
60 | if (count > ADT7316_REG_MAX_ADDR) |
61 | count = ADT7316_REG_MAX_ADDR; |
62 | |
63 | buf[0] = ADT7316_SPI_CMD_WRITE; |
64 | buf[1] = reg; |
65 | for (i = 0; i < count; i++) |
66 | buf[i + 2] = data[i]; |
67 | |
68 | ret = spi_write(spi: spi_dev, buf, len: count + 2); |
69 | if (ret < 0) { |
70 | dev_err(&spi_dev->dev, "SPI write error\n" ); |
71 | return ret; |
72 | } |
73 | |
74 | return ret; |
75 | } |
76 | |
77 | static int adt7316_spi_read(void *client, u8 reg, u8 *data) |
78 | { |
79 | return adt7316_spi_multi_read(client, reg, count: 1, data); |
80 | } |
81 | |
82 | static int adt7316_spi_write(void *client, u8 reg, u8 val) |
83 | { |
84 | return adt7316_spi_multi_write(client, reg, count: 1, data: &val); |
85 | } |
86 | |
87 | /* |
88 | * device probe and remove |
89 | */ |
90 | |
91 | static int adt7316_spi_probe(struct spi_device *spi_dev) |
92 | { |
93 | struct adt7316_bus bus = { |
94 | .client = spi_dev, |
95 | .irq = spi_dev->irq, |
96 | .read = adt7316_spi_read, |
97 | .write = adt7316_spi_write, |
98 | .multi_read = adt7316_spi_multi_read, |
99 | .multi_write = adt7316_spi_multi_write, |
100 | }; |
101 | |
102 | /* don't exceed max specified SPI CLK frequency */ |
103 | if (spi_dev->max_speed_hz > ADT7316_SPI_MAX_FREQ_HZ) { |
104 | dev_err(&spi_dev->dev, "SPI CLK %d Hz?\n" , |
105 | spi_dev->max_speed_hz); |
106 | return -EINVAL; |
107 | } |
108 | |
109 | /* switch from default I2C protocol to SPI protocol */ |
110 | adt7316_spi_write(client: spi_dev, reg: 0, val: 0); |
111 | adt7316_spi_write(client: spi_dev, reg: 0, val: 0); |
112 | adt7316_spi_write(client: spi_dev, reg: 0, val: 0); |
113 | |
114 | return adt7316_probe(dev: &spi_dev->dev, bus: &bus, name: spi_dev->modalias); |
115 | } |
116 | |
117 | static const struct spi_device_id adt7316_spi_id[] = { |
118 | { "adt7316" , 0 }, |
119 | { "adt7317" , 0 }, |
120 | { "adt7318" , 0 }, |
121 | { "adt7516" , 0 }, |
122 | { "adt7517" , 0 }, |
123 | { "adt7519" , 0 }, |
124 | { } |
125 | }; |
126 | |
127 | MODULE_DEVICE_TABLE(spi, adt7316_spi_id); |
128 | |
129 | static const struct of_device_id adt7316_of_spi_match[] = { |
130 | { .compatible = "adi,adt7316" }, |
131 | { .compatible = "adi,adt7317" }, |
132 | { .compatible = "adi,adt7318" }, |
133 | { .compatible = "adi,adt7516" }, |
134 | { .compatible = "adi,adt7517" }, |
135 | { .compatible = "adi,adt7519" }, |
136 | { } |
137 | }; |
138 | |
139 | MODULE_DEVICE_TABLE(of, adt7316_of_spi_match); |
140 | |
141 | static struct spi_driver adt7316_driver = { |
142 | .driver = { |
143 | .name = "adt7316" , |
144 | .of_match_table = adt7316_of_spi_match, |
145 | .pm = ADT7316_PM_OPS, |
146 | }, |
147 | .probe = adt7316_spi_probe, |
148 | .id_table = adt7316_spi_id, |
149 | }; |
150 | module_spi_driver(adt7316_driver); |
151 | |
152 | MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>" ); |
153 | MODULE_DESCRIPTION("SPI bus driver for Analog Devices ADT7316/7/8 and ADT7516/7/9 digital temperature sensor, ADC and DAC" ); |
154 | MODULE_LICENSE("GPL v2" ); |
155 | |