hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
kernel/drivers/base/regmap/regmap-i2c.c
....@@ -1,14 +1,10 @@
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
- */
1
+// SPDX-License-Identifier: GPL-2.0
2
+//
3
+// Register map access API - I2C support
4
+//
5
+// Copyright 2011 Wolfson Microelectronics plc
6
+//
7
+// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
128
139 #include <linux/regmap.h>
1410 #include <linux/i2c.h>
....@@ -47,7 +43,7 @@
4743 return i2c_smbus_write_byte_data(i2c, reg, val);
4844 }
4945
50
-static struct regmap_bus regmap_smbus_byte = {
46
+static const struct regmap_bus regmap_smbus_byte = {
5147 .reg_write = regmap_smbus_byte_reg_write,
5248 .reg_read = regmap_smbus_byte_reg_read,
5349 };
....@@ -83,7 +79,7 @@
8379 return i2c_smbus_write_word_data(i2c, reg, val);
8480 }
8581
86
-static struct regmap_bus regmap_smbus_word = {
82
+static const struct regmap_bus regmap_smbus_word = {
8783 .reg_write = regmap_smbus_word_reg_write,
8884 .reg_read = regmap_smbus_word_reg_read,
8985 };
....@@ -119,7 +115,7 @@
119115 return i2c_smbus_write_word_swapped(i2c, reg, val);
120116 }
121117
122
-static struct regmap_bus regmap_smbus_word_swapped = {
118
+static const struct regmap_bus regmap_smbus_word_swapped = {
123119 .reg_write = regmap_smbus_word_write_swapped,
124120 .reg_read = regmap_smbus_word_read_swapped,
125121 };
....@@ -201,7 +197,7 @@
201197 return -EIO;
202198 }
203199
204
-static struct regmap_bus regmap_i2c = {
200
+static const struct regmap_bus regmap_i2c = {
205201 .write = regmap_i2c_write,
206202 .gather_write = regmap_i2c_gather_write,
207203 .read = regmap_i2c_read,
....@@ -243,11 +239,68 @@
243239 return -EIO;
244240 }
245241
246
-static struct regmap_bus regmap_i2c_smbus_i2c_block = {
242
+static const struct regmap_bus regmap_i2c_smbus_i2c_block = {
247243 .write = regmap_i2c_smbus_i2c_write,
248244 .read = regmap_i2c_smbus_i2c_read,
249
- .max_raw_read = I2C_SMBUS_BLOCK_MAX,
250
- .max_raw_write = I2C_SMBUS_BLOCK_MAX,
245
+ .max_raw_read = I2C_SMBUS_BLOCK_MAX - 1,
246
+ .max_raw_write = I2C_SMBUS_BLOCK_MAX - 1,
247
+};
248
+
249
+static int regmap_i2c_smbus_i2c_write_reg16(void *context, const void *data,
250
+ size_t count)
251
+{
252
+ struct device *dev = context;
253
+ struct i2c_client *i2c = to_i2c_client(dev);
254
+
255
+ if (count < 2)
256
+ return -EINVAL;
257
+
258
+ count--;
259
+ return i2c_smbus_write_i2c_block_data(i2c, ((u8 *)data)[0], count,
260
+ (u8 *)data + 1);
261
+}
262
+
263
+static int regmap_i2c_smbus_i2c_read_reg16(void *context, const void *reg,
264
+ size_t reg_size, void *val,
265
+ size_t val_size)
266
+{
267
+ struct device *dev = context;
268
+ struct i2c_client *i2c = to_i2c_client(dev);
269
+ int ret, count, len = val_size;
270
+
271
+ if (reg_size != 2)
272
+ return -EINVAL;
273
+
274
+ ret = i2c_smbus_write_byte_data(i2c, ((u16 *)reg)[0] & 0xff,
275
+ ((u16 *)reg)[0] >> 8);
276
+ if (ret < 0)
277
+ return ret;
278
+
279
+ count = 0;
280
+ do {
281
+ /* Current Address Read */
282
+ ret = i2c_smbus_read_byte(i2c);
283
+ if (ret < 0)
284
+ break;
285
+
286
+ *((u8 *)val++) = ret;
287
+ count++;
288
+ len--;
289
+ } while (len > 0);
290
+
291
+ if (count == val_size)
292
+ return 0;
293
+ else if (ret < 0)
294
+ return ret;
295
+ else
296
+ return -EIO;
297
+}
298
+
299
+static const struct regmap_bus regmap_i2c_smbus_i2c_block_reg16 = {
300
+ .write = regmap_i2c_smbus_i2c_write_reg16,
301
+ .read = regmap_i2c_smbus_i2c_read_reg16,
302
+ .max_raw_read = I2C_SMBUS_BLOCK_MAX - 2,
303
+ .max_raw_write = I2C_SMBUS_BLOCK_MAX - 2,
251304 };
252305
253306 static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
....@@ -259,6 +312,10 @@
259312 i2c_check_functionality(i2c->adapter,
260313 I2C_FUNC_SMBUS_I2C_BLOCK))
261314 return &regmap_i2c_smbus_i2c_block;
315
+ else if (config->val_bits == 8 && config->reg_bits == 16 &&
316
+ i2c_check_functionality(i2c->adapter,
317
+ I2C_FUNC_SMBUS_I2C_BLOCK))
318
+ return &regmap_i2c_smbus_i2c_block_reg16;
262319 else if (config->val_bits == 16 && config->reg_bits == 8 &&
263320 i2c_check_functionality(i2c->adapter,
264321 I2C_FUNC_SMBUS_WORD_DATA))