pcie_dw_ti.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2018 Texas Instruments, Inc
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <log.h>
  8. #include <pci.h>
  9. #include <generic-phy.h>
  10. #include <power-domain.h>
  11. #include <regmap.h>
  12. #include <syscon.h>
  13. #include <asm/global_data.h>
  14. #include <asm/io.h>
  15. #include <asm-generic/gpio.h>
  16. #include <dm/device_compat.h>
  17. #include <linux/bitops.h>
  18. #include <linux/delay.h>
  19. #include <linux/err.h>
  20. #include "pcie_dw_common.h"
  21. DECLARE_GLOBAL_DATA_PTR;
  22. #define PCIE_VENDORID_MASK GENMASK(15, 0)
  23. #define PCIE_DEVICEID_SHIFT 16
  24. #define PCIE_LINK_CAPABILITY 0x7c
  25. #define PCIE_LINK_CTL_2 0xa0
  26. #define TARGET_LINK_SPEED_MASK 0xf
  27. #define LINK_SPEED_GEN_1 0x1
  28. #define LINK_SPEED_GEN_2 0x2
  29. #define LINK_SPEED_GEN_3 0x3
  30. #define PCIE_MISC_CONTROL_1_OFF 0x8bc
  31. #define PCIE_DBI_RO_WR_EN BIT(0)
  32. #define PLR_OFFSET 0x700
  33. #define PCIE_PORT_DEBUG0 (PLR_OFFSET + 0x28)
  34. #define PORT_LOGIC_LTSSM_STATE_MASK 0x1f
  35. #define PORT_LOGIC_LTSSM_STATE_L0 0x11
  36. #define PCIE_LINK_UP_TIMEOUT_MS 100
  37. /* Offsets from App base */
  38. #define PCIE_CMD_STATUS 0x04
  39. #define LTSSM_EN_VAL BIT(0)
  40. #define AM654_PCIE_DEV_TYPE_MASK 0x3
  41. #define EP 0x0
  42. #define LEG_EP 0x1
  43. #define RC 0x2
  44. /**
  45. * struct pcie_dw_ti - TI DW PCIe controller state
  46. *
  47. * @pci: The common PCIe DW structure
  48. * @app_base: The base address of application register space
  49. */
  50. struct pcie_dw_ti {
  51. /* Must be first member of the struct */
  52. struct pcie_dw dw;
  53. void *app_base;
  54. };
  55. enum dw_pcie_device_mode {
  56. DW_PCIE_UNKNOWN_TYPE,
  57. DW_PCIE_EP_TYPE,
  58. DW_PCIE_LEG_EP_TYPE,
  59. DW_PCIE_RC_TYPE,
  60. };
  61. /**
  62. * pcie_dw_configure() - Configure link capabilities and speed
  63. *
  64. * @regs_base: A pointer to the PCIe controller registers
  65. * @cap_speed: The capabilities and speed to configure
  66. *
  67. * Configure the link capabilities and speed in the PCIe root complex.
  68. */
  69. static void pcie_dw_configure(struct pcie_dw_ti *pci, u32 cap_speed)
  70. {
  71. u32 val;
  72. dw_pcie_dbi_write_enable(&pci->dw, true);
  73. val = readl(pci->dw.dbi_base + PCIE_LINK_CAPABILITY);
  74. val &= ~TARGET_LINK_SPEED_MASK;
  75. val |= cap_speed;
  76. writel(val, pci->dw.dbi_base + PCIE_LINK_CAPABILITY);
  77. val = readl(pci->dw.dbi_base + PCIE_LINK_CTL_2);
  78. val &= ~TARGET_LINK_SPEED_MASK;
  79. val |= cap_speed;
  80. writel(val, pci->dw.dbi_base + PCIE_LINK_CTL_2);
  81. dw_pcie_dbi_write_enable(&pci->dw, false);
  82. }
  83. /**
  84. * is_link_up() - Return the link state
  85. *
  86. * @regs_base: A pointer to the PCIe DBICS registers
  87. *
  88. * Return: 1 (true) for active line and 0 (false) for no link
  89. */
  90. static int is_link_up(struct pcie_dw_ti *pci)
  91. {
  92. u32 val;
  93. val = readl(pci->dw.dbi_base + PCIE_PORT_DEBUG0);
  94. val &= PORT_LOGIC_LTSSM_STATE_MASK;
  95. return (val == PORT_LOGIC_LTSSM_STATE_L0);
  96. }
  97. /**
  98. * wait_link_up() - Wait for the link to come up
  99. *
  100. * @regs_base: A pointer to the PCIe controller registers
  101. *
  102. * Return: 1 (true) for active line and 0 (false) for no link (timeout)
  103. */
  104. static int wait_link_up(struct pcie_dw_ti *pci)
  105. {
  106. unsigned long timeout;
  107. timeout = get_timer(0) + PCIE_LINK_UP_TIMEOUT_MS;
  108. while (!is_link_up(pci)) {
  109. if (get_timer(0) > timeout)
  110. return 0;
  111. };
  112. return 1;
  113. }
  114. static int pcie_dw_ti_pcie_link_up(struct pcie_dw_ti *pci, u32 cap_speed)
  115. {
  116. u32 val;
  117. if (is_link_up(pci)) {
  118. printf("PCI Link already up before configuration!\n");
  119. return 1;
  120. }
  121. /* DW pre link configurations */
  122. pcie_dw_configure(pci, cap_speed);
  123. /* Initiate link training */
  124. val = readl(pci->app_base + PCIE_CMD_STATUS);
  125. val |= LTSSM_EN_VAL;
  126. writel(val, pci->app_base + PCIE_CMD_STATUS);
  127. /* Check that link was established */
  128. if (!wait_link_up(pci))
  129. return 0;
  130. /*
  131. * Link can be established in Gen 1. still need to wait
  132. * till MAC nagaotiation is completed
  133. */
  134. udelay(100);
  135. return 1;
  136. }
  137. static int pcie_am654_set_mode(struct pcie_dw_ti *pci,
  138. enum dw_pcie_device_mode mode)
  139. {
  140. struct regmap *syscon;
  141. u32 val;
  142. u32 mask;
  143. int ret;
  144. syscon = syscon_regmap_lookup_by_phandle(pci->dw.dev,
  145. "ti,syscon-pcie-mode");
  146. if (IS_ERR(syscon))
  147. return 0;
  148. mask = AM654_PCIE_DEV_TYPE_MASK;
  149. switch (mode) {
  150. case DW_PCIE_RC_TYPE:
  151. val = RC;
  152. break;
  153. case DW_PCIE_EP_TYPE:
  154. val = EP;
  155. break;
  156. default:
  157. dev_err(pci->dw.dev, "INVALID device type %d\n", mode);
  158. return -EINVAL;
  159. }
  160. ret = regmap_update_bits(syscon, 0, mask, val);
  161. if (ret) {
  162. dev_err(pci->dw.dev, "failed to set pcie mode\n");
  163. return ret;
  164. }
  165. return 0;
  166. }
  167. static int pcie_dw_init_id(struct pcie_dw_ti *pci)
  168. {
  169. struct regmap *devctrl_regs;
  170. unsigned int id;
  171. int ret;
  172. devctrl_regs = syscon_regmap_lookup_by_phandle(pci->dw.dev,
  173. "ti,syscon-pcie-id");
  174. if (IS_ERR(devctrl_regs))
  175. return PTR_ERR(devctrl_regs);
  176. ret = regmap_read(devctrl_regs, 0, &id);
  177. if (ret)
  178. return ret;
  179. dw_pcie_dbi_write_enable(&pci->dw, true);
  180. writew(id & PCIE_VENDORID_MASK, pci->dw.dbi_base + PCI_VENDOR_ID);
  181. writew(id >> PCIE_DEVICEID_SHIFT, pci->dw.dbi_base + PCI_DEVICE_ID);
  182. dw_pcie_dbi_write_enable(&pci->dw, false);
  183. return 0;
  184. }
  185. /**
  186. * pcie_dw_ti_probe() - Probe the PCIe bus for active link
  187. *
  188. * @dev: A pointer to the device being operated on
  189. *
  190. * Probe for an active link on the PCIe bus and configure the controller
  191. * to enable this port.
  192. *
  193. * Return: 0 on success, else -ENODEV
  194. */
  195. static int pcie_dw_ti_probe(struct udevice *dev)
  196. {
  197. struct pcie_dw_ti *pci = dev_get_priv(dev);
  198. struct udevice *ctlr = pci_get_controller(dev);
  199. struct pci_controller *hose = dev_get_uclass_priv(ctlr);
  200. struct power_domain pci_pwrdmn;
  201. struct phy phy0, phy1;
  202. int ret;
  203. ret = power_domain_get_by_index(dev, &pci_pwrdmn, 0);
  204. if (ret) {
  205. dev_err(dev, "failed to get power domain\n");
  206. return ret;
  207. }
  208. ret = power_domain_on(&pci_pwrdmn);
  209. if (ret) {
  210. dev_err(dev, "Power domain on failed\n");
  211. return ret;
  212. }
  213. ret = generic_phy_get_by_name(dev, "pcie-phy0", &phy0);
  214. if (ret) {
  215. dev_err(dev, "Unable to get phy0");
  216. return ret;
  217. }
  218. generic_phy_reset(&phy0);
  219. generic_phy_init(&phy0);
  220. generic_phy_power_on(&phy0);
  221. ret = generic_phy_get_by_name(dev, "pcie-phy1", &phy1);
  222. if (ret) {
  223. dev_err(dev, "Unable to get phy1");
  224. return ret;
  225. }
  226. generic_phy_reset(&phy1);
  227. generic_phy_init(&phy1);
  228. generic_phy_power_on(&phy1);
  229. pci->dw.first_busno = dev_seq(dev);
  230. pci->dw.dev = dev;
  231. pcie_dw_setup_host(&pci->dw);
  232. pcie_dw_init_id(pci);
  233. if (device_is_compatible(dev, "ti,am654-pcie-rc"))
  234. pcie_am654_set_mode(pci, DW_PCIE_RC_TYPE);
  235. if (!pcie_dw_ti_pcie_link_up(pci, LINK_SPEED_GEN_2)) {
  236. printf("PCIE-%d: Link down\n", dev_seq(dev));
  237. return -ENODEV;
  238. }
  239. printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", dev_seq(dev),
  240. pcie_dw_get_link_speed(&pci->dw),
  241. pcie_dw_get_link_width(&pci->dw),
  242. hose->first_busno);
  243. pcie_dw_prog_outbound_atu_unroll(&pci->dw, PCIE_ATU_REGION_INDEX0,
  244. PCIE_ATU_TYPE_MEM,
  245. pci->dw.mem.phys_start,
  246. pci->dw.mem.bus_start, pci->dw.mem.size);
  247. return 0;
  248. }
  249. /**
  250. * pcie_dw_ti_of_to_plat() - Translate from DT to device state
  251. *
  252. * @dev: A pointer to the device being operated on
  253. *
  254. * Translate relevant data from the device tree pertaining to device @dev into
  255. * state that the driver will later make use of. This state is stored in the
  256. * device's private data structure.
  257. *
  258. * Return: 0 on success, else -EINVAL
  259. */
  260. static int pcie_dw_ti_of_to_plat(struct udevice *dev)
  261. {
  262. struct pcie_dw_ti *pcie = dev_get_priv(dev);
  263. /* Get the controller base address */
  264. pcie->dw.dbi_base = (void *)dev_read_addr_name(dev, "dbics");
  265. if ((fdt_addr_t)pcie->dw.dbi_base == FDT_ADDR_T_NONE)
  266. return -EINVAL;
  267. /* Get the config space base address and size */
  268. pcie->dw.cfg_base = (void *)dev_read_addr_size_name(dev, "config",
  269. &pcie->dw.cfg_size);
  270. if ((fdt_addr_t)pcie->dw.cfg_base == FDT_ADDR_T_NONE)
  271. return -EINVAL;
  272. /* Get the iATU base address and size */
  273. pcie->dw.atu_base = (void *)dev_read_addr_name(dev, "atu");
  274. if ((fdt_addr_t)pcie->dw.atu_base == FDT_ADDR_T_NONE)
  275. return -EINVAL;
  276. /* Get the app base address and size */
  277. pcie->app_base = (void *)dev_read_addr_name(dev, "app");
  278. if ((fdt_addr_t)pcie->app_base == FDT_ADDR_T_NONE)
  279. return -EINVAL;
  280. return 0;
  281. }
  282. static const struct dm_pci_ops pcie_dw_ti_ops = {
  283. .read_config = pcie_dw_read_config,
  284. .write_config = pcie_dw_write_config,
  285. };
  286. static const struct udevice_id pcie_dw_ti_ids[] = {
  287. { .compatible = "ti,am654-pcie-rc" },
  288. { }
  289. };
  290. U_BOOT_DRIVER(pcie_dw_ti) = {
  291. .name = "pcie_dw_ti",
  292. .id = UCLASS_PCI,
  293. .of_match = pcie_dw_ti_ids,
  294. .ops = &pcie_dw_ti_ops,
  295. .of_to_plat = pcie_dw_ti_of_to_plat,
  296. .probe = pcie_dw_ti_probe,
  297. .priv_auto = sizeof(struct pcie_dw_ti),
  298. };