1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * AD5446 SPI DAC driver 4 * 5 * Copyright 2025 Analog Devices Inc. 6 */ 7 #include <linux/err.h> 8 #include <linux/module.h> 9 #include <linux/mod_devicetable.h> 10 #include <linux/spi/spi.h> 11 #include <linux/unaligned.h> 12 13 #include <asm/byteorder.h> 14 15 #include "ad5446.h" 16 17 static int ad5446_write(struct ad5446_state *st, unsigned int val) 18 { 19 struct spi_device *spi = to_spi_device(st->dev); 20 21 st->d16 = cpu_to_be16(val); 22 23 return spi_write(spi, &st->d16, sizeof(st->d16)); 24 } 25 26 static int ad5660_write(struct ad5446_state *st, unsigned int val) 27 { 28 struct spi_device *spi = to_spi_device(st->dev); 29 30 put_unaligned_be24(val, st->d24); 31 32 return spi_write(spi, st->d24, sizeof(st->d24)); 33 } 34 35 static int ad5446_spi_probe(struct spi_device *spi) 36 { 37 const struct spi_device_id *id = spi_get_device_id(spi); 38 const struct ad5446_chip_info *chip_info; 39 40 chip_info = spi_get_device_match_data(spi); 41 if (!chip_info) 42 return -ENODEV; 43 44 return ad5446_probe(&spi->dev, id->name, chip_info); 45 } 46 47 /* 48 * ad5446_supported_spi_device_ids: 49 * The AD5620/40/60 parts are available in different fixed internal reference 50 * voltage options. The actual part numbers may look differently 51 * (and a bit cryptic), however this style is used to make clear which 52 * parts are supported here. 53 */ 54 55 static const struct ad5446_chip_info ad5300_chip_info = { 56 .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4), 57 .write = ad5446_write, 58 }; 59 60 static const struct ad5446_chip_info ad5310_chip_info = { 61 .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2), 62 .write = ad5446_write, 63 }; 64 65 static const struct ad5446_chip_info ad5320_chip_info = { 66 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0), 67 .write = ad5446_write, 68 }; 69 70 static const struct ad5446_chip_info ad5444_chip_info = { 71 .channel = AD5446_CHANNEL(12, 16, 2), 72 .write = ad5446_write, 73 }; 74 75 static const struct ad5446_chip_info ad5446_chip_info = { 76 .channel = AD5446_CHANNEL(14, 16, 0), 77 .write = ad5446_write, 78 }; 79 80 static const struct ad5446_chip_info ad5450_chip_info = { 81 .channel = AD5446_CHANNEL(8, 16, 6), 82 .write = ad5446_write, 83 }; 84 85 static const struct ad5446_chip_info ad5451_chip_info = { 86 .channel = AD5446_CHANNEL(10, 16, 4), 87 .write = ad5446_write, 88 }; 89 90 static const struct ad5446_chip_info ad5541a_chip_info = { 91 .channel = AD5446_CHANNEL(16, 16, 0), 92 .write = ad5446_write, 93 }; 94 95 static const struct ad5446_chip_info ad5512a_chip_info = { 96 .channel = AD5446_CHANNEL(12, 16, 4), 97 .write = ad5446_write, 98 }; 99 100 static const struct ad5446_chip_info ad5553_chip_info = { 101 .channel = AD5446_CHANNEL(14, 16, 0), 102 .write = ad5446_write, 103 }; 104 105 static const struct ad5446_chip_info ad5601_chip_info = { 106 .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6), 107 .write = ad5446_write, 108 }; 109 110 static const struct ad5446_chip_info ad5611_chip_info = { 111 .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4), 112 .write = ad5446_write, 113 }; 114 115 static const struct ad5446_chip_info ad5621_chip_info = { 116 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), 117 .write = ad5446_write, 118 }; 119 120 static const struct ad5446_chip_info ad5641_chip_info = { 121 .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0), 122 .write = ad5446_write, 123 }; 124 125 static const struct ad5446_chip_info ad5620_2500_chip_info = { 126 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), 127 .int_vref_mv = 2500, 128 .write = ad5446_write, 129 }; 130 131 static const struct ad5446_chip_info ad5620_1250_chip_info = { 132 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2), 133 .int_vref_mv = 1250, 134 .write = ad5446_write, 135 }; 136 137 static const struct ad5446_chip_info ad5640_2500_chip_info = { 138 .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0), 139 .int_vref_mv = 2500, 140 .write = ad5446_write, 141 }; 142 143 static const struct ad5446_chip_info ad5640_1250_chip_info = { 144 .channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0), 145 .int_vref_mv = 1250, 146 .write = ad5446_write, 147 }; 148 149 static const struct ad5446_chip_info ad5660_2500_chip_info = { 150 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), 151 .int_vref_mv = 2500, 152 .write = ad5660_write, 153 }; 154 155 static const struct ad5446_chip_info ad5660_1250_chip_info = { 156 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), 157 .int_vref_mv = 1250, 158 .write = ad5660_write, 159 }; 160 161 static const struct ad5446_chip_info ad5662_chip_info = { 162 .channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0), 163 .write = ad5660_write, 164 }; 165 166 static const struct spi_device_id ad5446_spi_ids[] = { 167 {"ad5300", (kernel_ulong_t)&ad5300_chip_info}, 168 {"ad5310", (kernel_ulong_t)&ad5310_chip_info}, 169 {"ad5320", (kernel_ulong_t)&ad5320_chip_info}, 170 {"ad5444", (kernel_ulong_t)&ad5444_chip_info}, 171 {"ad5446", (kernel_ulong_t)&ad5446_chip_info}, 172 {"ad5450", (kernel_ulong_t)&ad5450_chip_info}, 173 {"ad5451", (kernel_ulong_t)&ad5451_chip_info}, 174 {"ad5452", (kernel_ulong_t)&ad5444_chip_info}, /* ad5452 is compatible to the ad5444 */ 175 {"ad5453", (kernel_ulong_t)&ad5446_chip_info}, /* ad5453 is compatible to the ad5446 */ 176 {"ad5512a", (kernel_ulong_t)&ad5512a_chip_info}, 177 {"ad5541a", (kernel_ulong_t)&ad5541a_chip_info}, 178 {"ad5542", (kernel_ulong_t)&ad5541a_chip_info}, /* ad5541a and ad5542 are compatible */ 179 {"ad5542a", (kernel_ulong_t)&ad5541a_chip_info}, /* ad5541a and ad5542a are compatible */ 180 {"ad5543", (kernel_ulong_t)&ad5541a_chip_info}, /* ad5541a and ad5543 are compatible */ 181 {"ad5553", (kernel_ulong_t)&ad5553_chip_info}, 182 {"ad5600", (kernel_ulong_t)&ad5541a_chip_info}, /* ad5541a and ad5600 are compatible */ 183 {"ad5601", (kernel_ulong_t)&ad5601_chip_info}, 184 {"ad5611", (kernel_ulong_t)&ad5611_chip_info}, 185 {"ad5621", (kernel_ulong_t)&ad5621_chip_info}, 186 {"ad5641", (kernel_ulong_t)&ad5641_chip_info}, 187 {"ad5620-2500", (kernel_ulong_t)&ad5620_2500_chip_info}, /* AD5620/40/60: */ 188 /* part numbers may look differently */ 189 {"ad5620-1250", (kernel_ulong_t)&ad5620_1250_chip_info}, 190 {"ad5640-2500", (kernel_ulong_t)&ad5640_2500_chip_info}, 191 {"ad5640-1250", (kernel_ulong_t)&ad5640_1250_chip_info}, 192 {"ad5660-2500", (kernel_ulong_t)&ad5660_2500_chip_info}, 193 {"ad5660-1250", (kernel_ulong_t)&ad5660_1250_chip_info}, 194 {"ad5662", (kernel_ulong_t)&ad5662_chip_info}, 195 {"dac081s101", (kernel_ulong_t)&ad5300_chip_info}, /* compatible Texas Instruments chips */ 196 {"dac101s101", (kernel_ulong_t)&ad5310_chip_info}, 197 {"dac121s101", (kernel_ulong_t)&ad5320_chip_info}, 198 {"dac7512", (kernel_ulong_t)&ad5320_chip_info}, 199 { } 200 }; 201 MODULE_DEVICE_TABLE(spi, ad5446_spi_ids); 202 203 static const struct of_device_id ad5446_of_ids[] = { 204 { .compatible = "adi,ad5300", .data = &ad5300_chip_info }, 205 { .compatible = "adi,ad5310", .data = &ad5310_chip_info }, 206 { .compatible = "adi,ad5320", .data = &ad5320_chip_info }, 207 { .compatible = "adi,ad5444", .data = &ad5444_chip_info }, 208 { .compatible = "adi,ad5446", .data = &ad5446_chip_info }, 209 { .compatible = "adi,ad5450", .data = &ad5450_chip_info }, 210 { .compatible = "adi,ad5451", .data = &ad5451_chip_info }, 211 { .compatible = "adi,ad5452", .data = &ad5444_chip_info }, 212 { .compatible = "adi,ad5453", .data = &ad5446_chip_info }, 213 { .compatible = "adi,ad5512a", .data = &ad5512a_chip_info }, 214 { .compatible = "adi,ad5541a", .data = &ad5541a_chip_info }, 215 { .compatible = "adi,ad5542", .data = &ad5541a_chip_info }, 216 { .compatible = "adi,ad5542a", .data = &ad5541a_chip_info }, 217 { .compatible = "adi,ad5543", .data = &ad5541a_chip_info }, 218 { .compatible = "adi,ad5553", .data = &ad5553_chip_info }, 219 { .compatible = "adi,ad5600", .data = &ad5541a_chip_info }, 220 { .compatible = "adi,ad5601", .data = &ad5601_chip_info }, 221 { .compatible = "adi,ad5611", .data = &ad5611_chip_info }, 222 { .compatible = "adi,ad5621", .data = &ad5621_chip_info }, 223 { .compatible = "adi,ad5641", .data = &ad5641_chip_info }, 224 { .compatible = "adi,ad5620-2500", .data = &ad5620_2500_chip_info }, 225 { .compatible = "adi,ad5620-1250", .data = &ad5620_1250_chip_info }, 226 { .compatible = "adi,ad5640-2500", .data = &ad5640_2500_chip_info }, 227 { .compatible = "adi,ad5640-1250", .data = &ad5640_1250_chip_info }, 228 { .compatible = "adi,ad5660-2500", .data = &ad5660_2500_chip_info }, 229 { .compatible = "adi,ad5660-1250", .data = &ad5660_1250_chip_info }, 230 { .compatible = "adi,ad5662", .data = &ad5662_chip_info }, 231 { .compatible = "ti,dac081s101", .data = &ad5300_chip_info }, 232 { .compatible = "ti,dac101s101", .data = &ad5310_chip_info }, 233 { .compatible = "ti,dac121s101", .data = &ad5320_chip_info }, 234 { .compatible = "ti,dac7512", .data = &ad5320_chip_info }, 235 { } 236 }; 237 MODULE_DEVICE_TABLE(of, ad5446_of_ids); 238 239 static struct spi_driver ad5446_spi_driver = { 240 .driver = { 241 .name = "ad5446", 242 .of_match_table = ad5446_of_ids, 243 }, 244 .probe = ad5446_spi_probe, 245 .id_table = ad5446_spi_ids, 246 }; 247 module_spi_driver(ad5446_spi_driver); 248 249 MODULE_AUTHOR("Nuno Sá <nuno.sa@analog.com>"); 250 MODULE_DESCRIPTION("Analog Devices AD5446 and similar SPI DACs"); 251 MODULE_LICENSE("GPL"); 252 MODULE_IMPORT_NS("IIO_AD5446"); 253