Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
0002 /*
0003  * Microsemi Ocelot Switch driver
0004  *
0005  * Copyright (c) 2017 Microsemi Corporation
0006  */
0007 #include <linux/io.h>
0008 #include <linux/kernel.h>
0009 #include <linux/platform_device.h>
0010 
0011 #include "ocelot.h"
0012 
0013 int __ocelot_bulk_read_ix(struct ocelot *ocelot, u32 reg, u32 offset, void *buf,
0014               int count)
0015 {
0016     u16 target = reg >> TARGET_OFFSET;
0017 
0018     WARN_ON(!target);
0019 
0020     return regmap_bulk_read(ocelot->targets[target],
0021                 ocelot->map[target][reg & REG_MASK] + offset,
0022                 buf, count);
0023 }
0024 EXPORT_SYMBOL_GPL(__ocelot_bulk_read_ix);
0025 
0026 u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset)
0027 {
0028     u16 target = reg >> TARGET_OFFSET;
0029     u32 val;
0030 
0031     WARN_ON(!target);
0032 
0033     regmap_read(ocelot->targets[target],
0034             ocelot->map[target][reg & REG_MASK] + offset, &val);
0035     return val;
0036 }
0037 EXPORT_SYMBOL_GPL(__ocelot_read_ix);
0038 
0039 void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset)
0040 {
0041     u16 target = reg >> TARGET_OFFSET;
0042 
0043     WARN_ON(!target);
0044 
0045     regmap_write(ocelot->targets[target],
0046              ocelot->map[target][reg & REG_MASK] + offset, val);
0047 }
0048 EXPORT_SYMBOL_GPL(__ocelot_write_ix);
0049 
0050 void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
0051              u32 offset)
0052 {
0053     u16 target = reg >> TARGET_OFFSET;
0054 
0055     WARN_ON(!target);
0056 
0057     regmap_update_bits(ocelot->targets[target],
0058                ocelot->map[target][reg & REG_MASK] + offset,
0059                mask, val);
0060 }
0061 EXPORT_SYMBOL_GPL(__ocelot_rmw_ix);
0062 
0063 u32 ocelot_port_readl(struct ocelot_port *port, u32 reg)
0064 {
0065     struct ocelot *ocelot = port->ocelot;
0066     u16 target = reg >> TARGET_OFFSET;
0067     u32 val;
0068 
0069     WARN_ON(!target);
0070 
0071     regmap_read(port->target, ocelot->map[target][reg & REG_MASK], &val);
0072     return val;
0073 }
0074 EXPORT_SYMBOL_GPL(ocelot_port_readl);
0075 
0076 void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg)
0077 {
0078     struct ocelot *ocelot = port->ocelot;
0079     u16 target = reg >> TARGET_OFFSET;
0080 
0081     WARN_ON(!target);
0082 
0083     regmap_write(port->target, ocelot->map[target][reg & REG_MASK], val);
0084 }
0085 EXPORT_SYMBOL_GPL(ocelot_port_writel);
0086 
0087 void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask, u32 reg)
0088 {
0089     u32 cur = ocelot_port_readl(port, reg);
0090 
0091     ocelot_port_writel(port, (cur & (~mask)) | val, reg);
0092 }
0093 EXPORT_SYMBOL_GPL(ocelot_port_rmwl);
0094 
0095 u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
0096                 u32 reg, u32 offset)
0097 {
0098     u32 val;
0099 
0100     regmap_read(ocelot->targets[target],
0101             ocelot->map[target][reg] + offset, &val);
0102     return val;
0103 }
0104 
0105 void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,
0106                   u32 val, u32 reg, u32 offset)
0107 {
0108     regmap_write(ocelot->targets[target],
0109              ocelot->map[target][reg] + offset, val);
0110 }
0111 
0112 int ocelot_regfields_init(struct ocelot *ocelot,
0113               const struct reg_field *const regfields)
0114 {
0115     unsigned int i;
0116     u16 target;
0117 
0118     for (i = 0; i < REGFIELD_MAX; i++) {
0119         struct reg_field regfield = {};
0120         u32 reg = regfields[i].reg;
0121 
0122         if (!reg)
0123             continue;
0124 
0125         target = regfields[i].reg >> TARGET_OFFSET;
0126 
0127         regfield.reg = ocelot->map[target][reg & REG_MASK];
0128         regfield.lsb = regfields[i].lsb;
0129         regfield.msb = regfields[i].msb;
0130         regfield.id_size = regfields[i].id_size;
0131         regfield.id_offset = regfields[i].id_offset;
0132 
0133         ocelot->regfields[i] =
0134         devm_regmap_field_alloc(ocelot->dev,
0135                     ocelot->targets[target],
0136                     regfield);
0137 
0138         if (IS_ERR(ocelot->regfields[i]))
0139             return PTR_ERR(ocelot->regfields[i]);
0140     }
0141 
0142     return 0;
0143 }
0144 EXPORT_SYMBOL_GPL(ocelot_regfields_init);
0145 
0146 static struct regmap_config ocelot_regmap_config = {
0147     .reg_bits   = 32,
0148     .val_bits   = 32,
0149     .reg_stride = 4,
0150 };
0151 
0152 struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res)
0153 {
0154     void __iomem *regs;
0155 
0156     regs = devm_ioremap_resource(ocelot->dev, res);
0157     if (IS_ERR(regs))
0158         return ERR_CAST(regs);
0159 
0160     ocelot_regmap_config.name = res->name;
0161 
0162     return devm_regmap_init_mmio(ocelot->dev, regs, &ocelot_regmap_config);
0163 }
0164 EXPORT_SYMBOL_GPL(ocelot_regmap_init);