1fb5103f9SPierre-Louis Bossart // SPDX-License-Identifier: GPL-2.0
2fb5103f9SPierre-Louis Bossart // Copyright(c) 2020 Intel Corporation.
3fb5103f9SPierre-Louis Bossart
4fb5103f9SPierre-Louis Bossart #include <linux/device.h>
5fb5103f9SPierre-Louis Bossart #include <linux/errno.h>
6fb5103f9SPierre-Louis Bossart #include <linux/module.h>
7fb5103f9SPierre-Louis Bossart #include <linux/regmap.h>
8fb5103f9SPierre-Louis Bossart #include <linux/soundwire/sdw.h>
9fb5103f9SPierre-Louis Bossart #include <linux/soundwire/sdw_registers.h>
10fb5103f9SPierre-Louis Bossart #include "internal.h"
11fb5103f9SPierre-Louis Bossart
regmap_sdw_mbq_write(void * context,unsigned int reg,unsigned int val)12fb5103f9SPierre-Louis Bossart static int regmap_sdw_mbq_write(void *context, unsigned int reg, unsigned int val)
13fb5103f9SPierre-Louis Bossart {
14fb5103f9SPierre-Louis Bossart struct device *dev = context;
15fb5103f9SPierre-Louis Bossart struct sdw_slave *slave = dev_to_sdw_dev(dev);
16fb5103f9SPierre-Louis Bossart int ret;
17fb5103f9SPierre-Louis Bossart
184038e54bSBard Liao ret = sdw_write_no_pm(slave, SDW_SDCA_MBQ_CTL(reg), (val >> 8) & 0xff);
19fb5103f9SPierre-Louis Bossart if (ret < 0)
20fb5103f9SPierre-Louis Bossart return ret;
21fb5103f9SPierre-Louis Bossart
224038e54bSBard Liao return sdw_write_no_pm(slave, reg, val & 0xff);
23fb5103f9SPierre-Louis Bossart }
24fb5103f9SPierre-Louis Bossart
regmap_sdw_mbq_read(void * context,unsigned int reg,unsigned int * val)25fb5103f9SPierre-Louis Bossart static int regmap_sdw_mbq_read(void *context, unsigned int reg, unsigned int *val)
26fb5103f9SPierre-Louis Bossart {
27fb5103f9SPierre-Louis Bossart struct device *dev = context;
28fb5103f9SPierre-Louis Bossart struct sdw_slave *slave = dev_to_sdw_dev(dev);
29fb5103f9SPierre-Louis Bossart int read0;
30fb5103f9SPierre-Louis Bossart int read1;
31fb5103f9SPierre-Louis Bossart
324038e54bSBard Liao read0 = sdw_read_no_pm(slave, reg);
33fb5103f9SPierre-Louis Bossart if (read0 < 0)
34fb5103f9SPierre-Louis Bossart return read0;
35fb5103f9SPierre-Louis Bossart
364038e54bSBard Liao read1 = sdw_read_no_pm(slave, SDW_SDCA_MBQ_CTL(reg));
37fb5103f9SPierre-Louis Bossart if (read1 < 0)
38fb5103f9SPierre-Louis Bossart return read1;
39fb5103f9SPierre-Louis Bossart
40fb5103f9SPierre-Louis Bossart *val = (read1 << 8) | read0;
41fb5103f9SPierre-Louis Bossart
42fb5103f9SPierre-Louis Bossart return 0;
43fb5103f9SPierre-Louis Bossart }
44fb5103f9SPierre-Louis Bossart
45*bd941dfaSRikard Falkeborn static const struct regmap_bus regmap_sdw_mbq = {
46fb5103f9SPierre-Louis Bossart .reg_read = regmap_sdw_mbq_read,
47fb5103f9SPierre-Louis Bossart .reg_write = regmap_sdw_mbq_write,
48fb5103f9SPierre-Louis Bossart .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
49fb5103f9SPierre-Louis Bossart .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
50fb5103f9SPierre-Louis Bossart };
51fb5103f9SPierre-Louis Bossart
regmap_sdw_mbq_config_check(const struct regmap_config * config)52fb5103f9SPierre-Louis Bossart static int regmap_sdw_mbq_config_check(const struct regmap_config *config)
53fb5103f9SPierre-Louis Bossart {
54fb5103f9SPierre-Louis Bossart /* MBQ-based controls are only 16-bits for now */
55fb5103f9SPierre-Louis Bossart if (config->val_bits != 16)
56fb5103f9SPierre-Louis Bossart return -ENOTSUPP;
57fb5103f9SPierre-Louis Bossart
58fb5103f9SPierre-Louis Bossart /* Registers are 32 bits wide */
59fb5103f9SPierre-Louis Bossart if (config->reg_bits != 32)
60fb5103f9SPierre-Louis Bossart return -ENOTSUPP;
61fb5103f9SPierre-Louis Bossart
62fb5103f9SPierre-Louis Bossart if (config->pad_bits != 0)
63fb5103f9SPierre-Louis Bossart return -ENOTSUPP;
64fb5103f9SPierre-Louis Bossart
65fb5103f9SPierre-Louis Bossart return 0;
66fb5103f9SPierre-Louis Bossart }
67fb5103f9SPierre-Louis Bossart
__regmap_init_sdw_mbq(struct sdw_slave * sdw,const struct regmap_config * config,struct lock_class_key * lock_key,const char * lock_name)68fb5103f9SPierre-Louis Bossart struct regmap *__regmap_init_sdw_mbq(struct sdw_slave *sdw,
69fb5103f9SPierre-Louis Bossart const struct regmap_config *config,
70fb5103f9SPierre-Louis Bossart struct lock_class_key *lock_key,
71fb5103f9SPierre-Louis Bossart const char *lock_name)
72fb5103f9SPierre-Louis Bossart {
73fb5103f9SPierre-Louis Bossart int ret;
74fb5103f9SPierre-Louis Bossart
75fb5103f9SPierre-Louis Bossart ret = regmap_sdw_mbq_config_check(config);
76fb5103f9SPierre-Louis Bossart if (ret)
77fb5103f9SPierre-Louis Bossart return ERR_PTR(ret);
78fb5103f9SPierre-Louis Bossart
79fb5103f9SPierre-Louis Bossart return __regmap_init(&sdw->dev, ®map_sdw_mbq,
80fb5103f9SPierre-Louis Bossart &sdw->dev, config, lock_key, lock_name);
81fb5103f9SPierre-Louis Bossart }
82fb5103f9SPierre-Louis Bossart EXPORT_SYMBOL_GPL(__regmap_init_sdw_mbq);
83fb5103f9SPierre-Louis Bossart
__devm_regmap_init_sdw_mbq(struct sdw_slave * sdw,const struct regmap_config * config,struct lock_class_key * lock_key,const char * lock_name)84fb5103f9SPierre-Louis Bossart struct regmap *__devm_regmap_init_sdw_mbq(struct sdw_slave *sdw,
85fb5103f9SPierre-Louis Bossart const struct regmap_config *config,
86fb5103f9SPierre-Louis Bossart struct lock_class_key *lock_key,
87fb5103f9SPierre-Louis Bossart const char *lock_name)
88fb5103f9SPierre-Louis Bossart {
89fb5103f9SPierre-Louis Bossart int ret;
90fb5103f9SPierre-Louis Bossart
91fb5103f9SPierre-Louis Bossart ret = regmap_sdw_mbq_config_check(config);
92fb5103f9SPierre-Louis Bossart if (ret)
93fb5103f9SPierre-Louis Bossart return ERR_PTR(ret);
94fb5103f9SPierre-Louis Bossart
95fb5103f9SPierre-Louis Bossart return __devm_regmap_init(&sdw->dev, ®map_sdw_mbq,
96fb5103f9SPierre-Louis Bossart &sdw->dev, config, lock_key, lock_name);
97fb5103f9SPierre-Louis Bossart }
98fb5103f9SPierre-Louis Bossart EXPORT_SYMBOL_GPL(__devm_regmap_init_sdw_mbq);
99fb5103f9SPierre-Louis Bossart
100fb5103f9SPierre-Louis Bossart MODULE_DESCRIPTION("Regmap SoundWire MBQ Module");
1018d8d9584SBard Liao MODULE_LICENSE("GPL");
102