1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * AD5446 SPI I2C 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/i2c.h> 11 12 #include <asm/byteorder.h> 13 14 #include "ad5446.h" 15 16 static int ad5622_write(struct ad5446_state *st, unsigned int val) 17 { 18 struct i2c_client *client = to_i2c_client(st->dev); 19 int ret; 20 21 st->d16 = cpu_to_be16(val); 22 23 ret = i2c_master_send_dmasafe(client, (char *)&st->d16, sizeof(st->d16)); 24 if (ret < 0) 25 return ret; 26 if (ret != sizeof(st->d16)) 27 return -EIO; 28 29 return 0; 30 } 31 32 static int ad5446_i2c_probe(struct i2c_client *i2c) 33 { 34 const struct i2c_device_id *id = i2c_client_get_device_id(i2c); 35 const struct ad5446_chip_info *chip_info; 36 37 chip_info = i2c_get_match_data(i2c); 38 if (!chip_info) 39 return -ENODEV; 40 41 return ad5446_probe(&i2c->dev, id->name, chip_info); 42 } 43 44 /* 45 * ad5446_supported_i2c_device_ids: 46 * The AD5620/40/60 parts are available in different fixed internal reference 47 * voltage options. The actual part numbers may look differently 48 * (and a bit cryptic), however this style is used to make clear which 49 * parts are supported here. 50 */ 51 52 static const struct ad5446_chip_info ad5602_chip_info = { 53 .channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4), 54 .write = ad5622_write, 55 }; 56 57 static const struct ad5446_chip_info ad5612_chip_info = { 58 .channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2), 59 .write = ad5622_write, 60 }; 61 62 static const struct ad5446_chip_info ad5622_chip_info = { 63 .channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0), 64 .write = ad5622_write, 65 }; 66 67 static const struct i2c_device_id ad5446_i2c_ids[] = { 68 {"ad5301", (kernel_ulong_t)&ad5602_chip_info}, 69 {"ad5311", (kernel_ulong_t)&ad5612_chip_info}, 70 {"ad5321", (kernel_ulong_t)&ad5622_chip_info}, 71 {"ad5602", (kernel_ulong_t)&ad5602_chip_info}, 72 {"ad5612", (kernel_ulong_t)&ad5612_chip_info}, 73 {"ad5622", (kernel_ulong_t)&ad5622_chip_info}, 74 { } 75 }; 76 MODULE_DEVICE_TABLE(i2c, ad5446_i2c_ids); 77 78 static const struct of_device_id ad5446_i2c_of_ids[] = { 79 { .compatible = "adi,ad5301", .data = &ad5602_chip_info }, 80 { .compatible = "adi,ad5311", .data = &ad5612_chip_info }, 81 { .compatible = "adi,ad5321", .data = &ad5622_chip_info }, 82 { .compatible = "adi,ad5602", .data = &ad5602_chip_info }, 83 { .compatible = "adi,ad5612", .data = &ad5612_chip_info }, 84 { .compatible = "adi,ad5622", .data = &ad5622_chip_info }, 85 { } 86 }; 87 MODULE_DEVICE_TABLE(OF, ad5446_i2c_of_ids); 88 89 static struct i2c_driver ad5446_i2c_driver = { 90 .driver = { 91 .name = "ad5446", 92 .of_match_table = ad5446_i2c_of_ids, 93 }, 94 .probe = ad5446_i2c_probe, 95 .id_table = ad5446_i2c_ids, 96 }; 97 module_i2c_driver(ad5446_i2c_driver); 98 99 MODULE_AUTHOR("Nuno Sá <nuno.sa@analog.com>"); 100 MODULE_DESCRIPTION("Analog Devices AD5622 and similar I2C DACs"); 101 MODULE_LICENSE("GPL"); 102 MODULE_IMPORT_NS("IIO_AD5446"); 103