ocelot_io.c 3.8 KB

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