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 13 int __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 } 25 EXPORT_SYMBOL_GPL(__ocelot_bulk_read_ix); 26 27 u32 __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 } 38 EXPORT_SYMBOL_GPL(__ocelot_read_ix); 39 40 void __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 } 51 EXPORT_SYMBOL_GPL(__ocelot_write_ix); 52 53 void __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 } 64 EXPORT_SYMBOL_GPL(__ocelot_rmw_ix); 65 66 u32 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 } 77 EXPORT_SYMBOL_GPL(ocelot_port_readl); 78 79 void 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 } 88 EXPORT_SYMBOL_GPL(ocelot_port_writel); 89 90 void 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 } 97 EXPORT_SYMBOL_GPL(ocelot_port_rmwl); 98 99 u32 __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 109 void __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 116 int 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 } 148 EXPORT_SYMBOL_GPL(ocelot_regfields_init); 149 150 static struct regmap_config ocelot_regmap_config = { 151 .reg_bits = 32, 152 .val_bits = 32, 153 .reg_stride = 4, 154 }; 155 156 struct 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 } 168 EXPORT_SYMBOL_GPL(ocelot_regmap_init); 169