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