Linux Audio

Check our new training course

Loading...
  1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
  2/*
  3 * Microsemi Ocelot Switch driver
  4 *
  5 * Copyright (c) 2017 Microsemi Corporation
  6 */
  7#include <linux/io.h>
  8#include <linux/kernel.h>
  9#include <linux/platform_device.h>
 10
 11#include "ocelot.h"
 12
 13int __ocelot_bulk_read_ix(struct ocelot *ocelot, enum ocelot_reg reg,
 14			  u32 offset, void *buf, int count)
 15{
 16	enum ocelot_target target;
 17	u32 addr;
 18
 19	ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
 20	WARN_ON(!target);
 21
 22	return regmap_bulk_read(ocelot->targets[target], addr + offset,
 23				buf, count);
 24}
 25EXPORT_SYMBOL_GPL(__ocelot_bulk_read_ix);
 26
 27u32 __ocelot_read_ix(struct ocelot *ocelot, enum ocelot_reg reg, u32 offset)
 28{
 29	enum ocelot_target target;
 30	u32 addr, val;
 31
 32	ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
 33	WARN_ON(!target);
 34
 35	regmap_read(ocelot->targets[target], addr + offset, &val);
 36	return val;
 37}
 38EXPORT_SYMBOL_GPL(__ocelot_read_ix);
 39
 40void __ocelot_write_ix(struct ocelot *ocelot, u32 val, enum ocelot_reg reg,
 41		       u32 offset)
 42{
 43	enum ocelot_target target;
 44	u32 addr;
 45
 46	ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
 47	WARN_ON(!target);
 48
 49	regmap_write(ocelot->targets[target], addr + offset, val);
 50}
 51EXPORT_SYMBOL_GPL(__ocelot_write_ix);
 52
 53void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask,
 54		     enum ocelot_reg reg, u32 offset)
 55{
 56	enum ocelot_target target;
 57	u32 addr;
 58
 59	ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
 60	WARN_ON(!target);
 61
 62	regmap_update_bits(ocelot->targets[target], addr + offset, mask, val);
 63}
 64EXPORT_SYMBOL_GPL(__ocelot_rmw_ix);
 65
 66u32 ocelot_port_readl(struct ocelot_port *port, enum ocelot_reg reg)
 67{
 68	struct ocelot *ocelot = port->ocelot;
 69	u16 target = reg >> TARGET_OFFSET;
 70	u32 val;
 71
 72	WARN_ON(!target);
 73
 74	regmap_read(port->target, ocelot->map[target][reg & REG_MASK], &val);
 75	return val;
 76}
 77EXPORT_SYMBOL_GPL(ocelot_port_readl);
 78
 79void ocelot_port_writel(struct ocelot_port *port, u32 val, enum ocelot_reg reg)
 80{
 81	struct ocelot *ocelot = port->ocelot;
 82	u16 target = reg >> TARGET_OFFSET;
 83
 84	WARN_ON(!target);
 85
 86	regmap_write(port->target, ocelot->map[target][reg & REG_MASK], val);
 87}
 88EXPORT_SYMBOL_GPL(ocelot_port_writel);
 89
 90void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask,
 91		      enum ocelot_reg reg)
 92{
 93	u32 cur = ocelot_port_readl(port, reg);
 94
 95	ocelot_port_writel(port, (cur & (~mask)) | val, reg);
 96}
 97EXPORT_SYMBOL_GPL(ocelot_port_rmwl);
 98
 99u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
100			    u32 reg, u32 offset)
101{
102	u32 val;
103
104	regmap_read(ocelot->targets[target],
105		    ocelot->map[target][reg] + offset, &val);
106	return val;
107}
108
109void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,
110			      u32 val, u32 reg, u32 offset)
111{
112	regmap_write(ocelot->targets[target],
113		     ocelot->map[target][reg] + offset, val);
114}
115
116int ocelot_regfields_init(struct ocelot *ocelot,
117			  const struct reg_field *const regfields)
118{
119	unsigned int i;
120	u16 target;
121
122	for (i = 0; i < REGFIELD_MAX; i++) {
123		struct reg_field regfield = {};
124		u32 reg = regfields[i].reg;
125
126		if (!reg)
127			continue;
128
129		target = regfields[i].reg >> TARGET_OFFSET;
130
131		regfield.reg = ocelot->map[target][reg & REG_MASK];
132		regfield.lsb = regfields[i].lsb;
133		regfield.msb = regfields[i].msb;
134		regfield.id_size = regfields[i].id_size;
135		regfield.id_offset = regfields[i].id_offset;
136
137		ocelot->regfields[i] =
138		devm_regmap_field_alloc(ocelot->dev,
139					ocelot->targets[target],
140					regfield);
141
142		if (IS_ERR(ocelot->regfields[i]))
143			return PTR_ERR(ocelot->regfields[i]);
144	}
145
146	return 0;
147}
148EXPORT_SYMBOL_GPL(ocelot_regfields_init);
149
150static struct regmap_config ocelot_regmap_config = {
151	.reg_bits	= 32,
152	.val_bits	= 32,
153	.reg_stride	= 4,
154};
155
156struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res)
157{
158	void __iomem *regs;
159
160	regs = devm_ioremap_resource(ocelot->dev, res);
161	if (IS_ERR(regs))
162		return ERR_CAST(regs);
163
164	ocelot_regmap_config.name = res->name;
165
166	return devm_regmap_init_mmio(ocelot->dev, regs, &ocelot_regmap_config);
167}
168EXPORT_SYMBOL_GPL(ocelot_regmap_init);