platform.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * ARC HSDK Platform support code
  3. *
  4. * Copyright (C) 2017 Synopsys, Inc. (www.synopsys.com)
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include <linux/init.h>
  11. #include <linux/smp.h>
  12. #include <asm/arcregs.h>
  13. #include <asm/io.h>
  14. #include <asm/mach_desc.h>
  15. #define ARC_CCM_UNUSED_ADDR 0x60000000
  16. static void __init hsdk_init_per_cpu(unsigned int cpu)
  17. {
  18. /*
  19. * By default ICCM is mapped to 0x7z while this area is used for
  20. * kernel virtual mappings, so move it to currently unused area.
  21. */
  22. if (cpuinfo_arc700[cpu].iccm.sz)
  23. write_aux_reg(ARC_REG_AUX_ICCM, ARC_CCM_UNUSED_ADDR);
  24. /*
  25. * By default DCCM is mapped to 0x8z while this area is used by kernel,
  26. * so move it to currently unused area.
  27. */
  28. if (cpuinfo_arc700[cpu].dccm.sz)
  29. write_aux_reg(ARC_REG_AUX_DCCM, ARC_CCM_UNUSED_ADDR);
  30. }
  31. #define ARC_PERIPHERAL_BASE 0xf0000000
  32. #define CREG_BASE (ARC_PERIPHERAL_BASE + 0x1000)
  33. #define CREG_PAE (CREG_BASE + 0x180)
  34. #define CREG_PAE_UPDATE (CREG_BASE + 0x194)
  35. #define SDIO_BASE (ARC_PERIPHERAL_BASE + 0xA000)
  36. #define SDIO_UHS_REG_EXT (SDIO_BASE + 0x108)
  37. #define SDIO_UHS_REG_EXT_DIV_2 (2 << 30)
  38. #define HSDK_GPIO_INTC (ARC_PERIPHERAL_BASE + 0x3000)
  39. static void __init hsdk_enable_gpio_intc_wire(void)
  40. {
  41. /*
  42. * Peripherals on CPU Card are wired to cpu intc via intermediate
  43. * DW APB GPIO blocks (mainly for debouncing)
  44. *
  45. * ---------------------
  46. * | snps,archs-intc |
  47. * ---------------------
  48. * |
  49. * ----------------------
  50. * | snps,archs-idu-intc |
  51. * ----------------------
  52. * | | | | |
  53. * | [eth] [USB] [... other peripherals]
  54. * |
  55. * -------------------
  56. * | snps,dw-apb-intc |
  57. * -------------------
  58. * | | | |
  59. * [Bt] [HAPS] [... other peripherals]
  60. *
  61. * Current implementation of "irq-dw-apb-ictl" driver doesn't work well
  62. * with stacked INTCs. In particular problem happens if its master INTC
  63. * not yet instantiated. See discussion here -
  64. * https://lkml.org/lkml/2015/3/4/755
  65. *
  66. * So setup the first gpio block as a passive pass thru and hide it from
  67. * DT hardware topology - connect intc directly to cpu intc
  68. * The GPIO "wire" needs to be init nevertheless (here)
  69. *
  70. * One side adv is that peripheral interrupt handling avoids one nested
  71. * intc ISR hop
  72. *
  73. * According to HSDK User's Manual [1], "Table 2 Interrupt Mapping"
  74. * we have the following GPIO input lines used as sources of interrupt:
  75. * - GPIO[0] - Bluetooth interrupt of RS9113 module
  76. * - GPIO[2] - HAPS interrupt (on HapsTrak 3 connector)
  77. * - GPIO[3] - Audio codec (MAX9880A) interrupt
  78. * - GPIO[8-23] - Available on Arduino and PMOD_x headers
  79. * For now there's no use of Arduino and PMOD_x headers in Linux
  80. * use-case so we only enable lines 0, 2 and 3.
  81. *
  82. * [1] https://github.com/foss-for-synopsys-dwc-arc-processors/ARC-Development-Systems-Forum/wiki/docs/ARC_HSDK_User_Guide.pdf
  83. */
  84. #define GPIO_INTEN (HSDK_GPIO_INTC + 0x30)
  85. #define GPIO_INTMASK (HSDK_GPIO_INTC + 0x34)
  86. #define GPIO_INTTYPE_LEVEL (HSDK_GPIO_INTC + 0x38)
  87. #define GPIO_INT_POLARITY (HSDK_GPIO_INTC + 0x3c)
  88. #define GPIO_INT_CONNECTED_MASK 0x0d
  89. iowrite32(0xffffffff, (void __iomem *) GPIO_INTMASK);
  90. iowrite32(~GPIO_INT_CONNECTED_MASK, (void __iomem *) GPIO_INTMASK);
  91. iowrite32(0x00000000, (void __iomem *) GPIO_INTTYPE_LEVEL);
  92. iowrite32(0xffffffff, (void __iomem *) GPIO_INT_POLARITY);
  93. iowrite32(GPIO_INT_CONNECTED_MASK, (void __iomem *) GPIO_INTEN);
  94. }
  95. static void __init hsdk_init_early(void)
  96. {
  97. /*
  98. * PAE remapping for DMA clients does not work due to an RTL bug, so
  99. * CREG_PAE register must be programmed to all zeroes, otherwise it
  100. * will cause problems with DMA to/from peripherals even if PAE40 is
  101. * not used.
  102. */
  103. /* Default is 1, which means "PAE offset = 4GByte" */
  104. writel_relaxed(0, (void __iomem *) CREG_PAE);
  105. /* Really apply settings made above */
  106. writel(1, (void __iomem *) CREG_PAE_UPDATE);
  107. /*
  108. * Switch SDIO external ciu clock divider from default div-by-8 to
  109. * minimum possible div-by-2.
  110. */
  111. iowrite32(SDIO_UHS_REG_EXT_DIV_2, (void __iomem *) SDIO_UHS_REG_EXT);
  112. hsdk_enable_gpio_intc_wire();
  113. }
  114. static const char *hsdk_compat[] __initconst = {
  115. "snps,hsdk",
  116. NULL,
  117. };
  118. MACHINE_START(SIMULATION, "hsdk")
  119. .dt_compat = hsdk_compat,
  120. .init_early = hsdk_init_early,
  121. .init_per_cpu = hsdk_init_per_cpu,
  122. MACHINE_END