1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * AD5338R, AD5671R, AD5673R, AD5675R, AD5677R, AD5691R, AD5692R, AD5693, 4 * AD5693R, AD5694, AD5694R, AD5695R, AD5696, AD5696R 5 * Digital to analog converters driver 6 * 7 * Copyright 2018 Analog Devices Inc. 8 */ 9 10 #include <linux/errno.h> 11 #include <linux/i2c.h> 12 #include <linux/mod_devicetable.h> 13 #include <linux/module.h> 14 15 #include <asm/byteorder.h> 16 17 #include "ad5686.h" 18 19 static int ad5686_i2c_read(struct ad5686_state *st, u8 addr) 20 { 21 struct i2c_client *i2c = to_i2c_client(st->dev); 22 struct i2c_msg msg[2] = { 23 { 24 .addr = i2c->addr, 25 .flags = i2c->flags, 26 .len = 3, 27 .buf = &st->data[0].d8[1], 28 }, 29 { 30 .addr = i2c->addr, 31 .flags = i2c->flags | I2C_M_RD, 32 .len = 2, 33 .buf = (char *)&st->data[0].d16, 34 }, 35 }; 36 int ret; 37 38 st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP) | 39 AD5686_ADDR(addr) | 40 0x00); 41 42 ret = i2c_transfer(i2c->adapter, msg, 2); 43 if (ret < 0) 44 return ret; 45 46 return be16_to_cpu(st->data[0].d16); 47 } 48 49 static int ad5686_i2c_write(struct ad5686_state *st, 50 u8 cmd, u8 addr, u16 val) 51 { 52 struct i2c_client *i2c = to_i2c_client(st->dev); 53 int ret; 54 55 st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | AD5686_ADDR(addr) 56 | val); 57 58 ret = i2c_master_send(i2c, &st->data[0].d8[1], 3); 59 if (ret < 0) 60 return ret; 61 62 return (ret != 3) ? -EIO : 0; 63 } 64 65 static const struct ad5686_bus_ops ad5686_i2c_ops = { 66 .write = ad5686_i2c_write, 67 .read = ad5686_i2c_read, 68 }; 69 70 static int ad5686_i2c_probe(struct i2c_client *i2c) 71 { 72 return ad5686_probe(&i2c->dev, i2c_get_match_data(i2c), 73 i2c->name, &ad5686_i2c_ops); 74 } 75 76 static const struct i2c_device_id ad5686_i2c_id[] = { 77 { .name = "ad5311r", .driver_data = (kernel_ulong_t)&ad5311r_chip_info }, 78 { .name = "ad5337r", .driver_data = (kernel_ulong_t)&ad5337r_chip_info }, 79 { .name = "ad5338r", .driver_data = (kernel_ulong_t)&ad5338r_chip_info }, 80 { .name = "ad5671r", .driver_data = (kernel_ulong_t)&ad5672r_chip_info }, 81 { .name = "ad5673r", .driver_data = (kernel_ulong_t)&ad5674r_chip_info }, 82 { .name = "ad5675r", .driver_data = (kernel_ulong_t)&ad5676r_chip_info }, 83 { .name = "ad5677r", .driver_data = (kernel_ulong_t)&ad5679r_chip_info }, 84 { .name = "ad5691r", .driver_data = (kernel_ulong_t)&ad5681r_chip_info }, 85 { .name = "ad5692r", .driver_data = (kernel_ulong_t)&ad5682r_chip_info }, 86 { .name = "ad5693", .driver_data = (kernel_ulong_t)&ad5683_chip_info }, 87 { .name = "ad5693r", .driver_data = (kernel_ulong_t)&ad5683r_chip_info }, 88 { .name = "ad5694", .driver_data = (kernel_ulong_t)&ad5684_chip_info }, 89 { .name = "ad5694r", .driver_data = (kernel_ulong_t)&ad5684r_chip_info }, 90 { .name = "ad5695r", .driver_data = (kernel_ulong_t)&ad5685r_chip_info }, 91 { .name = "ad5696", .driver_data = (kernel_ulong_t)&ad5686_chip_info }, 92 { .name = "ad5696r", .driver_data = (kernel_ulong_t)&ad5686r_chip_info }, 93 { } 94 }; 95 MODULE_DEVICE_TABLE(i2c, ad5686_i2c_id); 96 97 static const struct of_device_id ad5686_of_match[] = { 98 { .compatible = "adi,ad5311r", .data = &ad5311r_chip_info }, 99 { .compatible = "adi,ad5337r", .data = &ad5337r_chip_info }, 100 { .compatible = "adi,ad5338r", .data = &ad5338r_chip_info }, 101 { .compatible = "adi,ad5671r", .data = &ad5672r_chip_info }, 102 { .compatible = "adi,ad5675r", .data = &ad5676r_chip_info }, 103 { .compatible = "adi,ad5691r", .data = &ad5681r_chip_info }, 104 { .compatible = "adi,ad5692r", .data = &ad5682r_chip_info }, 105 { .compatible = "adi,ad5693", .data = &ad5683_chip_info }, 106 { .compatible = "adi,ad5693r", .data = &ad5683r_chip_info }, 107 { .compatible = "adi,ad5694", .data = &ad5684_chip_info }, 108 { .compatible = "adi,ad5694r", .data = &ad5684r_chip_info }, 109 { .compatible = "adi,ad5695r", .data = &ad5685r_chip_info }, 110 { .compatible = "adi,ad5696", .data = &ad5686_chip_info }, 111 { .compatible = "adi,ad5696r", .data = &ad5686r_chip_info }, 112 { } 113 }; 114 MODULE_DEVICE_TABLE(of, ad5686_of_match); 115 116 static struct i2c_driver ad5686_i2c_driver = { 117 .driver = { 118 .name = "ad5696", 119 .of_match_table = ad5686_of_match, 120 }, 121 .probe = ad5686_i2c_probe, 122 .id_table = ad5686_i2c_id, 123 }; 124 125 module_i2c_driver(ad5686_i2c_driver); 126 127 MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>"); 128 MODULE_DESCRIPTION("Analog Devices AD5686 and similar multi-channel DACs"); 129 MODULE_LICENSE("GPL v2"); 130 MODULE_IMPORT_NS("IIO_AD5686"); 131