diff options
| -rw-r--r-- | drivers/base/regmap/regcache-rbtree.c | 8 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap-i2c.c | 104 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap-irq.c | 9 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap-mmio.c | 35 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap.c | 83 | ||||
| -rw-r--r-- | include/linux/regmap.h | 6 |
6 files changed, 227 insertions, 18 deletions
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 930cad4e5df8..6a7e4fa12854 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c | |||
| @@ -23,16 +23,16 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, | |||
| 23 | static int regcache_rbtree_exit(struct regmap *map); | 23 | static int regcache_rbtree_exit(struct regmap *map); |
| 24 | 24 | ||
| 25 | struct regcache_rbtree_node { | 25 | struct regcache_rbtree_node { |
| 26 | /* the actual rbtree node holding this block */ | ||
| 27 | struct rb_node node; | ||
| 28 | /* base register handled by this block */ | ||
| 29 | unsigned int base_reg; | ||
| 30 | /* block of adjacent registers */ | 26 | /* block of adjacent registers */ |
| 31 | void *block; | 27 | void *block; |
| 32 | /* Which registers are present */ | 28 | /* Which registers are present */ |
| 33 | long *cache_present; | 29 | long *cache_present; |
| 30 | /* base register handled by this block */ | ||
| 31 | unsigned int base_reg; | ||
| 34 | /* number of registers available in the block */ | 32 | /* number of registers available in the block */ |
| 35 | unsigned int blklen; | 33 | unsigned int blklen; |
| 34 | /* the actual rbtree node holding this block */ | ||
| 35 | struct rb_node node; | ||
| 36 | } __attribute__ ((packed)); | 36 | } __attribute__ ((packed)); |
| 37 | 37 | ||
| 38 | struct regcache_rbtree_ctx { | 38 | struct regcache_rbtree_ctx { |
diff --git a/drivers/base/regmap/regmap-i2c.c b/drivers/base/regmap/regmap-i2c.c index ebd189529760..ca193d1ef47c 100644 --- a/drivers/base/regmap/regmap-i2c.c +++ b/drivers/base/regmap/regmap-i2c.c | |||
| @@ -14,6 +14,79 @@ | |||
| 14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | 16 | ||
| 17 | |||
| 18 | static int regmap_smbus_byte_reg_read(void *context, unsigned int reg, | ||
| 19 | unsigned int *val) | ||
| 20 | { | ||
| 21 | struct device *dev = context; | ||
| 22 | struct i2c_client *i2c = to_i2c_client(dev); | ||
| 23 | int ret; | ||
| 24 | |||
| 25 | if (reg > 0xff) | ||
| 26 | return -EINVAL; | ||
| 27 | |||
| 28 | ret = i2c_smbus_read_byte_data(i2c, reg); | ||
| 29 | if (ret < 0) | ||
| 30 | return ret; | ||
| 31 | |||
| 32 | *val = ret; | ||
| 33 | |||
| 34 | return 0; | ||
| 35 | } | ||
| 36 | |||
| 37 | static int regmap_smbus_byte_reg_write(void *context, unsigned int reg, | ||
| 38 | unsigned int val) | ||
| 39 | { | ||
| 40 | struct device *dev = context; | ||
| 41 | struct i2c_client *i2c = to_i2c_client(dev); | ||
| 42 | |||
| 43 | if (val > 0xff || reg > 0xff) | ||
| 44 | return -EINVAL; | ||
| 45 | |||
| 46 | return i2c_smbus_write_byte_data(i2c, reg, val); | ||
| 47 | } | ||
| 48 | |||
| 49 | static struct regmap_bus regmap_smbus_byte = { | ||
| 50 | .reg_write = regmap_smbus_byte_reg_write, | ||
| 51 | .reg_read = regmap_smbus_byte_reg_read, | ||
| 52 | }; | ||
| 53 | |||
| 54 | static int regmap_smbus_word_reg_read(void *context, unsigned int reg, | ||
| 55 | unsigned int *val) | ||
| 56 | { | ||
| 57 | struct device *dev = context; | ||
| 58 | struct i2c_client *i2c = to_i2c_client(dev); | ||
| 59 | int ret; | ||
| 60 | |||
| 61 | if (reg > 0xff) | ||
| 62 | return -EINVAL; | ||
| 63 | |||
| 64 | ret = i2c_smbus_read_word_data(i2c, reg); | ||
| 65 | if (ret < 0) | ||
| 66 | return ret; | ||
| 67 | |||
| 68 | *val = ret; | ||
| 69 | |||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | static int regmap_smbus_word_reg_write(void *context, unsigned int reg, | ||
| 74 | unsigned int val) | ||
| 75 | { | ||
| 76 | struct device *dev = context; | ||
| 77 | struct i2c_client *i2c = to_i2c_client(dev); | ||
| 78 | |||
| 79 | if (val > 0xffff || reg > 0xff) | ||
| 80 | return -EINVAL; | ||
| 81 | |||
| 82 | return i2c_smbus_write_word_data(i2c, reg, val); | ||
| 83 | } | ||
| 84 | |||
| 85 | static struct regmap_bus regmap_smbus_word = { | ||
| 86 | .reg_write = regmap_smbus_word_reg_write, | ||
| 87 | .reg_read = regmap_smbus_word_reg_read, | ||
| 88 | }; | ||
| 89 | |||
| 17 | static int regmap_i2c_write(void *context, const void *data, size_t count) | 90 | static int regmap_i2c_write(void *context, const void *data, size_t count) |
| 18 | { | 91 | { |
| 19 | struct device *dev = context; | 92 | struct device *dev = context; |
| @@ -97,6 +170,23 @@ static struct regmap_bus regmap_i2c = { | |||
| 97 | .read = regmap_i2c_read, | 170 | .read = regmap_i2c_read, |
| 98 | }; | 171 | }; |
| 99 | 172 | ||
| 173 | static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c, | ||
| 174 | const struct regmap_config *config) | ||
| 175 | { | ||
| 176 | if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) | ||
| 177 | return ®map_i2c; | ||
| 178 | else if (config->val_bits == 16 && config->reg_bits == 8 && | ||
| 179 | i2c_check_functionality(i2c->adapter, | ||
| 180 | I2C_FUNC_SMBUS_WORD_DATA)) | ||
| 181 | return ®map_smbus_word; | ||
| 182 | else if (config->val_bits == 8 && config->reg_bits == 8 && | ||
| 183 | i2c_check_functionality(i2c->adapter, | ||
| 184 | I2C_FUNC_SMBUS_BYTE_DATA)) | ||
| 185 | return ®map_smbus_byte; | ||
| 186 | |||
| 187 | return ERR_PTR(-ENOTSUPP); | ||
| 188 | } | ||
| 189 | |||
| 100 | /** | 190 | /** |
| 101 | * regmap_init_i2c(): Initialise register map | 191 | * regmap_init_i2c(): Initialise register map |
| 102 | * | 192 | * |
| @@ -109,7 +199,12 @@ static struct regmap_bus regmap_i2c = { | |||
| 109 | struct regmap *regmap_init_i2c(struct i2c_client *i2c, | 199 | struct regmap *regmap_init_i2c(struct i2c_client *i2c, |
| 110 | const struct regmap_config *config) | 200 | const struct regmap_config *config) |
| 111 | { | 201 | { |
| 112 | return regmap_init(&i2c->dev, ®map_i2c, &i2c->dev, config); | 202 | const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config); |
| 203 | |||
| 204 | if (IS_ERR(bus)) | ||
| 205 | return ERR_CAST(bus); | ||
| 206 | |||
| 207 | return regmap_init(&i2c->dev, bus, &i2c->dev, config); | ||
| 113 | } | 208 | } |
| 114 | EXPORT_SYMBOL_GPL(regmap_init_i2c); | 209 | EXPORT_SYMBOL_GPL(regmap_init_i2c); |
| 115 | 210 | ||
| @@ -126,7 +221,12 @@ EXPORT_SYMBOL_GPL(regmap_init_i2c); | |||
| 126 | struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, | 221 | struct regmap *devm_regmap_init_i2c(struct i2c_client *i2c, |
| 127 | const struct regmap_config *config) | 222 | const struct regmap_config *config) |
| 128 | { | 223 | { |
| 129 | return devm_regmap_init(&i2c->dev, ®map_i2c, &i2c->dev, config); | 224 | const struct regmap_bus *bus = regmap_get_i2c_bus(i2c, config); |
| 225 | |||
| 226 | if (IS_ERR(bus)) | ||
| 227 | return ERR_CAST(bus); | ||
| 228 | |||
| 229 | return devm_regmap_init(&i2c->dev, bus, &i2c->dev, config); | ||
| 130 | } | 230 | } |
| 131 | EXPORT_SYMBOL_GPL(devm_regmap_init_i2c); | 231 | EXPORT_SYMBOL_GPL(devm_regmap_init_i2c); |
| 132 | 232 | ||
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index edf88f20cbce..6299a50a5960 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c | |||
| @@ -10,13 +10,13 @@ | |||
| 10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/export.h> | ||
| 14 | #include <linux/device.h> | 13 | #include <linux/device.h> |
| 15 | #include <linux/regmap.h> | 14 | #include <linux/export.h> |
| 16 | #include <linux/irq.h> | ||
| 17 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 16 | #include <linux/irq.h> | ||
| 18 | #include <linux/irqdomain.h> | 17 | #include <linux/irqdomain.h> |
| 19 | #include <linux/pm_runtime.h> | 18 | #include <linux/pm_runtime.h> |
| 19 | #include <linux/regmap.h> | ||
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | 21 | ||
| 22 | #include "internal.h" | 22 | #include "internal.h" |
| @@ -347,6 +347,9 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, | |||
| 347 | int ret = -ENOMEM; | 347 | int ret = -ENOMEM; |
| 348 | u32 reg; | 348 | u32 reg; |
| 349 | 349 | ||
| 350 | if (chip->num_regs <= 0) | ||
| 351 | return -EINVAL; | ||
| 352 | |||
| 350 | for (i = 0; i < chip->num_irqs; i++) { | 353 | for (i = 0; i < chip->num_irqs; i++) { |
| 351 | if (chip->irqs[i].reg_offset % map->reg_stride) | 354 | if (chip->irqs[i].reg_offset % map->reg_stride) |
| 352 | return -EINVAL; | 355 | return -EINVAL; |
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 1e03e7f8bacb..04a329a377e9 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c | |||
| @@ -61,9 +61,28 @@ static int regmap_mmio_regbits_check(size_t reg_bits) | |||
| 61 | } | 61 | } |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static inline void regmap_mmio_count_check(size_t count) | 64 | static inline void regmap_mmio_count_check(size_t count, u32 offset) |
| 65 | { | 65 | { |
| 66 | BUG_ON(count % 2 != 0); | 66 | BUG_ON(count <= offset); |
| 67 | } | ||
| 68 | |||
| 69 | static inline unsigned int | ||
| 70 | regmap_mmio_get_offset(const void *reg, size_t reg_size) | ||
| 71 | { | ||
| 72 | switch (reg_size) { | ||
| 73 | case 1: | ||
| 74 | return *(u8 *)reg; | ||
| 75 | case 2: | ||
| 76 | return *(u16 *)reg; | ||
| 77 | case 4: | ||
| 78 | return *(u32 *)reg; | ||
| 79 | #ifdef CONFIG_64BIT | ||
| 80 | case 8: | ||
| 81 | return *(u64 *)reg; | ||
| 82 | #endif | ||
| 83 | default: | ||
| 84 | BUG(); | ||
| 85 | } | ||
| 67 | } | 86 | } |
| 68 | 87 | ||
| 69 | static int regmap_mmio_gather_write(void *context, | 88 | static int regmap_mmio_gather_write(void *context, |
| @@ -71,7 +90,7 @@ static int regmap_mmio_gather_write(void *context, | |||
| 71 | const void *val, size_t val_size) | 90 | const void *val, size_t val_size) |
| 72 | { | 91 | { |
| 73 | struct regmap_mmio_context *ctx = context; | 92 | struct regmap_mmio_context *ctx = context; |
| 74 | u32 offset; | 93 | unsigned int offset; |
| 75 | int ret; | 94 | int ret; |
| 76 | 95 | ||
| 77 | regmap_mmio_regsize_check(reg_size); | 96 | regmap_mmio_regsize_check(reg_size); |
| @@ -82,7 +101,7 @@ static int regmap_mmio_gather_write(void *context, | |||
| 82 | return ret; | 101 | return ret; |
| 83 | } | 102 | } |
| 84 | 103 | ||
| 85 | offset = *(u32 *)reg; | 104 | offset = regmap_mmio_get_offset(reg, reg_size); |
| 86 | 105 | ||
| 87 | while (val_size) { | 106 | while (val_size) { |
| 88 | switch (ctx->val_bytes) { | 107 | switch (ctx->val_bytes) { |
| @@ -118,9 +137,9 @@ static int regmap_mmio_gather_write(void *context, | |||
| 118 | static int regmap_mmio_write(void *context, const void *data, size_t count) | 137 | static int regmap_mmio_write(void *context, const void *data, size_t count) |
| 119 | { | 138 | { |
| 120 | struct regmap_mmio_context *ctx = context; | 139 | struct regmap_mmio_context *ctx = context; |
| 121 | u32 offset = ctx->reg_bytes + ctx->pad_bytes; | 140 | unsigned int offset = ctx->reg_bytes + ctx->pad_bytes; |
| 122 | 141 | ||
| 123 | regmap_mmio_count_check(count); | 142 | regmap_mmio_count_check(count, offset); |
| 124 | 143 | ||
| 125 | return regmap_mmio_gather_write(context, data, ctx->reg_bytes, | 144 | return regmap_mmio_gather_write(context, data, ctx->reg_bytes, |
| 126 | data + offset, count - offset); | 145 | data + offset, count - offset); |
| @@ -131,7 +150,7 @@ static int regmap_mmio_read(void *context, | |||
| 131 | void *val, size_t val_size) | 150 | void *val, size_t val_size) |
| 132 | { | 151 | { |
| 133 | struct regmap_mmio_context *ctx = context; | 152 | struct regmap_mmio_context *ctx = context; |
| 134 | u32 offset; | 153 | unsigned int offset; |
| 135 | int ret; | 154 | int ret; |
| 136 | 155 | ||
| 137 | regmap_mmio_regsize_check(reg_size); | 156 | regmap_mmio_regsize_check(reg_size); |
| @@ -142,7 +161,7 @@ static int regmap_mmio_read(void *context, | |||
| 142 | return ret; | 161 | return ret; |
| 143 | } | 162 | } |
| 144 | 163 | ||
| 145 | offset = *(u32 *)reg; | 164 | offset = regmap_mmio_get_offset(reg, reg_size); |
| 146 | 165 | ||
| 147 | while (val_size) { | 166 | while (val_size) { |
| 148 | switch (ctx->val_bytes) { | 167 | switch (ctx->val_bytes) { |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 63e30ef096e2..74d8c0672cf6 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
| @@ -35,10 +35,14 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, | |||
| 35 | unsigned int mask, unsigned int val, | 35 | unsigned int mask, unsigned int val, |
| 36 | bool *change); | 36 | bool *change); |
| 37 | 37 | ||
| 38 | static int _regmap_bus_reg_read(void *context, unsigned int reg, | ||
| 39 | unsigned int *val); | ||
| 38 | static int _regmap_bus_read(void *context, unsigned int reg, | 40 | static int _regmap_bus_read(void *context, unsigned int reg, |
| 39 | unsigned int *val); | 41 | unsigned int *val); |
| 40 | static int _regmap_bus_formatted_write(void *context, unsigned int reg, | 42 | static int _regmap_bus_formatted_write(void *context, unsigned int reg, |
| 41 | unsigned int val); | 43 | unsigned int val); |
| 44 | static int _regmap_bus_reg_write(void *context, unsigned int reg, | ||
| 45 | unsigned int val); | ||
| 42 | static int _regmap_bus_raw_write(void *context, unsigned int reg, | 46 | static int _regmap_bus_raw_write(void *context, unsigned int reg, |
| 43 | unsigned int val); | 47 | unsigned int val); |
| 44 | 48 | ||
| @@ -192,6 +196,13 @@ static void regmap_format_16_be(void *buf, unsigned int val, unsigned int shift) | |||
| 192 | b[0] = cpu_to_be16(val << shift); | 196 | b[0] = cpu_to_be16(val << shift); |
| 193 | } | 197 | } |
| 194 | 198 | ||
| 199 | static void regmap_format_16_le(void *buf, unsigned int val, unsigned int shift) | ||
| 200 | { | ||
| 201 | __le16 *b = buf; | ||
| 202 | |||
| 203 | b[0] = cpu_to_le16(val << shift); | ||
| 204 | } | ||
| 205 | |||
| 195 | static void regmap_format_16_native(void *buf, unsigned int val, | 206 | static void regmap_format_16_native(void *buf, unsigned int val, |
| 196 | unsigned int shift) | 207 | unsigned int shift) |
| 197 | { | 208 | { |
| @@ -216,6 +227,13 @@ static void regmap_format_32_be(void *buf, unsigned int val, unsigned int shift) | |||
| 216 | b[0] = cpu_to_be32(val << shift); | 227 | b[0] = cpu_to_be32(val << shift); |
| 217 | } | 228 | } |
| 218 | 229 | ||
| 230 | static void regmap_format_32_le(void *buf, unsigned int val, unsigned int shift) | ||
| 231 | { | ||
| 232 | __le32 *b = buf; | ||
| 233 | |||
| 234 | b[0] = cpu_to_le32(val << shift); | ||
| 235 | } | ||
| 236 | |||
| 219 | static void regmap_format_32_native(void *buf, unsigned int val, | 237 | static void regmap_format_32_native(void *buf, unsigned int val, |
| 220 | unsigned int shift) | 238 | unsigned int shift) |
| 221 | { | 239 | { |
| @@ -240,6 +258,13 @@ static unsigned int regmap_parse_16_be(const void *buf) | |||
| 240 | return be16_to_cpu(b[0]); | 258 | return be16_to_cpu(b[0]); |
| 241 | } | 259 | } |
| 242 | 260 | ||
| 261 | static unsigned int regmap_parse_16_le(const void *buf) | ||
| 262 | { | ||
| 263 | const __le16 *b = buf; | ||
| 264 | |||
| 265 | return le16_to_cpu(b[0]); | ||
| 266 | } | ||
| 267 | |||
| 243 | static void regmap_parse_16_be_inplace(void *buf) | 268 | static void regmap_parse_16_be_inplace(void *buf) |
| 244 | { | 269 | { |
| 245 | __be16 *b = buf; | 270 | __be16 *b = buf; |
| @@ -247,6 +272,13 @@ static void regmap_parse_16_be_inplace(void *buf) | |||
| 247 | b[0] = be16_to_cpu(b[0]); | 272 | b[0] = be16_to_cpu(b[0]); |
| 248 | } | 273 | } |
| 249 | 274 | ||
| 275 | static void regmap_parse_16_le_inplace(void *buf) | ||
| 276 | { | ||
| 277 | __le16 *b = buf; | ||
| 278 | |||
| 279 | b[0] = le16_to_cpu(b[0]); | ||
| 280 | } | ||
| 281 | |||
| 250 | static unsigned int regmap_parse_16_native(const void *buf) | 282 | static unsigned int regmap_parse_16_native(const void *buf) |
| 251 | { | 283 | { |
| 252 | return *(u16 *)buf; | 284 | return *(u16 *)buf; |
| @@ -269,6 +301,13 @@ static unsigned int regmap_parse_32_be(const void *buf) | |||
| 269 | return be32_to_cpu(b[0]); | 301 | return be32_to_cpu(b[0]); |
| 270 | } | 302 | } |
| 271 | 303 | ||
| 304 | static unsigned int regmap_parse_32_le(const void *buf) | ||
| 305 | { | ||
| 306 | const __le32 *b = buf; | ||
| 307 | |||
| 308 | return le32_to_cpu(b[0]); | ||
| 309 | } | ||
| 310 | |||
| 272 | static void regmap_parse_32_be_inplace(void *buf) | 311 | static void regmap_parse_32_be_inplace(void *buf) |
| 273 | { | 312 | { |
| 274 | __be32 *b = buf; | 313 | __be32 *b = buf; |
| @@ -276,6 +315,13 @@ static void regmap_parse_32_be_inplace(void *buf) | |||
| 276 | b[0] = be32_to_cpu(b[0]); | 315 | b[0] = be32_to_cpu(b[0]); |
| 277 | } | 316 | } |
| 278 | 317 | ||
| 318 | static void regmap_parse_32_le_inplace(void *buf) | ||
| 319 | { | ||
| 320 | __le32 *b = buf; | ||
| 321 | |||
| 322 | b[0] = le32_to_cpu(b[0]); | ||
| 323 | } | ||
| 324 | |||
| 279 | static unsigned int regmap_parse_32_native(const void *buf) | 325 | static unsigned int regmap_parse_32_native(const void *buf) |
| 280 | { | 326 | { |
| 281 | return *(u32 *)buf; | 327 | return *(u32 *)buf; |
| @@ -495,6 +541,12 @@ struct regmap *regmap_init(struct device *dev, | |||
| 495 | 541 | ||
| 496 | map->defer_caching = false; | 542 | map->defer_caching = false; |
| 497 | goto skip_format_initialization; | 543 | goto skip_format_initialization; |
| 544 | } else if (!bus->read || !bus->write) { | ||
| 545 | map->reg_read = _regmap_bus_reg_read; | ||
| 546 | map->reg_write = _regmap_bus_reg_write; | ||
| 547 | |||
| 548 | map->defer_caching = false; | ||
| 549 | goto skip_format_initialization; | ||
| 498 | } else { | 550 | } else { |
| 499 | map->reg_read = _regmap_bus_read; | 551 | map->reg_read = _regmap_bus_read; |
| 500 | } | 552 | } |
| @@ -608,6 +660,11 @@ struct regmap *regmap_init(struct device *dev, | |||
| 608 | map->format.parse_val = regmap_parse_16_be; | 660 | map->format.parse_val = regmap_parse_16_be; |
| 609 | map->format.parse_inplace = regmap_parse_16_be_inplace; | 661 | map->format.parse_inplace = regmap_parse_16_be_inplace; |
| 610 | break; | 662 | break; |
| 663 | case REGMAP_ENDIAN_LITTLE: | ||
| 664 | map->format.format_val = regmap_format_16_le; | ||
| 665 | map->format.parse_val = regmap_parse_16_le; | ||
| 666 | map->format.parse_inplace = regmap_parse_16_le_inplace; | ||
| 667 | break; | ||
| 611 | case REGMAP_ENDIAN_NATIVE: | 668 | case REGMAP_ENDIAN_NATIVE: |
| 612 | map->format.format_val = regmap_format_16_native; | 669 | map->format.format_val = regmap_format_16_native; |
| 613 | map->format.parse_val = regmap_parse_16_native; | 670 | map->format.parse_val = regmap_parse_16_native; |
| @@ -629,6 +686,11 @@ struct regmap *regmap_init(struct device *dev, | |||
| 629 | map->format.parse_val = regmap_parse_32_be; | 686 | map->format.parse_val = regmap_parse_32_be; |
| 630 | map->format.parse_inplace = regmap_parse_32_be_inplace; | 687 | map->format.parse_inplace = regmap_parse_32_be_inplace; |
| 631 | break; | 688 | break; |
| 689 | case REGMAP_ENDIAN_LITTLE: | ||
| 690 | map->format.format_val = regmap_format_32_le; | ||
| 691 | map->format.parse_val = regmap_parse_32_le; | ||
| 692 | map->format.parse_inplace = regmap_parse_32_le_inplace; | ||
| 693 | break; | ||
| 632 | case REGMAP_ENDIAN_NATIVE: | 694 | case REGMAP_ENDIAN_NATIVE: |
| 633 | map->format.format_val = regmap_format_32_native; | 695 | map->format.format_val = regmap_format_32_native; |
| 634 | map->format.parse_val = regmap_parse_32_native; | 696 | map->format.parse_val = regmap_parse_32_native; |
| @@ -1284,6 +1346,14 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg, | |||
| 1284 | return ret; | 1346 | return ret; |
| 1285 | } | 1347 | } |
| 1286 | 1348 | ||
| 1349 | static int _regmap_bus_reg_write(void *context, unsigned int reg, | ||
| 1350 | unsigned int val) | ||
| 1351 | { | ||
| 1352 | struct regmap *map = context; | ||
| 1353 | |||
| 1354 | return map->bus->reg_write(map->bus_context, reg, val); | ||
| 1355 | } | ||
| 1356 | |||
| 1287 | static int _regmap_bus_raw_write(void *context, unsigned int reg, | 1357 | static int _regmap_bus_raw_write(void *context, unsigned int reg, |
| 1288 | unsigned int val) | 1358 | unsigned int val) |
| 1289 | { | 1359 | { |
| @@ -1615,6 +1685,9 @@ static int _regmap_raw_multi_reg_write(struct regmap *map, | |||
| 1615 | size_t pair_size = reg_bytes + pad_bytes + val_bytes; | 1685 | size_t pair_size = reg_bytes + pad_bytes + val_bytes; |
| 1616 | size_t len = pair_size * num_regs; | 1686 | size_t len = pair_size * num_regs; |
| 1617 | 1687 | ||
| 1688 | if (!len) | ||
| 1689 | return -EINVAL; | ||
| 1690 | |||
| 1618 | buf = kzalloc(len, GFP_KERNEL); | 1691 | buf = kzalloc(len, GFP_KERNEL); |
| 1619 | if (!buf) | 1692 | if (!buf) |
| 1620 | return -ENOMEM; | 1693 | return -ENOMEM; |
| @@ -1662,7 +1735,7 @@ static int _regmap_range_multi_paged_reg_write(struct regmap *map, | |||
| 1662 | int ret; | 1735 | int ret; |
| 1663 | int i, n; | 1736 | int i, n; |
| 1664 | struct reg_default *base; | 1737 | struct reg_default *base; |
| 1665 | unsigned int this_page; | 1738 | unsigned int this_page = 0; |
| 1666 | /* | 1739 | /* |
| 1667 | * the set of registers are not neccessarily in order, but | 1740 | * the set of registers are not neccessarily in order, but |
| 1668 | * since the order of write must be preserved this algorithm | 1741 | * since the order of write must be preserved this algorithm |
| @@ -1925,6 +1998,14 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
| 1925 | return ret; | 1998 | return ret; |
| 1926 | } | 1999 | } |
| 1927 | 2000 | ||
| 2001 | static int _regmap_bus_reg_read(void *context, unsigned int reg, | ||
| 2002 | unsigned int *val) | ||
| 2003 | { | ||
| 2004 | struct regmap *map = context; | ||
| 2005 | |||
| 2006 | return map->bus->reg_read(map->bus_context, reg, val); | ||
| 2007 | } | ||
| 2008 | |||
| 1928 | static int _regmap_bus_read(void *context, unsigned int reg, | 2009 | static int _regmap_bus_read(void *context, unsigned int reg, |
| 1929 | unsigned int *val) | 2010 | unsigned int *val) |
| 1930 | { | 2011 | { |
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 85691b9b4fa7..7b0e4b425cdf 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
| @@ -276,6 +276,10 @@ typedef int (*regmap_hw_async_write)(void *context, | |||
| 276 | typedef int (*regmap_hw_read)(void *context, | 276 | typedef int (*regmap_hw_read)(void *context, |
| 277 | const void *reg_buf, size_t reg_size, | 277 | const void *reg_buf, size_t reg_size, |
| 278 | void *val_buf, size_t val_size); | 278 | void *val_buf, size_t val_size); |
| 279 | typedef int (*regmap_hw_reg_read)(void *context, unsigned int reg, | ||
| 280 | unsigned int *val); | ||
| 281 | typedef int (*regmap_hw_reg_write)(void *context, unsigned int reg, | ||
| 282 | unsigned int val); | ||
| 279 | typedef struct regmap_async *(*regmap_hw_async_alloc)(void); | 283 | typedef struct regmap_async *(*regmap_hw_async_alloc)(void); |
| 280 | typedef void (*regmap_hw_free_context)(void *context); | 284 | typedef void (*regmap_hw_free_context)(void *context); |
| 281 | 285 | ||
| @@ -309,7 +313,9 @@ struct regmap_bus { | |||
| 309 | regmap_hw_write write; | 313 | regmap_hw_write write; |
| 310 | regmap_hw_gather_write gather_write; | 314 | regmap_hw_gather_write gather_write; |
| 311 | regmap_hw_async_write async_write; | 315 | regmap_hw_async_write async_write; |
| 316 | regmap_hw_reg_write reg_write; | ||
| 312 | regmap_hw_read read; | 317 | regmap_hw_read read; |
| 318 | regmap_hw_reg_read reg_read; | ||
| 313 | regmap_hw_free_context free_context; | 319 | regmap_hw_free_context free_context; |
| 314 | regmap_hw_async_alloc async_alloc; | 320 | regmap_hw_async_alloc async_alloc; |
| 315 | u8 read_flag_mask; | 321 | u8 read_flag_mask; |
