1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * AD5672R, AD5676, AD5676R, AD5681R, AD5682R, AD5683, AD5683R, 4 * AD5684, AD5684R, AD5685R, AD5686, AD5686R 5 * Digital to analog converters driver 6 * 7 * Copyright 2018 Analog Devices Inc. 8 */ 9 10 #include "ad5686.h" 11 12 #include <linux/module.h> 13 #include <linux/spi/spi.h> 14 15 static int ad5686_spi_write(struct ad5686_state *st, 16 u8 cmd, u8 addr, u16 val) 17 { 18 struct spi_device *spi = to_spi_device(st->dev); 19 u8 tx_len, *buf; 20 21 switch (st->chip_info->regmap_type) { 22 case AD5683_REGMAP: 23 st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | 24 AD5683_DATA(val)); 25 buf = &st->data[0].d8[1]; 26 tx_len = 3; 27 break; 28 case AD5686_REGMAP: 29 st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | 30 AD5686_ADDR(addr) | 31 val); 32 buf = &st->data[0].d8[1]; 33 tx_len = 3; 34 break; 35 default: 36 return -EINVAL; 37 } 38 39 return spi_write(spi, buf, tx_len); 40 } 41 42 static int ad5686_spi_read(struct ad5686_state *st, u8 addr) 43 { 44 struct spi_transfer t[] = { 45 { 46 .tx_buf = &st->data[0].d8[1], 47 .len = 3, 48 .cs_change = 1, 49 }, { 50 .tx_buf = &st->data[1].d8[1], 51 .rx_buf = &st->data[2].d8[1], 52 .len = 3, 53 }, 54 }; 55 struct spi_device *spi = to_spi_device(st->dev); 56 u8 cmd = 0; 57 int ret; 58 59 if (st->chip_info->regmap_type == AD5686_REGMAP) 60 cmd = AD5686_CMD_READBACK_ENABLE; 61 else if (st->chip_info->regmap_type == AD5683_REGMAP) 62 cmd = AD5686_CMD_READBACK_ENABLE_V2; 63 64 st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | 65 AD5686_ADDR(addr)); 66 st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP)); 67 68 ret = spi_sync_transfer(spi, t, ARRAY_SIZE(t)); 69 if (ret < 0) 70 return ret; 71 72 return be32_to_cpu(st->data[2].d32); 73 } 74 75 static int ad5686_spi_probe(struct spi_device *spi) 76 { 77 const struct spi_device_id *id = spi_get_device_id(spi); 78 79 return ad5686_probe(&spi->dev, id->driver_data, id->name, 80 ad5686_spi_write, ad5686_spi_read); 81 } 82 83 static int ad5686_spi_remove(struct spi_device *spi) 84 { 85 return ad5686_remove(&spi->dev); 86 } 87 88 static const struct spi_device_id ad5686_spi_id[] = { 89 {"ad5672r", ID_AD5672R}, 90 {"ad5676", ID_AD5676}, 91 {"ad5676r", ID_AD5676R}, 92 {"ad5681r", ID_AD5681R}, 93 {"ad5682r", ID_AD5682R}, 94 {"ad5683", ID_AD5683}, 95 {"ad5683r", ID_AD5683R}, 96 {"ad5684", ID_AD5684}, 97 {"ad5684r", ID_AD5684R}, 98 {"ad5685", ID_AD5685R}, /* Does not exist */ 99 {"ad5685r", ID_AD5685R}, 100 {"ad5686", ID_AD5686}, 101 {"ad5686r", ID_AD5686R}, 102 {} 103 }; 104 MODULE_DEVICE_TABLE(spi, ad5686_spi_id); 105 106 static struct spi_driver ad5686_spi_driver = { 107 .driver = { 108 .name = "ad5686", 109 }, 110 .probe = ad5686_spi_probe, 111 .remove = ad5686_spi_remove, 112 .id_table = ad5686_spi_id, 113 }; 114 115 module_spi_driver(ad5686_spi_driver); 116 117 MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>"); 118 MODULE_DESCRIPTION("Analog Devices AD5686 and similar multi-channel DACs"); 119 MODULE_LICENSE("GPL v2"); 120