114-pcie-add-ctlr-init.patch 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. --- a/drivers/pci/host/pcie-qcom.c
  2. +++ b/drivers/pci/host/pcie-qcom.c
  3. @@ -29,8 +29,53 @@
  4. #include "pcie-designware.h"
  5. +/* DBI registers */
  6. +#define PCIE20_CAP 0x70
  7. +#define PCIE20_CAP_LINKCTRLSTATUS (PCIE20_CAP + 0x10)
  8. +
  9. +#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0 0x818
  10. +#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1 0x81c
  11. +
  12. +#define PCIE20_PLR_IATU_VIEWPORT 0x900
  13. +#define PCIE20_PLR_IATU_REGION_OUTBOUND (0x0 << 31)
  14. +#define PCIE20_PLR_IATU_REGION_INDEX(x) (x << 0)
  15. +
  16. +#define PCIE20_PLR_IATU_CTRL1 0x904
  17. +#define PCIE20_PLR_IATU_TYPE_CFG0 (0x4 << 0)
  18. +#define PCIE20_PLR_IATU_TYPE_MEM (0x0 << 0)
  19. +
  20. +#define PCIE20_PLR_IATU_CTRL2 0x908
  21. +#define PCIE20_PLR_IATU_ENABLE BIT(31)
  22. +
  23. +#define PCIE20_PLR_IATU_LBAR 0x90C
  24. +#define PCIE20_PLR_IATU_UBAR 0x910
  25. +#define PCIE20_PLR_IATU_LAR 0x914
  26. +#define PCIE20_PLR_IATU_LTAR 0x918
  27. +#define PCIE20_PLR_IATU_UTAR 0x91c
  28. +
  29. +#define MSM_PCIE_DEV_CFG_ADDR 0x01000000
  30. +
  31. +/* PARF registers */
  32. +#define PCIE20_PARF_PCS_DEEMPH 0x34
  33. +#define PCS_DEEMPH_TX_DEEMPH_GEN1(x) (x << 16)
  34. +#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x) (x << 8)
  35. +#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x) (x << 0)
  36. +
  37. +#define PCIE20_PARF_PCS_SWING 0x38
  38. +#define PCS_SWING_TX_SWING_FULL(x) (x << 8)
  39. +#define PCS_SWING_TX_SWING_LOW(x) (x << 0)
  40. +
  41. #define PCIE20_PARF_PHY_CTRL 0x40
  42. +#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK (0x1f << 16)
  43. +#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x) (x << 16)
  44. +
  45. #define PCIE20_PARF_PHY_REFCLK 0x4C
  46. +#define REF_SSP_EN BIT(16)
  47. +#define REF_USE_PAD BIT(12)
  48. +
  49. +#define PCIE20_PARF_CONFIG_BITS 0x50
  50. +#define PHY_RX0_EQ(x) (x << 24)
  51. +
  52. #define PCIE20_PARF_DBI_BASE_ADDR 0x168
  53. #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16c
  54. #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178
  55. @@ -39,9 +84,6 @@
  56. #define PCIE20_ELBI_SYS_STTS 0x08
  57. #define XMLH_LINK_UP BIT(10)
  58. -#define PCIE20_CAP 0x70
  59. -#define PCIE20_CAP_LINKCTRLSTATUS (PCIE20_CAP + 0x10)
  60. -
  61. #define PERST_DELAY_MIN_US 1000
  62. #define PERST_DELAY_MAX_US 1005
  63. @@ -56,14 +98,18 @@ struct qcom_pcie_resources_v0 {
  64. struct clk *iface_clk;
  65. struct clk *core_clk;
  66. struct clk *phy_clk;
  67. + struct clk *aux_clk;
  68. + struct clk *ref_clk;
  69. struct reset_control *pci_reset;
  70. struct reset_control *axi_reset;
  71. struct reset_control *ahb_reset;
  72. struct reset_control *por_reset;
  73. struct reset_control *phy_reset;
  74. + struct reset_control *ext_reset;
  75. struct regulator *vdda;
  76. struct regulator *vdda_phy;
  77. struct regulator *vdda_refclk;
  78. + uint8_t phy_tx0_term_offset;
  79. };
  80. struct qcom_pcie_resources_v1 {
  81. @@ -106,20 +152,10 @@ writel_masked(void __iomem *addr, u32 cl
  82. static void qcom_ep_reset_assert_deassert(struct qcom_pcie *pcie, int assert)
  83. {
  84. - int val, active_low;
  85. -
  86. if (IS_ERR_OR_NULL(pcie->reset))
  87. return;
  88. - active_low = gpiod_is_active_low(pcie->reset);
  89. -
  90. - if (assert)
  91. - val = !!active_low;
  92. - else
  93. - val = !active_low;
  94. -
  95. - gpiod_set_value(pcie->reset, val);
  96. -
  97. + gpiod_set_value(pcie->reset, assert);
  98. usleep_range(PERST_DELAY_MIN_US, PERST_DELAY_MAX_US);
  99. }
  100. @@ -156,10 +192,13 @@ static void qcom_pcie_disable_resources_
  101. reset_control_assert(res->axi_reset);
  102. reset_control_assert(res->ahb_reset);
  103. reset_control_assert(res->por_reset);
  104. - reset_control_assert(res->pci_reset);
  105. + reset_control_assert(res->phy_reset);
  106. + reset_control_assert(res->ext_reset);
  107. clk_disable_unprepare(res->iface_clk);
  108. clk_disable_unprepare(res->core_clk);
  109. clk_disable_unprepare(res->phy_clk);
  110. + clk_disable_unprepare(res->aux_clk);
  111. + clk_disable_unprepare(res->ref_clk);
  112. regulator_disable(res->vdda);
  113. regulator_disable(res->vdda_phy);
  114. regulator_disable(res->vdda_refclk);
  115. @@ -201,6 +240,12 @@ static int qcom_pcie_enable_resources_v0
  116. goto err_vdda_phy;
  117. }
  118. + ret = reset_control_deassert(res->ext_reset);
  119. + if (ret) {
  120. + dev_err(dev, "cannot assert ext reset\n");
  121. + goto err_reset_ext;
  122. + }
  123. +
  124. ret = clk_prepare_enable(res->iface_clk);
  125. if (ret) {
  126. dev_err(dev, "cannot prepare/enable iface clock\n");
  127. @@ -219,21 +264,40 @@ static int qcom_pcie_enable_resources_v0
  128. goto err_clk_phy;
  129. }
  130. + ret = clk_prepare_enable(res->aux_clk);
  131. + if (ret) {
  132. + dev_err(dev, "cannot prepare/enable aux clock\n");
  133. + goto err_clk_aux;
  134. + }
  135. +
  136. + ret = clk_prepare_enable(res->ref_clk);
  137. + if (ret) {
  138. + dev_err(dev, "cannot prepare/enable ref clock\n");
  139. + goto err_clk_ref;
  140. + }
  141. +
  142. ret = reset_control_deassert(res->ahb_reset);
  143. if (ret) {
  144. dev_err(dev, "cannot deassert ahb reset\n");
  145. goto err_reset_ahb;
  146. }
  147. + udelay(1);
  148. return 0;
  149. err_reset_ahb:
  150. + clk_disable_unprepare(res->ref_clk);
  151. +err_clk_ref:
  152. + clk_disable_unprepare(res->aux_clk);
  153. +err_clk_aux:
  154. clk_disable_unprepare(res->phy_clk);
  155. err_clk_phy:
  156. clk_disable_unprepare(res->core_clk);
  157. err_clk_core:
  158. clk_disable_unprepare(res->iface_clk);
  159. err_iface:
  160. + reset_control_assert(res->ext_reset);
  161. +err_reset_ext:
  162. regulator_disable(res->vdda_phy);
  163. err_vdda_phy:
  164. regulator_disable(res->vdda_refclk);
  165. @@ -329,6 +393,14 @@ static int qcom_pcie_get_resources_v0(st
  166. if (IS_ERR(res->phy_clk))
  167. return PTR_ERR(res->phy_clk);
  168. + res->aux_clk = devm_clk_get(dev, "aux");
  169. + if (IS_ERR(res->aux_clk))
  170. + return PTR_ERR(res->aux_clk);
  171. +
  172. + res->ref_clk = devm_clk_get(dev, "ref");
  173. + if (IS_ERR(res->ref_clk))
  174. + return PTR_ERR(res->ref_clk);
  175. +
  176. res->pci_reset = devm_reset_control_get(dev, "pci");
  177. if (IS_ERR(res->pci_reset))
  178. return PTR_ERR(res->pci_reset);
  179. @@ -349,6 +421,14 @@ static int qcom_pcie_get_resources_v0(st
  180. if (IS_ERR(res->phy_reset))
  181. return PTR_ERR(res->phy_reset);
  182. + res->ext_reset = devm_reset_control_get(dev, "ext");
  183. + if (IS_ERR(res->ext_reset))
  184. + return PTR_ERR(res->ext_reset);
  185. +
  186. + if (of_property_read_u8(dev->of_node, "phy-tx0-term-offset",
  187. + &res->phy_tx0_term_offset))
  188. + res->phy_tx0_term_offset = 0;
  189. +
  190. return 0;
  191. }
  192. @@ -461,6 +541,57 @@ err_res:
  193. qcom_pcie_disable_resources_v1(pcie);
  194. }
  195. +static void qcom_pcie_prog_viewport_cfg0(struct qcom_pcie *pcie, u32 busdev)
  196. +{
  197. + struct pcie_port *pp = &pcie->pp;
  198. +
  199. + /*
  200. + * program and enable address translation region 0 (device config
  201. + * address space); region type config;
  202. + * axi config address range to device config address range
  203. + */
  204. + writel(PCIE20_PLR_IATU_REGION_OUTBOUND |
  205. + PCIE20_PLR_IATU_REGION_INDEX(0),
  206. + pcie->dbi + PCIE20_PLR_IATU_VIEWPORT);
  207. +
  208. + writel(PCIE20_PLR_IATU_TYPE_CFG0, pcie->dbi + PCIE20_PLR_IATU_CTRL1);
  209. + writel(PCIE20_PLR_IATU_ENABLE, pcie->dbi + PCIE20_PLR_IATU_CTRL2);
  210. + writel(pp->cfg0_base, pcie->dbi + PCIE20_PLR_IATU_LBAR);
  211. + writel((pp->cfg0_base >> 32), pcie->dbi + PCIE20_PLR_IATU_UBAR);
  212. + writel((pp->cfg0_base + pp->cfg0_size - 1),
  213. + pcie->dbi + PCIE20_PLR_IATU_LAR);
  214. + writel(busdev, pcie->dbi + PCIE20_PLR_IATU_LTAR);
  215. + writel(0, pcie->dbi + PCIE20_PLR_IATU_UTAR);
  216. +}
  217. +
  218. +static void qcom_pcie_prog_viewport_mem2_outbound(struct qcom_pcie *pcie)
  219. +{
  220. + struct pcie_port *pp = &pcie->pp;
  221. +
  222. + /*
  223. + * program and enable address translation region 2 (device resource
  224. + * address space); region type memory;
  225. + * axi device bar address range to device bar address range
  226. + */
  227. + writel(PCIE20_PLR_IATU_REGION_OUTBOUND |
  228. + PCIE20_PLR_IATU_REGION_INDEX(2),
  229. + pcie->dbi + PCIE20_PLR_IATU_VIEWPORT);
  230. +
  231. + writel(PCIE20_PLR_IATU_TYPE_MEM, pcie->dbi + PCIE20_PLR_IATU_CTRL1);
  232. + writel(PCIE20_PLR_IATU_ENABLE, pcie->dbi + PCIE20_PLR_IATU_CTRL2);
  233. + writel(pp->mem_base, pcie->dbi + PCIE20_PLR_IATU_LBAR);
  234. + writel((pp->mem_base >> 32), pcie->dbi + PCIE20_PLR_IATU_UBAR);
  235. + writel(pp->mem_base + pp->mem_size - 1,
  236. + pcie->dbi + PCIE20_PLR_IATU_LAR);
  237. + writel(pp->mem_bus_addr, pcie->dbi + PCIE20_PLR_IATU_LTAR);
  238. + writel(upper_32_bits(pp->mem_bus_addr),
  239. + pcie->dbi + PCIE20_PLR_IATU_UTAR);
  240. +
  241. + /* 256B PCIE buffer setting */
  242. + writel(0x1, pcie->dbi + PCIE20_AXI_MSTR_RESP_COMP_CTRL0);
  243. + writel(0x1, pcie->dbi + PCIE20_AXI_MSTR_RESP_COMP_CTRL1);
  244. +}
  245. +
  246. static void qcom_pcie_host_init_v0(struct pcie_port *pp)
  247. {
  248. struct qcom_pcie *pcie = to_qcom_pcie(pp);
  249. @@ -470,15 +601,34 @@ static void qcom_pcie_host_init_v0(struc
  250. qcom_ep_reset_assert(pcie);
  251. + reset_control_assert(res->ahb_reset);
  252. +
  253. ret = qcom_pcie_enable_resources_v0(pcie);
  254. if (ret)
  255. return;
  256. writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0);
  257. - /* enable external reference clock */
  258. - writel_masked(pcie->parf + PCIE20_PARF_PHY_REFCLK, 0, BIT(16));
  259. + /* Set Tx termination offset */
  260. + writel_masked(pcie->parf + PCIE20_PARF_PHY_CTRL,
  261. + PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK,
  262. + PHY_CTRL_PHY_TX0_TERM_OFFSET(res->phy_tx0_term_offset));
  263. +
  264. + /* PARF programming */
  265. + writel(PCS_DEEMPH_TX_DEEMPH_GEN1(0x18) |
  266. + PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(0x18) |
  267. + PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(0x22),
  268. + pcie->parf + PCIE20_PARF_PCS_DEEMPH);
  269. + writel(PCS_SWING_TX_SWING_FULL(0x78) |
  270. + PCS_SWING_TX_SWING_LOW(0x78),
  271. + pcie->parf + PCIE20_PARF_PCS_SWING);
  272. + writel(PHY_RX0_EQ(0x4), pcie->parf + PCIE20_PARF_CONFIG_BITS);
  273. +
  274. + /* Enable reference clock */
  275. + writel_masked(pcie->parf + PCIE20_PARF_PHY_REFCLK,
  276. + REF_USE_PAD, REF_SSP_EN);
  277. + /* De-assert PHY, PCIe, POR and AXI resets */
  278. ret = reset_control_deassert(res->phy_reset);
  279. if (ret) {
  280. dev_err(dev, "cannot deassert phy reset\n");
  281. @@ -517,6 +667,9 @@ static void qcom_pcie_host_init_v0(struc
  282. if (ret)
  283. goto err;
  284. + qcom_pcie_prog_viewport_cfg0(pcie, MSM_PCIE_DEV_CFG_ADDR);
  285. + qcom_pcie_prog_viewport_mem2_outbound(pcie);
  286. +
  287. return;
  288. err:
  289. qcom_ep_reset_assert(pcie);