1 /* 2 * Register map access API - I2C support 3 * 4 * Copyright 2011 Wolfson Microelectronics plc 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13 #include <linux/regmap.h> 14 #include <linux/i2c.h> 15 #include <linux/module.h> 16 #include <linux/init.h> 17 18 static int regmap_i2c_write(struct device *dev, const void *data, size_t count) 19 { 20 struct i2c_client *i2c = to_i2c_client(dev); 21 int ret; 22 23 ret = i2c_master_send(i2c, data, count); 24 if (ret == count) 25 return 0; 26 else if (ret < 0) 27 return ret; 28 else 29 return -EIO; 30 } 31 32 static int regmap_i2c_gather_write(struct device *dev, 33 const void *reg, size_t reg_size, 34 const void *val, size_t val_size) 35 { 36 struct i2c_client *i2c = to_i2c_client(dev); 37 struct i2c_msg xfer[2]; 38 int ret; 39 40 /* If the I2C controller can't do a gather tell the core, it 41 * will substitute in a linear write for us. 42 */ 43 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_PROTOCOL_MANGLING)) 44 return -ENOTSUPP; 45 46 xfer[0].addr = i2c->addr; 47 xfer[0].flags = 0; 48 xfer[0].len = reg_size; 49 xfer[0].buf = (void *)reg; 50 51 xfer[1].addr = i2c->addr; 52 xfer[1].flags = I2C_M_NOSTART; 53 xfer[1].len = val_size; 54 xfer[1].buf = (void *)val; 55 56 ret = i2c_transfer(i2c->adapter, xfer, 2); 57 if (ret == 2) 58 return 0; 59 if (ret < 0) 60 return ret; 61 else 62 return -EIO; 63 } 64 65 static int regmap_i2c_read(struct device *dev, 66 const void *reg, size_t reg_size, 67 void *val, size_t val_size) 68 { 69 struct i2c_client *i2c = to_i2c_client(dev); 70 struct i2c_msg xfer[2]; 71 int ret; 72 73 xfer[0].addr = i2c->addr; 74 xfer[0].flags = 0; 75 xfer[0].len = reg_size; 76 xfer[0].buf = (void *)reg; 77 78 xfer[1].addr = i2c->addr; 79 xfer[1].flags = I2C_M_RD; 80 xfer[1].len = val_size; 81 xfer[1].buf = val; 82 83 ret = i2c_transfer(i2c->adapter, xfer, 2); 84 if (ret == 2) 85 return 0; 86 else if (ret < 0) 87 return ret; 88 else 89 return -EIO; 90 } 91 92 static struct regmap_bus regmap_i2c = { 93 .type = &i2c_bus_type, 94 .write = regmap_i2c_write, 95 .gather_write = regmap_i2c_gather_write, 96 .read = regmap_i2c_read, 97 .owner = THIS_MODULE, 98 }; 99 100 /** 101 * regmap_init_i2c(): Initialise register map 102 * 103 * @i2c: Device that will be interacted with 104 * @config: Configuration for register map 105 * 106 * The return value will be an ERR_PTR() on error or a valid pointer to 107 * a struct regmap. 108 */ 109 struct regmap *regmap_init_i2c(struct i2c_client *i2c, 110 const struct regmap_config *config) 111 { 112 return regmap_init(&i2c->dev, ®map_i2c, config); 113 } 114 EXPORT_SYMBOL_GPL(regmap_init_i2c); 115 116 MODULE_LICENSE("GPL"); 117