driver_chipcommon.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * Broadcom specific AMBA
  3. * ChipCommon core driver
  4. *
  5. * Copyright 2005, Broadcom Corporation
  6. * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
  7. * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
  8. *
  9. * Licensed under the GNU/GPL. See COPYING for details.
  10. */
  11. #include "bcma_private.h"
  12. #include <linux/bcm47xx_wdt.h>
  13. #include <linux/export.h>
  14. #include <linux/bcma/bcma.h>
  15. static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
  16. u32 mask, u32 value)
  17. {
  18. value &= mask;
  19. value |= bcma_cc_read32(cc, offset) & ~mask;
  20. bcma_cc_write32(cc, offset, value);
  21. return value;
  22. }
  23. static u32 bcma_chipco_alp_clock(struct bcma_drv_cc *cc)
  24. {
  25. if (cc->capabilities & BCMA_CC_CAP_PMU)
  26. return bcma_pmu_alp_clock(cc);
  27. return 20000000;
  28. }
  29. static u32 bcma_chipco_watchdog_get_max_timer(struct bcma_drv_cc *cc)
  30. {
  31. struct bcma_bus *bus = cc->core->bus;
  32. u32 nb;
  33. if (cc->capabilities & BCMA_CC_CAP_PMU) {
  34. if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
  35. nb = 32;
  36. else if (cc->core->id.rev < 26)
  37. nb = 16;
  38. else
  39. nb = (cc->core->id.rev >= 37) ? 32 : 24;
  40. } else {
  41. nb = 28;
  42. }
  43. if (nb == 32)
  44. return 0xffffffff;
  45. else
  46. return (1 << nb) - 1;
  47. }
  48. static u32 bcma_chipco_watchdog_timer_set_wdt(struct bcm47xx_wdt *wdt,
  49. u32 ticks)
  50. {
  51. struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
  52. return bcma_chipco_watchdog_timer_set(cc, ticks);
  53. }
  54. static u32 bcma_chipco_watchdog_timer_set_ms_wdt(struct bcm47xx_wdt *wdt,
  55. u32 ms)
  56. {
  57. struct bcma_drv_cc *cc = bcm47xx_wdt_get_drvdata(wdt);
  58. u32 ticks;
  59. ticks = bcma_chipco_watchdog_timer_set(cc, cc->ticks_per_ms * ms);
  60. return ticks / cc->ticks_per_ms;
  61. }
  62. static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc)
  63. {
  64. struct bcma_bus *bus = cc->core->bus;
  65. if (cc->capabilities & BCMA_CC_CAP_PMU) {
  66. if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
  67. /* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
  68. return bcma_chipco_alp_clock(cc) / 4000;
  69. else
  70. /* based on 32KHz ILP clock */
  71. return 32;
  72. } else {
  73. return bcma_chipco_alp_clock(cc) / 1000;
  74. }
  75. }
  76. void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
  77. {
  78. if (cc->early_setup_done)
  79. return;
  80. if (cc->core->id.rev >= 11)
  81. cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
  82. cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
  83. if (cc->core->id.rev >= 35)
  84. cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
  85. if (cc->capabilities & BCMA_CC_CAP_PMU)
  86. bcma_pmu_early_init(cc);
  87. cc->early_setup_done = true;
  88. }
  89. void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
  90. {
  91. u32 leddc_on = 10;
  92. u32 leddc_off = 90;
  93. if (cc->setup_done)
  94. return;
  95. bcma_core_chipcommon_early_init(cc);
  96. if (cc->core->id.rev >= 20) {
  97. bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
  98. bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0);
  99. }
  100. if (cc->capabilities & BCMA_CC_CAP_PMU)
  101. bcma_pmu_init(cc);
  102. if (cc->capabilities & BCMA_CC_CAP_PCTL)
  103. bcma_err(cc->core->bus, "Power control not implemented!\n");
  104. if (cc->core->id.rev >= 16) {
  105. if (cc->core->bus->sprom.leddc_on_time &&
  106. cc->core->bus->sprom.leddc_off_time) {
  107. leddc_on = cc->core->bus->sprom.leddc_on_time;
  108. leddc_off = cc->core->bus->sprom.leddc_off_time;
  109. }
  110. bcma_cc_write32(cc, BCMA_CC_GPIOTIMER,
  111. ((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
  112. (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
  113. }
  114. cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc);
  115. cc->setup_done = true;
  116. }
  117. /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
  118. u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks)
  119. {
  120. u32 maxt;
  121. enum bcma_clkmode clkmode;
  122. maxt = bcma_chipco_watchdog_get_max_timer(cc);
  123. if (cc->capabilities & BCMA_CC_CAP_PMU) {
  124. if (ticks == 1)
  125. ticks = 2;
  126. else if (ticks > maxt)
  127. ticks = maxt;
  128. bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks);
  129. } else {
  130. clkmode = ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC;
  131. bcma_core_set_clockmode(cc->core, clkmode);
  132. if (ticks > maxt)
  133. ticks = maxt;
  134. /* instant NMI */
  135. bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks);
  136. }
  137. return ticks;
  138. }
  139. void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value)
  140. {
  141. bcma_cc_write32_masked(cc, BCMA_CC_IRQMASK, mask, value);
  142. }
  143. u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask)
  144. {
  145. return bcma_cc_read32(cc, BCMA_CC_IRQSTAT) & mask;
  146. }
  147. u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask)
  148. {
  149. return bcma_cc_read32(cc, BCMA_CC_GPIOIN) & mask;
  150. }
  151. u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value)
  152. {
  153. return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value);
  154. }
  155. u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value)
  156. {
  157. return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value);
  158. }
  159. u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value)
  160. {
  161. return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value);
  162. }
  163. EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control);
  164. u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value)
  165. {
  166. return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value);
  167. }
  168. u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value)
  169. {
  170. return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value);
  171. }
  172. #ifdef CONFIG_BCMA_DRIVER_MIPS
  173. void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
  174. {
  175. unsigned int irq;
  176. u32 baud_base;
  177. u32 i;
  178. unsigned int ccrev = cc->core->id.rev;
  179. struct bcma_serial_port *ports = cc->serial_ports;
  180. if (ccrev >= 11 && ccrev != 15) {
  181. baud_base = bcma_chipco_alp_clock(cc);
  182. if (ccrev >= 21) {
  183. /* Turn off UART clock before switching clocksource. */
  184. bcma_cc_write32(cc, BCMA_CC_CORECTL,
  185. bcma_cc_read32(cc, BCMA_CC_CORECTL)
  186. & ~BCMA_CC_CORECTL_UARTCLKEN);
  187. }
  188. /* Set the override bit so we don't divide it */
  189. bcma_cc_write32(cc, BCMA_CC_CORECTL,
  190. bcma_cc_read32(cc, BCMA_CC_CORECTL)
  191. | BCMA_CC_CORECTL_UARTCLK0);
  192. if (ccrev >= 21) {
  193. /* Re-enable the UART clock. */
  194. bcma_cc_write32(cc, BCMA_CC_CORECTL,
  195. bcma_cc_read32(cc, BCMA_CC_CORECTL)
  196. | BCMA_CC_CORECTL_UARTCLKEN);
  197. }
  198. } else {
  199. bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev);
  200. return;
  201. }
  202. irq = bcma_core_mips_irq(cc->core);
  203. /* Determine the registers of the UARTs */
  204. cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
  205. for (i = 0; i < cc->nr_serial_ports; i++) {
  206. ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
  207. (i * 256);
  208. ports[i].irq = irq;
  209. ports[i].baud_base = baud_base;
  210. ports[i].reg_shift = 0;
  211. }
  212. }
  213. #endif /* CONFIG_BCMA_DRIVER_MIPS */