ocelot_io.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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. #include "ocelot.h"
  11. int __ocelot_bulk_read_ix(struct ocelot *ocelot, enum ocelot_reg reg,
  12. u32 offset, void *buf, int count)
  13. {
  14. enum ocelot_target target;
  15. u32 addr;
  16. ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
  17. WARN_ON(!target);
  18. return regmap_bulk_read(ocelot->targets[target], addr + offset,
  19. buf, count);
  20. }
  21. EXPORT_SYMBOL_GPL(__ocelot_bulk_read_ix);
  22. u32 __ocelot_read_ix(struct ocelot *ocelot, enum ocelot_reg reg, u32 offset)
  23. {
  24. enum ocelot_target target;
  25. u32 addr, val;
  26. ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
  27. WARN_ON(!target);
  28. regmap_read(ocelot->targets[target], addr + offset, &val);
  29. return val;
  30. }
  31. EXPORT_SYMBOL_GPL(__ocelot_read_ix);
  32. void __ocelot_write_ix(struct ocelot *ocelot, u32 val, enum ocelot_reg reg,
  33. u32 offset)
  34. {
  35. enum ocelot_target target;
  36. u32 addr;
  37. ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
  38. WARN_ON(!target);
  39. regmap_write(ocelot->targets[target], addr + offset, val);
  40. }
  41. EXPORT_SYMBOL_GPL(__ocelot_write_ix);
  42. void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask,
  43. enum ocelot_reg reg, u32 offset)
  44. {
  45. enum ocelot_target target;
  46. u32 addr;
  47. ocelot_reg_to_target_addr(ocelot, reg, &target, &addr);
  48. WARN_ON(!target);
  49. regmap_update_bits(ocelot->targets[target], addr + offset, mask, val);
  50. }
  51. EXPORT_SYMBOL_GPL(__ocelot_rmw_ix);
  52. u32 ocelot_port_readl(struct ocelot_port *port, enum ocelot_reg reg)
  53. {
  54. struct ocelot *ocelot = port->ocelot;
  55. u16 target = reg >> TARGET_OFFSET;
  56. u32 val;
  57. WARN_ON(!target);
  58. regmap_read(port->target, ocelot->map[target][reg & REG_MASK], &val);
  59. return val;
  60. }
  61. EXPORT_SYMBOL_GPL(ocelot_port_readl);
  62. void ocelot_port_writel(struct ocelot_port *port, u32 val, enum ocelot_reg reg)
  63. {
  64. struct ocelot *ocelot = port->ocelot;
  65. u16 target = reg >> TARGET_OFFSET;
  66. WARN_ON(!target);
  67. regmap_write(port->target, ocelot->map[target][reg & REG_MASK], val);
  68. }
  69. EXPORT_SYMBOL_GPL(ocelot_port_writel);
  70. void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask,
  71. enum ocelot_reg reg)
  72. {
  73. u32 cur = ocelot_port_readl(port, reg);
  74. ocelot_port_writel(port, (cur & (~mask)) | val, reg);
  75. }
  76. EXPORT_SYMBOL_GPL(ocelot_port_rmwl);
  77. u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
  78. u32 reg, u32 offset)
  79. {
  80. u32 val;
  81. regmap_read(ocelot->targets[target],
  82. ocelot->map[target][reg] + offset, &val);
  83. return val;
  84. }
  85. void __ocelot_target_write_ix(struct ocelot *ocelot, enum ocelot_target target,
  86. u32 val, u32 reg, u32 offset)
  87. {
  88. regmap_write(ocelot->targets[target],
  89. ocelot->map[target][reg] + offset, val);
  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. for (i = 0; i < REGFIELD_MAX; i++) {
  97. struct reg_field regfield = {};
  98. u32 reg = regfields[i].reg;
  99. if (!reg)
  100. continue;
  101. target = regfields[i].reg >> TARGET_OFFSET;
  102. regfield.reg = ocelot->map[target][reg & REG_MASK];
  103. regfield.lsb = regfields[i].lsb;
  104. regfield.msb = regfields[i].msb;
  105. regfield.id_size = regfields[i].id_size;
  106. regfield.id_offset = regfields[i].id_offset;
  107. ocelot->regfields[i] =
  108. devm_regmap_field_alloc(ocelot->dev,
  109. ocelot->targets[target],
  110. regfield);
  111. if (IS_ERR(ocelot->regfields[i]))
  112. return PTR_ERR(ocelot->regfields[i]);
  113. }
  114. return 0;
  115. }
  116. EXPORT_SYMBOL_GPL(ocelot_regfields_init);
  117. static struct regmap_config ocelot_regmap_config = {
  118. .reg_bits = 32,
  119. .val_bits = 32,
  120. .reg_stride = 4,
  121. };
  122. struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res)
  123. {
  124. void __iomem *regs;
  125. regs = devm_ioremap_resource(ocelot->dev, res);
  126. if (IS_ERR(regs))
  127. return ERR_CAST(regs);
  128. ocelot_regmap_config.name = res->name;
  129. return devm_regmap_init_mmio(ocelot->dev, regs, &ocelot_regmap_config);
  130. }
  131. EXPORT_SYMBOL_GPL(ocelot_regmap_init);