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 */
20static 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(cl, 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
42static 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(cl, reg, data);
48	if (ret < 0)
49		dev_err(&cl->dev, "I2C write error\n");
50
51	return ret;
52}
53
54static 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(cl, reg, &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
73static 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(cl, reg, 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
96static 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(&client->dev, &bus, id->name);
109}
110
111static 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
121MODULE_DEVICE_TABLE(i2c, adt7316_i2c_id);
122
123static 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
133MODULE_DEVICE_TABLE(of, adt7316_of_match);
134
135static 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};
144module_i2c_driver(adt7316_driver);
145
146MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
147MODULE_DESCRIPTION("I2C bus driver for Analog Devices ADT7316/7/9 and ADT7516/7/8 digital temperature sensor, ADC and DAC");
148MODULE_LICENSE("GPL v2");
149