1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright(c) 2015-17 Intel Corporation. |
3 | |
4 | #include <linux/device.h> |
5 | #include <linux/errno.h> |
6 | #include <linux/module.h> |
7 | #include <linux/regmap.h> |
8 | #include <linux/soundwire/sdw.h> |
9 | #include <linux/types.h> |
10 | #include "internal.h" |
11 | |
12 | static int regmap_sdw_write(void *context, const void *val_buf, size_t val_size) |
13 | { |
14 | struct device *dev = context; |
15 | struct sdw_slave *slave = dev_to_sdw_dev(dev); |
16 | /* First word of buffer contains the destination address */ |
17 | u32 addr = le32_to_cpu(*(const __le32 *)val_buf); |
18 | const u8 *val = val_buf; |
19 | |
20 | return sdw_nwrite_no_pm(slave, addr, count: val_size - sizeof(addr), val: val + sizeof(addr)); |
21 | } |
22 | |
23 | static int regmap_sdw_gather_write(void *context, |
24 | const void *reg_buf, size_t reg_size, |
25 | const void *val_buf, size_t val_size) |
26 | { |
27 | struct device *dev = context; |
28 | struct sdw_slave *slave = dev_to_sdw_dev(dev); |
29 | u32 addr = le32_to_cpu(*(const __le32 *)reg_buf); |
30 | |
31 | return sdw_nwrite_no_pm(slave, addr, count: val_size, val: val_buf); |
32 | } |
33 | |
34 | static int regmap_sdw_read(void *context, |
35 | const void *reg_buf, size_t reg_size, |
36 | void *val_buf, size_t val_size) |
37 | { |
38 | struct device *dev = context; |
39 | struct sdw_slave *slave = dev_to_sdw_dev(dev); |
40 | u32 addr = le32_to_cpu(*(const __le32 *)reg_buf); |
41 | |
42 | return sdw_nread_no_pm(slave, addr, count: val_size, val: val_buf); |
43 | } |
44 | |
45 | static const struct regmap_bus regmap_sdw = { |
46 | .write = regmap_sdw_write, |
47 | .gather_write = regmap_sdw_gather_write, |
48 | .read = regmap_sdw_read, |
49 | .reg_format_endian_default = REGMAP_ENDIAN_LITTLE, |
50 | .val_format_endian_default = REGMAP_ENDIAN_LITTLE, |
51 | }; |
52 | |
53 | static int regmap_sdw_config_check(const struct regmap_config *config) |
54 | { |
55 | /* Register addresses are 32 bits wide */ |
56 | if (config->reg_bits != 32) |
57 | return -ENOTSUPP; |
58 | |
59 | if (config->pad_bits != 0) |
60 | return -ENOTSUPP; |
61 | |
62 | /* Only bulk writes are supported not multi-register writes */ |
63 | if (config->can_multi_write) |
64 | return -ENOTSUPP; |
65 | |
66 | return 0; |
67 | } |
68 | |
69 | struct regmap *__regmap_init_sdw(struct sdw_slave *sdw, |
70 | const struct regmap_config *config, |
71 | struct lock_class_key *lock_key, |
72 | const char *lock_name) |
73 | { |
74 | int ret; |
75 | |
76 | ret = regmap_sdw_config_check(config); |
77 | if (ret) |
78 | return ERR_PTR(error: ret); |
79 | |
80 | return __regmap_init(dev: &sdw->dev, bus: ®map_sdw, |
81 | bus_context: &sdw->dev, config, lock_key, lock_name); |
82 | } |
83 | EXPORT_SYMBOL_GPL(__regmap_init_sdw); |
84 | |
85 | struct regmap *__devm_regmap_init_sdw(struct sdw_slave *sdw, |
86 | const struct regmap_config *config, |
87 | struct lock_class_key *lock_key, |
88 | const char *lock_name) |
89 | { |
90 | int ret; |
91 | |
92 | ret = regmap_sdw_config_check(config); |
93 | if (ret) |
94 | return ERR_PTR(error: ret); |
95 | |
96 | return __devm_regmap_init(dev: &sdw->dev, bus: ®map_sdw, |
97 | bus_context: &sdw->dev, config, lock_key, lock_name); |
98 | } |
99 | EXPORT_SYMBOL_GPL(__devm_regmap_init_sdw); |
100 | |
101 | MODULE_DESCRIPTION("Regmap SoundWire Module" ); |
102 | MODULE_LICENSE("GPL v2" ); |
103 | |