1 /* 2 * Driver for the Analog Devices digital potentiometers (SPI bus) 3 * 4 * Copyright (C) 2010 Michael Hennerich, Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later. 7 */ 8 9 #include <linux/spi/spi.h> 10 #include <linux/module.h> 11 12 #include "ad525x_dpot.h" 13 14 static const struct ad_dpot_id ad_dpot_spi_devlist[] = { 15 {.name = "ad5160", .devid = AD5160_ID}, 16 {.name = "ad5161", .devid = AD5161_ID}, 17 {.name = "ad5162", .devid = AD5162_ID}, 18 {.name = "ad5165", .devid = AD5165_ID}, 19 {.name = "ad5200", .devid = AD5200_ID}, 20 {.name = "ad5201", .devid = AD5201_ID}, 21 {.name = "ad5203", .devid = AD5203_ID}, 22 {.name = "ad5204", .devid = AD5204_ID}, 23 {.name = "ad5206", .devid = AD5206_ID}, 24 {.name = "ad5207", .devid = AD5207_ID}, 25 {.name = "ad5231", .devid = AD5231_ID}, 26 {.name = "ad5232", .devid = AD5232_ID}, 27 {.name = "ad5233", .devid = AD5233_ID}, 28 {.name = "ad5235", .devid = AD5235_ID}, 29 {.name = "ad5260", .devid = AD5260_ID}, 30 {.name = "ad5262", .devid = AD5262_ID}, 31 {.name = "ad5263", .devid = AD5263_ID}, 32 {.name = "ad5290", .devid = AD5290_ID}, 33 {.name = "ad5291", .devid = AD5291_ID}, 34 {.name = "ad5292", .devid = AD5292_ID}, 35 {.name = "ad5293", .devid = AD5293_ID}, 36 {.name = "ad7376", .devid = AD7376_ID}, 37 {.name = "ad8400", .devid = AD8400_ID}, 38 {.name = "ad8402", .devid = AD8402_ID}, 39 {.name = "ad8403", .devid = AD8403_ID}, 40 {.name = "adn2850", .devid = ADN2850_ID}, 41 {.name = "ad5270", .devid = AD5270_ID}, 42 {.name = "ad5271", .devid = AD5271_ID}, 43 {} 44 }; 45 46 /* ------------------------------------------------------------------------- */ 47 48 /* SPI bus functions */ 49 static int write8(void *client, u8 val) 50 { 51 u8 data = val; 52 return spi_write(client, &data, 1); 53 } 54 55 static int write16(void *client, u8 reg, u8 val) 56 { 57 u8 data[2] = {reg, val}; 58 return spi_write(client, data, 2); 59 } 60 61 static int write24(void *client, u8 reg, u16 val) 62 { 63 u8 data[3] = {reg, val >> 8, val}; 64 return spi_write(client, data, 3); 65 } 66 67 static int read8(void *client) 68 { 69 int ret; 70 u8 data; 71 ret = spi_read(client, &data, 1); 72 if (ret < 0) 73 return ret; 74 75 return data; 76 } 77 78 static int read16(void *client, u8 reg) 79 { 80 int ret; 81 u8 buf_rx[2]; 82 83 write16(client, reg, 0); 84 ret = spi_read(client, buf_rx, 2); 85 if (ret < 0) 86 return ret; 87 88 return (buf_rx[0] << 8) | buf_rx[1]; 89 } 90 91 static int read24(void *client, u8 reg) 92 { 93 int ret; 94 u8 buf_rx[3]; 95 96 write24(client, reg, 0); 97 ret = spi_read(client, buf_rx, 3); 98 if (ret < 0) 99 return ret; 100 101 return (buf_rx[1] << 8) | buf_rx[2]; 102 } 103 104 static const struct ad_dpot_bus_ops bops = { 105 .read_d8 = read8, 106 .read_r8d8 = read16, 107 .read_r8d16 = read24, 108 .write_d8 = write8, 109 .write_r8d8 = write16, 110 .write_r8d16 = write24, 111 }; 112 113 static const struct ad_dpot_id *dpot_match_id(const struct ad_dpot_id *id, 114 char *name) 115 { 116 while (id->name && id->name[0]) { 117 if (strcmp(name, id->name) == 0) 118 return id; 119 id++; 120 } 121 return NULL; 122 } 123 124 static int __devinit ad_dpot_spi_probe(struct spi_device *spi) 125 { 126 char *name = spi->dev.platform_data; 127 const struct ad_dpot_id *dpot_id; 128 129 struct ad_dpot_bus_data bdata = { 130 .client = spi, 131 .bops = &bops, 132 }; 133 134 dpot_id = dpot_match_id(ad_dpot_spi_devlist, name); 135 136 if (dpot_id == NULL) { 137 dev_err(&spi->dev, "%s not in supported device list", name); 138 return -ENODEV; 139 } 140 141 return ad_dpot_probe(&spi->dev, &bdata, dpot_id); 142 } 143 144 static int __devexit ad_dpot_spi_remove(struct spi_device *spi) 145 { 146 return ad_dpot_remove(&spi->dev); 147 } 148 149 static struct spi_driver ad_dpot_spi_driver = { 150 .driver = { 151 .name = "ad_dpot", 152 .bus = &spi_bus_type, 153 .owner = THIS_MODULE, 154 }, 155 .probe = ad_dpot_spi_probe, 156 .remove = __devexit_p(ad_dpot_spi_remove), 157 }; 158 159 static int __init ad_dpot_spi_init(void) 160 { 161 return spi_register_driver(&ad_dpot_spi_driver); 162 } 163 module_init(ad_dpot_spi_init); 164 165 static void __exit ad_dpot_spi_exit(void) 166 { 167 spi_unregister_driver(&ad_dpot_spi_driver); 168 } 169 module_exit(ad_dpot_spi_exit); 170 171 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 172 MODULE_DESCRIPTION("digital potentiometer SPI bus driver"); 173 MODULE_LICENSE("GPL"); 174 MODULE_ALIAS("spi:ad_dpot"); 175