Linux Audio

Check our new training course

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