1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2023 Anshul Dalal <anshulusr@gmail.com> 4 * 5 * Driver for Microchip MCP4801, MCP4802, MCP4811, MCP4812, MCP4821 and MCP4822 6 * 7 * Based on the work of: 8 * Michael Welling (MCP4922 Driver) 9 * 10 * Datasheet: 11 * MCP48x1: https://ww1.microchip.com/downloads/en/DeviceDoc/22244B.pdf 12 * MCP48x2: https://ww1.microchip.com/downloads/en/DeviceDoc/20002249B.pdf 13 * 14 * TODO: 15 * - Configurable gain 16 * - Regulator control 17 */ 18 19 #include <linux/module.h> 20 #include <linux/mod_devicetable.h> 21 #include <linux/spi/spi.h> 22 23 #include <linux/iio/iio.h> 24 #include <linux/iio/types.h> 25 26 #include <linux/unaligned.h> 27 28 #define MCP4821_ACTIVE_MODE BIT(12) 29 #define MCP4802_SECOND_CHAN BIT(15) 30 31 /* DAC uses an internal Voltage reference of 4.096V at a gain of 2x */ 32 #define MCP4821_2X_GAIN_VREF_MV 4096 33 34 enum mcp4821_supported_drvice_ids { 35 ID_MCP4801, 36 ID_MCP4802, 37 ID_MCP4811, 38 ID_MCP4812, 39 ID_MCP4821, 40 ID_MCP4822, 41 }; 42 43 struct mcp4821_state { 44 struct spi_device *spi; 45 u16 dac_value[2]; 46 }; 47 48 struct mcp4821_chip_info { 49 const char *name; 50 int num_channels; 51 const struct iio_chan_spec channels[2]; 52 }; 53 54 #define MCP4821_CHAN(channel_id, resolution) \ 55 { \ 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), \ 60 .scan_type = { \ 61 .realbits = (resolution), \ 62 .shift = 12 - (resolution), \ 63 }, \ 64 } 65 66 static const struct mcp4821_chip_info mcp4821_chip_info_table[6] = { 67 [ID_MCP4801] = { 68 .name = "mcp4801", 69 .num_channels = 1, 70 .channels = { 71 MCP4821_CHAN(0, 8), 72 }, 73 }, 74 [ID_MCP4802] = { 75 .name = "mcp4802", 76 .num_channels = 2, 77 .channels = { 78 MCP4821_CHAN(0, 8), 79 MCP4821_CHAN(1, 8), 80 }, 81 }, 82 [ID_MCP4811] = { 83 .name = "mcp4811", 84 .num_channels = 1, 85 .channels = { 86 MCP4821_CHAN(0, 10), 87 }, 88 }, 89 [ID_MCP4812] = { 90 .name = "mcp4812", 91 .num_channels = 2, 92 .channels = { 93 MCP4821_CHAN(0, 10), 94 MCP4821_CHAN(1, 10), 95 }, 96 }, 97 [ID_MCP4821] = { 98 .name = "mcp4821", 99 .num_channels = 1, 100 .channels = { 101 MCP4821_CHAN(0, 12), 102 }, 103 }, 104 [ID_MCP4822] = { 105 .name = "mcp4822", 106 .num_channels = 2, 107 .channels = { 108 MCP4821_CHAN(0, 12), 109 MCP4821_CHAN(1, 12), 110 }, 111 }, 112 }; 113 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) 117 { 118 struct mcp4821_state *state; 119 120 switch (mask) { 121 case IIO_CHAN_INFO_RAW: 122 state = iio_priv(indio_dev); 123 *val = state->dac_value[chan->channel]; 124 return IIO_VAL_INT; 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; 129 default: 130 return -EINVAL; 131 } 132 } 133 134 static int mcp4821_write_raw(struct iio_dev *indio_dev, 135 struct iio_chan_spec const *chan, int val, 136 int val2, long mask) 137 { 138 struct mcp4821_state *state = iio_priv(indio_dev); 139 u16 write_val; 140 __be16 write_buffer; 141 int ret; 142 143 if (val2 != 0) 144 return -EINVAL; 145 146 if (val < 0 || val >= BIT(chan->scan_type.realbits)) 147 return -EINVAL; 148 149 if (mask != IIO_CHAN_INFO_RAW) 150 return -EINVAL; 151 152 write_val = MCP4821_ACTIVE_MODE | val << chan->scan_type.shift; 153 if (chan->channel) 154 write_val |= MCP4802_SECOND_CHAN; 155 156 write_buffer = cpu_to_be16(write_val); 157 ret = spi_write(state->spi, &write_buffer, sizeof(write_buffer)); 158 if (ret) { 159 dev_err(&state->spi->dev, "Failed to write to device: %d", ret); 160 return ret; 161 } 162 163 state->dac_value[chan->channel] = val; 164 165 return 0; 166 } 167 168 static const struct iio_info mcp4821_info = { 169 .read_raw = &mcp4821_read_raw, 170 .write_raw = &mcp4821_write_raw, 171 }; 172 173 static int mcp4821_probe(struct spi_device *spi) 174 { 175 struct iio_dev *indio_dev; 176 struct mcp4821_state *state; 177 const struct mcp4821_chip_info *info; 178 179 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state)); 180 if (indio_dev == NULL) 181 return -ENOMEM; 182 183 state = iio_priv(indio_dev); 184 state->spi = spi; 185 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; 192 193 return devm_iio_device_register(&spi->dev, indio_dev); 194 } 195 196 #define MCP4821_COMPATIBLE(of_compatible, id) \ 197 { \ 198 .compatible = of_compatible, \ 199 .data = &mcp4821_chip_info_table[id] \ 200 } 201 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), 209 { /* Sentinel */ } 210 }; 211 MODULE_DEVICE_TABLE(of, mcp4821_of_table); 212 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]}, 220 { /* Sentinel */ } 221 }; 222 MODULE_DEVICE_TABLE(spi, mcp4821_id_table); 223 224 static struct spi_driver mcp4821_driver = { 225 .driver = { 226 .name = "mcp4821", 227 .of_match_table = mcp4821_of_table, 228 }, 229 .probe = mcp4821_probe, 230 .id_table = mcp4821_id_table, 231 }; 232 module_spi_driver(mcp4821_driver); 233 234 MODULE_AUTHOR("Anshul Dalal <anshulusr@gmail.com>"); 235 MODULE_DESCRIPTION("Microchip MCP4821 DAC Driver"); 236 MODULE_LICENSE("GPL"); 237