hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/phy/qualcomm/phy-qcom-qusb2.c
....@@ -1,6 +1,6 @@
11 // SPDX-License-Identifier: GPL-2.0
22 /*
3
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
3
+ * Copyright (c) 2017, 2019, The Linux Foundation. All rights reserved.
44 */
55
66 #include <linux/clk.h>
....@@ -66,12 +66,24 @@
6666 #define IMP_RES_OFFSET_MASK GENMASK(5, 0)
6767 #define IMP_RES_OFFSET_SHIFT 0x0
6868
69
+/* QUSB2PHY_PLL_BIAS_CONTROL_2 register bits */
70
+#define BIAS_CTRL2_RES_OFFSET_MASK GENMASK(5, 0)
71
+#define BIAS_CTRL2_RES_OFFSET_SHIFT 0x0
72
+
73
+/* QUSB2PHY_CHG_CONTROL_2 register bits */
74
+#define CHG_CTRL2_OFFSET_MASK GENMASK(5, 4)
75
+#define CHG_CTRL2_OFFSET_SHIFT 0x4
76
+
6977 /* QUSB2PHY_PORT_TUNE1 register bits */
7078 #define HSTX_TRIM_MASK GENMASK(7, 4)
7179 #define HSTX_TRIM_SHIFT 0x4
7280 #define PREEMPH_WIDTH_HALF_BIT BIT(2)
7381 #define PREEMPHASIS_EN_MASK GENMASK(1, 0)
7482 #define PREEMPHASIS_EN_SHIFT 0x0
83
+
84
+/* QUSB2PHY_PORT_TUNE2 register bits */
85
+#define HSDISC_TRIM_MASK GENMASK(1, 0)
86
+#define HSDISC_TRIM_SHIFT 0x0
7587
7688 #define QUSB2PHY_PLL_ANALOG_CONTROLS_TWO 0x04
7789 #define QUSB2PHY_PLL_CLOCK_INVERTERS 0x18c
....@@ -152,7 +164,32 @@
152164 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
153165 };
154166
155
-static const unsigned int sdm845_regs_layout[] = {
167
+static const unsigned int msm8998_regs_layout[] = {
168
+ [QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8,
169
+ [QUSB2PHY_PLL_STATUS] = 0x1a0,
170
+ [QUSB2PHY_PORT_TUNE1] = 0x23c,
171
+ [QUSB2PHY_PORT_TUNE2] = 0x240,
172
+ [QUSB2PHY_PORT_TUNE3] = 0x244,
173
+ [QUSB2PHY_PORT_TUNE4] = 0x248,
174
+ [QUSB2PHY_PORT_TEST1] = 0x24c,
175
+ [QUSB2PHY_PORT_TEST2] = 0x250,
176
+ [QUSB2PHY_PORT_POWERDOWN] = 0x210,
177
+ [QUSB2PHY_INTR_CTRL] = 0x22c,
178
+};
179
+
180
+static const struct qusb2_phy_init_tbl msm8998_init_tbl[] = {
181
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x13),
182
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c),
183
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CMODE, 0x80),
184
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_LOCK_DELAY, 0x0a),
185
+
186
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0xa5),
187
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0x09),
188
+
189
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_DIGITAL_TIMERS_TWO, 0x19),
190
+};
191
+
192
+static const unsigned int qusb2_v2_regs_layout[] = {
156193 [QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8,
157194 [QUSB2PHY_PLL_STATUS] = 0x1a0,
158195 [QUSB2PHY_PORT_TUNE1] = 0x240,
....@@ -166,7 +203,7 @@
166203 [QUSB2PHY_INTR_CTRL] = 0x230,
167204 };
168205
169
-static const struct qusb2_phy_init_tbl sdm845_init_tbl[] = {
206
+static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = {
170207 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03),
171208 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c),
172209 QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CMODE, 0x80),
....@@ -221,10 +258,22 @@
221258 .autoresume_en = BIT(3),
222259 };
223260
224
-static const struct qusb2_phy_cfg sdm845_phy_cfg = {
225
- .tbl = sdm845_init_tbl,
226
- .tbl_num = ARRAY_SIZE(sdm845_init_tbl),
227
- .regs = sdm845_regs_layout,
261
+static const struct qusb2_phy_cfg msm8998_phy_cfg = {
262
+ .tbl = msm8998_init_tbl,
263
+ .tbl_num = ARRAY_SIZE(msm8998_init_tbl),
264
+ .regs = msm8998_regs_layout,
265
+
266
+ .disable_ctrl = POWER_DOWN,
267
+ .mask_core_ready = CORE_READY_STATUS,
268
+ .has_pll_override = true,
269
+ .autoresume_en = BIT(0),
270
+ .update_tune1_with_efuse = true,
271
+};
272
+
273
+static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = {
274
+ .tbl = qusb2_v2_init_tbl,
275
+ .tbl_num = ARRAY_SIZE(qusb2_v2_init_tbl),
276
+ .regs = qusb2_v2_regs_layout,
228277
229278 .disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN |
230279 POWER_DOWN),
....@@ -239,6 +288,34 @@
239288 };
240289
241290 #define QUSB2_NUM_VREGS ARRAY_SIZE(qusb2_phy_vreg_names)
291
+
292
+/* struct override_param - structure holding qusb2 v2 phy overriding param
293
+ * set override true if the device tree property exists and read and assign
294
+ * to value
295
+ */
296
+struct override_param {
297
+ bool override;
298
+ u8 value;
299
+};
300
+
301
+/*struct override_params - structure holding qusb2 v2 phy overriding params
302
+ * @imp_res_offset: rescode offset to be updated in IMP_CTRL1 register
303
+ * @hstx_trim: HSTX_TRIM to be updated in TUNE1 register
304
+ * @preemphasis: Amplitude Pre-Emphasis to be updated in TUNE1 register
305
+ * @preemphasis_width: half/full-width Pre-Emphasis updated via TUNE1
306
+ * @bias_ctrl: bias ctrl to be updated in BIAS_CONTROL_2 register
307
+ * @charge_ctrl: charge ctrl to be updated in CHG_CTRL2 register
308
+ * @hsdisc_trim: disconnect threshold to be updated in TUNE2 register
309
+ */
310
+struct override_params {
311
+ struct override_param imp_res_offset;
312
+ struct override_param hstx_trim;
313
+ struct override_param preemphasis;
314
+ struct override_param preemphasis_width;
315
+ struct override_param bias_ctrl;
316
+ struct override_param charge_ctrl;
317
+ struct override_param hsdisc_trim;
318
+};
242319
243320 /**
244321 * struct qusb2_phy - structure holding qusb2 phy attributes
....@@ -255,14 +332,7 @@
255332 * @tcsr: TCSR syscon register map
256333 * @cell: nvmem cell containing phy tuning value
257334 *
258
- * @override_imp_res_offset: PHY should use different rescode offset
259
- * @imp_res_offset_value: rescode offset to be updated in IMP_CTRL1 register
260
- * @override_hstx_trim: PHY should use different HSTX o/p current value
261
- * @hstx_trim_value: HSTX_TRIM value to be updated in TUNE1 register
262
- * @override_preemphasis: PHY should use different pre-amphasis amplitude
263
- * @preemphasis_level: Amplitude Pre-Emphasis to be updated in TUNE1 register
264
- * @override_preemphasis_width: PHY should use different pre-emphasis duration
265
- * @preemphasis_width: half/full-width Pre-Emphasis updated via TUNE1
335
+ * @overrides: pointer to structure for all overriding tuning params
266336 *
267337 * @cfg: phy config data
268338 * @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme
....@@ -282,14 +352,7 @@
282352 struct regmap *tcsr;
283353 struct nvmem_cell *cell;
284354
285
- bool override_imp_res_offset;
286
- u8 imp_res_offset_value;
287
- bool override_hstx_trim;
288
- u8 hstx_trim_value;
289
- bool override_preemphasis;
290
- u8 preemphasis_level;
291
- bool override_preemphasis_width;
292
- u8 preemphasis_width;
355
+ struct override_params overrides;
293356
294357 const struct qusb2_phy_cfg *cfg;
295358 bool has_se_clk_scheme;
....@@ -357,24 +420,35 @@
357420 static void qusb2_phy_override_phy_params(struct qusb2_phy *qphy)
358421 {
359422 const struct qusb2_phy_cfg *cfg = qphy->cfg;
423
+ struct override_params *or = &qphy->overrides;
360424
361
- if (qphy->override_imp_res_offset)
425
+ if (or->imp_res_offset.override)
362426 qusb2_write_mask(qphy->base, QUSB2PHY_IMP_CTRL1,
363
- qphy->imp_res_offset_value << IMP_RES_OFFSET_SHIFT,
427
+ or->imp_res_offset.value << IMP_RES_OFFSET_SHIFT,
364428 IMP_RES_OFFSET_MASK);
365429
366
- if (qphy->override_hstx_trim)
430
+ if (or->bias_ctrl.override)
431
+ qusb2_write_mask(qphy->base, QUSB2PHY_PLL_BIAS_CONTROL_2,
432
+ or->bias_ctrl.value << BIAS_CTRL2_RES_OFFSET_SHIFT,
433
+ BIAS_CTRL2_RES_OFFSET_MASK);
434
+
435
+ if (or->charge_ctrl.override)
436
+ qusb2_write_mask(qphy->base, QUSB2PHY_CHG_CTRL2,
437
+ or->charge_ctrl.value << CHG_CTRL2_OFFSET_SHIFT,
438
+ CHG_CTRL2_OFFSET_MASK);
439
+
440
+ if (or->hstx_trim.override)
367441 qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1],
368
- qphy->hstx_trim_value << HSTX_TRIM_SHIFT,
442
+ or->hstx_trim.value << HSTX_TRIM_SHIFT,
369443 HSTX_TRIM_MASK);
370444
371
- if (qphy->override_preemphasis)
445
+ if (or->preemphasis.override)
372446 qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1],
373
- qphy->preemphasis_level << PREEMPHASIS_EN_SHIFT,
447
+ or->preemphasis.value << PREEMPHASIS_EN_SHIFT,
374448 PREEMPHASIS_EN_MASK);
375449
376
- if (qphy->override_preemphasis_width) {
377
- if (qphy->preemphasis_width ==
450
+ if (or->preemphasis_width.override) {
451
+ if (or->preemphasis_width.value ==
378452 QUSB2_V2_PREEMPHASIS_WIDTH_HALF_BIT)
379453 qusb2_setbits(qphy->base,
380454 cfg->regs[QUSB2PHY_PORT_TUNE1],
....@@ -384,6 +458,11 @@
384458 cfg->regs[QUSB2PHY_PORT_TUNE1],
385459 PREEMPH_WIDTH_HALF_BIT);
386460 }
461
+
462
+ if (or->hsdisc_trim.override)
463
+ qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2],
464
+ or->hsdisc_trim.value << HSDISC_TRIM_SHIFT,
465
+ HSDISC_TRIM_MASK);
387466 }
388467
389468 /*
....@@ -429,7 +508,8 @@
429508 hstx_trim << HSTX_TRIM_SHIFT, HSTX_TRIM_MASK);
430509 }
431510
432
-static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
511
+static int qusb2_phy_set_mode(struct phy *phy,
512
+ enum phy_mode mode, int submode)
433513 {
434514 struct qusb2_phy *qphy = phy_get_drvdata(phy);
435515
....@@ -734,11 +814,24 @@
734814
735815 static const struct of_device_id qusb2_phy_of_match_table[] = {
736816 {
817
+ .compatible = "qcom,ipq8074-qusb2-phy",
818
+ .data = &msm8996_phy_cfg,
819
+ }, {
737820 .compatible = "qcom,msm8996-qusb2-phy",
738821 .data = &msm8996_phy_cfg,
739822 }, {
823
+ .compatible = "qcom,msm8998-qusb2-phy",
824
+ .data = &msm8998_phy_cfg,
825
+ }, {
826
+ /*
827
+ * Deprecated. Only here to support legacy device
828
+ * trees that didn't include "qcom,qusb2-v2-phy"
829
+ */
740830 .compatible = "qcom,sdm845-qusb2-phy",
741
- .data = &sdm845_phy_cfg,
831
+ .data = &qusb2_v2_phy_cfg,
832
+ }, {
833
+ .compatible = "qcom,qusb2-v2-phy",
834
+ .data = &qusb2_v2_phy_cfg,
742835 },
743836 { },
744837 };
....@@ -759,10 +852,12 @@
759852 int ret, i;
760853 int num;
761854 u32 value;
855
+ struct override_params *or;
762856
763857 qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL);
764858 if (!qphy)
765859 return -ENOMEM;
860
+ or = &qphy->overrides;
766861
767862 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
768863 qphy->base = devm_ioremap_resource(dev, res);
....@@ -785,14 +880,9 @@
785880 return ret;
786881 }
787882
788
- qphy->iface_clk = devm_clk_get(dev, "iface");
789
- if (IS_ERR(qphy->iface_clk)) {
790
- ret = PTR_ERR(qphy->iface_clk);
791
- if (ret == -EPROBE_DEFER)
792
- return ret;
793
- qphy->iface_clk = NULL;
794
- dev_dbg(dev, "failed to get iface clk, %d\n", ret);
795
- }
883
+ qphy->iface_clk = devm_clk_get_optional(dev, "iface");
884
+ if (IS_ERR(qphy->iface_clk))
885
+ return PTR_ERR(qphy->iface_clk);
796886
797887 qphy->phy_reset = devm_reset_control_get_by_index(&pdev->dev, 0);
798888 if (IS_ERR(qphy->phy_reset)) {
....@@ -806,7 +896,9 @@
806896
807897 ret = devm_regulator_bulk_get(dev, num, qphy->vregs);
808898 if (ret) {
809
- dev_err(dev, "failed to get regulator supplies\n");
899
+ if (ret != -EPROBE_DEFER)
900
+ dev_err(dev, "failed to get regulator supplies: %d\n",
901
+ ret);
810902 return ret;
811903 }
812904
....@@ -830,26 +922,44 @@
830922
831923 if (!of_property_read_u32(dev->of_node, "qcom,imp-res-offset-value",
832924 &value)) {
833
- qphy->imp_res_offset_value = (u8)value;
834
- qphy->override_imp_res_offset = true;
925
+ or->imp_res_offset.value = (u8)value;
926
+ or->imp_res_offset.override = true;
927
+ }
928
+
929
+ if (!of_property_read_u32(dev->of_node, "qcom,bias-ctrl-value",
930
+ &value)) {
931
+ or->bias_ctrl.value = (u8)value;
932
+ or->bias_ctrl.override = true;
933
+ }
934
+
935
+ if (!of_property_read_u32(dev->of_node, "qcom,charge-ctrl-value",
936
+ &value)) {
937
+ or->charge_ctrl.value = (u8)value;
938
+ or->charge_ctrl.override = true;
835939 }
836940
837941 if (!of_property_read_u32(dev->of_node, "qcom,hstx-trim-value",
838942 &value)) {
839
- qphy->hstx_trim_value = (u8)value;
840
- qphy->override_hstx_trim = true;
943
+ or->hstx_trim.value = (u8)value;
944
+ or->hstx_trim.override = true;
841945 }
842946
843947 if (!of_property_read_u32(dev->of_node, "qcom,preemphasis-level",
844948 &value)) {
845
- qphy->preemphasis_level = (u8)value;
846
- qphy->override_preemphasis = true;
949
+ or->preemphasis.value = (u8)value;
950
+ or->preemphasis.override = true;
847951 }
848952
849953 if (!of_property_read_u32(dev->of_node, "qcom,preemphasis-width",
850954 &value)) {
851
- qphy->preemphasis_width = (u8)value;
852
- qphy->override_preemphasis_width = true;
955
+ or->preemphasis_width.value = (u8)value;
956
+ or->preemphasis_width.override = true;
957
+ }
958
+
959
+ if (!of_property_read_u32(dev->of_node, "qcom,hsdisc-trim-value",
960
+ &value)) {
961
+ or->hsdisc_trim.value = (u8)value;
962
+ or->hsdisc_trim.override = true;
853963 }
854964
855965 pm_runtime_set_active(dev);