linux/drivers/net/ethernet/mscc/ocelot_io.c
<<
>>
Prefs
   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
  13u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset)
  14{
  15        u16 target = reg >> TARGET_OFFSET;
  16        u32 val;
  17
  18        WARN_ON(!target);
  19
  20        regmap_read(ocelot->targets[target],
  21                    ocelot->map[target][reg & REG_MASK] + offset, &val);
  22        return val;
  23}
  24EXPORT_SYMBOL_GPL(__ocelot_read_ix);
  25
  26void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset)
  27{
  28        u16 target = reg >> TARGET_OFFSET;
  29
  30        WARN_ON(!target);
  31
  32        regmap_write(ocelot->targets[target],
  33                     ocelot->map[target][reg & REG_MASK] + offset, val);
  34}
  35EXPORT_SYMBOL_GPL(__ocelot_write_ix);
  36
  37void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
  38                     u32 offset)
  39{
  40        u16 target = reg >> TARGET_OFFSET;
  41
  42        WARN_ON(!target);
  43
  44        regmap_update_bits(ocelot->targets[target],
  45                           ocelot->map[target][reg & REG_MASK] + offset,
  46                           mask, val);
  47}
  48EXPORT_SYMBOL_GPL(__ocelot_rmw_ix);
  49
  50u32 ocelot_port_readl(struct ocelot_port *port, u32 reg)
  51{
  52        struct ocelot *ocelot = port->ocelot;
  53        u16 target = reg >> TARGET_OFFSET;
  54        u32 val;
  55
  56        WARN_ON(!target);
  57
  58        regmap_read(port->target, ocelot->map[target][reg & REG_MASK], &val);
  59        return val;
  60}
  61EXPORT_SYMBOL_GPL(ocelot_port_readl);
  62
  63void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg)
  64{
  65        struct ocelot *ocelot = port->ocelot;
  66        u16 target = reg >> TARGET_OFFSET;
  67
  68        WARN_ON(!target);
  69
  70        regmap_write(port->target, ocelot->map[target][reg & REG_MASK], val);
  71}
  72EXPORT_SYMBOL_GPL(ocelot_port_writel);
  73
  74void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask, u32 reg)
  75{
  76        u32 cur = ocelot_port_readl(port, reg);
  77
  78        ocelot_port_writel(port, (cur & (~mask)) | val, reg);
  79}
  80EXPORT_SYMBOL_GPL(ocelot_port_rmwl);
  81
  82u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
  83                            u32 reg, u32 offset)
  84{
  85        u32 val;
  86
  87        regmap_read(ocelot->targets[target],
  88                    ocelot->map[target][reg] + offset, &val);
  89        return val;
  90}
  91
  92void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,
  93                              u32 val, u32 reg, u32 offset)
  94{
  95        regmap_write(ocelot->targets[target],
  96                     ocelot->map[target][reg] + offset, val);
  97}
  98
  99int ocelot_regfields_init(struct ocelot *ocelot,
 100                          const struct reg_field *const regfields)
 101{
 102        unsigned int i;
 103        u16 target;
 104
 105        for (i = 0; i < REGFIELD_MAX; i++) {
 106                struct reg_field regfield = {};
 107                u32 reg = regfields[i].reg;
 108
 109                if (!reg)
 110                        continue;
 111
 112                target = regfields[i].reg >> TARGET_OFFSET;
 113
 114                regfield.reg = ocelot->map[target][reg & REG_MASK];
 115                regfield.lsb = regfields[i].lsb;
 116                regfield.msb = regfields[i].msb;
 117                regfield.id_size = regfields[i].id_size;
 118                regfield.id_offset = regfields[i].id_offset;
 119
 120                ocelot->regfields[i] =
 121                devm_regmap_field_alloc(ocelot->dev,
 122                                        ocelot->targets[target],
 123                                        regfield);
 124
 125                if (IS_ERR(ocelot->regfields[i]))
 126                        return PTR_ERR(ocelot->regfields[i]);
 127        }
 128
 129        return 0;
 130}
 131EXPORT_SYMBOL_GPL(ocelot_regfields_init);
 132
 133static struct regmap_config ocelot_regmap_config = {
 134        .reg_bits       = 32,
 135        .val_bits       = 32,
 136        .reg_stride     = 4,
 137};
 138
 139struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res)
 140{
 141        void __iomem *regs;
 142
 143        regs = devm_ioremap_resource(ocelot->dev, res);
 144        if (IS_ERR(regs))
 145                return ERR_CAST(regs);
 146
 147        ocelot_regmap_config.name = res->name;
 148
 149        return devm_regmap_init_mmio(ocelot->dev, regs, &ocelot_regmap_config);
 150}
 151EXPORT_SYMBOL_GPL(ocelot_regmap_init);
 152