Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

regmap: Allow longer flag masks for read and write

We currently only support masking the top bit for read and write
flags. Let's make the mask unsigned long and mask the bytes based
on the configured register length to make things more generic.

This allows using regmap for more exotic combinations like SPI
devices that need little endian addressing.

Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Tony Lindgren and committed by
Mark Brown
f50e38c9 29b4817d

+25 -19
+2 -2
drivers/base/regmap/internal.h
··· 105 105 106 106 bool defer_caching; 107 107 108 - u8 read_flag_mask; 109 - u8 write_flag_mask; 108 + unsigned long read_flag_mask; 109 + unsigned long write_flag_mask; 110 110 111 111 /* number of bits to (left) shift the reg value when formatting*/ 112 112 int reg_shift;
+19 -13
drivers/base/regmap/regmap.c
··· 1296 1296 return 0; 1297 1297 } 1298 1298 1299 + static void regmap_set_work_buf_flag_mask(struct regmap *map, int max_bytes, 1300 + unsigned long mask) 1301 + { 1302 + u8 *buf; 1303 + int i; 1304 + 1305 + if (!mask || !map->work_buf) 1306 + return; 1307 + 1308 + buf = map->work_buf; 1309 + 1310 + for (i = 0; i < max_bytes; i++) 1311 + buf[i] |= (mask >> (8 * i)) & 0xff; 1312 + } 1313 + 1299 1314 int _regmap_raw_write(struct regmap *map, unsigned int reg, 1300 1315 const void *val, size_t val_len) 1301 1316 { 1302 1317 struct regmap_range_node *range; 1303 1318 unsigned long flags; 1304 - u8 *u8 = map->work_buf; 1305 1319 void *work_val = map->work_buf + map->format.reg_bytes + 1306 1320 map->format.pad_bytes; 1307 1321 void *buf; ··· 1384 1370 } 1385 1371 1386 1372 map->format.format_reg(map->work_buf, reg, map->reg_shift); 1387 - 1388 - u8[0] |= map->write_flag_mask; 1373 + regmap_set_work_buf_flag_mask(map, map->format.reg_bytes, 1374 + map->write_flag_mask); 1389 1375 1390 1376 /* 1391 1377 * Essentially all I/O mechanisms will be faster with a single ··· 2259 2245 unsigned int val_len) 2260 2246 { 2261 2247 struct regmap_range_node *range; 2262 - u8 *u8 = map->work_buf; 2263 2248 int ret; 2264 2249 2265 2250 WARN_ON(!map->bus); ··· 2275 2262 } 2276 2263 2277 2264 map->format.format_reg(map->work_buf, reg, map->reg_shift); 2278 - 2279 - /* 2280 - * Some buses or devices flag reads by setting the high bits in the 2281 - * register address; since it's always the high bits for all 2282 - * current formats we can do this here rather than in 2283 - * formatting. This may break if we get interesting formats. 2284 - */ 2285 - u8[0] |= map->read_flag_mask; 2286 - 2265 + regmap_set_work_buf_flag_mask(map, map->format.reg_bytes, 2266 + map->read_flag_mask); 2287 2267 trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes); 2288 2268 2289 2269 ret = map->bus->read(map->bus_context, map->work_buf,
+4 -4
include/linux/regmap.h
··· 241 241 * register cache support). 242 242 * @num_reg_defaults: Number of elements in reg_defaults. 243 243 * 244 - * @read_flag_mask: Mask to be set in the top byte of the register when doing 244 + * @read_flag_mask: Mask to be set in the top bytes of the register when doing 245 245 * a read. 246 - * @write_flag_mask: Mask to be set in the top byte of the register when doing 246 + * @write_flag_mask: Mask to be set in the top bytes of the register when doing 247 247 * a write. If both read_flag_mask and write_flag_mask are 248 248 * empty the regmap_bus default masks are used. 249 249 * @use_single_rw: If set, converts the bulk read and write operations into ··· 299 299 const void *reg_defaults_raw; 300 300 unsigned int num_reg_defaults_raw; 301 301 302 - u8 read_flag_mask; 303 - u8 write_flag_mask; 302 + unsigned long read_flag_mask; 303 + unsigned long write_flag_mask; 304 304 305 305 bool use_single_rw; 306 306 bool can_multi_write;