blob: 665fa6bd9ced7476f0f58e5cc6d5ac584f8e1c1c [file] [log] [blame]
Stefan Popa0357e482018-04-11 14:53:17 +03001// SPDX-License-Identifier: GPL-2.0+
2/*
Stefan Popa1dbae4c2018-05-18 18:23:34 +03003 * AD5672R, AD5676, AD5676R, AD5681R, AD5682R, AD5683, AD5683R,
4 * AD5684, AD5684R, AD5685R, AD5686, AD5686R
Stefan Popa0357e482018-04-11 14:53:17 +03005 * Digital to analog converters driver
6 *
7 * Copyright 2018 Analog Devices Inc.
8 */
9
10#include "ad5686.h"
11
12#include <linux/module.h>
13#include <linux/spi/spi.h>
14
15static int ad5686_spi_write(struct ad5686_state *st,
16 u8 cmd, u8 addr, u16 val)
17{
18 struct spi_device *spi = to_spi_device(st->dev);
Stefan Popa1dbae4c2018-05-18 18:23:34 +030019 u8 tx_len, *buf;
Stefan Popa0357e482018-04-11 14:53:17 +030020
Stefan Popa1dbae4c2018-05-18 18:23:34 +030021 switch (st->chip_info->regmap_type) {
Stefan Popa12d323c2018-12-06 15:38:30 +020022 case AD5310_REGMAP:
23 st->data[0].d16 = cpu_to_be16(AD5310_CMD(cmd) |
24 val);
25 buf = &st->data[0].d8[0];
26 tx_len = 2;
27 break;
Stefan Popa1dbae4c2018-05-18 18:23:34 +030028 case AD5683_REGMAP:
29 st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
30 AD5683_DATA(val));
31 buf = &st->data[0].d8[1];
32 tx_len = 3;
33 break;
34 case AD5686_REGMAP:
35 st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
36 AD5686_ADDR(addr) |
37 val);
38 buf = &st->data[0].d8[1];
39 tx_len = 3;
40 break;
41 default:
42 return -EINVAL;
43 }
Stefan Popa0357e482018-04-11 14:53:17 +030044
Stefan Popa1dbae4c2018-05-18 18:23:34 +030045 return spi_write(spi, buf, tx_len);
Stefan Popa0357e482018-04-11 14:53:17 +030046}
47
48static int ad5686_spi_read(struct ad5686_state *st, u8 addr)
49{
50 struct spi_transfer t[] = {
51 {
52 .tx_buf = &st->data[0].d8[1],
53 .len = 3,
54 .cs_change = 1,
55 }, {
56 .tx_buf = &st->data[1].d8[1],
57 .rx_buf = &st->data[2].d8[1],
58 .len = 3,
59 },
60 };
61 struct spi_device *spi = to_spi_device(st->dev);
Stefan Popa1dbae4c2018-05-18 18:23:34 +030062 u8 cmd = 0;
Stefan Popa0357e482018-04-11 14:53:17 +030063 int ret;
64
Stefan Popa12d323c2018-12-06 15:38:30 +020065 switch (st->chip_info->regmap_type) {
66 case AD5310_REGMAP:
67 return -ENOTSUPP;
68 case AD5683_REGMAP:
Stefan Popa1dbae4c2018-05-18 18:23:34 +030069 cmd = AD5686_CMD_READBACK_ENABLE_V2;
Stefan Popa12d323c2018-12-06 15:38:30 +020070 break;
71 case AD5686_REGMAP:
72 cmd = AD5686_CMD_READBACK_ENABLE;
73 break;
74 default:
75 return -EINVAL;
76 }
Stefan Popa1dbae4c2018-05-18 18:23:34 +030077
78 st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) |
Stefan Popa0357e482018-04-11 14:53:17 +030079 AD5686_ADDR(addr));
80 st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP));
81
82 ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t));
83 if (ret < 0)
84 return ret;
85
86 return be32_to_cpu(st->data[2].d32);
87}
88
89static int ad5686_spi_probe(struct spi_device *spi)
90{
91 const struct spi_device_id *id = spi_get_device_id(spi);
92
93 return ad5686_probe(&spi->dev, id->driver_data, id->name,
94 ad5686_spi_write, ad5686_spi_read);
95}
96
97static int ad5686_spi_remove(struct spi_device *spi)
98{
99 return ad5686_remove(&spi->dev);
100}
101
102static const struct spi_device_id ad5686_spi_id[] = {
Stefan Popa12d323c2018-12-06 15:38:30 +0200103 {"ad5310r", ID_AD5310R},
Stefan Popa0357e482018-04-11 14:53:17 +0300104 {"ad5672r", ID_AD5672R},
105 {"ad5676", ID_AD5676},
106 {"ad5676r", ID_AD5676R},
Stefan Popa1dbae4c2018-05-18 18:23:34 +0300107 {"ad5681r", ID_AD5681R},
108 {"ad5682r", ID_AD5682R},
109 {"ad5683", ID_AD5683},
110 {"ad5683r", ID_AD5683R},
Stefan Popa0357e482018-04-11 14:53:17 +0300111 {"ad5684", ID_AD5684},
112 {"ad5684r", ID_AD5684R},
113 {"ad5685", ID_AD5685R}, /* Does not exist */
114 {"ad5685r", ID_AD5685R},
115 {"ad5686", ID_AD5686},
116 {"ad5686r", ID_AD5686R},
117 {}
118};
119MODULE_DEVICE_TABLE(spi, ad5686_spi_id);
120
121static struct spi_driver ad5686_spi_driver = {
122 .driver = {
123 .name = "ad5686",
124 },
125 .probe = ad5686_spi_probe,
126 .remove = ad5686_spi_remove,
127 .id_table = ad5686_spi_id,
128};
129
130module_spi_driver(ad5686_spi_driver);
131
132MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
133MODULE_DESCRIPTION("Analog Devices AD5686 and similar multi-channel DACs");
134MODULE_LICENSE("GPL v2");