169 lines · c
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)2/*3 * Microsemi Ocelot Switch driver4 *5 * Copyright (c) 2017 Microsemi Corporation6 */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);169