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 {} 42 }; 43 44 /* ------------------------------------------------------------------------- */ 45 46 /* SPI bus functions */ 47 static int write8(void *client, u8 val) 48 { 49 u8 data = val; 50 return spi_write(client, &data, 1); 51 } 52 53 static int write16(void *client, u8 reg, u8 val) 54 { 55 u8 data[2] = {reg, val}; 56 return spi_write(client, data, 1); 57 } 58 59 static int write24(void *client, u8 reg, u16 val) 60 { 61 u8 data[3] = {reg, val >> 8, val}; 62 return spi_write(client, data, 1); 63 } 64 65 static int read8(void *client) 66 { 67 int ret; 68 u8 data; 69 ret = spi_read(client, &data, 1); 70 if (ret < 0) 71 return ret; 72 73 return data; 74 } 75 76 static int read16(void *client, u8 reg) 77 { 78 int ret; 79 u8 buf_rx[2]; 80 81 write16(client, reg, 0); 82 ret = spi_read(client, buf_rx, 2); 83 if (ret < 0) 84 return ret; 85 86 return (buf_rx[0] << 8) | buf_rx[1]; 87 } 88 89 static int read24(void *client, u8 reg) 90 { 91 int ret; 92 u8 buf_rx[3]; 93 94 write24(client, reg, 0); 95 ret = spi_read(client, buf_rx, 3); 96 if (ret < 0) 97 return ret; 98 99 return (buf_rx[1] << 8) | buf_rx[2]; 100 } 101 102 static const struct ad_dpot_bus_ops bops = { 103 .read_d8 = read8, 104 .read_r8d8 = read16, 105 .read_r8d16 = read24, 106 .write_d8 = write8, 107 .write_r8d8 = write16, 108 .write_r8d16 = write24, 109 }; 110 111 static const struct ad_dpot_id *dpot_match_id(const struct ad_dpot_id *id, 112 char *name) 113 { 114 while (id->name && id->name[0]) { 115 if (strcmp(name, id->name) == 0) 116 return id; 117 id++; 118 } 119 return NULL; 120 } 121 122 static int __devinit ad_dpot_spi_probe(struct spi_device *spi) 123 { 124 char *name = spi->dev.platform_data; 125 const struct ad_dpot_id *dpot_id; 126 127 struct ad_dpot_bus_data bdata = { 128 .client = spi, 129 .bops = &bops, 130 }; 131 132 dpot_id = dpot_match_id(ad_dpot_spi_devlist, name); 133 134 if (dpot_id == NULL) { 135 dev_err(&spi->dev, "%s not in supported device list", name); 136 return -ENODEV; 137 } 138 139 return ad_dpot_probe(&spi->dev, &bdata, dpot_id); 140 } 141 142 static int __devexit ad_dpot_spi_remove(struct spi_device *spi) 143 { 144 return ad_dpot_remove(&spi->dev); 145 } 146 147 static struct spi_driver ad_dpot_spi_driver = { 148 .driver = { 149 .name = "ad_dpot", 150 .bus = &spi_bus_type, 151 .owner = THIS_MODULE, 152 }, 153 .probe = ad_dpot_spi_probe, 154 .remove = __devexit_p(ad_dpot_spi_remove), 155 }; 156 157 static int __init ad_dpot_spi_init(void) 158 { 159 return spi_register_driver(&ad_dpot_spi_driver); 160 } 161 module_init(ad_dpot_spi_init); 162 163 static void __exit ad_dpot_spi_exit(void) 164 { 165 spi_unregister_driver(&ad_dpot_spi_driver); 166 } 167 module_exit(ad_dpot_spi_exit); 168 169 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); 170 MODULE_DESCRIPTION("digital potentiometer SPI bus driver"); 171 MODULE_LICENSE("GPL"); 172 MODULE_ALIAS("spi:ad_dpot"); 173