xref: /openbmc/linux/drivers/base/regmap/regmap-fsi.c (revision bf0d29fb)
1*bf0d29fbSEddie James // SPDX-License-Identifier: GPL-2.0
2*bf0d29fbSEddie James //
3*bf0d29fbSEddie James // Register map access API - FSI support
4*bf0d29fbSEddie James //
5*bf0d29fbSEddie James // Copyright 2022 IBM Corp
6*bf0d29fbSEddie James //
7*bf0d29fbSEddie James // Author: Eddie James <eajames@linux.ibm.com>
8*bf0d29fbSEddie James 
9*bf0d29fbSEddie James #include <linux/fsi.h>
10*bf0d29fbSEddie James #include <linux/module.h>
11*bf0d29fbSEddie James #include <linux/regmap.h>
12*bf0d29fbSEddie James 
13*bf0d29fbSEddie James #include "internal.h"
14*bf0d29fbSEddie James 
regmap_fsi32_reg_read(void * context,unsigned int reg,unsigned int * val)15*bf0d29fbSEddie James static int regmap_fsi32_reg_read(void *context, unsigned int reg, unsigned int *val)
16*bf0d29fbSEddie James {
17*bf0d29fbSEddie James 	u32 v;
18*bf0d29fbSEddie James 	int ret;
19*bf0d29fbSEddie James 
20*bf0d29fbSEddie James 	ret = fsi_slave_read(context, reg, &v, sizeof(v));
21*bf0d29fbSEddie James 	if (ret)
22*bf0d29fbSEddie James 		return ret;
23*bf0d29fbSEddie James 
24*bf0d29fbSEddie James 	*val = v;
25*bf0d29fbSEddie James 	return 0;
26*bf0d29fbSEddie James }
27*bf0d29fbSEddie James 
regmap_fsi32_reg_write(void * context,unsigned int reg,unsigned int val)28*bf0d29fbSEddie James static int regmap_fsi32_reg_write(void *context, unsigned int reg, unsigned int val)
29*bf0d29fbSEddie James {
30*bf0d29fbSEddie James 	u32 v = val;
31*bf0d29fbSEddie James 
32*bf0d29fbSEddie James 	return fsi_slave_write(context, reg, &v, sizeof(v));
33*bf0d29fbSEddie James }
34*bf0d29fbSEddie James 
35*bf0d29fbSEddie James static const struct regmap_bus regmap_fsi32 = {
36*bf0d29fbSEddie James 	.reg_write = regmap_fsi32_reg_write,
37*bf0d29fbSEddie James 	.reg_read = regmap_fsi32_reg_read,
38*bf0d29fbSEddie James };
39*bf0d29fbSEddie James 
regmap_fsi32le_reg_read(void * context,unsigned int reg,unsigned int * val)40*bf0d29fbSEddie James static int regmap_fsi32le_reg_read(void *context, unsigned int reg, unsigned int *val)
41*bf0d29fbSEddie James {
42*bf0d29fbSEddie James 	__be32 v;
43*bf0d29fbSEddie James 	int ret;
44*bf0d29fbSEddie James 
45*bf0d29fbSEddie James 	ret = fsi_slave_read(context, reg, &v, sizeof(v));
46*bf0d29fbSEddie James 	if (ret)
47*bf0d29fbSEddie James 		return ret;
48*bf0d29fbSEddie James 
49*bf0d29fbSEddie James 	*val = be32_to_cpu(v);
50*bf0d29fbSEddie James 	return 0;
51*bf0d29fbSEddie James }
52*bf0d29fbSEddie James 
regmap_fsi32le_reg_write(void * context,unsigned int reg,unsigned int val)53*bf0d29fbSEddie James static int regmap_fsi32le_reg_write(void *context, unsigned int reg, unsigned int val)
54*bf0d29fbSEddie James {
55*bf0d29fbSEddie James 	__be32 v = cpu_to_be32(val);
56*bf0d29fbSEddie James 
57*bf0d29fbSEddie James 	return fsi_slave_write(context, reg, &v, sizeof(v));
58*bf0d29fbSEddie James }
59*bf0d29fbSEddie James 
60*bf0d29fbSEddie James static const struct regmap_bus regmap_fsi32le = {
61*bf0d29fbSEddie James 	.reg_write = regmap_fsi32le_reg_write,
62*bf0d29fbSEddie James 	.reg_read = regmap_fsi32le_reg_read,
63*bf0d29fbSEddie James };
64*bf0d29fbSEddie James 
regmap_fsi16_reg_read(void * context,unsigned int reg,unsigned int * val)65*bf0d29fbSEddie James static int regmap_fsi16_reg_read(void *context, unsigned int reg, unsigned int *val)
66*bf0d29fbSEddie James {
67*bf0d29fbSEddie James 	u16 v;
68*bf0d29fbSEddie James 	int ret;
69*bf0d29fbSEddie James 
70*bf0d29fbSEddie James 	ret = fsi_slave_read(context, reg, &v, sizeof(v));
71*bf0d29fbSEddie James 	if (ret)
72*bf0d29fbSEddie James 		return ret;
73*bf0d29fbSEddie James 
74*bf0d29fbSEddie James 	*val = v;
75*bf0d29fbSEddie James 	return 0;
76*bf0d29fbSEddie James }
77*bf0d29fbSEddie James 
regmap_fsi16_reg_write(void * context,unsigned int reg,unsigned int val)78*bf0d29fbSEddie James static int regmap_fsi16_reg_write(void *context, unsigned int reg, unsigned int val)
79*bf0d29fbSEddie James {
80*bf0d29fbSEddie James 	u16 v;
81*bf0d29fbSEddie James 
82*bf0d29fbSEddie James 	if (val > 0xffff)
83*bf0d29fbSEddie James 		return -EINVAL;
84*bf0d29fbSEddie James 
85*bf0d29fbSEddie James 	v = val;
86*bf0d29fbSEddie James 	return fsi_slave_write(context, reg, &v, sizeof(v));
87*bf0d29fbSEddie James }
88*bf0d29fbSEddie James 
89*bf0d29fbSEddie James static const struct regmap_bus regmap_fsi16 = {
90*bf0d29fbSEddie James 	.reg_write = regmap_fsi16_reg_write,
91*bf0d29fbSEddie James 	.reg_read = regmap_fsi16_reg_read,
92*bf0d29fbSEddie James };
93*bf0d29fbSEddie James 
regmap_fsi16le_reg_read(void * context,unsigned int reg,unsigned int * val)94*bf0d29fbSEddie James static int regmap_fsi16le_reg_read(void *context, unsigned int reg, unsigned int *val)
95*bf0d29fbSEddie James {
96*bf0d29fbSEddie James 	__be16 v;
97*bf0d29fbSEddie James 	int ret;
98*bf0d29fbSEddie James 
99*bf0d29fbSEddie James 	ret = fsi_slave_read(context, reg, &v, sizeof(v));
100*bf0d29fbSEddie James 	if (ret)
101*bf0d29fbSEddie James 		return ret;
102*bf0d29fbSEddie James 
103*bf0d29fbSEddie James 	*val = be16_to_cpu(v);
104*bf0d29fbSEddie James 	return 0;
105*bf0d29fbSEddie James }
106*bf0d29fbSEddie James 
regmap_fsi16le_reg_write(void * context,unsigned int reg,unsigned int val)107*bf0d29fbSEddie James static int regmap_fsi16le_reg_write(void *context, unsigned int reg, unsigned int val)
108*bf0d29fbSEddie James {
109*bf0d29fbSEddie James 	__be16 v;
110*bf0d29fbSEddie James 
111*bf0d29fbSEddie James 	if (val > 0xffff)
112*bf0d29fbSEddie James 		return -EINVAL;
113*bf0d29fbSEddie James 
114*bf0d29fbSEddie James 	v = cpu_to_be16(val);
115*bf0d29fbSEddie James 	return fsi_slave_write(context, reg, &v, sizeof(v));
116*bf0d29fbSEddie James }
117*bf0d29fbSEddie James 
118*bf0d29fbSEddie James static const struct regmap_bus regmap_fsi16le = {
119*bf0d29fbSEddie James 	.reg_write = regmap_fsi16le_reg_write,
120*bf0d29fbSEddie James 	.reg_read = regmap_fsi16le_reg_read,
121*bf0d29fbSEddie James };
122*bf0d29fbSEddie James 
regmap_fsi8_reg_read(void * context,unsigned int reg,unsigned int * val)123*bf0d29fbSEddie James static int regmap_fsi8_reg_read(void *context, unsigned int reg, unsigned int *val)
124*bf0d29fbSEddie James {
125*bf0d29fbSEddie James 	u8 v;
126*bf0d29fbSEddie James 	int ret;
127*bf0d29fbSEddie James 
128*bf0d29fbSEddie James 	ret = fsi_slave_read(context, reg, &v, sizeof(v));
129*bf0d29fbSEddie James 	if (ret)
130*bf0d29fbSEddie James 		return ret;
131*bf0d29fbSEddie James 
132*bf0d29fbSEddie James 	*val = v;
133*bf0d29fbSEddie James 	return 0;
134*bf0d29fbSEddie James }
135*bf0d29fbSEddie James 
regmap_fsi8_reg_write(void * context,unsigned int reg,unsigned int val)136*bf0d29fbSEddie James static int regmap_fsi8_reg_write(void *context, unsigned int reg, unsigned int val)
137*bf0d29fbSEddie James {
138*bf0d29fbSEddie James 	u8 v;
139*bf0d29fbSEddie James 
140*bf0d29fbSEddie James 	if (val > 0xff)
141*bf0d29fbSEddie James 		return -EINVAL;
142*bf0d29fbSEddie James 
143*bf0d29fbSEddie James 	v = val;
144*bf0d29fbSEddie James 	return fsi_slave_write(context, reg, &v, sizeof(v));
145*bf0d29fbSEddie James }
146*bf0d29fbSEddie James 
147*bf0d29fbSEddie James static const struct regmap_bus regmap_fsi8 = {
148*bf0d29fbSEddie James 	.reg_write = regmap_fsi8_reg_write,
149*bf0d29fbSEddie James 	.reg_read = regmap_fsi8_reg_read,
150*bf0d29fbSEddie James };
151*bf0d29fbSEddie James 
regmap_get_fsi_bus(struct fsi_device * fsi_dev,const struct regmap_config * config)152*bf0d29fbSEddie James static const struct regmap_bus *regmap_get_fsi_bus(struct fsi_device *fsi_dev,
153*bf0d29fbSEddie James 						   const struct regmap_config *config)
154*bf0d29fbSEddie James {
155*bf0d29fbSEddie James 	const struct regmap_bus *bus = NULL;
156*bf0d29fbSEddie James 
157*bf0d29fbSEddie James 	if (config->reg_bits == 8 || config->reg_bits == 16 || config->reg_bits == 32) {
158*bf0d29fbSEddie James 		switch (config->val_bits) {
159*bf0d29fbSEddie James 		case 8:
160*bf0d29fbSEddie James 			bus = &regmap_fsi8;
161*bf0d29fbSEddie James 			break;
162*bf0d29fbSEddie James 		case 16:
163*bf0d29fbSEddie James 			switch (regmap_get_val_endian(&fsi_dev->dev, NULL, config)) {
164*bf0d29fbSEddie James 			case REGMAP_ENDIAN_LITTLE:
165*bf0d29fbSEddie James #ifdef __LITTLE_ENDIAN
166*bf0d29fbSEddie James 			case REGMAP_ENDIAN_NATIVE:
167*bf0d29fbSEddie James #endif
168*bf0d29fbSEddie James 				bus = &regmap_fsi16le;
169*bf0d29fbSEddie James 				break;
170*bf0d29fbSEddie James 			case REGMAP_ENDIAN_DEFAULT:
171*bf0d29fbSEddie James 			case REGMAP_ENDIAN_BIG:
172*bf0d29fbSEddie James #ifdef __BIG_ENDIAN
173*bf0d29fbSEddie James 			case REGMAP_ENDIAN_NATIVE:
174*bf0d29fbSEddie James #endif
175*bf0d29fbSEddie James 				bus = &regmap_fsi16;
176*bf0d29fbSEddie James 				break;
177*bf0d29fbSEddie James 			default:
178*bf0d29fbSEddie James 				break;
179*bf0d29fbSEddie James 			}
180*bf0d29fbSEddie James 			break;
181*bf0d29fbSEddie James 		case 32:
182*bf0d29fbSEddie James 			switch (regmap_get_val_endian(&fsi_dev->dev, NULL, config)) {
183*bf0d29fbSEddie James 			case REGMAP_ENDIAN_LITTLE:
184*bf0d29fbSEddie James #ifdef __LITTLE_ENDIAN
185*bf0d29fbSEddie James 			case REGMAP_ENDIAN_NATIVE:
186*bf0d29fbSEddie James #endif
187*bf0d29fbSEddie James 				bus = &regmap_fsi32le;
188*bf0d29fbSEddie James 				break;
189*bf0d29fbSEddie James 			case REGMAP_ENDIAN_DEFAULT:
190*bf0d29fbSEddie James 			case REGMAP_ENDIAN_BIG:
191*bf0d29fbSEddie James #ifdef __BIG_ENDIAN
192*bf0d29fbSEddie James 			case REGMAP_ENDIAN_NATIVE:
193*bf0d29fbSEddie James #endif
194*bf0d29fbSEddie James 				bus = &regmap_fsi32;
195*bf0d29fbSEddie James 				break;
196*bf0d29fbSEddie James 			default:
197*bf0d29fbSEddie James 				break;
198*bf0d29fbSEddie James 			}
199*bf0d29fbSEddie James 			break;
200*bf0d29fbSEddie James 		}
201*bf0d29fbSEddie James 	}
202*bf0d29fbSEddie James 
203*bf0d29fbSEddie James 	return bus ?: ERR_PTR(-EOPNOTSUPP);
204*bf0d29fbSEddie James }
205*bf0d29fbSEddie James 
__regmap_init_fsi(struct fsi_device * fsi_dev,const struct regmap_config * config,struct lock_class_key * lock_key,const char * lock_name)206*bf0d29fbSEddie James struct regmap *__regmap_init_fsi(struct fsi_device *fsi_dev, const struct regmap_config *config,
207*bf0d29fbSEddie James 				 struct lock_class_key *lock_key, const char *lock_name)
208*bf0d29fbSEddie James {
209*bf0d29fbSEddie James 	const struct regmap_bus *bus = regmap_get_fsi_bus(fsi_dev, config);
210*bf0d29fbSEddie James 
211*bf0d29fbSEddie James 	if (IS_ERR(bus))
212*bf0d29fbSEddie James 		return ERR_CAST(bus);
213*bf0d29fbSEddie James 
214*bf0d29fbSEddie James 	return __regmap_init(&fsi_dev->dev, bus, fsi_dev->slave, config, lock_key, lock_name);
215*bf0d29fbSEddie James }
216*bf0d29fbSEddie James EXPORT_SYMBOL_GPL(__regmap_init_fsi);
217*bf0d29fbSEddie James 
__devm_regmap_init_fsi(struct fsi_device * fsi_dev,const struct regmap_config * config,struct lock_class_key * lock_key,const char * lock_name)218*bf0d29fbSEddie James struct regmap *__devm_regmap_init_fsi(struct fsi_device *fsi_dev,
219*bf0d29fbSEddie James 				      const struct regmap_config *config,
220*bf0d29fbSEddie James 				      struct lock_class_key *lock_key, const char *lock_name)
221*bf0d29fbSEddie James {
222*bf0d29fbSEddie James 	const struct regmap_bus *bus = regmap_get_fsi_bus(fsi_dev, config);
223*bf0d29fbSEddie James 
224*bf0d29fbSEddie James 	if (IS_ERR(bus))
225*bf0d29fbSEddie James 		return ERR_CAST(bus);
226*bf0d29fbSEddie James 
227*bf0d29fbSEddie James 	return __devm_regmap_init(&fsi_dev->dev, bus, fsi_dev->slave, config, lock_key, lock_name);
228*bf0d29fbSEddie James }
229*bf0d29fbSEddie James EXPORT_SYMBOL_GPL(__devm_regmap_init_fsi);
230*bf0d29fbSEddie James 
231*bf0d29fbSEddie James MODULE_LICENSE("GPL");
232