xref: /openbmc/linux/drivers/base/regmap/regmap-sdw.c (revision 95856d1f)
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, &regmap_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, &regmap_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