17c22ce6eSVinod Koul // SPDX-License-Identifier: GPL-2.0
27c22ce6eSVinod Koul // Copyright(c) 2015-17 Intel Corporation.
37c22ce6eSVinod Koul
47c22ce6eSVinod Koul #include <linux/device.h>
5d9a500b2SPierre-Louis Bossart #include <linux/errno.h>
67c22ce6eSVinod Koul #include <linux/module.h>
7d9a500b2SPierre-Louis Bossart #include <linux/regmap.h>
87c22ce6eSVinod Koul #include <linux/soundwire/sdw.h>
952227204SLucas Tanure #include <linux/types.h>
107c22ce6eSVinod Koul #include "internal.h"
117c22ce6eSVinod Koul
regmap_sdw_write(void * context,const void * val_buf,size_t val_size)1252227204SLucas Tanure static int regmap_sdw_write(void *context, const void *val_buf, size_t val_size)
137c22ce6eSVinod Koul {
147c22ce6eSVinod Koul struct device *dev = context;
157c22ce6eSVinod Koul struct sdw_slave *slave = dev_to_sdw_dev(dev);
1652227204SLucas Tanure /* First word of buffer contains the destination address */
1752227204SLucas Tanure u32 addr = le32_to_cpu(*(const __le32 *)val_buf);
1852227204SLucas Tanure const u8 *val = val_buf;
197c22ce6eSVinod Koul
2052227204SLucas Tanure return sdw_nwrite_no_pm(slave, addr, val_size - sizeof(addr), val + sizeof(addr));
217c22ce6eSVinod Koul }
227c22ce6eSVinod Koul
regmap_sdw_gather_write(void * context,const void * reg_buf,size_t reg_size,const void * val_buf,size_t val_size)2352227204SLucas Tanure static int regmap_sdw_gather_write(void *context,
2452227204SLucas Tanure const void *reg_buf, size_t reg_size,
2552227204SLucas Tanure const void *val_buf, size_t val_size)
267c22ce6eSVinod Koul {
277c22ce6eSVinod Koul struct device *dev = context;
287c22ce6eSVinod Koul struct sdw_slave *slave = dev_to_sdw_dev(dev);
2952227204SLucas Tanure u32 addr = le32_to_cpu(*(const __le32 *)reg_buf);
307c22ce6eSVinod Koul
3152227204SLucas Tanure return sdw_nwrite_no_pm(slave, addr, val_size, val_buf);
3252227204SLucas Tanure }
337c22ce6eSVinod Koul
regmap_sdw_read(void * context,const void * reg_buf,size_t reg_size,void * val_buf,size_t val_size)3452227204SLucas Tanure static int regmap_sdw_read(void *context,
3552227204SLucas Tanure const void *reg_buf, size_t reg_size,
3652227204SLucas Tanure void *val_buf, size_t val_size)
3752227204SLucas Tanure {
3852227204SLucas Tanure struct device *dev = context;
3952227204SLucas Tanure struct sdw_slave *slave = dev_to_sdw_dev(dev);
4052227204SLucas Tanure u32 addr = le32_to_cpu(*(const __le32 *)reg_buf);
4152227204SLucas Tanure
4252227204SLucas Tanure return sdw_nread_no_pm(slave, addr, val_size, val_buf);
437c22ce6eSVinod Koul }
447c22ce6eSVinod Koul
45bd941dfaSRikard Falkeborn static const struct regmap_bus regmap_sdw = {
4652227204SLucas Tanure .write = regmap_sdw_write,
4752227204SLucas Tanure .gather_write = regmap_sdw_gather_write,
4852227204SLucas Tanure .read = regmap_sdw_read,
497c22ce6eSVinod Koul .reg_format_endian_default = REGMAP_ENDIAN_LITTLE,
507c22ce6eSVinod Koul .val_format_endian_default = REGMAP_ENDIAN_LITTLE,
517c22ce6eSVinod Koul };
527c22ce6eSVinod Koul
regmap_sdw_config_check(const struct regmap_config * config)537c22ce6eSVinod Koul static int regmap_sdw_config_check(const struct regmap_config *config)
547c22ce6eSVinod Koul {
556466b376SCharles Keepax /* Register addresses are 32 bits wide */
567c22ce6eSVinod Koul if (config->reg_bits != 32)
577c22ce6eSVinod Koul return -ENOTSUPP;
587c22ce6eSVinod Koul
597c22ce6eSVinod Koul if (config->pad_bits != 0)
607c22ce6eSVinod Koul return -ENOTSUPP;
617c22ce6eSVinod Koul
62*95856d1fSSrinivas Kandagatla /* Only bulk writes are supported not multi-register writes */
63*95856d1fSSrinivas Kandagatla if (config->can_multi_write)
64*95856d1fSSrinivas Kandagatla return -ENOTSUPP;
65*95856d1fSSrinivas Kandagatla
667c22ce6eSVinod Koul return 0;
677c22ce6eSVinod Koul }
687c22ce6eSVinod Koul
__regmap_init_sdw(struct sdw_slave * sdw,const struct regmap_config * config,struct lock_class_key * lock_key,const char * lock_name)697c22ce6eSVinod Koul struct regmap *__regmap_init_sdw(struct sdw_slave *sdw,
707c22ce6eSVinod Koul const struct regmap_config *config,
717c22ce6eSVinod Koul struct lock_class_key *lock_key,
727c22ce6eSVinod Koul const char *lock_name)
737c22ce6eSVinod Koul {
747c22ce6eSVinod Koul int ret;
757c22ce6eSVinod Koul
767c22ce6eSVinod Koul ret = regmap_sdw_config_check(config);
777c22ce6eSVinod Koul if (ret)
787c22ce6eSVinod Koul return ERR_PTR(ret);
797c22ce6eSVinod Koul
807c22ce6eSVinod Koul return __regmap_init(&sdw->dev, ®map_sdw,
817c22ce6eSVinod Koul &sdw->dev, config, lock_key, lock_name);
827c22ce6eSVinod Koul }
837c22ce6eSVinod Koul EXPORT_SYMBOL_GPL(__regmap_init_sdw);
847c22ce6eSVinod Koul
__devm_regmap_init_sdw(struct sdw_slave * sdw,const struct regmap_config * config,struct lock_class_key * lock_key,const char * lock_name)857c22ce6eSVinod Koul struct regmap *__devm_regmap_init_sdw(struct sdw_slave *sdw,
867c22ce6eSVinod Koul const struct regmap_config *config,
877c22ce6eSVinod Koul struct lock_class_key *lock_key,
887c22ce6eSVinod Koul const char *lock_name)
897c22ce6eSVinod Koul {
907c22ce6eSVinod Koul int ret;
917c22ce6eSVinod Koul
927c22ce6eSVinod Koul ret = regmap_sdw_config_check(config);
937c22ce6eSVinod Koul if (ret)
947c22ce6eSVinod Koul return ERR_PTR(ret);
957c22ce6eSVinod Koul
967c22ce6eSVinod Koul return __devm_regmap_init(&sdw->dev, ®map_sdw,
977c22ce6eSVinod Koul &sdw->dev, config, lock_key, lock_name);
987c22ce6eSVinod Koul }
997c22ce6eSVinod Koul EXPORT_SYMBOL_GPL(__devm_regmap_init_sdw);
1007c22ce6eSVinod Koul
1017c22ce6eSVinod Koul MODULE_DESCRIPTION("Regmap SoundWire Module");
1027c22ce6eSVinod Koul MODULE_LICENSE("GPL v2");
103