pcie_uniphier.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * pcie_uniphier.c - Socionext UniPhier PCIe driver
  4. * Copyright 2019-2021 Socionext, Inc.
  5. */
  6. #include <clk.h>
  7. #include <common.h>
  8. #include <dm.h>
  9. #include <dm/device_compat.h>
  10. #include <generic-phy.h>
  11. #include <linux/bitfield.h>
  12. #include <linux/bitops.h>
  13. #include <linux/compat.h>
  14. #include <linux/delay.h>
  15. #include <linux/io.h>
  16. #include <pci.h>
  17. #include <reset.h>
  18. DECLARE_GLOBAL_DATA_PTR;
  19. /* DBI registers */
  20. #define PCIE_LINK_STATUS_REG 0x0080
  21. #define PCIE_LINK_STATUS_WIDTH_MASK GENMASK(25, 20)
  22. #define PCIE_LINK_STATUS_SPEED_MASK GENMASK(19, 16)
  23. #define PCIE_MISC_CONTROL_1_OFF 0x08BC
  24. #define PCIE_DBI_RO_WR_EN BIT(0)
  25. /* DBI iATU registers */
  26. #define PCIE_ATU_VIEWPORT 0x0900
  27. #define PCIE_ATU_REGION_INBOUND BIT(31)
  28. #define PCIE_ATU_REGION_OUTBOUND 0
  29. #define PCIE_ATU_REGION_INDEX_MASK GENMASK(3, 0)
  30. #define PCIE_ATU_CR1 0x0904
  31. #define PCIE_ATU_TYPE_MEM 0
  32. #define PCIE_ATU_TYPE_IO 2
  33. #define PCIE_ATU_TYPE_CFG0 4
  34. #define PCIE_ATU_TYPE_CFG1 5
  35. #define PCIE_ATU_CR2 0x0908
  36. #define PCIE_ATU_ENABLE BIT(31)
  37. #define PCIE_ATU_MATCH_MODE BIT(30)
  38. #define PCIE_ATU_BAR_NUM_MASK GENMASK(10, 8)
  39. #define PCIE_ATU_LOWER_BASE 0x090C
  40. #define PCIE_ATU_UPPER_BASE 0x0910
  41. #define PCIE_ATU_LIMIT 0x0914
  42. #define PCIE_ATU_LOWER_TARGET 0x0918
  43. #define PCIE_ATU_BUS(x) FIELD_PREP(GENMASK(31, 24), x)
  44. #define PCIE_ATU_DEV(x) FIELD_PREP(GENMASK(23, 19), x)
  45. #define PCIE_ATU_FUNC(x) FIELD_PREP(GENMASK(18, 16), x)
  46. #define PCIE_ATU_UPPER_TARGET 0x091C
  47. /* Link Glue registers */
  48. #define PCL_PINCTRL0 0x002c
  49. #define PCL_PERST_PLDN_REGEN BIT(12)
  50. #define PCL_PERST_NOE_REGEN BIT(11)
  51. #define PCL_PERST_OUT_REGEN BIT(8)
  52. #define PCL_PERST_PLDN_REGVAL BIT(4)
  53. #define PCL_PERST_NOE_REGVAL BIT(3)
  54. #define PCL_PERST_OUT_REGVAL BIT(0)
  55. #define PCL_MODE 0x8000
  56. #define PCL_MODE_REGEN BIT(8)
  57. #define PCL_MODE_REGVAL BIT(0)
  58. #define PCL_APP_READY_CTRL 0x8008
  59. #define PCL_APP_LTSSM_ENABLE BIT(0)
  60. #define PCL_APP_PM0 0x8078
  61. #define PCL_SYS_AUX_PWR_DET BIT(8)
  62. #define PCL_STATUS_LINK 0x8140
  63. #define PCL_RDLH_LINK_UP BIT(1)
  64. #define PCL_XMLH_LINK_UP BIT(0)
  65. #define LINK_UP_TIMEOUT_MS 100
  66. struct uniphier_pcie_priv {
  67. void *base;
  68. void *dbi_base;
  69. void *cfg_base;
  70. fdt_size_t cfg_size;
  71. struct fdt_resource link_res;
  72. struct fdt_resource dbi_res;
  73. struct fdt_resource cfg_res;
  74. struct clk clk;
  75. struct reset_ctl rst;
  76. struct phy phy;
  77. struct pci_region io;
  78. struct pci_region mem;
  79. };
  80. static int pcie_dw_get_link_speed(struct uniphier_pcie_priv *priv)
  81. {
  82. u32 val = readl(priv->dbi_base + PCIE_LINK_STATUS_REG);
  83. return FIELD_GET(PCIE_LINK_STATUS_SPEED_MASK, val);
  84. }
  85. static int pcie_dw_get_link_width(struct uniphier_pcie_priv *priv)
  86. {
  87. u32 val = readl(priv->dbi_base + PCIE_LINK_STATUS_REG);
  88. return FIELD_GET(PCIE_LINK_STATUS_WIDTH_MASK, val);
  89. }
  90. static void pcie_dw_prog_outbound_atu(struct uniphier_pcie_priv *priv,
  91. int index, int type, u64 cpu_addr,
  92. u64 pci_addr, u32 size)
  93. {
  94. writel(PCIE_ATU_REGION_OUTBOUND
  95. | FIELD_PREP(PCIE_ATU_REGION_INDEX_MASK, index),
  96. priv->dbi_base + PCIE_ATU_VIEWPORT);
  97. writel(lower_32_bits(cpu_addr),
  98. priv->dbi_base + PCIE_ATU_LOWER_BASE);
  99. writel(upper_32_bits(cpu_addr),
  100. priv->dbi_base + PCIE_ATU_UPPER_BASE);
  101. writel(lower_32_bits(cpu_addr + size - 1),
  102. priv->dbi_base + PCIE_ATU_LIMIT);
  103. writel(lower_32_bits(pci_addr),
  104. priv->dbi_base + PCIE_ATU_LOWER_TARGET);
  105. writel(upper_32_bits(pci_addr),
  106. priv->dbi_base + PCIE_ATU_UPPER_TARGET);
  107. writel(type, priv->dbi_base + PCIE_ATU_CR1);
  108. writel(PCIE_ATU_ENABLE, priv->dbi_base + PCIE_ATU_CR2);
  109. }
  110. static int uniphier_pcie_addr_valid(pci_dev_t bdf, int first_busno)
  111. {
  112. /* accept only device {0,1} on first bus */
  113. if ((PCI_BUS(bdf) != first_busno) || (PCI_DEV(bdf) > 1))
  114. return -EINVAL;
  115. return 0;
  116. }
  117. static int uniphier_pcie_conf_address(const struct udevice *dev, pci_dev_t bdf,
  118. uint offset, void **paddr)
  119. {
  120. struct uniphier_pcie_priv *priv = dev_get_priv(dev);
  121. u32 busdev;
  122. int seq = dev_seq(dev);
  123. int ret;
  124. ret = uniphier_pcie_addr_valid(bdf, seq);
  125. if (ret)
  126. return ret;
  127. if ((PCI_BUS(bdf) == seq) && !PCI_DEV(bdf)) {
  128. *paddr = (void *)(priv->dbi_base + offset);
  129. return 0;
  130. }
  131. busdev = PCIE_ATU_BUS(PCI_BUS(bdf) - seq)
  132. | PCIE_ATU_DEV(PCI_DEV(bdf))
  133. | PCIE_ATU_FUNC(PCI_FUNC(bdf));
  134. pcie_dw_prog_outbound_atu(priv, 0,
  135. PCIE_ATU_TYPE_CFG0, (u64)priv->cfg_base,
  136. busdev, priv->cfg_size);
  137. *paddr = (void *)(priv->cfg_base + offset);
  138. return 0;
  139. }
  140. static int uniphier_pcie_read_config(const struct udevice *dev, pci_dev_t bdf,
  141. uint offset, ulong *valp,
  142. enum pci_size_t size)
  143. {
  144. return pci_generic_mmap_read_config(dev, uniphier_pcie_conf_address,
  145. bdf, offset, valp, size);
  146. }
  147. static int uniphier_pcie_write_config(struct udevice *dev, pci_dev_t bdf,
  148. uint offset, ulong val,
  149. enum pci_size_t size)
  150. {
  151. return pci_generic_mmap_write_config(dev, uniphier_pcie_conf_address,
  152. bdf, offset, val, size);
  153. }
  154. static void uniphier_pcie_ltssm_enable(struct uniphier_pcie_priv *priv,
  155. bool enable)
  156. {
  157. u32 val;
  158. val = readl(priv->base + PCL_APP_READY_CTRL);
  159. if (enable)
  160. val |= PCL_APP_LTSSM_ENABLE;
  161. else
  162. val &= ~PCL_APP_LTSSM_ENABLE;
  163. writel(val, priv->base + PCL_APP_READY_CTRL);
  164. }
  165. static int uniphier_pcie_link_up(struct uniphier_pcie_priv *priv)
  166. {
  167. u32 val, mask;
  168. val = readl(priv->base + PCL_STATUS_LINK);
  169. mask = PCL_RDLH_LINK_UP | PCL_XMLH_LINK_UP;
  170. return (val & mask) == mask;
  171. }
  172. static int uniphier_pcie_wait_link(struct uniphier_pcie_priv *priv)
  173. {
  174. unsigned long timeout;
  175. timeout = get_timer(0) + LINK_UP_TIMEOUT_MS;
  176. while (get_timer(0) < timeout) {
  177. if (uniphier_pcie_link_up(priv))
  178. return 0;
  179. }
  180. return -ETIMEDOUT;
  181. }
  182. static int uniphier_pcie_establish_link(struct uniphier_pcie_priv *priv)
  183. {
  184. if (uniphier_pcie_link_up(priv))
  185. return 0;
  186. uniphier_pcie_ltssm_enable(priv, true);
  187. return uniphier_pcie_wait_link(priv);
  188. }
  189. static void uniphier_pcie_init_rc(struct uniphier_pcie_priv *priv)
  190. {
  191. u32 val;
  192. /* set RC mode */
  193. val = readl(priv->base + PCL_MODE);
  194. val |= PCL_MODE_REGEN;
  195. val &= ~PCL_MODE_REGVAL;
  196. writel(val, priv->base + PCL_MODE);
  197. /* use auxiliary power detection */
  198. val = readl(priv->base + PCL_APP_PM0);
  199. val |= PCL_SYS_AUX_PWR_DET;
  200. writel(val, priv->base + PCL_APP_PM0);
  201. /* assert PERST# */
  202. val = readl(priv->base + PCL_PINCTRL0);
  203. val &= ~(PCL_PERST_NOE_REGVAL | PCL_PERST_OUT_REGVAL
  204. | PCL_PERST_PLDN_REGVAL);
  205. val |= PCL_PERST_NOE_REGEN | PCL_PERST_OUT_REGEN
  206. | PCL_PERST_PLDN_REGEN;
  207. writel(val, priv->base + PCL_PINCTRL0);
  208. uniphier_pcie_ltssm_enable(priv, false);
  209. mdelay(100);
  210. /* deassert PERST# */
  211. val = readl(priv->base + PCL_PINCTRL0);
  212. val |= PCL_PERST_OUT_REGVAL | PCL_PERST_OUT_REGEN;
  213. writel(val, priv->base + PCL_PINCTRL0);
  214. }
  215. static void uniphier_pcie_setup_rc(struct uniphier_pcie_priv *priv,
  216. struct pci_controller *hose)
  217. {
  218. /* Store the IO and MEM windows settings for future use by the ATU */
  219. priv->io.phys_start = hose->regions[0].phys_start; /* IO base */
  220. priv->io.bus_start = hose->regions[0].bus_start; /* IO_bus_addr */
  221. priv->io.size = hose->regions[0].size; /* IO size */
  222. priv->mem.phys_start = hose->regions[1].phys_start; /* MEM base */
  223. priv->mem.bus_start = hose->regions[1].bus_start; /* MEM_bus_addr */
  224. priv->mem.size = hose->regions[1].size; /* MEM size */
  225. /* outbound: IO */
  226. pcie_dw_prog_outbound_atu(priv, 0,
  227. PCIE_ATU_TYPE_IO, priv->io.phys_start,
  228. priv->io.bus_start, priv->io.size);
  229. /* outbound: MEM */
  230. pcie_dw_prog_outbound_atu(priv, 1,
  231. PCIE_ATU_TYPE_MEM, priv->mem.phys_start,
  232. priv->mem.bus_start, priv->mem.size);
  233. }
  234. static int uniphier_pcie_probe(struct udevice *dev)
  235. {
  236. struct uniphier_pcie_priv *priv = dev_get_priv(dev);
  237. struct udevice *ctlr = pci_get_controller(dev);
  238. struct pci_controller *hose = dev_get_uclass_priv(ctlr);
  239. int ret;
  240. priv->base = map_physmem(priv->link_res.start,
  241. fdt_resource_size(&priv->link_res),
  242. MAP_NOCACHE);
  243. priv->dbi_base = map_physmem(priv->dbi_res.start,
  244. fdt_resource_size(&priv->dbi_res),
  245. MAP_NOCACHE);
  246. priv->cfg_size = fdt_resource_size(&priv->cfg_res);
  247. priv->cfg_base = map_physmem(priv->cfg_res.start,
  248. priv->cfg_size, MAP_NOCACHE);
  249. ret = clk_enable(&priv->clk);
  250. if (ret) {
  251. dev_err(dev, "Failed to enable clk: %d\n", ret);
  252. return ret;
  253. }
  254. ret = reset_deassert(&priv->rst);
  255. if (ret) {
  256. dev_err(dev, "Failed to deassert reset: %d\n", ret);
  257. goto out_clk_release;
  258. }
  259. ret = generic_phy_init(&priv->phy);
  260. if (ret) {
  261. dev_err(dev, "Failed to initialize phy: %d\n", ret);
  262. goto out_reset_release;
  263. }
  264. ret = generic_phy_power_on(&priv->phy);
  265. if (ret) {
  266. dev_err(dev, "Failed to power on phy: %d\n", ret);
  267. goto out_phy_exit;
  268. }
  269. uniphier_pcie_init_rc(priv);
  270. /* set DBI to read only */
  271. writel(0, priv->dbi_base + PCIE_MISC_CONTROL_1_OFF);
  272. uniphier_pcie_setup_rc(priv, hose);
  273. if (uniphier_pcie_establish_link(priv)) {
  274. printf("PCIE-%d: Link down\n", dev_seq(dev));
  275. } else {
  276. printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n",
  277. dev_seq(dev), pcie_dw_get_link_speed(priv),
  278. pcie_dw_get_link_width(priv), hose->first_busno);
  279. }
  280. return 0;
  281. out_phy_exit:
  282. generic_phy_exit(&priv->phy);
  283. out_reset_release:
  284. reset_release_all(&priv->rst, 1);
  285. out_clk_release:
  286. clk_release_all(&priv->clk, 1);
  287. return ret;
  288. }
  289. static int uniphier_pcie_of_to_plat(struct udevice *dev)
  290. {
  291. struct uniphier_pcie_priv *priv = dev_get_priv(dev);
  292. const void *fdt = gd->fdt_blob;
  293. int node = dev_of_offset(dev);
  294. int ret;
  295. ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
  296. "link", &priv->link_res);
  297. if (ret) {
  298. dev_err(dev, "Failed to get link regs: %d\n", ret);
  299. return ret;
  300. }
  301. ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
  302. "dbi", &priv->dbi_res);
  303. if (ret) {
  304. dev_err(dev, "Failed to get dbi regs: %d\n", ret);
  305. return ret;
  306. }
  307. ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
  308. "config", &priv->cfg_res);
  309. if (ret) {
  310. dev_err(dev, "Failed to get config regs: %d\n", ret);
  311. return ret;
  312. }
  313. ret = clk_get_by_index(dev, 0, &priv->clk);
  314. if (ret) {
  315. dev_err(dev, "Failed to get clocks property: %d\n", ret);
  316. return ret;
  317. }
  318. ret = reset_get_by_index(dev, 0, &priv->rst);
  319. if (ret) {
  320. dev_err(dev, "Failed to get resets property: %d\n", ret);
  321. return ret;
  322. }
  323. ret = generic_phy_get_by_index(dev, 0, &priv->phy);
  324. if (ret) {
  325. dev_err(dev, "Failed to get phy property: %d\n", ret);
  326. return ret;
  327. }
  328. return 0;
  329. }
  330. static const struct dm_pci_ops uniphier_pcie_ops = {
  331. .read_config = uniphier_pcie_read_config,
  332. .write_config = uniphier_pcie_write_config,
  333. };
  334. static const struct udevice_id uniphier_pcie_ids[] = {
  335. { .compatible = "socionext,uniphier-pcie", },
  336. { /* Sentinel */ }
  337. };
  338. U_BOOT_DRIVER(pcie_uniphier) = {
  339. .name = "uniphier-pcie",
  340. .id = UCLASS_PCI,
  341. .of_match = uniphier_pcie_ids,
  342. .probe = uniphier_pcie_probe,
  343. .ops = &uniphier_pcie_ops,
  344. .of_to_plat = uniphier_pcie_of_to_plat,
  345. .priv_auto = sizeof(struct uniphier_pcie_priv),
  346. };