phy-qcom-snps-femto-v2.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2020, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/clk.h>
  6. #include <linux/delay.h>
  7. #include <linux/err.h>
  8. #include <linux/io.h>
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/of.h>
  12. #include <linux/of_device.h>
  13. #include <linux/phy/phy.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/regmap.h>
  16. #include <linux/regulator/consumer.h>
  17. #include <linux/reset.h>
  18. #include <linux/slab.h>
  19. #define USB2_PHY_USB_PHY_UTMI_CTRL0 (0x3c)
  20. #define SLEEPM BIT(0)
  21. #define OPMODE_MASK GENMASK(4, 3)
  22. #define OPMODE_NORMAL (0x00)
  23. #define OPMODE_NONDRIVING BIT(3)
  24. #define TERMSEL BIT(5)
  25. #define USB2_PHY_USB_PHY_UTMI_CTRL1 (0x40)
  26. #define XCVRSEL BIT(0)
  27. #define USB2_PHY_USB_PHY_UTMI_CTRL5 (0x50)
  28. #define POR BIT(1)
  29. #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0 (0x54)
  30. #define SIDDQ BIT(2)
  31. #define RETENABLEN BIT(3)
  32. #define FSEL_MASK GENMASK(6, 4)
  33. #define FSEL_DEFAULT (0x3 << 4)
  34. #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1 (0x58)
  35. #define VBUSVLDEXTSEL0 BIT(4)
  36. #define PLLBTUNE BIT(5)
  37. #define USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2 (0x5c)
  38. #define VREGBYPASS BIT(0)
  39. #define USB2_PHY_USB_PHY_HS_PHY_CTRL1 (0x60)
  40. #define VBUSVLDEXT0 BIT(0)
  41. #define USB2_PHY_USB_PHY_HS_PHY_CTRL2 (0x64)
  42. #define USB2_AUTO_RESUME BIT(0)
  43. #define USB2_SUSPEND_N BIT(2)
  44. #define USB2_SUSPEND_N_SEL BIT(3)
  45. #define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0 (0x6c)
  46. #define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1 (0x70)
  47. #define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2 (0x74)
  48. #define USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X3 (0x78)
  49. #define PARAM_OVRD_MASK 0xFF
  50. #define USB2_PHY_USB_PHY_CFG0 (0x94)
  51. #define UTMI_PHY_DATAPATH_CTRL_OVERRIDE_EN BIT(0)
  52. #define UTMI_PHY_CMN_CTRL_OVERRIDE_EN BIT(1)
  53. #define USB2_PHY_USB_PHY_REFCLK_CTRL (0xa0)
  54. #define REFCLK_SEL_MASK GENMASK(1, 0)
  55. #define REFCLK_SEL_DEFAULT (0x2 << 0)
  56. #define HS_DISCONNECT_MASK GENMASK(2, 0)
  57. #define SQUELCH_DETECTOR_MASK GENMASK(7, 5)
  58. #define HS_AMPLITUDE_MASK GENMASK(3, 0)
  59. #define PREEMPHASIS_DURATION_MASK BIT(5)
  60. #define PREEMPHASIS_AMPLITUDE_MASK GENMASK(7, 6)
  61. #define HS_RISE_FALL_MASK GENMASK(1, 0)
  62. #define HS_CROSSOVER_VOLTAGE_MASK GENMASK(3, 2)
  63. #define HS_OUTPUT_IMPEDANCE_MASK GENMASK(5, 4)
  64. #define LS_FS_OUTPUT_IMPEDANCE_MASK GENMASK(3, 0)
  65. static const char * const qcom_snps_hsphy_vreg_names[] = {
  66. "vdda-pll", "vdda33", "vdda18",
  67. };
  68. #define SNPS_HS_NUM_VREGS ARRAY_SIZE(qcom_snps_hsphy_vreg_names)
  69. struct override_param {
  70. s32 value;
  71. u8 reg_val;
  72. };
  73. struct override_param_map {
  74. const char *prop_name;
  75. const struct override_param *param_table;
  76. u8 table_size;
  77. u8 reg_offset;
  78. u8 param_mask;
  79. };
  80. struct phy_override_seq {
  81. bool need_update;
  82. u8 offset;
  83. u8 value;
  84. u8 mask;
  85. };
  86. #define NUM_HSPHY_TUNING_PARAMS (9)
  87. /**
  88. * struct qcom_snps_hsphy - snps hs phy attributes
  89. *
  90. * @dev: device structure
  91. *
  92. * @phy: generic phy
  93. * @base: iomapped memory space for snps hs phy
  94. *
  95. * @num_clks: number of clocks
  96. * @clks: array of clocks
  97. * @phy_reset: phy reset control
  98. * @vregs: regulator supplies bulk data
  99. * @phy_initialized: if PHY has been initialized correctly
  100. * @mode: contains the current mode the PHY is in
  101. * @update_seq_cfg: tuning parameters for phy init
  102. */
  103. struct qcom_snps_hsphy {
  104. struct device *dev;
  105. struct phy *phy;
  106. void __iomem *base;
  107. int num_clks;
  108. struct clk_bulk_data *clks;
  109. struct reset_control *phy_reset;
  110. struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS];
  111. bool phy_initialized;
  112. enum phy_mode mode;
  113. struct phy_override_seq update_seq_cfg[NUM_HSPHY_TUNING_PARAMS];
  114. };
  115. static int qcom_snps_hsphy_clk_init(struct qcom_snps_hsphy *hsphy)
  116. {
  117. struct device *dev = hsphy->dev;
  118. hsphy->num_clks = 2;
  119. hsphy->clks = devm_kcalloc(dev, hsphy->num_clks, sizeof(*hsphy->clks), GFP_KERNEL);
  120. if (!hsphy->clks)
  121. return -ENOMEM;
  122. /*
  123. * TODO: Currently no device tree instantiation of the PHY is using the clock.
  124. * This needs to be fixed in order for this code to be able to use devm_clk_bulk_get().
  125. */
  126. hsphy->clks[0].id = "cfg_ahb";
  127. hsphy->clks[0].clk = devm_clk_get_optional(dev, "cfg_ahb");
  128. if (IS_ERR(hsphy->clks[0].clk))
  129. return dev_err_probe(dev, PTR_ERR(hsphy->clks[0].clk),
  130. "failed to get cfg_ahb clk\n");
  131. hsphy->clks[1].id = "ref";
  132. hsphy->clks[1].clk = devm_clk_get(dev, "ref");
  133. if (IS_ERR(hsphy->clks[1].clk))
  134. return dev_err_probe(dev, PTR_ERR(hsphy->clks[1].clk),
  135. "failed to get ref clk\n");
  136. return 0;
  137. }
  138. static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset,
  139. u32 mask, u32 val)
  140. {
  141. u32 reg;
  142. reg = readl_relaxed(base + offset);
  143. reg &= ~mask;
  144. reg |= val & mask;
  145. writel_relaxed(reg, base + offset);
  146. /* Ensure above write is completed */
  147. readl_relaxed(base + offset);
  148. }
  149. static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
  150. {
  151. dev_dbg(&hsphy->phy->dev, "Suspend QCOM SNPS PHY\n");
  152. if (hsphy->mode == PHY_MODE_USB_HOST) {
  153. /* Enable auto-resume to meet remote wakeup timing */
  154. qcom_snps_hsphy_write_mask(hsphy->base,
  155. USB2_PHY_USB_PHY_HS_PHY_CTRL2,
  156. USB2_AUTO_RESUME,
  157. USB2_AUTO_RESUME);
  158. usleep_range(500, 1000);
  159. qcom_snps_hsphy_write_mask(hsphy->base,
  160. USB2_PHY_USB_PHY_HS_PHY_CTRL2,
  161. 0, USB2_AUTO_RESUME);
  162. }
  163. return 0;
  164. }
  165. static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
  166. {
  167. dev_dbg(&hsphy->phy->dev, "Resume QCOM SNPS PHY, mode\n");
  168. return 0;
  169. }
  170. static int __maybe_unused qcom_snps_hsphy_runtime_suspend(struct device *dev)
  171. {
  172. struct qcom_snps_hsphy *hsphy = dev_get_drvdata(dev);
  173. if (!hsphy->phy_initialized)
  174. return 0;
  175. return qcom_snps_hsphy_suspend(hsphy);
  176. }
  177. static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
  178. {
  179. struct qcom_snps_hsphy *hsphy = dev_get_drvdata(dev);
  180. if (!hsphy->phy_initialized)
  181. return 0;
  182. return qcom_snps_hsphy_resume(hsphy);
  183. }
  184. static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode,
  185. int submode)
  186. {
  187. struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
  188. hsphy->mode = mode;
  189. return 0;
  190. }
  191. static const struct override_param hs_disconnect_sc7280[] = {
  192. { -272, 0 },
  193. { 0, 1 },
  194. { 317, 2 },
  195. { 630, 3 },
  196. { 973, 4 },
  197. { 1332, 5 },
  198. { 1743, 6 },
  199. { 2156, 7 },
  200. };
  201. static const struct override_param squelch_det_threshold_sc7280[] = {
  202. { -2090, 7 },
  203. { -1560, 6 },
  204. { -1030, 5 },
  205. { -530, 4 },
  206. { 0, 3 },
  207. { 530, 2 },
  208. { 1060, 1 },
  209. { 1590, 0 },
  210. };
  211. static const struct override_param hs_amplitude_sc7280[] = {
  212. { -660, 0 },
  213. { -440, 1 },
  214. { -220, 2 },
  215. { 0, 3 },
  216. { 230, 4 },
  217. { 440, 5 },
  218. { 650, 6 },
  219. { 890, 7 },
  220. { 1110, 8 },
  221. { 1330, 9 },
  222. { 1560, 10 },
  223. { 1780, 11 },
  224. { 2000, 12 },
  225. { 2220, 13 },
  226. { 2430, 14 },
  227. { 2670, 15 },
  228. };
  229. static const struct override_param preemphasis_duration_sc7280[] = {
  230. { 10000, 1 },
  231. { 20000, 0 },
  232. };
  233. static const struct override_param preemphasis_amplitude_sc7280[] = {
  234. { 10000, 1 },
  235. { 20000, 2 },
  236. { 30000, 3 },
  237. { 40000, 0 },
  238. };
  239. static const struct override_param hs_rise_fall_time_sc7280[] = {
  240. { -4100, 3 },
  241. { 0, 2 },
  242. { 2810, 1 },
  243. { 5430, 0 },
  244. };
  245. static const struct override_param hs_crossover_voltage_sc7280[] = {
  246. { -31000, 1 },
  247. { 0, 3 },
  248. { 28000, 2 },
  249. };
  250. static const struct override_param hs_output_impedance_sc7280[] = {
  251. { -2300000, 3 },
  252. { 0, 2 },
  253. { 2600000, 1 },
  254. { 6100000, 0 },
  255. };
  256. static const struct override_param ls_fs_output_impedance_sc7280[] = {
  257. { -1053, 15 },
  258. { -557, 7 },
  259. { 0, 3 },
  260. { 612, 1 },
  261. { 1310, 0 },
  262. };
  263. static const struct override_param_map sc7280_snps_7nm_phy[] = {
  264. {
  265. "qcom,hs-disconnect-bp",
  266. hs_disconnect_sc7280,
  267. ARRAY_SIZE(hs_disconnect_sc7280),
  268. USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0,
  269. HS_DISCONNECT_MASK
  270. },
  271. {
  272. "qcom,squelch-detector-bp",
  273. squelch_det_threshold_sc7280,
  274. ARRAY_SIZE(squelch_det_threshold_sc7280),
  275. USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X0,
  276. SQUELCH_DETECTOR_MASK
  277. },
  278. {
  279. "qcom,hs-amplitude-bp",
  280. hs_amplitude_sc7280,
  281. ARRAY_SIZE(hs_amplitude_sc7280),
  282. USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1,
  283. HS_AMPLITUDE_MASK
  284. },
  285. {
  286. "qcom,pre-emphasis-duration-bp",
  287. preemphasis_duration_sc7280,
  288. ARRAY_SIZE(preemphasis_duration_sc7280),
  289. USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1,
  290. PREEMPHASIS_DURATION_MASK,
  291. },
  292. {
  293. "qcom,pre-emphasis-amplitude-bp",
  294. preemphasis_amplitude_sc7280,
  295. ARRAY_SIZE(preemphasis_amplitude_sc7280),
  296. USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X1,
  297. PREEMPHASIS_AMPLITUDE_MASK,
  298. },
  299. {
  300. "qcom,hs-rise-fall-time-bp",
  301. hs_rise_fall_time_sc7280,
  302. ARRAY_SIZE(hs_rise_fall_time_sc7280),
  303. USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2,
  304. HS_RISE_FALL_MASK
  305. },
  306. {
  307. "qcom,hs-crossover-voltage-microvolt",
  308. hs_crossover_voltage_sc7280,
  309. ARRAY_SIZE(hs_crossover_voltage_sc7280),
  310. USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2,
  311. HS_CROSSOVER_VOLTAGE_MASK
  312. },
  313. {
  314. "qcom,hs-output-impedance-micro-ohms",
  315. hs_output_impedance_sc7280,
  316. ARRAY_SIZE(hs_output_impedance_sc7280),
  317. USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X2,
  318. HS_OUTPUT_IMPEDANCE_MASK,
  319. },
  320. {
  321. "qcom,ls-fs-output-impedance-bp",
  322. ls_fs_output_impedance_sc7280,
  323. ARRAY_SIZE(ls_fs_output_impedance_sc7280),
  324. USB2_PHY_USB_PHY_HS_PHY_OVERRIDE_X3,
  325. LS_FS_OUTPUT_IMPEDANCE_MASK,
  326. },
  327. {},
  328. };
  329. static int qcom_snps_hsphy_init(struct phy *phy)
  330. {
  331. struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
  332. int ret, i;
  333. dev_vdbg(&phy->dev, "%s(): Initializing SNPS HS phy\n", __func__);
  334. ret = regulator_bulk_enable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
  335. if (ret)
  336. return ret;
  337. ret = clk_bulk_prepare_enable(hsphy->num_clks, hsphy->clks);
  338. if (ret) {
  339. dev_err(&phy->dev, "failed to enable clocks, %d\n", ret);
  340. goto poweroff_phy;
  341. }
  342. ret = reset_control_assert(hsphy->phy_reset);
  343. if (ret) {
  344. dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
  345. goto disable_clks;
  346. }
  347. usleep_range(100, 150);
  348. ret = reset_control_deassert(hsphy->phy_reset);
  349. if (ret) {
  350. dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
  351. goto disable_clks;
  352. }
  353. qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
  354. UTMI_PHY_CMN_CTRL_OVERRIDE_EN,
  355. UTMI_PHY_CMN_CTRL_OVERRIDE_EN);
  356. qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5,
  357. POR, POR);
  358. qcom_snps_hsphy_write_mask(hsphy->base,
  359. USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0,
  360. FSEL_MASK, 0);
  361. qcom_snps_hsphy_write_mask(hsphy->base,
  362. USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1,
  363. PLLBTUNE, PLLBTUNE);
  364. qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_REFCLK_CTRL,
  365. REFCLK_SEL_DEFAULT, REFCLK_SEL_MASK);
  366. qcom_snps_hsphy_write_mask(hsphy->base,
  367. USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON1,
  368. VBUSVLDEXTSEL0, VBUSVLDEXTSEL0);
  369. qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL1,
  370. VBUSVLDEXT0, VBUSVLDEXT0);
  371. for (i = 0; i < ARRAY_SIZE(hsphy->update_seq_cfg); i++) {
  372. if (hsphy->update_seq_cfg[i].need_update)
  373. qcom_snps_hsphy_write_mask(hsphy->base,
  374. hsphy->update_seq_cfg[i].offset,
  375. hsphy->update_seq_cfg[i].mask,
  376. hsphy->update_seq_cfg[i].value);
  377. }
  378. qcom_snps_hsphy_write_mask(hsphy->base,
  379. USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2,
  380. VREGBYPASS, VREGBYPASS);
  381. qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2,
  382. USB2_SUSPEND_N_SEL | USB2_SUSPEND_N,
  383. USB2_SUSPEND_N_SEL | USB2_SUSPEND_N);
  384. qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL0,
  385. SLEEPM, SLEEPM);
  386. qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON0,
  387. SIDDQ, 0);
  388. qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_UTMI_CTRL5,
  389. POR, 0);
  390. qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL2,
  391. USB2_SUSPEND_N_SEL, 0);
  392. qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
  393. UTMI_PHY_CMN_CTRL_OVERRIDE_EN, 0);
  394. hsphy->phy_initialized = true;
  395. return 0;
  396. disable_clks:
  397. clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
  398. poweroff_phy:
  399. regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
  400. return ret;
  401. }
  402. static int qcom_snps_hsphy_exit(struct phy *phy)
  403. {
  404. struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
  405. reset_control_assert(hsphy->phy_reset);
  406. clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
  407. regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
  408. hsphy->phy_initialized = false;
  409. return 0;
  410. }
  411. static const struct phy_ops qcom_snps_hsphy_gen_ops = {
  412. .init = qcom_snps_hsphy_init,
  413. .exit = qcom_snps_hsphy_exit,
  414. .set_mode = qcom_snps_hsphy_set_mode,
  415. .owner = THIS_MODULE,
  416. };
  417. static const struct of_device_id qcom_snps_hsphy_of_match_table[] = {
  418. { .compatible = "qcom,sm8150-usb-hs-phy", },
  419. { .compatible = "qcom,usb-snps-hs-5nm-phy", },
  420. {
  421. .compatible = "qcom,usb-snps-hs-7nm-phy",
  422. .data = &sc7280_snps_7nm_phy,
  423. },
  424. { .compatible = "qcom,usb-snps-femto-v2-phy", },
  425. { }
  426. };
  427. MODULE_DEVICE_TABLE(of, qcom_snps_hsphy_of_match_table);
  428. static const struct dev_pm_ops qcom_snps_hsphy_pm_ops = {
  429. SET_RUNTIME_PM_OPS(qcom_snps_hsphy_runtime_suspend,
  430. qcom_snps_hsphy_runtime_resume, NULL)
  431. };
  432. static void qcom_snps_hsphy_override_param_update_val(
  433. const struct override_param_map map,
  434. s32 dt_val, struct phy_override_seq *seq_entry)
  435. {
  436. int i;
  437. /*
  438. * Param table for each param is in increasing order
  439. * of dt values. We need to iterate over the list to
  440. * select the entry that matches the dt value and pick
  441. * up the corresponding register value.
  442. */
  443. for (i = 0; i < map.table_size - 1; i++) {
  444. if (map.param_table[i].value == dt_val)
  445. break;
  446. }
  447. seq_entry->need_update = true;
  448. seq_entry->offset = map.reg_offset;
  449. seq_entry->mask = map.param_mask;
  450. seq_entry->value = map.param_table[i].reg_val << __ffs(map.param_mask);
  451. }
  452. static void qcom_snps_hsphy_read_override_param_seq(struct device *dev)
  453. {
  454. struct device_node *node = dev->of_node;
  455. s32 val;
  456. int ret, i;
  457. struct qcom_snps_hsphy *hsphy;
  458. const struct override_param_map *cfg = of_device_get_match_data(dev);
  459. if (!cfg)
  460. return;
  461. hsphy = dev_get_drvdata(dev);
  462. for (i = 0; cfg[i].prop_name != NULL; i++) {
  463. ret = of_property_read_s32(node, cfg[i].prop_name, &val);
  464. if (ret)
  465. continue;
  466. qcom_snps_hsphy_override_param_update_val(cfg[i], val,
  467. &hsphy->update_seq_cfg[i]);
  468. dev_dbg(&hsphy->phy->dev, "Read param: %s dt_val: %d reg_val: 0x%x\n",
  469. cfg[i].prop_name, val, hsphy->update_seq_cfg[i].value);
  470. }
  471. }
  472. static int qcom_snps_hsphy_probe(struct platform_device *pdev)
  473. {
  474. struct device *dev = &pdev->dev;
  475. struct qcom_snps_hsphy *hsphy;
  476. struct phy_provider *phy_provider;
  477. struct phy *generic_phy;
  478. int ret, i;
  479. int num;
  480. hsphy = devm_kzalloc(dev, sizeof(*hsphy), GFP_KERNEL);
  481. if (!hsphy)
  482. return -ENOMEM;
  483. hsphy->dev = dev;
  484. hsphy->base = devm_platform_ioremap_resource(pdev, 0);
  485. if (IS_ERR(hsphy->base))
  486. return PTR_ERR(hsphy->base);
  487. ret = qcom_snps_hsphy_clk_init(hsphy);
  488. if (ret)
  489. return dev_err_probe(dev, ret, "failed to initialize clocks\n");
  490. hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
  491. if (IS_ERR(hsphy->phy_reset)) {
  492. dev_err(dev, "failed to get phy core reset\n");
  493. return PTR_ERR(hsphy->phy_reset);
  494. }
  495. num = ARRAY_SIZE(hsphy->vregs);
  496. for (i = 0; i < num; i++)
  497. hsphy->vregs[i].supply = qcom_snps_hsphy_vreg_names[i];
  498. ret = devm_regulator_bulk_get(dev, num, hsphy->vregs);
  499. if (ret)
  500. return dev_err_probe(dev, ret,
  501. "failed to get regulator supplies\n");
  502. pm_runtime_set_active(dev);
  503. pm_runtime_enable(dev);
  504. /*
  505. * Prevent runtime pm from being ON by default. Users can enable
  506. * it using power/control in sysfs.
  507. */
  508. pm_runtime_forbid(dev);
  509. generic_phy = devm_phy_create(dev, NULL, &qcom_snps_hsphy_gen_ops);
  510. if (IS_ERR(generic_phy)) {
  511. ret = PTR_ERR(generic_phy);
  512. dev_err(dev, "failed to create phy, %d\n", ret);
  513. return ret;
  514. }
  515. hsphy->phy = generic_phy;
  516. dev_set_drvdata(dev, hsphy);
  517. phy_set_drvdata(generic_phy, hsphy);
  518. qcom_snps_hsphy_read_override_param_seq(dev);
  519. phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
  520. if (!IS_ERR(phy_provider))
  521. dev_dbg(dev, "Registered Qcom-SNPS HS phy\n");
  522. else
  523. pm_runtime_disable(dev);
  524. return PTR_ERR_OR_ZERO(phy_provider);
  525. }
  526. static struct platform_driver qcom_snps_hsphy_driver = {
  527. .probe = qcom_snps_hsphy_probe,
  528. .driver = {
  529. .name = "qcom-snps-hs-femto-v2-phy",
  530. .pm = &qcom_snps_hsphy_pm_ops,
  531. .of_match_table = qcom_snps_hsphy_of_match_table,
  532. },
  533. };
  534. module_platform_driver(qcom_snps_hsphy_driver);
  535. MODULE_DESCRIPTION("Qualcomm SNPS FEMTO USB HS PHY V2 driver");
  536. MODULE_LICENSE("GPL v2");