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
12static 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, val_size - sizeof(addr), val + sizeof(addr));
21}
22
23static 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, val_size, val_buf);
32}
33
34static 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, val_size, val_buf);
43}
44
45static 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
53static 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
69struct 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(ret);
79
80	return __regmap_init(&sdw->dev, &regmap_sdw,
81			&sdw->dev, config, lock_key, lock_name);
82}
83EXPORT_SYMBOL_GPL(__regmap_init_sdw);
84
85struct 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(ret);
95
96	return __devm_regmap_init(&sdw->dev, &regmap_sdw,
97			&sdw->dev, config, lock_key, lock_name);
98}
99EXPORT_SYMBOL_GPL(__devm_regmap_init_sdw);
100
101MODULE_DESCRIPTION("regmap SoundWire Module");
102MODULE_LICENSE("GPL v2");
103