18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * AD5671R, AD5675R, AD5691R, AD5692R, AD5693, AD5693R, 48c2ecf20Sopenharmony_ci * AD5694, AD5694R, AD5695R, AD5696, AD5696R 58c2ecf20Sopenharmony_ci * Digital to analog converters driver 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright 2018 Analog Devices Inc. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include "ad5686.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/i2c.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic int ad5686_i2c_read(struct ad5686_state *st, u8 addr) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci struct i2c_client *i2c = to_i2c_client(st->dev); 188c2ecf20Sopenharmony_ci struct i2c_msg msg[2] = { 198c2ecf20Sopenharmony_ci { 208c2ecf20Sopenharmony_ci .addr = i2c->addr, 218c2ecf20Sopenharmony_ci .flags = i2c->flags, 228c2ecf20Sopenharmony_ci .len = 3, 238c2ecf20Sopenharmony_ci .buf = &st->data[0].d8[1], 248c2ecf20Sopenharmony_ci }, 258c2ecf20Sopenharmony_ci { 268c2ecf20Sopenharmony_ci .addr = i2c->addr, 278c2ecf20Sopenharmony_ci .flags = i2c->flags | I2C_M_RD, 288c2ecf20Sopenharmony_ci .len = 2, 298c2ecf20Sopenharmony_ci .buf = (char *)&st->data[0].d16, 308c2ecf20Sopenharmony_ci }, 318c2ecf20Sopenharmony_ci }; 328c2ecf20Sopenharmony_ci int ret; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP) | 358c2ecf20Sopenharmony_ci AD5686_ADDR(addr) | 368c2ecf20Sopenharmony_ci 0x00); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci ret = i2c_transfer(i2c->adapter, msg, 2); 398c2ecf20Sopenharmony_ci if (ret < 0) 408c2ecf20Sopenharmony_ci return ret; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci return be16_to_cpu(st->data[0].d16); 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic int ad5686_i2c_write(struct ad5686_state *st, 468c2ecf20Sopenharmony_ci u8 cmd, u8 addr, u16 val) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci struct i2c_client *i2c = to_i2c_client(st->dev); 498c2ecf20Sopenharmony_ci int ret; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | AD5686_ADDR(addr) 528c2ecf20Sopenharmony_ci | val); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci ret = i2c_master_send(i2c, &st->data[0].d8[1], 3); 558c2ecf20Sopenharmony_ci if (ret < 0) 568c2ecf20Sopenharmony_ci return ret; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci return (ret != 3) ? -EIO : 0; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic int ad5686_i2c_probe(struct i2c_client *i2c, 628c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci return ad5686_probe(&i2c->dev, id->driver_data, id->name, 658c2ecf20Sopenharmony_ci ad5686_i2c_write, ad5686_i2c_read); 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cistatic int ad5686_i2c_remove(struct i2c_client *i2c) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci return ad5686_remove(&i2c->dev); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic const struct i2c_device_id ad5686_i2c_id[] = { 748c2ecf20Sopenharmony_ci {"ad5311r", ID_AD5311R}, 758c2ecf20Sopenharmony_ci {"ad5671r", ID_AD5671R}, 768c2ecf20Sopenharmony_ci {"ad5675r", ID_AD5675R}, 778c2ecf20Sopenharmony_ci {"ad5691r", ID_AD5691R}, 788c2ecf20Sopenharmony_ci {"ad5692r", ID_AD5692R}, 798c2ecf20Sopenharmony_ci {"ad5693", ID_AD5693}, 808c2ecf20Sopenharmony_ci {"ad5693r", ID_AD5693R}, 818c2ecf20Sopenharmony_ci {"ad5694", ID_AD5694}, 828c2ecf20Sopenharmony_ci {"ad5694r", ID_AD5694R}, 838c2ecf20Sopenharmony_ci {"ad5695r", ID_AD5695R}, 848c2ecf20Sopenharmony_ci {"ad5696", ID_AD5696}, 858c2ecf20Sopenharmony_ci {"ad5696r", ID_AD5696R}, 868c2ecf20Sopenharmony_ci {} 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, ad5686_i2c_id); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic struct i2c_driver ad5686_i2c_driver = { 918c2ecf20Sopenharmony_ci .driver = { 928c2ecf20Sopenharmony_ci .name = "ad5696", 938c2ecf20Sopenharmony_ci }, 948c2ecf20Sopenharmony_ci .probe = ad5686_i2c_probe, 958c2ecf20Sopenharmony_ci .remove = ad5686_i2c_remove, 968c2ecf20Sopenharmony_ci .id_table = ad5686_i2c_id, 978c2ecf20Sopenharmony_ci}; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cimodule_i2c_driver(ad5686_i2c_driver); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ciMODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>"); 1028c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD5686 and similar multi-channel DACs"); 1038c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 104