1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2023 Anshul Dalal <anshulusr@gmail.com>
5 * Driver for Microchip MCP4801, MCP4802, MCP4811, MCP4812, MCP4821 and MCP4822
7 * Based on the work of:
8 * Michael Welling (MCP4922 Driver)
11 * MCP48x1: https://ww1.microchip.com/downloads/en/DeviceDoc/22244B.pdf
12 * MCP48x2: https://ww1.microchip.com/downloads/en/DeviceDoc/20002249B.pdf
19 #include <linux/module.h>
20 #include <linux/mod_devicetable.h>
21 #include <linux/spi/spi.h>
23 #include <linux/iio/iio.h>
24 #include <linux/iio/types.h>
26 #include <linux/unaligned.h>
28 #define MCP4821_ACTIVE_MODE BIT(12)
29 #define MCP4802_SECOND_CHAN BIT(15)
31 /* DAC uses an internal Voltage reference of 4.096V at a gain of 2x */
32 #define MCP4821_2X_GAIN_VREF_MV 4096
34 enum mcp4821_supported_drvice_ids
{
43 struct mcp4821_state
{
44 struct spi_device
*spi
;
48 struct mcp4821_chip_info
{
51 const struct iio_chan_spec channels
[2];
54 #define MCP4821_CHAN(channel_id, resolution) \
56 .type = IIO_VOLTAGE, .output = 1, .indexed = 1, \
57 .channel = (channel_id), \
58 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
59 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
61 .realbits = (resolution), \
62 .shift = 12 - (resolution), \
66 static const struct mcp4821_chip_info mcp4821_chip_info_table
[6] = {
114 static int mcp4821_read_raw(struct iio_dev
*indio_dev
,
115 struct iio_chan_spec
const *chan
, int *val
,
116 int *val2
, long mask
)
118 struct mcp4821_state
*state
;
121 case IIO_CHAN_INFO_RAW
:
122 state
= iio_priv(indio_dev
);
123 *val
= state
->dac_value
[chan
->channel
];
125 case IIO_CHAN_INFO_SCALE
:
126 *val
= MCP4821_2X_GAIN_VREF_MV
;
127 *val2
= chan
->scan_type
.realbits
;
128 return IIO_VAL_FRACTIONAL_LOG2
;
134 static int mcp4821_write_raw(struct iio_dev
*indio_dev
,
135 struct iio_chan_spec
const *chan
, int val
,
138 struct mcp4821_state
*state
= iio_priv(indio_dev
);
146 if (val
< 0 || val
>= BIT(chan
->scan_type
.realbits
))
149 if (mask
!= IIO_CHAN_INFO_RAW
)
152 write_val
= MCP4821_ACTIVE_MODE
| val
<< chan
->scan_type
.shift
;
154 write_val
|= MCP4802_SECOND_CHAN
;
156 write_buffer
= cpu_to_be16(write_val
);
157 ret
= spi_write(state
->spi
, &write_buffer
, sizeof(write_buffer
));
159 dev_err(&state
->spi
->dev
, "Failed to write to device: %d", ret
);
163 state
->dac_value
[chan
->channel
] = val
;
168 static const struct iio_info mcp4821_info
= {
169 .read_raw
= &mcp4821_read_raw
,
170 .write_raw
= &mcp4821_write_raw
,
173 static int mcp4821_probe(struct spi_device
*spi
)
175 struct iio_dev
*indio_dev
;
176 struct mcp4821_state
*state
;
177 const struct mcp4821_chip_info
*info
;
179 indio_dev
= devm_iio_device_alloc(&spi
->dev
, sizeof(*state
));
180 if (indio_dev
== NULL
)
183 state
= iio_priv(indio_dev
);
186 info
= spi_get_device_match_data(spi
);
187 indio_dev
->name
= info
->name
;
188 indio_dev
->info
= &mcp4821_info
;
189 indio_dev
->modes
= INDIO_DIRECT_MODE
;
190 indio_dev
->channels
= info
->channels
;
191 indio_dev
->num_channels
= info
->num_channels
;
193 return devm_iio_device_register(&spi
->dev
, indio_dev
);
196 #define MCP4821_COMPATIBLE(of_compatible, id) \
198 .compatible = of_compatible, \
199 .data = &mcp4821_chip_info_table[id] \
202 static const struct of_device_id mcp4821_of_table
[] = {
203 MCP4821_COMPATIBLE("microchip,mcp4801", ID_MCP4801
),
204 MCP4821_COMPATIBLE("microchip,mcp4802", ID_MCP4802
),
205 MCP4821_COMPATIBLE("microchip,mcp4811", ID_MCP4811
),
206 MCP4821_COMPATIBLE("microchip,mcp4812", ID_MCP4812
),
207 MCP4821_COMPATIBLE("microchip,mcp4821", ID_MCP4821
),
208 MCP4821_COMPATIBLE("microchip,mcp4822", ID_MCP4822
),
211 MODULE_DEVICE_TABLE(of
, mcp4821_of_table
);
213 static const struct spi_device_id mcp4821_id_table
[] = {
214 { "mcp4801", (kernel_ulong_t
)&mcp4821_chip_info_table
[ID_MCP4801
]},
215 { "mcp4802", (kernel_ulong_t
)&mcp4821_chip_info_table
[ID_MCP4802
]},
216 { "mcp4811", (kernel_ulong_t
)&mcp4821_chip_info_table
[ID_MCP4811
]},
217 { "mcp4812", (kernel_ulong_t
)&mcp4821_chip_info_table
[ID_MCP4812
]},
218 { "mcp4821", (kernel_ulong_t
)&mcp4821_chip_info_table
[ID_MCP4821
]},
219 { "mcp4822", (kernel_ulong_t
)&mcp4821_chip_info_table
[ID_MCP4822
]},
222 MODULE_DEVICE_TABLE(spi
, mcp4821_id_table
);
224 static struct spi_driver mcp4821_driver
= {
227 .of_match_table
= mcp4821_of_table
,
229 .probe
= mcp4821_probe
,
230 .id_table
= mcp4821_id_table
,
232 module_spi_driver(mcp4821_driver
);
234 MODULE_AUTHOR("Anshul Dalal <anshulusr@gmail.com>");
235 MODULE_DESCRIPTION("Microchip MCP4821 DAC Driver");
236 MODULE_LICENSE("GPL");