1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * AD5671R, AD5675R, AD5691R, AD5692R, AD5693, AD5693R,
4*4882a593Smuzhiyun * AD5694, AD5694R, AD5695R, AD5696, AD5696R
5*4882a593Smuzhiyun * Digital to analog converters driver
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright 2018 Analog Devices Inc.
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include "ad5686.h"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/i2c.h>
14*4882a593Smuzhiyun
ad5686_i2c_read(struct ad5686_state * st,u8 addr)15*4882a593Smuzhiyun static int ad5686_i2c_read(struct ad5686_state *st, u8 addr)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun struct i2c_client *i2c = to_i2c_client(st->dev);
18*4882a593Smuzhiyun struct i2c_msg msg[2] = {
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun .addr = i2c->addr,
21*4882a593Smuzhiyun .flags = i2c->flags,
22*4882a593Smuzhiyun .len = 3,
23*4882a593Smuzhiyun .buf = &st->data[0].d8[1],
24*4882a593Smuzhiyun },
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun .addr = i2c->addr,
27*4882a593Smuzhiyun .flags = i2c->flags | I2C_M_RD,
28*4882a593Smuzhiyun .len = 2,
29*4882a593Smuzhiyun .buf = (char *)&st->data[0].d16,
30*4882a593Smuzhiyun },
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun int ret;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP) |
35*4882a593Smuzhiyun AD5686_ADDR(addr) |
36*4882a593Smuzhiyun 0x00);
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun ret = i2c_transfer(i2c->adapter, msg, 2);
39*4882a593Smuzhiyun if (ret < 0)
40*4882a593Smuzhiyun return ret;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun return be16_to_cpu(st->data[0].d16);
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
ad5686_i2c_write(struct ad5686_state * st,u8 cmd,u8 addr,u16 val)45*4882a593Smuzhiyun static int ad5686_i2c_write(struct ad5686_state *st,
46*4882a593Smuzhiyun u8 cmd, u8 addr, u16 val)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun struct i2c_client *i2c = to_i2c_client(st->dev);
49*4882a593Smuzhiyun int ret;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | AD5686_ADDR(addr)
52*4882a593Smuzhiyun | val);
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun ret = i2c_master_send(i2c, &st->data[0].d8[1], 3);
55*4882a593Smuzhiyun if (ret < 0)
56*4882a593Smuzhiyun return ret;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun return (ret != 3) ? -EIO : 0;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
ad5686_i2c_probe(struct i2c_client * i2c,const struct i2c_device_id * id)61*4882a593Smuzhiyun static int ad5686_i2c_probe(struct i2c_client *i2c,
62*4882a593Smuzhiyun const struct i2c_device_id *id)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun return ad5686_probe(&i2c->dev, id->driver_data, id->name,
65*4882a593Smuzhiyun ad5686_i2c_write, ad5686_i2c_read);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
ad5686_i2c_remove(struct i2c_client * i2c)68*4882a593Smuzhiyun static int ad5686_i2c_remove(struct i2c_client *i2c)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun return ad5686_remove(&i2c->dev);
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun static const struct i2c_device_id ad5686_i2c_id[] = {
74*4882a593Smuzhiyun {"ad5311r", ID_AD5311R},
75*4882a593Smuzhiyun {"ad5671r", ID_AD5671R},
76*4882a593Smuzhiyun {"ad5675r", ID_AD5675R},
77*4882a593Smuzhiyun {"ad5691r", ID_AD5691R},
78*4882a593Smuzhiyun {"ad5692r", ID_AD5692R},
79*4882a593Smuzhiyun {"ad5693", ID_AD5693},
80*4882a593Smuzhiyun {"ad5693r", ID_AD5693R},
81*4882a593Smuzhiyun {"ad5694", ID_AD5694},
82*4882a593Smuzhiyun {"ad5694r", ID_AD5694R},
83*4882a593Smuzhiyun {"ad5695r", ID_AD5695R},
84*4882a593Smuzhiyun {"ad5696", ID_AD5696},
85*4882a593Smuzhiyun {"ad5696r", ID_AD5696R},
86*4882a593Smuzhiyun {}
87*4882a593Smuzhiyun };
88*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, ad5686_i2c_id);
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun static struct i2c_driver ad5686_i2c_driver = {
91*4882a593Smuzhiyun .driver = {
92*4882a593Smuzhiyun .name = "ad5696",
93*4882a593Smuzhiyun },
94*4882a593Smuzhiyun .probe = ad5686_i2c_probe,
95*4882a593Smuzhiyun .remove = ad5686_i2c_remove,
96*4882a593Smuzhiyun .id_table = ad5686_i2c_id,
97*4882a593Smuzhiyun };
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun module_i2c_driver(ad5686_i2c_driver);
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
102*4882a593Smuzhiyun MODULE_DESCRIPTION("Analog Devices AD5686 and similar multi-channel DACs");
103*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
104