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 int ocelot_regfields_init(struct ocelot *ocelot, 75 const struct reg_field *const regfields) 76 { 77 unsigned int i; 78 u16 target; 79 80 for (i = 0; i < REGFIELD_MAX; i++) { 81 struct reg_field regfield = {}; 82 u32 reg = regfields[i].reg; 83 84 if (!reg) 85 continue; 86 87 target = regfields[i].reg >> TARGET_OFFSET; 88 89 regfield.reg = ocelot->map[target][reg & REG_MASK]; 90 regfield.lsb = regfields[i].lsb; 91 regfield.msb = regfields[i].msb; 92 regfield.id_size = regfields[i].id_size; 93 regfield.id_offset = regfields[i].id_offset; 94 95 ocelot->regfields[i] = 96 devm_regmap_field_alloc(ocelot->dev, 97 ocelot->targets[target], 98 regfield); 99 100 if (IS_ERR(ocelot->regfields[i])) 101 return PTR_ERR(ocelot->regfields[i]); 102 } 103 104 return 0; 105 } 106 EXPORT_SYMBOL(ocelot_regfields_init); 107 108 static struct regmap_config ocelot_regmap_config = { 109 .reg_bits = 32, 110 .val_bits = 32, 111 .reg_stride = 4, 112 }; 113 114 struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res) 115 { 116 void __iomem *regs; 117 118 regs = devm_ioremap_resource(ocelot->dev, res); 119 if (IS_ERR(regs)) 120 return ERR_CAST(regs); 121 122 ocelot_regmap_config.name = res->name; 123 124 return devm_regmap_init_mmio(ocelot->dev, regs, &ocelot_regmap_config); 125 } 126 EXPORT_SYMBOL(ocelot_regmap_init); 127