iomux.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2004-2006,2010 Freescale Semiconductor, Inc. All Rights Reserved.
  4. * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
  5. * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
  6. * <armlinux@phytec.de>
  7. */
  8. #include <common.h>
  9. #include <linux/errno.h>
  10. #include <asm/io.h>
  11. #include <asm/arch/clock.h>
  12. #include <asm/arch/iomux.h>
  13. #include <asm/arch/imx-regs.h>
  14. #if defined(CONFIG_MX23)
  15. #define DRIVE_OFFSET 0x200
  16. #define PULL_OFFSET 0x400
  17. #elif defined(CONFIG_MX28)
  18. #define DRIVE_OFFSET 0x300
  19. #define PULL_OFFSET 0x600
  20. #else
  21. #error "Please select CONFIG_MX23 or CONFIG_MX28"
  22. #endif
  23. /*
  24. * configures a single pad in the iomuxer
  25. */
  26. int mxs_iomux_setup_pad(iomux_cfg_t pad)
  27. {
  28. u32 reg, ofs, bp, bm;
  29. void *iomux_base = (void *)MXS_PINCTRL_BASE;
  30. struct mxs_register_32 *mxs_reg;
  31. /* muxsel */
  32. ofs = 0x100;
  33. ofs += PAD_BANK(pad) * 0x20 + PAD_PIN(pad) / 16 * 0x10;
  34. bp = PAD_PIN(pad) % 16 * 2;
  35. bm = 0x3 << bp;
  36. reg = readl(iomux_base + ofs);
  37. reg &= ~bm;
  38. reg |= PAD_MUXSEL(pad) << bp;
  39. writel(reg, iomux_base + ofs);
  40. /* drive */
  41. ofs = DRIVE_OFFSET;
  42. ofs += PAD_BANK(pad) * 0x40 + PAD_PIN(pad) / 8 * 0x10;
  43. /* mA */
  44. if (PAD_MA_VALID(pad)) {
  45. bp = PAD_PIN(pad) % 8 * 4;
  46. bm = 0x3 << bp;
  47. reg = readl(iomux_base + ofs);
  48. reg &= ~bm;
  49. reg |= PAD_MA(pad) << bp;
  50. writel(reg, iomux_base + ofs);
  51. }
  52. /* vol */
  53. if (PAD_VOL_VALID(pad)) {
  54. bp = PAD_PIN(pad) % 8 * 4 + 2;
  55. mxs_reg = (struct mxs_register_32 *)(iomux_base + ofs);
  56. if (PAD_VOL(pad))
  57. writel(1 << bp, &mxs_reg->reg_set);
  58. else
  59. writel(1 << bp, &mxs_reg->reg_clr);
  60. }
  61. /* pull */
  62. if (PAD_PULL_VALID(pad)) {
  63. ofs = PULL_OFFSET;
  64. ofs += PAD_BANK(pad) * 0x10;
  65. bp = PAD_PIN(pad);
  66. mxs_reg = (struct mxs_register_32 *)(iomux_base + ofs);
  67. if (PAD_PULL(pad))
  68. writel(1 << bp, &mxs_reg->reg_set);
  69. else
  70. writel(1 << bp, &mxs_reg->reg_clr);
  71. }
  72. return 0;
  73. }
  74. int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count)
  75. {
  76. const iomux_cfg_t *p = pad_list;
  77. int i;
  78. int ret;
  79. for (i = 0; i < count; i++) {
  80. ret = mxs_iomux_setup_pad(*p);
  81. if (ret)
  82. return ret;
  83. p++;
  84. }
  85. return 0;
  86. }