1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * I2C 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/i2c.h> |
12 | #include <linux/interrupt.h> |
13 | #include <linux/module.h> |
14 | |
15 | #include "adt7316.h" |
16 | |
17 | /* |
18 | * adt7316 register access by I2C |
19 | */ |
20 | static int adt7316_i2c_read(void *client, u8 reg, u8 *data) |
21 | { |
22 | struct i2c_client *cl = client; |
23 | int ret; |
24 | |
25 | ret = i2c_smbus_write_byte(client: cl, value: reg); |
26 | if (ret < 0) { |
27 | dev_err(&cl->dev, "I2C fail to select reg\n" ); |
28 | return ret; |
29 | } |
30 | |
31 | ret = i2c_smbus_read_byte(client); |
32 | if (ret < 0) { |
33 | dev_err(&cl->dev, "I2C read error\n" ); |
34 | return ret; |
35 | } |
36 | |
37 | *data = ret; |
38 | |
39 | return 0; |
40 | } |
41 | |
42 | static int adt7316_i2c_write(void *client, u8 reg, u8 data) |
43 | { |
44 | struct i2c_client *cl = client; |
45 | int ret; |
46 | |
47 | ret = i2c_smbus_write_byte_data(client: cl, command: reg, value: data); |
48 | if (ret < 0) |
49 | dev_err(&cl->dev, "I2C write error\n" ); |
50 | |
51 | return ret; |
52 | } |
53 | |
54 | static int adt7316_i2c_multi_read(void *client, u8 reg, u8 count, u8 *data) |
55 | { |
56 | struct i2c_client *cl = client; |
57 | int i, ret; |
58 | |
59 | if (count > ADT7316_REG_MAX_ADDR) |
60 | count = ADT7316_REG_MAX_ADDR; |
61 | |
62 | for (i = 0; i < count; i++) { |
63 | ret = adt7316_i2c_read(client: cl, reg, data: &data[i]); |
64 | if (ret < 0) { |
65 | dev_err(&cl->dev, "I2C multi read error\n" ); |
66 | return ret; |
67 | } |
68 | } |
69 | |
70 | return 0; |
71 | } |
72 | |
73 | static int adt7316_i2c_multi_write(void *client, u8 reg, u8 count, u8 *data) |
74 | { |
75 | struct i2c_client *cl = client; |
76 | int i, ret; |
77 | |
78 | if (count > ADT7316_REG_MAX_ADDR) |
79 | count = ADT7316_REG_MAX_ADDR; |
80 | |
81 | for (i = 0; i < count; i++) { |
82 | ret = adt7316_i2c_write(client: cl, reg, data: data[i]); |
83 | if (ret < 0) { |
84 | dev_err(&cl->dev, "I2C multi write error\n" ); |
85 | return ret; |
86 | } |
87 | } |
88 | |
89 | return 0; |
90 | } |
91 | |
92 | /* |
93 | * device probe and remove |
94 | */ |
95 | |
96 | static int adt7316_i2c_probe(struct i2c_client *client) |
97 | { |
98 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
99 | struct adt7316_bus bus = { |
100 | .client = client, |
101 | .irq = client->irq, |
102 | .read = adt7316_i2c_read, |
103 | .write = adt7316_i2c_write, |
104 | .multi_read = adt7316_i2c_multi_read, |
105 | .multi_write = adt7316_i2c_multi_write, |
106 | }; |
107 | |
108 | return adt7316_probe(dev: &client->dev, bus: &bus, name: id->name); |
109 | } |
110 | |
111 | static const struct i2c_device_id adt7316_i2c_id[] = { |
112 | { "adt7316" , 0 }, |
113 | { "adt7317" , 0 }, |
114 | { "adt7318" , 0 }, |
115 | { "adt7516" , 0 }, |
116 | { "adt7517" , 0 }, |
117 | { "adt7519" , 0 }, |
118 | { } |
119 | }; |
120 | |
121 | MODULE_DEVICE_TABLE(i2c, adt7316_i2c_id); |
122 | |
123 | static const struct of_device_id adt7316_of_match[] = { |
124 | { .compatible = "adi,adt7316" }, |
125 | { .compatible = "adi,adt7317" }, |
126 | { .compatible = "adi,adt7318" }, |
127 | { .compatible = "adi,adt7516" }, |
128 | { .compatible = "adi,adt7517" }, |
129 | { .compatible = "adi,adt7519" }, |
130 | { }, |
131 | }; |
132 | |
133 | MODULE_DEVICE_TABLE(of, adt7316_of_match); |
134 | |
135 | static struct i2c_driver adt7316_driver = { |
136 | .driver = { |
137 | .name = "adt7316" , |
138 | .of_match_table = adt7316_of_match, |
139 | .pm = ADT7316_PM_OPS, |
140 | }, |
141 | .probe = adt7316_i2c_probe, |
142 | .id_table = adt7316_i2c_id, |
143 | }; |
144 | module_i2c_driver(adt7316_driver); |
145 | |
146 | MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>" ); |
147 | MODULE_DESCRIPTION("I2C bus driver for Analog Devices ADT7316/7/9 and ADT7516/7/8 digital temperature sensor, ADC and DAC" ); |
148 | MODULE_LICENSE("GPL v2" ); |
149 | |