pinctrl-meson8-pmx.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * First generation of pinmux driver for Amlogic Meson SoCs
  4. *
  5. * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
  6. * Copyright (C) 2017 Jerome Brunet <jbrunet@baylibre.com>
  7. */
  8. /* For this first generation of pinctrl driver every pinmux group can be
  9. * enabled by a specific bit in the first register range. When all groups for
  10. * a given pin are disabled the pin acts as a GPIO.
  11. */
  12. #include <linux/device.h>
  13. #include <linux/regmap.h>
  14. #include <linux/pinctrl/pinctrl.h>
  15. #include <linux/pinctrl/pinmux.h>
  16. #include "pinctrl-meson.h"
  17. #include "pinctrl-meson8-pmx.h"
  18. /**
  19. * meson8_pmx_disable_other_groups() - disable other groups using a given pin
  20. *
  21. * @pc: meson pin controller device
  22. * @pin: number of the pin
  23. * @sel_group: index of the selected group, or -1 if none
  24. *
  25. * The function disables all pinmux groups using a pin except the
  26. * selected one. If @sel_group is -1 all groups are disabled, leaving
  27. * the pin in GPIO mode.
  28. */
  29. static void meson8_pmx_disable_other_groups(struct meson_pinctrl *pc,
  30. unsigned int pin, int sel_group)
  31. {
  32. struct meson_pmx_group *group;
  33. struct meson8_pmx_data *pmx_data;
  34. int i, j;
  35. for (i = 0; i < pc->data->num_groups; i++) {
  36. group = &pc->data->groups[i];
  37. pmx_data = (struct meson8_pmx_data *)group->data;
  38. if (pmx_data->is_gpio || i == sel_group)
  39. continue;
  40. for (j = 0; j < group->num_pins; j++) {
  41. if (group->pins[j] == pin) {
  42. /* We have found a group using the pin */
  43. regmap_update_bits(pc->reg_mux,
  44. pmx_data->reg * 4,
  45. BIT(pmx_data->bit), 0);
  46. }
  47. }
  48. }
  49. }
  50. static int meson8_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned func_num,
  51. unsigned group_num)
  52. {
  53. struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
  54. struct meson_pmx_func *func = &pc->data->funcs[func_num];
  55. struct meson_pmx_group *group = &pc->data->groups[group_num];
  56. struct meson8_pmx_data *pmx_data =
  57. (struct meson8_pmx_data *)group->data;
  58. int i, ret = 0;
  59. dev_dbg(pc->dev, "enable function %s, group %s\n", func->name,
  60. group->name);
  61. /*
  62. * Disable groups using the same pin.
  63. * The selected group is not disabled to avoid glitches.
  64. */
  65. for (i = 0; i < group->num_pins; i++)
  66. meson8_pmx_disable_other_groups(pc, group->pins[i], group_num);
  67. /* Function 0 (GPIO) doesn't need any additional setting */
  68. if (func_num)
  69. ret = regmap_update_bits(pc->reg_mux, pmx_data->reg * 4,
  70. BIT(pmx_data->bit),
  71. BIT(pmx_data->bit));
  72. return ret;
  73. }
  74. static int meson8_pmx_request_gpio(struct pinctrl_dev *pcdev,
  75. struct pinctrl_gpio_range *range,
  76. unsigned offset)
  77. {
  78. struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev);
  79. meson8_pmx_disable_other_groups(pc, offset, -1);
  80. return 0;
  81. }
  82. const struct pinmux_ops meson8_pmx_ops = {
  83. .set_mux = meson8_pmx_set_mux,
  84. .get_functions_count = meson_pmx_get_funcs_count,
  85. .get_function_name = meson_pmx_get_func_name,
  86. .get_function_groups = meson_pmx_get_groups,
  87. .gpio_request_enable = meson8_pmx_request_gpio,
  88. };
  89. EXPORT_SYMBOL_GPL(meson8_pmx_ops);
  90. MODULE_LICENSE("GPL v2");