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