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 u32 __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 } 24 EXPORT_SYMBOL(__ocelot_read_ix); 25 26 void __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 } 35 EXPORT_SYMBOL(__ocelot_write_ix); 36 37 void __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 } 48 EXPORT_SYMBOL(__ocelot_rmw_ix); 49 50 u32 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 } 61 EXPORT_SYMBOL(ocelot_port_readl); 62 63 void 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 } 72 EXPORT_SYMBOL(ocelot_port_writel); 73 74 u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target, 75 u32 reg, u32 offset) 76 { 77 u32 val; 78 79 regmap_read(ocelot->targets[target], 80 ocelot->map[target][reg] + offset, &val); 81 return val; 82 } 83 84 void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target, 85 u32 val, u32 reg, u32 offset) 86 { 87 regmap_write(ocelot->targets[target], 88 ocelot->map[target][reg] + offset, val); 89 } 90 91 int ocelot_regfields_init(struct ocelot *ocelot, 92 const struct reg_field *const regfields) 93 { 94 unsigned int i; 95 u16 target; 96 97 for (i = 0; i < REGFIELD_MAX; i++) { 98 struct reg_field regfield = {}; 99 u32 reg = regfields[i].reg; 100 101 if (!reg) 102 continue; 103 104 target = regfields[i].reg >> TARGET_OFFSET; 105 106 regfield.reg = ocelot->map[target][reg & REG_MASK]; 107 regfield.lsb = regfields[i].lsb; 108 regfield.msb = regfields[i].msb; 109 regfield.id_size = regfields[i].id_size; 110 regfield.id_offset = regfields[i].id_offset; 111 112 ocelot->regfields[i] = 113 devm_regmap_field_alloc(ocelot->dev, 114 ocelot->targets[target], 115 regfield); 116 117 if (IS_ERR(ocelot->regfields[i])) 118 return PTR_ERR(ocelot->regfields[i]); 119 } 120 121 return 0; 122 } 123 EXPORT_SYMBOL(ocelot_regfields_init); 124 125 static struct regmap_config ocelot_regmap_config = { 126 .reg_bits = 32, 127 .val_bits = 32, 128 .reg_stride = 4, 129 }; 130 131 struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res) 132 { 133 void __iomem *regs; 134 135 regs = devm_ioremap_resource(ocelot->dev, res); 136 if (IS_ERR(regs)) 137 return ERR_CAST(regs); 138 139 ocelot_regmap_config.name = res->name; 140 141 return devm_regmap_init_mmio(ocelot->dev, regs, &ocelot_regmap_config); 142 } 143 EXPORT_SYMBOL(ocelot_regmap_init); 144