1/* 2 * ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver (I2C Bus) 3 * 4 * Copyright 2010 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later. 7 */ 8 9#include <linux/device.h> 10#include <linux/kernel.h> 11#include <linux/i2c.h> 12#include <linux/slab.h> 13#include <linux/module.h> 14 15#include <linux/iio/iio.h> 16#include "ade7854.h" 17 18static int ade7854_i2c_write_reg_8(struct device *dev, 19 u16 reg_address, 20 u8 value) 21{ 22 int ret; 23 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 24 struct ade7854_state *st = iio_priv(indio_dev); 25 26 mutex_lock(&st->buf_lock); 27 st->tx[0] = (reg_address >> 8) & 0xFF; 28 st->tx[1] = reg_address & 0xFF; 29 st->tx[2] = value; 30 31 ret = i2c_master_send(st->i2c, st->tx, 3); 32 mutex_unlock(&st->buf_lock); 33 34 return ret; 35} 36 37static int ade7854_i2c_write_reg_16(struct device *dev, 38 u16 reg_address, 39 u16 value) 40{ 41 int ret; 42 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 43 struct ade7854_state *st = iio_priv(indio_dev); 44 45 mutex_lock(&st->buf_lock); 46 st->tx[0] = (reg_address >> 8) & 0xFF; 47 st->tx[1] = reg_address & 0xFF; 48 st->tx[2] = (value >> 8) & 0xFF; 49 st->tx[3] = value & 0xFF; 50 51 ret = i2c_master_send(st->i2c, st->tx, 4); 52 mutex_unlock(&st->buf_lock); 53 54 return ret; 55} 56 57static int ade7854_i2c_write_reg_24(struct device *dev, 58 u16 reg_address, 59 u32 value) 60{ 61 int ret; 62 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 63 struct ade7854_state *st = iio_priv(indio_dev); 64 65 mutex_lock(&st->buf_lock); 66 st->tx[0] = (reg_address >> 8) & 0xFF; 67 st->tx[1] = reg_address & 0xFF; 68 st->tx[2] = (value >> 16) & 0xFF; 69 st->tx[3] = (value >> 8) & 0xFF; 70 st->tx[4] = value & 0xFF; 71 72 ret = i2c_master_send(st->i2c, st->tx, 5); 73 mutex_unlock(&st->buf_lock); 74 75 return ret; 76} 77 78static int ade7854_i2c_write_reg_32(struct device *dev, 79 u16 reg_address, 80 u32 value) 81{ 82 int ret; 83 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 84 struct ade7854_state *st = iio_priv(indio_dev); 85 86 mutex_lock(&st->buf_lock); 87 st->tx[0] = (reg_address >> 8) & 0xFF; 88 st->tx[1] = reg_address & 0xFF; 89 st->tx[2] = (value >> 24) & 0xFF; 90 st->tx[3] = (value >> 16) & 0xFF; 91 st->tx[4] = (value >> 8) & 0xFF; 92 st->tx[5] = value & 0xFF; 93 94 ret = i2c_master_send(st->i2c, st->tx, 6); 95 mutex_unlock(&st->buf_lock); 96 97 return ret; 98} 99 100static int ade7854_i2c_read_reg_8(struct device *dev, 101 u16 reg_address, 102 u8 *val) 103{ 104 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 105 struct ade7854_state *st = iio_priv(indio_dev); 106 int ret; 107 108 mutex_lock(&st->buf_lock); 109 st->tx[0] = (reg_address >> 8) & 0xFF; 110 st->tx[1] = reg_address & 0xFF; 111 112 ret = i2c_master_send(st->i2c, st->tx, 2); 113 if (ret) 114 goto out; 115 116 ret = i2c_master_recv(st->i2c, st->rx, 1); 117 if (ret) 118 goto out; 119 120 *val = st->rx[0]; 121out: 122 mutex_unlock(&st->buf_lock); 123 return ret; 124} 125 126static int ade7854_i2c_read_reg_16(struct device *dev, 127 u16 reg_address, 128 u16 *val) 129{ 130 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 131 struct ade7854_state *st = iio_priv(indio_dev); 132 int ret; 133 134 mutex_lock(&st->buf_lock); 135 st->tx[0] = (reg_address >> 8) & 0xFF; 136 st->tx[1] = reg_address & 0xFF; 137 138 ret = i2c_master_send(st->i2c, st->tx, 2); 139 if (ret) 140 goto out; 141 142 ret = i2c_master_recv(st->i2c, st->rx, 2); 143 if (ret) 144 goto out; 145 146 *val = (st->rx[0] << 8) | st->rx[1]; 147out: 148 mutex_unlock(&st->buf_lock); 149 return ret; 150} 151 152static int ade7854_i2c_read_reg_24(struct device *dev, 153 u16 reg_address, 154 u32 *val) 155{ 156 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 157 struct ade7854_state *st = iio_priv(indio_dev); 158 int ret; 159 160 mutex_lock(&st->buf_lock); 161 st->tx[0] = (reg_address >> 8) & 0xFF; 162 st->tx[1] = reg_address & 0xFF; 163 164 ret = i2c_master_send(st->i2c, st->tx, 2); 165 if (ret) 166 goto out; 167 168 ret = i2c_master_recv(st->i2c, st->rx, 3); 169 if (ret) 170 goto out; 171 172 *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2]; 173out: 174 mutex_unlock(&st->buf_lock); 175 return ret; 176} 177 178static int ade7854_i2c_read_reg_32(struct device *dev, 179 u16 reg_address, 180 u32 *val) 181{ 182 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 183 struct ade7854_state *st = iio_priv(indio_dev); 184 int ret; 185 186 mutex_lock(&st->buf_lock); 187 st->tx[0] = (reg_address >> 8) & 0xFF; 188 st->tx[1] = reg_address & 0xFF; 189 190 ret = i2c_master_send(st->i2c, st->tx, 2); 191 if (ret) 192 goto out; 193 194 ret = i2c_master_recv(st->i2c, st->rx, 3); 195 if (ret) 196 goto out; 197 198 *val = (st->rx[0] << 24) | (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3]; 199out: 200 mutex_unlock(&st->buf_lock); 201 return ret; 202} 203 204static int ade7854_i2c_probe(struct i2c_client *client, 205 const struct i2c_device_id *id) 206{ 207 int ret; 208 struct ade7854_state *st; 209 struct iio_dev *indio_dev; 210 211 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); 212 if (indio_dev == NULL) 213 return -ENOMEM; 214 st = iio_priv(indio_dev); 215 i2c_set_clientdata(client, indio_dev); 216 st->read_reg_8 = ade7854_i2c_read_reg_8; 217 st->read_reg_16 = ade7854_i2c_read_reg_16; 218 st->read_reg_24 = ade7854_i2c_read_reg_24; 219 st->read_reg_32 = ade7854_i2c_read_reg_32; 220 st->write_reg_8 = ade7854_i2c_write_reg_8; 221 st->write_reg_16 = ade7854_i2c_write_reg_16; 222 st->write_reg_24 = ade7854_i2c_write_reg_24; 223 st->write_reg_32 = ade7854_i2c_write_reg_32; 224 st->i2c = client; 225 st->irq = client->irq; 226 227 ret = ade7854_probe(indio_dev, &client->dev); 228 229 return ret; 230} 231 232static int ade7854_i2c_remove(struct i2c_client *client) 233{ 234 return ade7854_remove(i2c_get_clientdata(client)); 235} 236 237static const struct i2c_device_id ade7854_id[] = { 238 { "ade7854", 0 }, 239 { "ade7858", 0 }, 240 { "ade7868", 0 }, 241 { "ade7878", 0 }, 242 { } 243}; 244MODULE_DEVICE_TABLE(i2c, ade7854_id); 245 246static struct i2c_driver ade7854_i2c_driver = { 247 .driver = { 248 .name = "ade7854", 249 }, 250 .probe = ade7854_i2c_probe, 251 .remove = ade7854_i2c_remove, 252 .id_table = ade7854_id, 253}; 254module_i2c_driver(ade7854_i2c_driver); 255 256MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 257MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC I2C Driver"); 258MODULE_LICENSE("GPL v2"); 259