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(void *context, const void *data, size_t count) 19 { 20 struct device *dev = context; 21 struct i2c_client *i2c = to_i2c_client(dev); 22 int ret; 23 24 ret = i2c_master_send(i2c, data, count); 25 if (ret == count) 26 return 0; 27 else if (ret < 0) 28 return ret; 29 else 30 return -EIO; 31 } 32 33 static int regmap_i2c_gather_write(void *context, 34 const void *reg, size_t reg_size, 35 const void *val, size_t val_size) 36 { 37 struct device *dev = context; 38 struct i2c_client *i2c = to_i2c_client(dev); 39 struct i2c_msg xfer[2]; 40 int ret; 41 42 /* If the I2C controller can't do a gather tell the core, it 43 * will substitute in a linear write for us. 44 */ 45 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_NOSTART)) 46 return -ENOTSUPP; 47 48 xfer[0].addr = i2c->addr; 49 xfer[0].flags = 0; 50 xfer[0].len = reg_size; 51 xfer[0].buf = (void *)reg; 52 53 xfer[1].addr = i2c->addr; 54 xfer[1].flags = I2C_M_NOSTART; 55 xfer[1].len = val_size; 56 xfer[1].buf = (void *)val; 57 58 ret = i2c_transfer(i2c->adapter, xfer, 2); 59 if (ret == 2) 60 return 0; 61 if (ret < 0) 62 return ret; 63 else 64 return -EIO; 65 } 66 67 static int regmap_i2c_read(void *context, 68 const void *reg, size_t reg_size, 69 void *val, size_t val_size) 70 { 71 struct device *dev = context; 72 struct i2c_client *i2c = to_i2c_client(dev); 73 struct i2c_msg xfer[2]; 74 int ret; 75 76 xfer[0].addr = i2c->addr; 77 xfer[0].flags = 0; 78 xfer[0].len = reg_size; 79 xfer[0].buf = (void *)reg; 80 81 xfer[1].addr = i2c->addr; 82 xfer[1].flags = I2C_M_RD; 83 xfer[1].len = val_size; 84 xfer[1].buf = val; 85 86 ret = i2c_transfer(i2c->adapter, xfer, 2); 87 if (ret == 2) 88 return 0; 89 else if (ret < 0) 90 return ret; 91 else 92 return -EIO; 93 } 94 95 static struct regmap_bus regmap_i2c = { 96 .write = regmap_i2c_write, 97 .gather_write = regmap_i2c_gather_write, 98 .read = regmap_i2c_read, 99 }; 100 101 /** 102 * regmap_init_i2c(): Initialise register map 103 * 104 * @i2c: Device that will be interacted with 105 * @config: Configuration for register map 106 * 107 * The return value will be an ERR_PTR() on error or a valid pointer to 108 * a struct regmap. 109 */ 110 struct regmap *regmap_init_i2c(struct i2c_client *i2c, 111 const struct regmap_config *config) 112 { 113 return regmap_init(&i2c->dev, ®map_i2c, &i2c->dev, config); 114 } 115 EXPORT_SYMBOL_GPL(regmap_init_i2c); 116 117 /** 118 * devm_regmap_init_i2c(): Initialise managed register map 119 * 120 * @i2c: Device that will be interacted with 121 * @config: Configuration for register map 122 * 123 * The return value will be an ERR_PTR() on error or a valid pointer 124 * to a struct regmap. The regmap will be automatically freed by the 125 * device management code. 126 */ 127 struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, 128 const struct regmap_config *config) 129 { 130 return devm_regmap_init(&i2c->dev, ®map_i2c, &i2c->dev, config); 131 } 132 EXPORT_SYMBOL_GPL(devm_regmap_init_i2c); 133 134 MODULE_LICENSE("GPL"); 135