343-MIPS-BCM63XX-add-PCIe-support-for-BCM6318.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. From 11a8ab8dac4ef5d0d70199843043927edce1d4db Mon Sep 17 00:00:00 2001
  2. From: Jonas Gorski <jogo@openwrt.org>
  3. Date: Sun, 15 Dec 2013 20:47:34 +0100
  4. Subject: [PATCH 53/53] MIPS: BCM63XX: add PCIe support for BCM6318
  5. ---
  6. arch/mips/bcm63xx/clk.c | 25 ++++-
  7. arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h | 6 ++
  8. arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 60 +++++++++++-
  9. arch/mips/pci/ops-bcm63xx.c | 16 +++-
  10. arch/mips/pci/pci-bcm63xx.c | 106 ++++++++++++++++++----
  11. 5 files changed, 184 insertions(+), 29 deletions(-)
  12. --- a/arch/mips/bcm63xx/clk.c
  13. +++ b/arch/mips/bcm63xx/clk.c
  14. @@ -50,6 +50,18 @@ static void bcm_hwclock_set(u32 mask, in
  15. bcm_perf_writel(reg, PERF_CKCTL_REG);
  16. }
  17. +static void bcm_ub_hwclock_set(u32 mask, int enable)
  18. +{
  19. + u32 reg;
  20. +
  21. + reg = bcm_perf_readl(PERF_UB_CKCTL_REG);
  22. + if (enable)
  23. + reg |= mask;
  24. + else
  25. + reg &= ~mask;
  26. + bcm_perf_writel(reg, PERF_UB_CKCTL_REG);
  27. +}
  28. +
  29. /*
  30. * Ethernet MAC "misc" clock: dma clocks and main clock on 6348
  31. */
  32. @@ -317,12 +329,17 @@ static struct clk clk_ipsec = {
  33. static void pcie_set(struct clk *clk, int enable)
  34. {
  35. - if (BCMCPU_IS_6328())
  36. + if (BCMCPU_IS_6318()) {
  37. + bcm_hwclock_set(CKCTL_6318_PCIE_EN, enable);
  38. + bcm_hwclock_set(CKCTL_6318_PCIE25_EN, enable);
  39. + bcm_ub_hwclock_set(UB_CKCTL_6318_PCIE_EN, enable);
  40. + } else if (BCMCPU_IS_6328()) {
  41. bcm_hwclock_set(CKCTL_6328_PCIE_EN, enable);
  42. - else if (BCMCPU_IS_6362())
  43. + } else if (BCMCPU_IS_6362()) {
  44. bcm_hwclock_set(CKCTL_6362_PCIE_EN, enable);
  45. - else if (BCMCPU_IS_63268())
  46. + } else if (BCMCPU_IS_63268()) {
  47. bcm_hwclock_set(CKCTL_63268_PCIE_EN, enable);
  48. + }
  49. }
  50. static struct clk clk_pcie = {
  51. @@ -408,7 +425,7 @@ struct clk *clk_get(struct device *dev,
  52. if ((BCMCPU_IS_6362() || BCMCPU_IS_6368() || BCMCPU_IS_63268()) &&
  53. !strcmp(id, "ipsec"))
  54. return &clk_ipsec;
  55. - if ((BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268()) &&
  56. + if ((BCMCPU_IS_6318() || BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268()) &&
  57. !strcmp(id, "pcie"))
  58. return &clk_pcie;
  59. return ERR_PTR(-ENOENT);
  60. --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
  61. +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_io.h
  62. @@ -40,6 +40,12 @@
  63. #define BCM_CB_MEM_END_PA (BCM_CB_MEM_BASE_PA + \
  64. BCM_CB_MEM_SIZE - 1)
  65. +#define BCM_PCIE_MEM_BASE_PA_6318 0x10200000
  66. +#define BCM_PCIE_MEM_SIZE_6318 (1 * 1024 * 1024)
  67. +#define BCM_PCIE_MEM_END_PA_6318 (BCM_PCIE_MEM_BASE_PA_6318 + \
  68. + BCM_PCIE_MEM_SIZE_6318 - 1)
  69. +
  70. +
  71. #define BCM_PCIE_MEM_BASE_PA_6328 0x10f00000
  72. #define BCM_PCIE_MEM_SIZE_6328 (1 * 1024 * 1024)
  73. #define BCM_PCIE_MEM_END_PA_6328 (BCM_PCIE_MEM_BASE_PA_6328 + \
  74. --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
  75. +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
  76. @@ -1529,6 +1529,17 @@
  77. * _REG relative to RSET_PCIE
  78. *************************************************************************/
  79. +#define PCIE_SPECIFIC_REG 0x188
  80. +#define SPECIFIC_ENDIAN_MODE_BAR1_SHIFT 0
  81. +#define SPECIFIC_ENDIAN_MODE_BAR1_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
  82. +#define SPECIFIC_ENDIAN_MODE_BAR2_SHIFT 2
  83. +#define SPECIFIC_ENDIAN_MODE_BAR2_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
  84. +#define SPECIFIC_ENDIAN_MODE_BAR3_SHIFT 4
  85. +#define SPECIFIC_ENDIAN_MODE_BAR3_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
  86. +#define SPECIFIC_ENDIAN_MODE_WORD_ALIGN 0
  87. +#define SPECIFIC_ENDIAN_MODE_HALFWORD_ALIGN 1
  88. +#define SPECIFIC_ENDIAN_MODE_BYTE_ALIGN 2
  89. +
  90. #define PCIE_CONFIG2_REG 0x408
  91. #define CONFIG2_BAR1_SIZE_EN 1
  92. #define CONFIG2_BAR1_SIZE_MASK 0xf
  93. @@ -1574,7 +1585,54 @@
  94. #define PCIE_RC_INT_C (1 << 2)
  95. #define PCIE_RC_INT_D (1 << 3)
  96. -#define PCIE_DEVICE_OFFSET 0x8000
  97. +#define PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG 0x400c
  98. +#define C2P_MEM_WIN_ENDIAN_MODE_MASK 0x3
  99. +#define C2P_MEM_WIN_ENDIAN_NO_SWAP 0
  100. +#define C2P_MEM_WIN_ENDIAN_HALF_WORD_SWAP 1
  101. +#define C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP 2
  102. +#define C2P_MEM_WIN_BASE_ADDR_SHIFT 20
  103. +#define C2P_MEM_WIN_BASE_ADDR_MASK (0xfff << C2P_MEM_WIN_BASE_ADDR_SHIFT)
  104. +
  105. +#define PCIE_RC_BAR1_CONFIG_LO_REG 0x402c
  106. +#define RC_BAR_CFG_LO_SIZE_256MB 0xd
  107. +#define RC_BAR_CFG_LO_MATCH_ADDR_SHIFT 20
  108. +#define RC_BAR_CFG_LO_MATCH_ADDR_MASK (0xfff << RC_BAR_CFG_LO_MATCH_ADDR_SHIFT)
  109. +
  110. +#define PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG 0x4070
  111. +#define C2P_BASELIMIT_LIMIT_SHIFT 20
  112. +#define C2P_BASELIMIT_LIMIT_MASK (0xfff << C2P_BASELIMIT_LIMIT_SHIFT)
  113. +#define C2P_BASELIMIT_BASE_SHIFT 4
  114. +#define C2P_BASELIMIT_BASE_MASK (0xfff << C2P_BASELIMIT_BASE_SHIFT)
  115. +
  116. +#define PCIE_UBUS_BAR1_CFG_REMAP_REG 0x4088
  117. +#define BAR1_CFG_REMAP_OFFSET_SHIFT 20
  118. +#define BAR1_CFG_REMAP_OFFSET_MASK (0xfff << BAR1_CFG_REMAP_OFFSET_SHIFT)
  119. +#define BAR1_CFG_REMAP_ACCESS_EN 1
  120. +
  121. +#define PCIE_HARD_DEBUG_REG 0x4204
  122. +#define HARD_DEBUG_SERDES_IDDQ (1 << 23)
  123. +
  124. +#define PCIE_CPU_INT1_MASK_CLEAR_REG 0x830c
  125. +#define CPU_INT_PCIE_ERR_ATTN_CPU (1 << 0)
  126. +#define CPU_INT_PCIE_INTA (1 << 1)
  127. +#define CPU_INT_PCIE_INTB (1 << 2)
  128. +#define CPU_INT_PCIE_INTC (1 << 3)
  129. +#define CPU_INT_PCIE_INTD (1 << 4)
  130. +#define CPU_INT_PCIE_INTR (1 << 5)
  131. +#define CPU_INT_PCIE_NMI (1 << 6)
  132. +#define CPU_INT_PCIE_UBUS (1 << 7)
  133. +#define CPU_INT_IPI (1 << 8)
  134. +
  135. +#define PCIE_EXT_CFG_INDEX_REG 0x8400
  136. +#define EXT_CFG_FUNC_NUM_SHIFT 12
  137. +#define EXT_CFG_FUNC_NUM_MASK (0x7 << EXT_CFG_FUNC_NUM_SHIFT)
  138. +#define EXT_CFG_DEV_NUM_SHIFT 15
  139. +#define EXT_CFG_DEV_NUM_MASK (0xf << EXT_CFG_DEV_NUM_SHIFT)
  140. +#define EXT_CFG_BUS_NUM_SHIFT 20
  141. +#define EXT_CFG_BUS_NUM_MASK (0xff << EXT_CFG_BUS_NUM_SHIFT)
  142. +
  143. +#define PCIE_DEVICE_OFFSET_6318 0x9000
  144. +#define PCIE_DEVICE_OFFSET_6328 0x8000
  145. /*************************************************************************
  146. * _REG relative to RSET_OTP
  147. --- a/arch/mips/pci/ops-bcm63xx.c
  148. +++ b/arch/mips/pci/ops-bcm63xx.c
  149. @@ -488,8 +488,12 @@ static int bcm63xx_pcie_read(struct pci_
  150. if (!bcm63xx_pcie_can_access(bus, devfn))
  151. return PCIBIOS_DEVICE_NOT_FOUND;
  152. - if (bus->number == PCIE_BUS_DEVICE)
  153. - reg += PCIE_DEVICE_OFFSET;
  154. + if (bus->number == PCIE_BUS_DEVICE) {
  155. + if (BCMCPU_IS_6318())
  156. + reg += PCIE_DEVICE_OFFSET_6318;
  157. + else
  158. + reg += PCIE_DEVICE_OFFSET_6328;
  159. + }
  160. data = bcm_pcie_readl(reg);
  161. @@ -508,8 +512,12 @@ static int bcm63xx_pcie_write(struct pci
  162. if (!bcm63xx_pcie_can_access(bus, devfn))
  163. return PCIBIOS_DEVICE_NOT_FOUND;
  164. - if (bus->number == PCIE_BUS_DEVICE)
  165. - reg += PCIE_DEVICE_OFFSET;
  166. + if (bus->number == PCIE_BUS_DEVICE) {
  167. + if (BCMCPU_IS_6318())
  168. + reg += PCIE_DEVICE_OFFSET_6318;
  169. + else
  170. + reg += PCIE_DEVICE_OFFSET_6328;
  171. + }
  172. data = bcm_pcie_readl(reg);
  173. --- a/arch/mips/pci/pci-bcm63xx.c
  174. +++ b/arch/mips/pci/pci-bcm63xx.c
  175. @@ -118,7 +118,7 @@ static void bcm63xx_int_cfg_writel(u32 v
  176. void __iomem *pci_iospace_start;
  177. -static void __init bcm63xx_reset_pcie(void)
  178. +static void __init bcm63xx_reset_pcie_gen1(void)
  179. {
  180. u32 val;
  181. u32 reg;
  182. @@ -152,20 +152,32 @@ static void __init bcm63xx_reset_pcie(vo
  183. mdelay(200);
  184. }
  185. -static struct clk *pcie_clk;
  186. -
  187. -static int __init bcm63xx_register_pcie(void)
  188. +static void __init bcm63xx_reset_pcie_gen2(void)
  189. {
  190. u32 val;
  191. - /* enable clock */
  192. - pcie_clk = clk_get(NULL, "pcie");
  193. - if (IS_ERR_OR_NULL(pcie_clk))
  194. - return -ENODEV;
  195. + bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_HARD, 0);
  196. - clk_prepare_enable(pcie_clk);
  197. + /* reset the PCIe core */
  198. + bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 1);
  199. + bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 1);
  200. + bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_CORE, 1);
  201. + mdelay(10);
  202. + bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 0);
  203. + mdelay(10);
  204. + bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 0);
  205. + mdelay(10);
  206. + val = bcm_pcie_readl(PCIE_HARD_DEBUG_REG);
  207. + val &= ~HARD_DEBUG_SERDES_IDDQ;
  208. + bcm_pcie_writel(val, PCIE_HARD_DEBUG_REG);
  209. + mdelay(10);
  210. + bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_CORE, 0);
  211. + mdelay(200);
  212. +}
  213. - bcm63xx_reset_pcie();
  214. +static void __init bcm63xx_init_pcie_gen1(void)
  215. +{
  216. + u32 val;
  217. /* configure the PCIe bridge */
  218. val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG);
  219. @@ -190,6 +202,65 @@ static int __init bcm63xx_register_pcie(
  220. val |= OPT2_CFG_TYPE1_BD_SEL;
  221. bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG);
  222. + /* set bar0 to little endian */
  223. + val = (bcm_pcie_mem_resource.start >> 20) << BASEMASK_BASE_SHIFT;
  224. + val |= (bcm_pcie_mem_resource.end >> 20) << BASEMASK_MASK_SHIFT;
  225. + val |= BASEMASK_REMAP_EN;
  226. + bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
  227. +
  228. + val = (bcm_pcie_mem_resource.start >> 20) << REBASE_ADDR_BASE_SHIFT;
  229. + bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
  230. +}
  231. +
  232. +static void __init bcm63xx_init_pcie_gen2(void)
  233. +{
  234. + u32 val;
  235. +
  236. + bcm_pcie_writel(CPU_INT_PCIE_INTA | CPU_INT_PCIE_INTB |
  237. + CPU_INT_PCIE_INTC | CPU_INT_PCIE_INTD,
  238. + PCIE_CPU_INT1_MASK_CLEAR_REG);
  239. +
  240. + val = bcm_pcie_mem_resource.end & C2P_BASELIMIT_LIMIT_MASK;
  241. + val |= (bcm_pcie_mem_resource.start >> C2P_BASELIMIT_LIMIT_SHIFT) <<
  242. + C2P_BASELIMIT_BASE_SHIFT;
  243. +
  244. + bcm_pcie_writel(val, PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG);
  245. +
  246. + /* set bar0 to little endian */
  247. + val = bcm_pcie_readl(PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG);
  248. + val |= bcm_pcie_mem_resource.start & C2P_MEM_WIN_BASE_ADDR_MASK;
  249. + val |= C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP;
  250. + bcm_pcie_writel(val, PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG);
  251. +
  252. + bcm_pcie_writel(SPECIFIC_ENDIAN_MODE_BYTE_ALIGN, PCIE_SPECIFIC_REG);
  253. + bcm_pcie_writel(RC_BAR_CFG_LO_SIZE_256MB, PCIE_RC_BAR1_CONFIG_LO_REG);
  254. + bcm_pcie_writel(BAR1_CFG_REMAP_ACCESS_EN, PCIE_UBUS_BAR1_CFG_REMAP_REG);
  255. +
  256. + bcm_pcie_writel(PCIE_BUS_DEVICE << EXT_CFG_BUS_NUM_SHIFT,
  257. + PCIE_EXT_CFG_INDEX_REG);
  258. +}
  259. +
  260. +static struct clk *pcie_clk;
  261. +
  262. +static int __init bcm63xx_register_pcie(void)
  263. +{
  264. + u32 val;
  265. +
  266. + /* enable clock */
  267. + pcie_clk = clk_get(NULL, "pcie");
  268. + if (IS_ERR_OR_NULL(pcie_clk))
  269. + return -ENODEV;
  270. +
  271. + clk_prepare_enable(pcie_clk);
  272. +
  273. + if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_63268()) {
  274. + bcm63xx_reset_pcie_gen1();
  275. + bcm63xx_init_pcie_gen1();
  276. + } else {
  277. + bcm63xx_reset_pcie_gen2();
  278. + bcm63xx_init_pcie_gen2();
  279. + }
  280. +
  281. /* setup class code as bridge */
  282. val = bcm_pcie_readl(PCIE_IDVAL3_REG);
  283. val &= ~IDVAL3_CLASS_CODE_MASK;
  284. @@ -201,15 +272,6 @@ static int __init bcm63xx_register_pcie(
  285. val &= ~CONFIG2_BAR1_SIZE_MASK;
  286. bcm_pcie_writel(val, PCIE_CONFIG2_REG);
  287. - /* set bar0 to little endian */
  288. - val = (bcm_pcie_mem_resource.start >> 20) << BASEMASK_BASE_SHIFT;
  289. - val |= (bcm_pcie_mem_resource.end >> 20) << BASEMASK_MASK_SHIFT;
  290. - val |= BASEMASK_REMAP_EN;
  291. - bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
  292. -
  293. - val = (bcm_pcie_mem_resource.start >> 20) << REBASE_ADDR_BASE_SHIFT;
  294. - bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
  295. -
  296. register_pci_controller(&bcm63xx_pcie_controller);
  297. return 0;
  298. @@ -341,7 +403,10 @@ static int __init bcm63xx_pci_init(void)
  299. if (!bcm63xx_pci_enabled)
  300. return -ENODEV;
  301. - if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) {
  302. + if (BCMCPU_IS_6318()) {
  303. + bcm_pcie_mem_resource.start = BCM_PCIE_MEM_BASE_PA_6318;
  304. + bcm_pcie_mem_resource.end = BCM_PCIE_MEM_END_PA_6318;
  305. + } if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) {
  306. bcm_pcie_mem_resource.start = BCM_PCIE_MEM_BASE_PA_6328;
  307. bcm_pcie_mem_resource.end = BCM_PCIE_MEM_END_PA_6328;
  308. } else if (BCMCPU_IS_63268()) {
  309. @@ -350,6 +415,7 @@ static int __init bcm63xx_pci_init(void)
  310. }
  311. switch (bcm63xx_get_cpu_id()) {
  312. + case BCM6318_CPU_ID:
  313. case BCM6328_CPU_ID:
  314. case BCM6362_CPU_ID:
  315. case BCM63268_CPU_ID: