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