comphy_cp110.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2015-2016 Marvell International Ltd.
  4. */
  5. #include <common.h>
  6. #include <fdtdec.h>
  7. #include <log.h>
  8. #include <asm/global_data.h>
  9. #include <asm/io.h>
  10. #include <asm/ptrace.h>
  11. #include <asm/arch/cpu.h>
  12. #include <asm/arch/soc.h>
  13. #include <linux/delay.h>
  14. #include "comphy_core.h"
  15. #include "sata.h"
  16. #include "utmi_phy.h"
  17. DECLARE_GLOBAL_DATA_PTR;
  18. /* Firmware related definitions used for SMC calls */
  19. #define MV_SIP_COMPHY_POWER_ON 0x82000001
  20. #define MV_SIP_COMPHY_POWER_OFF 0x82000002
  21. #define MV_SIP_COMPHY_PLL_LOCK 0x82000003
  22. #define MV_SIP_COMPHY_XFI_TRAIN 0x82000004
  23. /* Used to distinguish between different possible callers (U-boot/Linux) */
  24. #define COMPHY_CALLER_UBOOT (0x1 << 21)
  25. #define COMPHY_FW_MODE_FORMAT(mode) ((mode) << 12)
  26. #define COMPHY_FW_FORMAT(mode, idx, speeds) \
  27. (((mode) << 12) | ((idx) << 8) | ((speeds) << 2))
  28. #define COMPHY_FW_PCIE_FORMAT(pcie_width, clk_src, mode, speeds) \
  29. (COMPHY_CALLER_UBOOT | ((pcie_width) << 18) | \
  30. ((clk_src) << 17) | COMPHY_FW_FORMAT(mode, 0, speeds))
  31. /* Invert polarity are bits 1-0 of the mode */
  32. #define COMPHY_FW_SATA_FORMAT(mode, invert) \
  33. ((invert) | COMPHY_FW_MODE_FORMAT(mode))
  34. #define COMPHY_SATA_MODE 0x1
  35. #define COMPHY_SGMII_MODE 0x2 /* SGMII 1G */
  36. #define COMPHY_HS_SGMII_MODE 0x3 /* SGMII 2.5G */
  37. #define COMPHY_USB3H_MODE 0x4
  38. #define COMPHY_USB3D_MODE 0x5
  39. #define COMPHY_PCIE_MODE 0x6
  40. #define COMPHY_RXAUI_MODE 0x7
  41. #define COMPHY_XFI_MODE 0x8
  42. #define COMPHY_SFI_MODE 0x9
  43. #define COMPHY_USB3_MODE 0xa
  44. #define COMPHY_AP_MODE 0xb
  45. /* Comphy unit index macro */
  46. #define COMPHY_UNIT_ID0 0
  47. #define COMPHY_UNIT_ID1 1
  48. #define COMPHY_UNIT_ID2 2
  49. #define COMPHY_UNIT_ID3 3
  50. struct utmi_phy_data {
  51. void __iomem *utmi_pll_addr;
  52. void __iomem *utmi_base_addr;
  53. void __iomem *usb_cfg_addr;
  54. void __iomem *utmi_cfg_addr;
  55. u32 utmi_phy_port;
  56. };
  57. static u32 polling_with_timeout(void __iomem *addr, u32 val,
  58. u32 mask, unsigned long usec_timout)
  59. {
  60. u32 data;
  61. do {
  62. udelay(1);
  63. data = readl(addr) & mask;
  64. } while (data != val && --usec_timout > 0);
  65. if (usec_timout == 0)
  66. return data;
  67. return 0;
  68. }
  69. static int comphy_smc(u32 function_id, void __iomem *comphy_base_addr,
  70. u32 lane, u32 mode)
  71. {
  72. struct pt_regs pregs = {0};
  73. pregs.regs[0] = function_id;
  74. pregs.regs[1] = (unsigned long)comphy_base_addr;
  75. pregs.regs[2] = lane;
  76. pregs.regs[3] = mode;
  77. smc_call(&pregs);
  78. /*
  79. * TODO: Firmware return 0 on success, temporary map it to u-boot
  80. * convention, but after all comphy will be reworked the convention in
  81. * u-boot should be change and this conversion removed
  82. */
  83. return pregs.regs[0] ? 0 : 1;
  84. }
  85. /* This function performs RX training for all FFE possible values.
  86. * We get the result for each FFE and eventually the best FFE will
  87. * be used and set to the HW.
  88. *
  89. * Return '1' on succsess.
  90. * Return '0' on failure.
  91. */
  92. int comphy_cp110_sfi_rx_training(struct chip_serdes_phy_config *ptr_chip_cfg,
  93. u32 lane)
  94. {
  95. int ret;
  96. u32 type = ptr_chip_cfg->comphy_map_data[lane].type;
  97. debug_enter();
  98. if (type != COMPHY_TYPE_SFI0 && type != COMPHY_TYPE_SFI1) {
  99. pr_err("Comphy %d isn't configured to SFI\n", lane);
  100. return 0;
  101. }
  102. /* Mode is not relevant for xfi training */
  103. ret = comphy_smc(MV_SIP_COMPHY_XFI_TRAIN,
  104. ptr_chip_cfg->comphy_base_addr, lane, 0);
  105. debug_exit();
  106. return ret;
  107. }
  108. static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base,
  109. void __iomem *comphy_base_addr, int cp_index,
  110. u32 type)
  111. {
  112. u32 mask, data, i, ret = 1;
  113. void __iomem *sata_base = NULL;
  114. int sata_node = -1; /* Set to -1 in order to read the first sata node */
  115. debug_enter();
  116. /*
  117. * Assumption - each CP has only one SATA controller
  118. * Calling fdt_node_offset_by_compatible first time (with sata_node = -1
  119. * will return the first node always.
  120. * In order to parse each CPs SATA node, fdt_node_offset_by_compatible
  121. * must be called again (according to the CP id)
  122. */
  123. for (i = 0; i < (cp_index + 1); i++)
  124. sata_node = fdt_node_offset_by_compatible(
  125. gd->fdt_blob, sata_node, "marvell,armada-8k-ahci");
  126. if (sata_node == 0) {
  127. pr_err("SATA node not found in FDT\n");
  128. return 0;
  129. }
  130. sata_base = (void __iomem *)fdtdec_get_addr_size_auto_noparent(
  131. gd->fdt_blob, sata_node, "reg", 0, NULL, true);
  132. if (sata_base == NULL) {
  133. pr_err("SATA address not found in FDT\n");
  134. return 0;
  135. }
  136. debug("SATA address found in FDT %p\n", sata_base);
  137. debug("stage: MAC configuration - power down comphy\n");
  138. /*
  139. * MAC configuration powe down comphy use indirect address for
  140. * vendor spesific SATA control register
  141. */
  142. reg_set(sata_base + SATA3_VENDOR_ADDRESS,
  143. SATA_CONTROL_REG << SATA3_VENDOR_ADDR_OFSSET,
  144. SATA3_VENDOR_ADDR_MASK);
  145. /* SATA 0 power down */
  146. mask = SATA3_CTRL_SATA0_PD_MASK;
  147. data = 0x1 << SATA3_CTRL_SATA0_PD_OFFSET;
  148. /* SATA 1 power down */
  149. mask |= SATA3_CTRL_SATA1_PD_MASK;
  150. data |= 0x1 << SATA3_CTRL_SATA1_PD_OFFSET;
  151. /* SATA SSU disable */
  152. mask |= SATA3_CTRL_SATA1_ENABLE_MASK;
  153. data |= 0x0 << SATA3_CTRL_SATA1_ENABLE_OFFSET;
  154. /* SATA port 1 disable */
  155. mask |= SATA3_CTRL_SATA_SSU_MASK;
  156. data |= 0x0 << SATA3_CTRL_SATA_SSU_OFFSET;
  157. reg_set(sata_base + SATA3_VENDOR_DATA, data, mask);
  158. ret = comphy_smc(MV_SIP_COMPHY_POWER_ON, comphy_base_addr, lane, type);
  159. /*
  160. * MAC configuration power up comphy - power up PLL/TX/RX
  161. * use indirect address for vendor spesific SATA control register
  162. */
  163. reg_set(sata_base + SATA3_VENDOR_ADDRESS,
  164. SATA_CONTROL_REG << SATA3_VENDOR_ADDR_OFSSET,
  165. SATA3_VENDOR_ADDR_MASK);
  166. /* SATA 0 power up */
  167. mask = SATA3_CTRL_SATA0_PD_MASK;
  168. data = 0x0 << SATA3_CTRL_SATA0_PD_OFFSET;
  169. /* SATA 1 power up */
  170. mask |= SATA3_CTRL_SATA1_PD_MASK;
  171. data |= 0x0 << SATA3_CTRL_SATA1_PD_OFFSET;
  172. /* SATA SSU enable */
  173. mask |= SATA3_CTRL_SATA1_ENABLE_MASK;
  174. data |= 0x1 << SATA3_CTRL_SATA1_ENABLE_OFFSET;
  175. /* SATA port 1 enable */
  176. mask |= SATA3_CTRL_SATA_SSU_MASK;
  177. data |= 0x1 << SATA3_CTRL_SATA_SSU_OFFSET;
  178. reg_set(sata_base + SATA3_VENDOR_DATA, data, mask);
  179. /* MBUS request size and interface select register */
  180. reg_set(sata_base + SATA3_VENDOR_ADDRESS,
  181. SATA_MBUS_SIZE_SELECT_REG << SATA3_VENDOR_ADDR_OFSSET,
  182. SATA3_VENDOR_ADDR_MASK);
  183. /* Mbus regret enable */
  184. reg_set(sata_base + SATA3_VENDOR_DATA,
  185. 0x1 << SATA_MBUS_REGRET_EN_OFFSET, SATA_MBUS_REGRET_EN_MASK);
  186. ret = comphy_smc(MV_SIP_COMPHY_PLL_LOCK, comphy_base_addr, lane, type);
  187. debug_exit();
  188. return ret;
  189. }
  190. static void comphy_utmi_power_down(u32 utmi_index, void __iomem *utmi_base_addr,
  191. void __iomem *usb_cfg_addr,
  192. void __iomem *utmi_cfg_addr,
  193. u32 utmi_phy_port)
  194. {
  195. u32 mask, data;
  196. debug_enter();
  197. debug("stage: UTMI %d - Power down transceiver (power down Phy), Power down PLL, and SuspendDM\n",
  198. utmi_index);
  199. /* Power down UTMI PHY */
  200. reg_set(utmi_cfg_addr, 0x0 << UTMI_PHY_CFG_PU_OFFSET,
  201. UTMI_PHY_CFG_PU_MASK);
  202. /*
  203. * If UTMI connected to USB Device, configure mux prior to PHY init
  204. * (Device can be connected to UTMI0 or to UTMI1)
  205. */
  206. if (utmi_phy_port == UTMI_PHY_TO_USB3_DEVICE0) {
  207. debug("stage: UTMI %d - Enable Device mode and configure UTMI mux\n",
  208. utmi_index);
  209. /* USB3 Device UTMI enable */
  210. mask = UTMI_USB_CFG_DEVICE_EN_MASK;
  211. data = 0x1 << UTMI_USB_CFG_DEVICE_EN_OFFSET;
  212. /* USB3 Device UTMI MUX */
  213. mask |= UTMI_USB_CFG_DEVICE_MUX_MASK;
  214. data |= utmi_index << UTMI_USB_CFG_DEVICE_MUX_OFFSET;
  215. reg_set(usb_cfg_addr, data, mask);
  216. }
  217. /* Set Test suspendm mode */
  218. mask = UTMI_CTRL_STATUS0_SUSPENDM_MASK;
  219. data = 0x1 << UTMI_CTRL_STATUS0_SUSPENDM_OFFSET;
  220. /* Enable Test UTMI select */
  221. mask |= UTMI_CTRL_STATUS0_TEST_SEL_MASK;
  222. data |= 0x1 << UTMI_CTRL_STATUS0_TEST_SEL_OFFSET;
  223. reg_set(utmi_base_addr + UTMI_CTRL_STATUS0_REG, data, mask);
  224. /* Wait for UTMI power down */
  225. mdelay(1);
  226. debug_exit();
  227. return;
  228. }
  229. static void comphy_utmi_phy_config(u32 utmi_index, void __iomem *utmi_pll_addr,
  230. void __iomem *utmi_base_addr,
  231. void __iomem *usb_cfg_addr,
  232. void __iomem *utmi_cfg_addr,
  233. u32 utmi_phy_port)
  234. {
  235. u32 mask, data;
  236. debug_exit();
  237. debug("stage: Configure UTMI PHY %d registers\n", utmi_index);
  238. /* Reference Clock Divider Select */
  239. mask = UTMI_PLL_CTRL_REFDIV_MASK;
  240. data = 0x5 << UTMI_PLL_CTRL_REFDIV_OFFSET;
  241. /* Feedback Clock Divider Select - 90 for 25Mhz*/
  242. mask |= UTMI_PLL_CTRL_FBDIV_MASK;
  243. data |= 0x60 << UTMI_PLL_CTRL_FBDIV_OFFSET;
  244. /* Select LPFR - 0x0 for 25Mhz/5=5Mhz*/
  245. mask |= UTMI_PLL_CTRL_SEL_LPFR_MASK;
  246. data |= 0x0 << UTMI_PLL_CTRL_SEL_LPFR_OFFSET;
  247. reg_set(utmi_pll_addr + UTMI_PLL_CTRL_REG, data, mask);
  248. /* Impedance Calibration Threshold Setting */
  249. mask = UTMI_CALIB_CTRL_IMPCAL_VTH_MASK;
  250. data = 0x7 << UTMI_CALIB_CTRL_IMPCAL_VTH_OFFSET;
  251. reg_set(utmi_pll_addr + UTMI_CALIB_CTRL_REG, data, mask);
  252. /* Start Impedance and PLL Calibration */
  253. mask = UTMI_CALIB_CTRL_PLLCAL_START_MASK;
  254. data = (0x1 << UTMI_CALIB_CTRL_PLLCAL_START_OFFSET);
  255. mask |= UTMI_CALIB_CTRL_IMPCAL_START_MASK;
  256. data |= (0x1 << UTMI_CALIB_CTRL_IMPCAL_START_OFFSET);
  257. reg_set(utmi_pll_addr + UTMI_CALIB_CTRL_REG, data, mask);
  258. /* Set LS TX driver strength coarse control */
  259. mask = UTMI_TX_CH_CTRL_AMP_MASK;
  260. data = 0x4 << UTMI_TX_CH_CTRL_AMP_OFFSET;
  261. mask |= UTMI_TX_CH_CTRL_IMP_SEL_LS_MASK;
  262. data |= 0x3 << UTMI_TX_CH_CTRL_IMP_SEL_LS_OFFSET;
  263. mask |= UTMI_TX_CH_CTRL_DRV_EN_LS_MASK;
  264. data |= 0x3 << UTMI_TX_CH_CTRL_DRV_EN_LS_OFFSET;
  265. reg_set(utmi_base_addr + UTMI_TX_CH_CTRL_REG, data, mask);
  266. /* Enable SQ */
  267. mask = UTMI_RX_CH_CTRL0_SQ_DET_MASK;
  268. data = 0x1 << UTMI_RX_CH_CTRL0_SQ_DET_OFFSET;
  269. /* Enable analog squelch detect */
  270. mask |= UTMI_RX_CH_CTRL0_SQ_ANA_DTC_MASK;
  271. data |= 0x0 << UTMI_RX_CH_CTRL0_SQ_ANA_DTC_OFFSET;
  272. mask |= UTMI_RX_CH_CTRL0_DISCON_THRESH_MASK;
  273. data |= 0x0 << UTMI_RX_CH_CTRL0_DISCON_THRESH_OFFSET;
  274. reg_set(utmi_base_addr + UTMI_RX_CH_CTRL0_REG, data, mask);
  275. /* Set External squelch calibration number */
  276. mask = UTMI_RX_CH_CTRL1_SQ_AMP_CAL_MASK;
  277. data = 0x1 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_OFFSET;
  278. /* Enable the External squelch calibration */
  279. mask |= UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_MASK;
  280. data |= 0x1 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_OFFSET;
  281. reg_set(utmi_base_addr + UTMI_RX_CH_CTRL1_REG, data, mask);
  282. /* Set Control VDAT Reference Voltage - 0.325V */
  283. mask = UTMI_CHGDTC_CTRL_VDAT_MASK;
  284. data = 0x1 << UTMI_CHGDTC_CTRL_VDAT_OFFSET;
  285. /* Set Control VSRC Reference Voltage - 0.6V */
  286. mask |= UTMI_CHGDTC_CTRL_VSRC_MASK;
  287. data |= 0x1 << UTMI_CHGDTC_CTRL_VSRC_OFFSET;
  288. reg_set(utmi_base_addr + UTMI_CHGDTC_CTRL_REG, data, mask);
  289. debug_exit();
  290. return;
  291. }
  292. static int comphy_utmi_power_up(u32 utmi_index, void __iomem *utmi_pll_addr,
  293. void __iomem *utmi_base_addr,
  294. void __iomem *usb_cfg_addr,
  295. void __iomem *utmi_cfg_addr, u32 utmi_phy_port)
  296. {
  297. u32 data, mask, ret = 1;
  298. void __iomem *addr;
  299. debug_enter();
  300. debug("stage: UTMI %d - Power up transceiver(Power up Phy), and exit SuspendDM\n",
  301. utmi_index);
  302. /* Power UP UTMI PHY */
  303. reg_set(utmi_cfg_addr, 0x1 << UTMI_PHY_CFG_PU_OFFSET,
  304. UTMI_PHY_CFG_PU_MASK);
  305. /* Disable Test UTMI select */
  306. reg_set(utmi_base_addr + UTMI_CTRL_STATUS0_REG,
  307. 0x0 << UTMI_CTRL_STATUS0_TEST_SEL_OFFSET,
  308. UTMI_CTRL_STATUS0_TEST_SEL_MASK);
  309. debug("stage: Polling for PLL and impedance calibration done, and PLL ready done\n");
  310. addr = utmi_pll_addr + UTMI_CALIB_CTRL_REG;
  311. data = UTMI_CALIB_CTRL_IMPCAL_DONE_MASK;
  312. mask = data;
  313. data = polling_with_timeout(addr, data, mask, 100);
  314. if (data != 0) {
  315. pr_err("Impedance calibration is not done\n");
  316. debug("Read from reg = %p - value = 0x%x\n", addr, data);
  317. ret = 0;
  318. }
  319. data = UTMI_CALIB_CTRL_PLLCAL_DONE_MASK;
  320. mask = data;
  321. data = polling_with_timeout(addr, data, mask, 100);
  322. if (data != 0) {
  323. pr_err("PLL calibration is not done\n");
  324. debug("Read from reg = %p - value = 0x%x\n", addr, data);
  325. ret = 0;
  326. }
  327. addr = utmi_pll_addr + UTMI_PLL_CTRL_REG;
  328. data = UTMI_PLL_CTRL_PLL_RDY_MASK;
  329. mask = data;
  330. data = polling_with_timeout(addr, data, mask, 100);
  331. if (data != 0) {
  332. pr_err("PLL is not ready\n");
  333. debug("Read from reg = %p - value = 0x%x\n", addr, data);
  334. ret = 0;
  335. }
  336. if (ret)
  337. debug("Passed\n");
  338. else
  339. debug("\n");
  340. debug_exit();
  341. return ret;
  342. }
  343. /*
  344. * comphy_utmi_phy_init initialize the UTMI PHY
  345. * the init split in 3 parts:
  346. * 1. Power down transceiver and PLL
  347. * 2. UTMI PHY configure
  348. * 3. Power up transceiver and PLL
  349. * Note: - Power down/up should be once for both UTMI PHYs
  350. * - comphy_dedicated_phys_init call this function if at least there is
  351. * one UTMI PHY exists in FDT blob. access to cp110_utmi_data[0] is
  352. * legal
  353. */
  354. static void comphy_utmi_phy_init(u32 utmi_phy_count,
  355. struct utmi_phy_data *cp110_utmi_data)
  356. {
  357. u32 i;
  358. debug_enter();
  359. /* UTMI Power down */
  360. for (i = 0; i < utmi_phy_count; i++) {
  361. comphy_utmi_power_down(i, cp110_utmi_data[i].utmi_base_addr,
  362. cp110_utmi_data[i].usb_cfg_addr,
  363. cp110_utmi_data[i].utmi_cfg_addr,
  364. cp110_utmi_data[i].utmi_phy_port);
  365. }
  366. /* PLL Power down */
  367. debug("stage: UTMI PHY power down PLL\n");
  368. for (i = 0; i < utmi_phy_count; i++) {
  369. reg_set(cp110_utmi_data[i].usb_cfg_addr,
  370. 0x0 << UTMI_USB_CFG_PLL_OFFSET, UTMI_USB_CFG_PLL_MASK);
  371. }
  372. /* UTMI configure */
  373. for (i = 0; i < utmi_phy_count; i++) {
  374. comphy_utmi_phy_config(i, cp110_utmi_data[i].utmi_pll_addr,
  375. cp110_utmi_data[i].utmi_base_addr,
  376. cp110_utmi_data[i].usb_cfg_addr,
  377. cp110_utmi_data[i].utmi_cfg_addr,
  378. cp110_utmi_data[i].utmi_phy_port);
  379. }
  380. /* UTMI Power up */
  381. for (i = 0; i < utmi_phy_count; i++) {
  382. if (!comphy_utmi_power_up(i, cp110_utmi_data[i].utmi_pll_addr,
  383. cp110_utmi_data[i].utmi_base_addr,
  384. cp110_utmi_data[i].usb_cfg_addr,
  385. cp110_utmi_data[i].utmi_cfg_addr,
  386. cp110_utmi_data[i].utmi_phy_port)) {
  387. pr_err("Failed to initialize UTMI PHY %d\n", i);
  388. continue;
  389. }
  390. printf("UTMI PHY %d initialized to ", i);
  391. if (cp110_utmi_data[i].utmi_phy_port ==
  392. UTMI_PHY_TO_USB3_DEVICE0)
  393. printf("USB Device\n");
  394. else
  395. printf("USB Host%d\n",
  396. cp110_utmi_data[i].utmi_phy_port);
  397. }
  398. /* PLL Power up */
  399. debug("stage: UTMI PHY power up PLL\n");
  400. for (i = 0; i < utmi_phy_count; i++) {
  401. reg_set(cp110_utmi_data[i].usb_cfg_addr,
  402. 0x1 << UTMI_USB_CFG_PLL_OFFSET, UTMI_USB_CFG_PLL_MASK);
  403. }
  404. debug_exit();
  405. return;
  406. }
  407. /*
  408. * comphy_dedicated_phys_init initialize the dedicated PHYs
  409. * - not muxed SerDes lanes e.g. UTMI PHY
  410. */
  411. void comphy_dedicated_phys_init(void)
  412. {
  413. struct utmi_phy_data cp110_utmi_data[MAX_UTMI_PHY_COUNT];
  414. int node = -1;
  415. int node_idx;
  416. int parent = -1;
  417. debug_enter();
  418. debug("Initialize USB UTMI PHYs\n");
  419. for (node_idx = 0; node_idx < MAX_UTMI_PHY_COUNT;) {
  420. /* Find the UTMI phy node in device tree */
  421. node = fdt_node_offset_by_compatible(gd->fdt_blob, node,
  422. "marvell,mvebu-utmi-2.6.0");
  423. if (node <= 0)
  424. break;
  425. /* check if node is enabled */
  426. if (!fdtdec_get_is_enabled(gd->fdt_blob, node))
  427. continue;
  428. parent = fdt_parent_offset(gd->fdt_blob, node);
  429. if (parent <= 0)
  430. break;
  431. /* get base address of UTMI PLL */
  432. cp110_utmi_data[node_idx].utmi_pll_addr =
  433. (void __iomem *)fdtdec_get_addr_size_auto_noparent(
  434. gd->fdt_blob, parent, "reg", 0, NULL, true);
  435. if (!cp110_utmi_data[node_idx].utmi_pll_addr) {
  436. pr_err("UTMI PHY PLL address is invalid\n");
  437. continue;
  438. }
  439. /* get base address of UTMI phy */
  440. cp110_utmi_data[node_idx].utmi_base_addr =
  441. (void __iomem *)fdtdec_get_addr_size_auto_noparent(
  442. gd->fdt_blob, node, "reg", 0, NULL, true);
  443. if (!cp110_utmi_data[node_idx].utmi_base_addr) {
  444. pr_err("UTMI PHY base address is invalid\n");
  445. continue;
  446. }
  447. /* get usb config address */
  448. cp110_utmi_data[node_idx].usb_cfg_addr =
  449. (void __iomem *)fdtdec_get_addr_size_auto_noparent(
  450. gd->fdt_blob, node, "reg", 1, NULL, true);
  451. if (!cp110_utmi_data[node_idx].usb_cfg_addr) {
  452. pr_err("UTMI PHY base address is invalid\n");
  453. continue;
  454. }
  455. /* get UTMI config address */
  456. cp110_utmi_data[node_idx].utmi_cfg_addr =
  457. (void __iomem *)fdtdec_get_addr_size_auto_noparent(
  458. gd->fdt_blob, node, "reg", 2, NULL, true);
  459. if (!cp110_utmi_data[node_idx].utmi_cfg_addr) {
  460. pr_err("UTMI PHY base address is invalid\n");
  461. continue;
  462. }
  463. /*
  464. * get the port number (to check if the utmi connected to
  465. * host/device)
  466. */
  467. cp110_utmi_data[node_idx].utmi_phy_port = fdtdec_get_int(
  468. gd->fdt_blob, node, "utmi-port", UTMI_PHY_INVALID);
  469. if (cp110_utmi_data[node_idx].utmi_phy_port ==
  470. UTMI_PHY_INVALID) {
  471. pr_err("UTMI PHY port type is invalid\n");
  472. continue;
  473. }
  474. /* count valid UTMI unit */
  475. node_idx++;
  476. }
  477. if (node_idx > 0)
  478. comphy_utmi_phy_init(node_idx, cp110_utmi_data);
  479. debug_exit();
  480. }
  481. int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
  482. struct comphy_map *serdes_map)
  483. {
  484. struct comphy_map *ptr_comphy_map;
  485. void __iomem *comphy_base_addr, *hpipe_base_addr;
  486. u32 comphy_max_count, lane, id, ret = 0;
  487. u32 pcie_width = 0;
  488. u32 mode;
  489. debug_enter();
  490. comphy_max_count = ptr_chip_cfg->comphy_lanes_count;
  491. comphy_base_addr = ptr_chip_cfg->comphy_base_addr;
  492. hpipe_base_addr = ptr_chip_cfg->hpipe3_base_addr;
  493. /* Check if the first 4 lanes configured as By-4 */
  494. for (lane = 0, ptr_comphy_map = serdes_map; lane < 4;
  495. lane++, ptr_comphy_map++) {
  496. if (ptr_comphy_map->type != COMPHY_TYPE_PEX0)
  497. break;
  498. pcie_width++;
  499. }
  500. for (lane = 0, ptr_comphy_map = serdes_map; lane < comphy_max_count;
  501. lane++, ptr_comphy_map++) {
  502. debug("Initialize serdes number %d\n", lane);
  503. debug("Serdes type = 0x%x\n", ptr_comphy_map->type);
  504. if (lane == 4) {
  505. /*
  506. * PCIe lanes above the first 4 lanes, can be only
  507. * by1
  508. */
  509. pcie_width = 1;
  510. }
  511. switch (ptr_comphy_map->type) {
  512. case COMPHY_TYPE_UNCONNECTED:
  513. mode = COMPHY_TYPE_UNCONNECTED | COMPHY_CALLER_UBOOT;
  514. ret = comphy_smc(MV_SIP_COMPHY_POWER_OFF,
  515. ptr_chip_cfg->comphy_base_addr,
  516. lane, mode);
  517. case COMPHY_TYPE_IGNORE:
  518. continue;
  519. break;
  520. case COMPHY_TYPE_PEX0:
  521. case COMPHY_TYPE_PEX1:
  522. case COMPHY_TYPE_PEX2:
  523. case COMPHY_TYPE_PEX3:
  524. mode = COMPHY_FW_PCIE_FORMAT(pcie_width,
  525. ptr_comphy_map->clk_src,
  526. COMPHY_PCIE_MODE,
  527. ptr_comphy_map->speed);
  528. ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
  529. ptr_chip_cfg->comphy_base_addr, lane,
  530. mode);
  531. break;
  532. case COMPHY_TYPE_SATA0:
  533. case COMPHY_TYPE_SATA1:
  534. mode = COMPHY_FW_SATA_FORMAT(COMPHY_SATA_MODE,
  535. serdes_map[lane].invert);
  536. ret = comphy_sata_power_up(lane, hpipe_base_addr,
  537. comphy_base_addr,
  538. ptr_chip_cfg->cp_index,
  539. mode);
  540. break;
  541. case COMPHY_TYPE_USB3_HOST0:
  542. case COMPHY_TYPE_USB3_HOST1:
  543. mode = COMPHY_FW_MODE_FORMAT(COMPHY_USB3H_MODE);
  544. ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
  545. ptr_chip_cfg->comphy_base_addr, lane,
  546. mode);
  547. break;
  548. case COMPHY_TYPE_USB3_DEVICE:
  549. mode = COMPHY_FW_MODE_FORMAT(COMPHY_USB3D_MODE);
  550. ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
  551. ptr_chip_cfg->comphy_base_addr, lane,
  552. mode);
  553. break;
  554. case COMPHY_TYPE_SGMII0:
  555. case COMPHY_TYPE_SGMII1:
  556. case COMPHY_TYPE_SGMII2:
  557. /* Calculate SGMII ID */
  558. id = ptr_comphy_map->type - COMPHY_TYPE_SGMII0;
  559. if (ptr_comphy_map->speed == COMPHY_SPEED_INVALID) {
  560. debug("Warning: SGMII PHY speed in lane %d is invalid, set PHY speed to 1.25G\n",
  561. lane);
  562. ptr_comphy_map->speed = COMPHY_SPEED_1_25G;
  563. }
  564. mode = COMPHY_FW_FORMAT(COMPHY_SGMII_MODE, id,
  565. ptr_comphy_map->speed);
  566. ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
  567. ptr_chip_cfg->comphy_base_addr, lane,
  568. mode);
  569. break;
  570. case COMPHY_TYPE_SFI0:
  571. case COMPHY_TYPE_SFI1:
  572. /* Calculate SFI id */
  573. id = ptr_comphy_map->type - COMPHY_TYPE_SFI0;
  574. mode = COMPHY_FW_FORMAT(COMPHY_SFI_MODE, id,
  575. ptr_comphy_map->speed);
  576. ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
  577. ptr_chip_cfg->comphy_base_addr, lane, mode);
  578. break;
  579. case COMPHY_TYPE_RXAUI0:
  580. case COMPHY_TYPE_RXAUI1:
  581. mode = COMPHY_FW_MODE_FORMAT(COMPHY_RXAUI_MODE);
  582. ret = comphy_smc(MV_SIP_COMPHY_POWER_ON,
  583. ptr_chip_cfg->comphy_base_addr, lane,
  584. mode);
  585. break;
  586. default:
  587. debug("Unknown SerDes type, skip initialize SerDes %d\n",
  588. lane);
  589. break;
  590. }
  591. if (ret == 0) {
  592. /*
  593. * If interface wans't initialized, set the lane to
  594. * COMPHY_TYPE_UNCONNECTED state.
  595. */
  596. ptr_comphy_map->type = COMPHY_TYPE_UNCONNECTED;
  597. pr_err("PLL is not locked - Failed to initialize lane %d\n",
  598. lane);
  599. }
  600. }
  601. debug_exit();
  602. return 0;
  603. }