* [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs
@ 2017-09-27 8:58 Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (16 more replies)
0 siblings, 17 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:58 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam
QUSB-v2 and QMP-v3 USB PHYs are present on Qualcomm's 14nm
and 10nm SOCs.
This patch series adds support for runtime PM for these
USB PHYs and adds fixes in drivers to follow PHY reset and
initialization sequence as per hardware programming manual.
Changes since v1:
- Incorporated review comments.
- Fixes to align with hardware programming manual.
- Added support for QUSBv2 and QMPv3 PHYs.
- Enable DP/DM asynchronous interrupts from QUSB2 USB2 PHY
for remote-wakeup.
- Enable LFPS and RX-TERM detection for attach and detach
events from QMP USB3 PHY for remotewakeup.
- Update sw-vbus overide in PHY wrapper for device mode.
- Dropped one dwc3 patch from this series which I will submit
with other dwc3 patches. ("usb: dwc3: core: Notify USB3 PHY as
well for DRD modes")
Manu Gautam (15):
phy: qcom-qmp: Power-on PHY before initialization
phy: qcom-qusb2: Power-on PHY before initialization
phy: qcom-qmp: Fix PHY block reset sequence
phy: qcom-qmp: Move SERDES/PCS START after PHY reset
phy: qcom-qusb2: Add support for different register layouts
dt-bindings: phy-qcom-qusb2: Update binding for QUSB2 V2 version
phy: qcom-qusb2: Add support for QUSB2 V2 version
phy: qcom-qmp: Move register offsets to header file
phy: qcom-qmp: Add register offsets for QMP V3 PHY
dt-bindings: phy-qcom-qmp: Update bindings for QMP V3 USB PHY
phy: qcom-qmp: Add support for QMP V3 USB3 PHY
phy: qcom-qusb2: Set vbus sw-override signal in device mode
phy: qcom-qusb2: Add support for runtime PM
phy: qcom-qmp: Override lane0_power_present signal in device mode
phy: qcom-qmp: Add support for runtime PM
Vivek Gautam (2):
phy: qcom-qmp: Fix phy pipe clock gating
phy: qcom-qmp: Adapt to clk_bulk_* APIs
.../devicetree/bindings/phy/qcom-qmp-phy.txt | 6 +-
.../devicetree/bindings/phy/qcom-qusb2-phy.txt | 5 +-
drivers/phy/qualcomm/phy-qcom-qmp.c | 696 +++++++++++++++------
drivers/phy/qualcomm/phy-qcom-qmp.h | 289 +++++++++
drivers/phy/qualcomm/phy-qcom-qusb2.c | 412 ++++++++++--
5 files changed, 1148 insertions(+), 260 deletions(-)
create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp.h
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v2 01/17] phy: qcom-qmp: Fix phy pipe clock gating
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:58 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:58 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Vivek Gautam,
Manu Gautam, Varadarajan Narayanan, Stephen Boyd, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
From: Vivek Gautam <vivek.gautam@codeaurora.org>
Pipe clock comes out of the phy and is available as long as
the phy is turned on. Clock controller fails to gate this
clock after the phy is turned off and generates a warning.
/ # [ 33.048561] gcc_usb3_phy_pipe_clk status stuck at 'on'
[ 33.048585] ------------[ cut here ]------------
[ 33.052621] WARNING: CPU: 1 PID: 18 at ../drivers/clk/qcom/clk-branch.c:97 clk_branch_wait+0xf0/0x108
[ 33.057384] Modules linked in:
[ 33.066497] CPU: 1 PID: 18 Comm: kworker/1:0 Tainted: G W 4.12.0-rc7-00024-gfe926e34c36d-dirty #96
[ 33.069451] Hardware name: Qualcomm Technologies, Inc. DB820c (DT)
...
[ 33.278565] [<ffff00000849b27c>] clk_branch_wait+0xf0/0x108
[ 33.286375] [<ffff00000849b2f4>] clk_branch2_disable+0x28/0x34
[ 33.291761] [<ffff0000084868dc>] clk_core_disable+0x5c/0x88
[ 33.297660] [<ffff000008487d68>] clk_core_disable_lock+0x20/0x34
[ 33.303129] [<ffff000008487d98>] clk_disable+0x1c/0x24
[ 33.309384] [<ffff0000083ccd78>] qcom_qmp_phy_poweroff+0x20/0x48
[ 33.314328] [<ffff0000083c53f4>] phy_power_off+0x80/0xdc
[ 33.320492] [<ffff00000875c950>] dwc3_core_exit+0x94/0xa0
[ 33.325784] [<ffff00000875c9ac>] dwc3_suspend_common+0x50/0x60
[ 33.331080] [<ffff00000875ca04>] dwc3_runtime_suspend+0x48/0x6c
[ 33.336810] [<ffff0000085b82f4>] pm_generic_runtime_suspend+0x28/0x38
[ 33.342627] [<ffff0000085bace0>] __rpm_callback+0x150/0x254
[ 33.349222] [<ffff0000085bae08>] rpm_callback+0x24/0x78
[ 33.354604] [<ffff0000085b9fd8>] rpm_suspend+0xe0/0x4e4
[ 33.359813] [<ffff0000085bb784>] pm_runtime_work+0xdc/0xf0
[ 33.365028] [<ffff0000080d7b30>] process_one_work+0x12c/0x28c
[ 33.370576] [<ffff0000080d7ce8>] worker_thread+0x58/0x3b8
[ 33.376393] [<ffff0000080dd4a8>] kthread+0x100/0x12c
[ 33.381776] [<ffff0000080836c0>] ret_from_fork+0x10/0x50
Fix this by enabling pipe clock at the end of phy_init(), and disabling
it as the first thing in phy_exit().
Fixes: e78f3d15e115 ("phy: qcom-qmp: new qmp phy driver for qcom-chipsets")
Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index e17f035..76acaec 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -731,19 +731,10 @@ static int qcom_qmp_phy_poweron(struct phy *phy)
/* turn on regulator supplies */
ret = regulator_bulk_enable(num, qmp->vregs);
- if (ret) {
+ if (ret)
dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
- return ret;
- }
-
- ret = clk_prepare_enable(qphy->pipe_clk);
- if (ret) {
- dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret);
- regulator_bulk_disable(num, qmp->vregs);
- return ret;
- }
- return 0;
+ return ret;
}
static int qcom_qmp_phy_poweroff(struct phy *phy)
@@ -751,8 +742,6 @@ static int qcom_qmp_phy_poweroff(struct phy *phy)
struct qmp_phy *qphy = phy_get_drvdata(phy);
struct qcom_qmp *qmp = qphy->qmp;
- clk_disable_unprepare(qphy->pipe_clk);
-
regulator_bulk_disable(qmp->cfg->num_vregs, qmp->vregs);
return 0;
@@ -915,7 +904,14 @@ static int qcom_qmp_phy_init(struct phy *phy)
goto err_pcs_ready;
}
- return ret;
+ /* phy is initialized; we can turn on the pipe clock now */
+ ret = clk_prepare_enable(qphy->pipe_clk);
+ if (ret) {
+ dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret);
+ goto err_pcs_ready;
+ }
+
+ return 0;
err_pcs_ready:
if (cfg->has_lane_rst)
@@ -936,6 +932,8 @@ static int qcom_qmp_phy_exit(struct phy *phy)
const struct qmp_phy_cfg *cfg = qmp->cfg;
int i = cfg->num_clks;
+ clk_disable_unprepare(qphy->pipe_clk);
+
/* PHY reset */
qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 01/17] phy: qcom-qmp: Fix phy pipe clock gating
@ 2017-09-27 8:58 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:58 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Vivek Gautam,
Manu Gautam, Varadarajan Narayanan, Stephen Boyd, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
From: Vivek Gautam <vivek.gautam@codeaurora.org>
Pipe clock comes out of the phy and is available as long as
the phy is turned on. Clock controller fails to gate this
clock after the phy is turned off and generates a warning.
/ # [ 33.048561] gcc_usb3_phy_pipe_clk status stuck at 'on'
[ 33.048585] ------------[ cut here ]------------
[ 33.052621] WARNING: CPU: 1 PID: 18 at ../drivers/clk/qcom/clk-branch.c:97 clk_branch_wait+0xf0/0x108
[ 33.057384] Modules linked in:
[ 33.066497] CPU: 1 PID: 18 Comm: kworker/1:0 Tainted: G W 4.12.0-rc7-00024-gfe926e34c36d-dirty #96
[ 33.069451] Hardware name: Qualcomm Technologies, Inc. DB820c (DT)
...
[ 33.278565] [<ffff00000849b27c>] clk_branch_wait+0xf0/0x108
[ 33.286375] [<ffff00000849b2f4>] clk_branch2_disable+0x28/0x34
[ 33.291761] [<ffff0000084868dc>] clk_core_disable+0x5c/0x88
[ 33.297660] [<ffff000008487d68>] clk_core_disable_lock+0x20/0x34
[ 33.303129] [<ffff000008487d98>] clk_disable+0x1c/0x24
[ 33.309384] [<ffff0000083ccd78>] qcom_qmp_phy_poweroff+0x20/0x48
[ 33.314328] [<ffff0000083c53f4>] phy_power_off+0x80/0xdc
[ 33.320492] [<ffff00000875c950>] dwc3_core_exit+0x94/0xa0
[ 33.325784] [<ffff00000875c9ac>] dwc3_suspend_common+0x50/0x60
[ 33.331080] [<ffff00000875ca04>] dwc3_runtime_suspend+0x48/0x6c
[ 33.336810] [<ffff0000085b82f4>] pm_generic_runtime_suspend+0x28/0x38
[ 33.342627] [<ffff0000085bace0>] __rpm_callback+0x150/0x254
[ 33.349222] [<ffff0000085bae08>] rpm_callback+0x24/0x78
[ 33.354604] [<ffff0000085b9fd8>] rpm_suspend+0xe0/0x4e4
[ 33.359813] [<ffff0000085bb784>] pm_runtime_work+0xdc/0xf0
[ 33.365028] [<ffff0000080d7b30>] process_one_work+0x12c/0x28c
[ 33.370576] [<ffff0000080d7ce8>] worker_thread+0x58/0x3b8
[ 33.376393] [<ffff0000080dd4a8>] kthread+0x100/0x12c
[ 33.381776] [<ffff0000080836c0>] ret_from_fork+0x10/0x50
Fix this by enabling pipe clock at the end of phy_init(), and disabling
it as the first thing in phy_exit().
Fixes: e78f3d15e115 ("phy: qcom-qmp: new qmp phy driver for qcom-chipsets")
Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index e17f035..76acaec 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -731,19 +731,10 @@ static int qcom_qmp_phy_poweron(struct phy *phy)
/* turn on regulator supplies */
ret = regulator_bulk_enable(num, qmp->vregs);
- if (ret) {
+ if (ret)
dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
- return ret;
- }
-
- ret = clk_prepare_enable(qphy->pipe_clk);
- if (ret) {
- dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret);
- regulator_bulk_disable(num, qmp->vregs);
- return ret;
- }
- return 0;
+ return ret;
}
static int qcom_qmp_phy_poweroff(struct phy *phy)
@@ -751,8 +742,6 @@ static int qcom_qmp_phy_poweroff(struct phy *phy)
struct qmp_phy *qphy = phy_get_drvdata(phy);
struct qcom_qmp *qmp = qphy->qmp;
- clk_disable_unprepare(qphy->pipe_clk);
-
regulator_bulk_disable(qmp->cfg->num_vregs, qmp->vregs);
return 0;
@@ -915,7 +904,14 @@ static int qcom_qmp_phy_init(struct phy *phy)
goto err_pcs_ready;
}
- return ret;
+ /* phy is initialized; we can turn on the pipe clock now */
+ ret = clk_prepare_enable(qphy->pipe_clk);
+ if (ret) {
+ dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret);
+ goto err_pcs_ready;
+ }
+
+ return 0;
err_pcs_ready:
if (cfg->has_lane_rst)
@@ -936,6 +932,8 @@ static int qcom_qmp_phy_exit(struct phy *phy)
const struct qmp_phy_cfg *cfg = qmp->cfg;
int i = cfg->num_clks;
+ clk_disable_unprepare(qphy->pipe_clk);
+
/* PHY reset */
qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 02/17] phy: qcom-qmp: Adapt to clk_bulk_* APIs
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:58 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:58 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Vivek Gautam,
Manu Gautam, Varadarajan Narayanan, Fengguang Wu, Wei Yongjun,
open list:GENERIC PHY FRAMEWORK
From: Vivek Gautam <vivek.gautam@codeaurora.org>
Move from using array of clocks to clk_bulk_* APIs that
are available now.
Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 50 ++++++++++++-------------------------
1 file changed, 16 insertions(+), 34 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 76acaec..90794dd 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -555,7 +555,7 @@ struct qcom_qmp {
struct device *dev;
void __iomem *serdes;
- struct clk **clks;
+ struct clk_bulk_data *clks;
struct reset_control **resets;
struct regulator_bulk_data *vregs;
@@ -848,22 +848,19 @@ static int qcom_qmp_phy_init(struct phy *phy)
void __iomem *pcs = qphy->pcs;
void __iomem *status;
unsigned int mask, val;
- int ret, i;
+ int ret;
dev_vdbg(qmp->dev, "Initializing QMP phy\n");
- for (i = 0; i < qmp->cfg->num_clks; i++) {
- ret = clk_prepare_enable(qmp->clks[i]);
- if (ret) {
- dev_err(qmp->dev, "failed to enable %s clk, err=%d\n",
- qmp->cfg->clk_list[i], ret);
- goto err_clk;
- }
+ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
+ if (ret) {
+ dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
+ return ret;
}
ret = qcom_qmp_phy_com_init(qmp);
if (ret)
- goto err_clk;
+ goto err_com_init;
if (cfg->has_lane_rst) {
ret = reset_control_deassert(qphy->lane_rst);
@@ -918,9 +915,8 @@ static int qcom_qmp_phy_init(struct phy *phy)
reset_control_assert(qphy->lane_rst);
err_lane_rst:
qcom_qmp_phy_com_exit(qmp);
-err_clk:
- while (--i >= 0)
- clk_disable_unprepare(qmp->clks[i]);
+err_com_init:
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
return ret;
}
@@ -930,7 +926,6 @@ static int qcom_qmp_phy_exit(struct phy *phy)
struct qmp_phy *qphy = phy_get_drvdata(phy);
struct qcom_qmp *qmp = qphy->qmp;
const struct qmp_phy_cfg *cfg = qmp->cfg;
- int i = cfg->num_clks;
clk_disable_unprepare(qphy->pipe_clk);
@@ -948,8 +943,7 @@ static int qcom_qmp_phy_exit(struct phy *phy)
qcom_qmp_phy_com_exit(qmp);
- while (--i >= 0)
- clk_disable_unprepare(qmp->clks[i]);
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
return 0;
}
@@ -998,29 +992,17 @@ static int qcom_qmp_phy_reset_init(struct device *dev)
static int qcom_qmp_phy_clk_init(struct device *dev)
{
struct qcom_qmp *qmp = dev_get_drvdata(dev);
- int ret, i;
+ int num = qmp->cfg->num_clks;
+ int i;
- qmp->clks = devm_kcalloc(dev, qmp->cfg->num_clks,
- sizeof(*qmp->clks), GFP_KERNEL);
+ qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL);
if (!qmp->clks)
return -ENOMEM;
- for (i = 0; i < qmp->cfg->num_clks; i++) {
- struct clk *_clk;
- const char *name = qmp->cfg->clk_list[i];
-
- _clk = devm_clk_get(dev, name);
- if (IS_ERR(_clk)) {
- ret = PTR_ERR(_clk);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "failed to get %s clk, %d\n",
- name, ret);
- return ret;
- }
- qmp->clks[i] = _clk;
- }
+ for (i = 0; i < num; i++)
+ qmp->clks->id = qmp->cfg->clk_list[i];
- return 0;
+ return devm_clk_bulk_get(dev, num, qmp->clks);
}
/*
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 02/17] phy: qcom-qmp: Adapt to clk_bulk_* APIs
@ 2017-09-27 8:58 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:58 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Vivek Gautam,
Manu Gautam, Varadarajan Narayanan, Fengguang Wu, Wei Yongjun,
open list:GENERIC PHY FRAMEWORK
From: Vivek Gautam <vivek.gautam@codeaurora.org>
Move from using array of clocks to clk_bulk_* APIs that
are available now.
Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 50 ++++++++++++-------------------------
1 file changed, 16 insertions(+), 34 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 76acaec..90794dd 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -555,7 +555,7 @@ struct qcom_qmp {
struct device *dev;
void __iomem *serdes;
- struct clk **clks;
+ struct clk_bulk_data *clks;
struct reset_control **resets;
struct regulator_bulk_data *vregs;
@@ -848,22 +848,19 @@ static int qcom_qmp_phy_init(struct phy *phy)
void __iomem *pcs = qphy->pcs;
void __iomem *status;
unsigned int mask, val;
- int ret, i;
+ int ret;
dev_vdbg(qmp->dev, "Initializing QMP phy\n");
- for (i = 0; i < qmp->cfg->num_clks; i++) {
- ret = clk_prepare_enable(qmp->clks[i]);
- if (ret) {
- dev_err(qmp->dev, "failed to enable %s clk, err=%d\n",
- qmp->cfg->clk_list[i], ret);
- goto err_clk;
- }
+ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
+ if (ret) {
+ dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
+ return ret;
}
ret = qcom_qmp_phy_com_init(qmp);
if (ret)
- goto err_clk;
+ goto err_com_init;
if (cfg->has_lane_rst) {
ret = reset_control_deassert(qphy->lane_rst);
@@ -918,9 +915,8 @@ static int qcom_qmp_phy_init(struct phy *phy)
reset_control_assert(qphy->lane_rst);
err_lane_rst:
qcom_qmp_phy_com_exit(qmp);
-err_clk:
- while (--i >= 0)
- clk_disable_unprepare(qmp->clks[i]);
+err_com_init:
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
return ret;
}
@@ -930,7 +926,6 @@ static int qcom_qmp_phy_exit(struct phy *phy)
struct qmp_phy *qphy = phy_get_drvdata(phy);
struct qcom_qmp *qmp = qphy->qmp;
const struct qmp_phy_cfg *cfg = qmp->cfg;
- int i = cfg->num_clks;
clk_disable_unprepare(qphy->pipe_clk);
@@ -948,8 +943,7 @@ static int qcom_qmp_phy_exit(struct phy *phy)
qcom_qmp_phy_com_exit(qmp);
- while (--i >= 0)
- clk_disable_unprepare(qmp->clks[i]);
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
return 0;
}
@@ -998,29 +992,17 @@ static int qcom_qmp_phy_reset_init(struct device *dev)
static int qcom_qmp_phy_clk_init(struct device *dev)
{
struct qcom_qmp *qmp = dev_get_drvdata(dev);
- int ret, i;
+ int num = qmp->cfg->num_clks;
+ int i;
- qmp->clks = devm_kcalloc(dev, qmp->cfg->num_clks,
- sizeof(*qmp->clks), GFP_KERNEL);
+ qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL);
if (!qmp->clks)
return -ENOMEM;
- for (i = 0; i < qmp->cfg->num_clks; i++) {
- struct clk *_clk;
- const char *name = qmp->cfg->clk_list[i];
-
- _clk = devm_clk_get(dev, name);
- if (IS_ERR(_clk)) {
- ret = PTR_ERR(_clk);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "failed to get %s clk, %d\n",
- name, ret);
- return ret;
- }
- qmp->clks[i] = _clk;
- }
+ for (i = 0; i < num; i++)
+ qmp->clks->id = qmp->cfg->clk_list[i];
- return 0;
+ return devm_clk_bulk_get(dev, num, qmp->clks);
}
/*
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 03/17] phy: qcom-qmp: Power-on PHY before initialization
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:58 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:58 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Jaehoon Chung, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
PHY must be powered on before turning ON clocks and
attempting to initialize it. Driver is exposing
separate init and power_on routines for this.
Apparently USB dwc3 core driver performs power-on after
init. Also, poweron and init for QMP PHY need to be
executed together always, hence remove poweron callback
from phy_ops and explicitly perform this from com_init,
similar changes needed for poweroff. On similar lines move
clk_enable from init to com_init which can be called once
for multi lane PHYs.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 61 +++++++++++++------------------------
1 file changed, 21 insertions(+), 40 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 90794dd..2f427e3 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -720,33 +720,6 @@ static void qcom_qmp_phy_configure(void __iomem *base,
}
}
-static int qcom_qmp_phy_poweron(struct phy *phy)
-{
- struct qmp_phy *qphy = phy_get_drvdata(phy);
- struct qcom_qmp *qmp = qphy->qmp;
- int num = qmp->cfg->num_vregs;
- int ret;
-
- dev_vdbg(&phy->dev, "Powering on QMP phy\n");
-
- /* turn on regulator supplies */
- ret = regulator_bulk_enable(num, qmp->vregs);
- if (ret)
- dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
-
- return ret;
-}
-
-static int qcom_qmp_phy_poweroff(struct phy *phy)
-{
- struct qmp_phy *qphy = phy_get_drvdata(phy);
- struct qcom_qmp *qmp = qphy->qmp;
-
- regulator_bulk_disable(qmp->cfg->num_vregs, qmp->vregs);
-
- return 0;
-}
-
static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -759,6 +732,19 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
return 0;
}
+ /* turn on regulator supplies */
+ ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
+ if (ret) {
+ mutex_unlock(&qmp->phy_mutex);
+ return ret;
+ }
+
+ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
+ if (ret) {
+ dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
+ goto err_clk_enable;
+ }
+
for (i = 0; i < cfg->num_resets; i++) {
ret = reset_control_deassert(qmp->resets[i]);
if (ret) {
@@ -803,6 +789,9 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
err_rst:
while (--i >= 0)
reset_control_assert(qmp->resets[i]);
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
+err_clk_enable:
+ regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
mutex_unlock(&qmp->phy_mutex);
return ret;
@@ -832,6 +821,10 @@ static int qcom_qmp_phy_com_exit(struct qcom_qmp *qmp)
while (--i >= 0)
reset_control_assert(qmp->resets[i]);
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
+
+ regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
+
mutex_unlock(&qmp->phy_mutex);
return 0;
@@ -852,15 +845,9 @@ static int qcom_qmp_phy_init(struct phy *phy)
dev_vdbg(qmp->dev, "Initializing QMP phy\n");
- ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
- if (ret) {
- dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
- return ret;
- }
-
ret = qcom_qmp_phy_com_init(qmp);
if (ret)
- goto err_com_init;
+ return ret;
if (cfg->has_lane_rst) {
ret = reset_control_deassert(qphy->lane_rst);
@@ -915,8 +902,6 @@ static int qcom_qmp_phy_init(struct phy *phy)
reset_control_assert(qphy->lane_rst);
err_lane_rst:
qcom_qmp_phy_com_exit(qmp);
-err_com_init:
- clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
return ret;
}
@@ -943,8 +928,6 @@ static int qcom_qmp_phy_exit(struct phy *phy)
qcom_qmp_phy_com_exit(qmp);
- clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
-
return 0;
}
@@ -1057,8 +1040,6 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np)
static const struct phy_ops qcom_qmp_phy_gen_ops = {
.init = qcom_qmp_phy_init,
.exit = qcom_qmp_phy_exit,
- .power_on = qcom_qmp_phy_poweron,
- .power_off = qcom_qmp_phy_poweroff,
.owner = THIS_MODULE,
};
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 03/17] phy: qcom-qmp: Power-on PHY before initialization
@ 2017-09-27 8:58 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:58 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Jaehoon Chung, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
PHY must be powered on before turning ON clocks and
attempting to initialize it. Driver is exposing
separate init and power_on routines for this.
Apparently USB dwc3 core driver performs power-on after
init. Also, poweron and init for QMP PHY need to be
executed together always, hence remove poweron callback
from phy_ops and explicitly perform this from com_init,
similar changes needed for poweroff. On similar lines move
clk_enable from init to com_init which can be called once
for multi lane PHYs.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 61 +++++++++++++------------------------
1 file changed, 21 insertions(+), 40 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 90794dd..2f427e3 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -720,33 +720,6 @@ static void qcom_qmp_phy_configure(void __iomem *base,
}
}
-static int qcom_qmp_phy_poweron(struct phy *phy)
-{
- struct qmp_phy *qphy = phy_get_drvdata(phy);
- struct qcom_qmp *qmp = qphy->qmp;
- int num = qmp->cfg->num_vregs;
- int ret;
-
- dev_vdbg(&phy->dev, "Powering on QMP phy\n");
-
- /* turn on regulator supplies */
- ret = regulator_bulk_enable(num, qmp->vregs);
- if (ret)
- dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
-
- return ret;
-}
-
-static int qcom_qmp_phy_poweroff(struct phy *phy)
-{
- struct qmp_phy *qphy = phy_get_drvdata(phy);
- struct qcom_qmp *qmp = qphy->qmp;
-
- regulator_bulk_disable(qmp->cfg->num_vregs, qmp->vregs);
-
- return 0;
-}
-
static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -759,6 +732,19 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
return 0;
}
+ /* turn on regulator supplies */
+ ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
+ if (ret) {
+ mutex_unlock(&qmp->phy_mutex);
+ return ret;
+ }
+
+ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
+ if (ret) {
+ dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
+ goto err_clk_enable;
+ }
+
for (i = 0; i < cfg->num_resets; i++) {
ret = reset_control_deassert(qmp->resets[i]);
if (ret) {
@@ -803,6 +789,9 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
err_rst:
while (--i >= 0)
reset_control_assert(qmp->resets[i]);
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
+err_clk_enable:
+ regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
mutex_unlock(&qmp->phy_mutex);
return ret;
@@ -832,6 +821,10 @@ static int qcom_qmp_phy_com_exit(struct qcom_qmp *qmp)
while (--i >= 0)
reset_control_assert(qmp->resets[i]);
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
+
+ regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
+
mutex_unlock(&qmp->phy_mutex);
return 0;
@@ -852,15 +845,9 @@ static int qcom_qmp_phy_init(struct phy *phy)
dev_vdbg(qmp->dev, "Initializing QMP phy\n");
- ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
- if (ret) {
- dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
- return ret;
- }
-
ret = qcom_qmp_phy_com_init(qmp);
if (ret)
- goto err_com_init;
+ return ret;
if (cfg->has_lane_rst) {
ret = reset_control_deassert(qphy->lane_rst);
@@ -915,8 +902,6 @@ static int qcom_qmp_phy_init(struct phy *phy)
reset_control_assert(qphy->lane_rst);
err_lane_rst:
qcom_qmp_phy_com_exit(qmp);
-err_com_init:
- clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
return ret;
}
@@ -943,8 +928,6 @@ static int qcom_qmp_phy_exit(struct phy *phy)
qcom_qmp_phy_com_exit(qmp);
- clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
-
return 0;
}
@@ -1057,8 +1040,6 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np)
static const struct phy_ops qcom_qmp_phy_gen_ops = {
.init = qcom_qmp_phy_init,
.exit = qcom_qmp_phy_exit,
- .power_on = qcom_qmp_phy_poweron,
- .power_off = qcom_qmp_phy_poweroff,
.owner = THIS_MODULE,
};
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 04/17] phy: qcom-qusb2: Power-on PHY before initialization
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Yoshihiro Shimoda, Krzysztof Kozlowski,
open list:GENERIC PHY FRAMEWORK
PHY must be powered on before turning ON clocks and
attempting to initialize it. Driver is exposing
separate init and power_on routines for this.
Apparently USB dwc3 core driver performs power-on
after init. Also, poweron and init for QUSB2 PHY
need to be executed together always, hence remove
poweron callback from phy_ops and explicitly perform
this from init, similar changes needed for poweroff.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 47 +++++++++++------------------------
1 file changed, 15 insertions(+), 32 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 6c57524..4a5b2a1 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -195,54 +195,31 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
qusb2_setbits(qphy->base, QUSB2PHY_PORT_TUNE2, val[0] << 0x4);
}
-static int qusb2_phy_poweron(struct phy *phy)
+static int qusb2_phy_init(struct phy *phy)
{
struct qusb2_phy *qphy = phy_get_drvdata(phy);
- int num = ARRAY_SIZE(qphy->vregs);
+ unsigned int val;
+ unsigned int clk_scheme;
int ret;
- dev_vdbg(&phy->dev, "%s(): Powering-on QUSB2 phy\n", __func__);
+ dev_vdbg(&phy->dev, "%s(): Initializing QUSB2 phy\n", __func__);
/* turn on regulator supplies */
- ret = regulator_bulk_enable(num, qphy->vregs);
+ ret = regulator_bulk_enable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
if (ret)
return ret;
ret = clk_prepare_enable(qphy->iface_clk);
if (ret) {
dev_err(&phy->dev, "failed to enable iface_clk, %d\n", ret);
- regulator_bulk_disable(num, qphy->vregs);
- return ret;
+ goto poweroff_phy;
}
- return 0;
-}
-
-static int qusb2_phy_poweroff(struct phy *phy)
-{
- struct qusb2_phy *qphy = phy_get_drvdata(phy);
-
- clk_disable_unprepare(qphy->iface_clk);
-
- regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
-
- return 0;
-}
-
-static int qusb2_phy_init(struct phy *phy)
-{
- struct qusb2_phy *qphy = phy_get_drvdata(phy);
- unsigned int val;
- unsigned int clk_scheme;
- int ret;
-
- dev_vdbg(&phy->dev, "%s(): Initializing QUSB2 phy\n", __func__);
-
/* enable ahb interface clock to program phy */
ret = clk_prepare_enable(qphy->cfg_ahb_clk);
if (ret) {
dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret);
- return ret;
+ goto disable_iface_clk;
}
/* Perform phy reset */
@@ -344,6 +321,11 @@ static int qusb2_phy_init(struct phy *phy)
reset_control_assert(qphy->phy_reset);
disable_ahb_clk:
clk_disable_unprepare(qphy->cfg_ahb_clk);
+disable_iface_clk:
+ clk_disable_unprepare(qphy->iface_clk);
+poweroff_phy:
+ regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
+
return ret;
}
@@ -361,6 +343,9 @@ static int qusb2_phy_exit(struct phy *phy)
reset_control_assert(qphy->phy_reset);
clk_disable_unprepare(qphy->cfg_ahb_clk);
+ clk_disable_unprepare(qphy->iface_clk);
+
+ regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
return 0;
}
@@ -368,8 +353,6 @@ static int qusb2_phy_exit(struct phy *phy)
static const struct phy_ops qusb2_phy_gen_ops = {
.init = qusb2_phy_init,
.exit = qusb2_phy_exit,
- .power_on = qusb2_phy_poweron,
- .power_off = qusb2_phy_poweroff,
.owner = THIS_MODULE,
};
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 04/17] phy: qcom-qusb2: Power-on PHY before initialization
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Yoshihiro Shimoda, Krzysztof Kozlowski,
open list:GENERIC PHY FRAMEWORK
PHY must be powered on before turning ON clocks and
attempting to initialize it. Driver is exposing
separate init and power_on routines for this.
Apparently USB dwc3 core driver performs power-on
after init. Also, poweron and init for QUSB2 PHY
need to be executed together always, hence remove
poweron callback from phy_ops and explicitly perform
this from init, similar changes needed for poweroff.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 47 +++++++++++------------------------
1 file changed, 15 insertions(+), 32 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 6c57524..4a5b2a1 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -195,54 +195,31 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
qusb2_setbits(qphy->base, QUSB2PHY_PORT_TUNE2, val[0] << 0x4);
}
-static int qusb2_phy_poweron(struct phy *phy)
+static int qusb2_phy_init(struct phy *phy)
{
struct qusb2_phy *qphy = phy_get_drvdata(phy);
- int num = ARRAY_SIZE(qphy->vregs);
+ unsigned int val;
+ unsigned int clk_scheme;
int ret;
- dev_vdbg(&phy->dev, "%s(): Powering-on QUSB2 phy\n", __func__);
+ dev_vdbg(&phy->dev, "%s(): Initializing QUSB2 phy\n", __func__);
/* turn on regulator supplies */
- ret = regulator_bulk_enable(num, qphy->vregs);
+ ret = regulator_bulk_enable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
if (ret)
return ret;
ret = clk_prepare_enable(qphy->iface_clk);
if (ret) {
dev_err(&phy->dev, "failed to enable iface_clk, %d\n", ret);
- regulator_bulk_disable(num, qphy->vregs);
- return ret;
+ goto poweroff_phy;
}
- return 0;
-}
-
-static int qusb2_phy_poweroff(struct phy *phy)
-{
- struct qusb2_phy *qphy = phy_get_drvdata(phy);
-
- clk_disable_unprepare(qphy->iface_clk);
-
- regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
-
- return 0;
-}
-
-static int qusb2_phy_init(struct phy *phy)
-{
- struct qusb2_phy *qphy = phy_get_drvdata(phy);
- unsigned int val;
- unsigned int clk_scheme;
- int ret;
-
- dev_vdbg(&phy->dev, "%s(): Initializing QUSB2 phy\n", __func__);
-
/* enable ahb interface clock to program phy */
ret = clk_prepare_enable(qphy->cfg_ahb_clk);
if (ret) {
dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret);
- return ret;
+ goto disable_iface_clk;
}
/* Perform phy reset */
@@ -344,6 +321,11 @@ static int qusb2_phy_init(struct phy *phy)
reset_control_assert(qphy->phy_reset);
disable_ahb_clk:
clk_disable_unprepare(qphy->cfg_ahb_clk);
+disable_iface_clk:
+ clk_disable_unprepare(qphy->iface_clk);
+poweroff_phy:
+ regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
+
return ret;
}
@@ -361,6 +343,9 @@ static int qusb2_phy_exit(struct phy *phy)
reset_control_assert(qphy->phy_reset);
clk_disable_unprepare(qphy->cfg_ahb_clk);
+ clk_disable_unprepare(qphy->iface_clk);
+
+ regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
return 0;
}
@@ -368,8 +353,6 @@ static int qusb2_phy_exit(struct phy *phy)
static const struct phy_ops qusb2_phy_gen_ops = {
.init = qusb2_phy_init,
.exit = qusb2_phy_exit,
- .power_on = qusb2_phy_poweron,
- .power_off = qusb2_phy_poweroff,
.owner = THIS_MODULE,
};
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 05/17] phy: qcom-qmp: Fix PHY block reset sequence
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Heiko Stuebner, Wei Yongjun,
Fengguang Wu, open list:GENERIC PHY FRAMEWORK
PHY block or asynchronous reset requires signal
to be asserted before de-asserting. Driver is only
de-asserting signal which is already low, hence
reset operation is a no-op. Fix this by asserting
signal first. Also, resetting requires PHY clocks
to be turned ON only after reset is finished. Fix
that as well.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 2f427e3..aa27757 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -739,13 +739,16 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
return ret;
}
- ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
- if (ret) {
- dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
- goto err_clk_enable;
+ for (i = 0; i < cfg->num_resets; i++) {
+ ret = reset_control_assert(qmp->resets[i]);
+ if (ret) {
+ dev_err(qmp->dev, "%s reset assert failed\n",
+ cfg->reset_list[i]);
+ goto err_rst_assert;
+ }
}
- for (i = 0; i < cfg->num_resets; i++) {
+ for (i = cfg->num_resets - 1; i >= 0; i--) {
ret = reset_control_deassert(qmp->resets[i]);
if (ret) {
dev_err(qmp->dev, "%s reset deassert failed\n",
@@ -754,6 +757,12 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
}
}
+ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
+ if (ret) {
+ dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
+ goto err_rst;
+ }
+
if (cfg->has_phy_com_ctrl)
qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
SW_PWRDN);
@@ -778,7 +787,7 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
if (ret) {
dev_err(qmp->dev,
"phy common block init timed-out\n");
- goto err_rst;
+ goto err_com_init;
}
}
@@ -786,11 +795,12 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
return 0;
+err_com_init:
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
err_rst:
- while (--i >= 0)
+ while (++i < cfg->num_resets)
reset_control_assert(qmp->resets[i]);
- clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
-err_clk_enable:
+err_rst_assert:
regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
mutex_unlock(&qmp->phy_mutex);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 05/17] phy: qcom-qmp: Fix PHY block reset sequence
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Heiko Stuebner, Wei Yongjun,
Fengguang Wu, open list:GENERIC PHY FRAMEWORK
PHY block or asynchronous reset requires signal
to be asserted before de-asserting. Driver is only
de-asserting signal which is already low, hence
reset operation is a no-op. Fix this by asserting
signal first. Also, resetting requires PHY clocks
to be turned ON only after reset is finished. Fix
that as well.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 2f427e3..aa27757 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -739,13 +739,16 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
return ret;
}
- ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
- if (ret) {
- dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
- goto err_clk_enable;
+ for (i = 0; i < cfg->num_resets; i++) {
+ ret = reset_control_assert(qmp->resets[i]);
+ if (ret) {
+ dev_err(qmp->dev, "%s reset assert failed\n",
+ cfg->reset_list[i]);
+ goto err_rst_assert;
+ }
}
- for (i = 0; i < cfg->num_resets; i++) {
+ for (i = cfg->num_resets - 1; i >= 0; i--) {
ret = reset_control_deassert(qmp->resets[i]);
if (ret) {
dev_err(qmp->dev, "%s reset deassert failed\n",
@@ -754,6 +757,12 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
}
}
+ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
+ if (ret) {
+ dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
+ goto err_rst;
+ }
+
if (cfg->has_phy_com_ctrl)
qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
SW_PWRDN);
@@ -778,7 +787,7 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
if (ret) {
dev_err(qmp->dev,
"phy common block init timed-out\n");
- goto err_rst;
+ goto err_com_init;
}
}
@@ -786,11 +795,12 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
return 0;
+err_com_init:
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
err_rst:
- while (--i >= 0)
+ while (++i < cfg->num_resets)
reset_control_assert(qmp->resets[i]);
- clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
-err_clk_enable:
+err_rst_assert:
regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
mutex_unlock(&qmp->phy_mutex);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 06/17] phy: qcom-qmp: Move SERDES/PCS START after PHY reset
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Heiko Stuebner, Wei Yongjun,
Fengguang Wu, open list:GENERIC PHY FRAMEWORK
Driver is currently performing PHY reset after starting
SERDES/PCS. As per hardware datasheet reset must be done
before starting PHY. Hence, update the sequence.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index aa27757..263cf50 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -882,12 +882,12 @@ static int qcom_qmp_phy_init(struct phy *phy)
if (cfg->has_pwrdn_delay)
usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max);
- /* start SerDes and Phy-Coding-Sublayer */
- qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
-
/* Pull PHY out of reset state */
qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
+ /* start SerDes and Phy-Coding-Sublayer */
+ qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
+
status = pcs + cfg->regs[QPHY_PCS_READY_STATUS];
mask = cfg->mask_pcs_ready;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 06/17] phy: qcom-qmp: Move SERDES/PCS START after PHY reset
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Heiko Stuebner, Wei Yongjun,
Fengguang Wu, open list:GENERIC PHY FRAMEWORK
Driver is currently performing PHY reset after starting
SERDES/PCS. As per hardware datasheet reset must be done
before starting PHY. Hence, update the sequence.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index aa27757..263cf50 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -882,12 +882,12 @@ static int qcom_qmp_phy_init(struct phy *phy)
if (cfg->has_pwrdn_delay)
usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max);
- /* start SerDes and Phy-Coding-Sublayer */
- qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
-
/* Pull PHY out of reset state */
qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
+ /* start SerDes and Phy-Coding-Sublayer */
+ qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
+
status = pcs + cfg->regs[QPHY_PCS_READY_STATUS];
mask = cfg->mask_pcs_ready;
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 07/17] phy: qcom-qusb2: Add support for different register layouts
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Jaehoon Chung, Heiko Stuebner,
open list:GENERIC PHY FRAMEWORK
New version of QUSB2 PHY has some registers offset changed.
Add support to have register layout for a target and update
the same in phy_configuration.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 131 ++++++++++++++++++++++++----------
1 file changed, 95 insertions(+), 36 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 4a5b2a1..c0c5358 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -37,17 +37,10 @@
#define QUSB2PHY_PLL_AUTOPGM_CTL1 0x1c
#define QUSB2PHY_PLL_PWR_CTRL 0x18
-#define QUSB2PHY_PLL_STATUS 0x38
+/* QUSB2PHY_PLL_STATUS register bits */
#define PLL_LOCKED BIT(5)
-#define QUSB2PHY_PORT_TUNE1 0x80
-#define QUSB2PHY_PORT_TUNE2 0x84
-#define QUSB2PHY_PORT_TUNE3 0x88
-#define QUSB2PHY_PORT_TUNE4 0x8c
-#define QUSB2PHY_PORT_TUNE5 0x90
-#define QUSB2PHY_PORT_TEST2 0x9c
-
-#define QUSB2PHY_PORT_POWERDOWN 0xb4
+/* QUSB2PHY_PORT_POWERDOWN register bits */
#define CLAMP_N_EN BIT(5)
#define FREEZIO_N BIT(1)
#define POWER_DOWN BIT(0)
@@ -59,6 +52,11 @@
struct qusb2_phy_init_tbl {
unsigned int offset;
unsigned int val;
+ /*
+ * register part of layout ?
+ * if yes, then offset gives index in the reg-layout
+ */
+ int in_layout;
};
#define QUSB2_PHY_INIT_CFG(o, v) \
@@ -67,15 +65,50 @@ struct qusb2_phy_init_tbl {
.val = v, \
}
+#define QUSB2_PHY_INIT_CFG_L(o, v) \
+ { \
+ .offset = o, \
+ .val = v, \
+ .in_layout = 1, \
+ }
+
+/* set of registers with offsets different per-PHY */
+enum qusb2phy_reg_layout {
+ QUSB2PHY_PLL_STATUS,
+ QUSB2PHY_PORT_TUNE1,
+ QUSB2PHY_PORT_TUNE2,
+ QUSB2PHY_PORT_TUNE3,
+ QUSB2PHY_PORT_TUNE4,
+ QUSB2PHY_PORT_TUNE5,
+ QUSB2PHY_PORT_TEST1,
+ QUSB2PHY_PORT_TEST2,
+ QUSB2PHY_PORT_POWERDOWN,
+ QUSB2PHY_INTR_CTRL,
+};
+
+static const unsigned int msm8996_regs_layout[] = {
+ [QUSB2PHY_PLL_STATUS] = 0x38,
+ [QUSB2PHY_PORT_TUNE1] = 0x80,
+ [QUSB2PHY_PORT_TUNE2] = 0x84,
+ [QUSB2PHY_PORT_TUNE3] = 0x88,
+ [QUSB2PHY_PORT_TUNE4] = 0x8c,
+ [QUSB2PHY_PORT_TUNE5] = 0x90,
+ [QUSB2PHY_PORT_TEST2] = 0x9c,
+ [QUSB2PHY_PORT_POWERDOWN] = 0xb4,
+};
+
static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = {
- QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE1, 0xf8),
- QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE2, 0xb3),
- QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE3, 0x83),
- QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE4, 0xc0),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0xf8),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0xb3),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0x83),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0xc0),
+
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21),
- QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TEST2, 0x14),
+
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TEST2, 0x14),
+
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
};
@@ -86,11 +119,24 @@ struct qusb2_phy_cfg {
unsigned int tbl_num;
/* offset to PHY_CLK_SCHEME register in TCSR map */
unsigned int clk_scheme_offset;
+
+ /* array of registers with different offsets */
+ const unsigned int *regs;
+ unsigned int mask_core_ready;
+ unsigned int disable_ctrl;
+
+ /* true if PHY has PLL_TEST register to select clk_scheme */
+ bool has_pll_test;
};
static const struct qusb2_phy_cfg msm8996_phy_cfg = {
- .tbl = msm8996_init_tbl,
- .tbl_num = ARRAY_SIZE(msm8996_init_tbl),
+ .tbl = msm8996_init_tbl,
+ .tbl_num = ARRAY_SIZE(msm8996_init_tbl),
+ .regs = msm8996_regs_layout,
+
+ .has_pll_test = true,
+ .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN),
+ .mask_core_ready = PLL_LOCKED,
};
static const char * const qusb2_phy_vreg_names[] = {
@@ -160,12 +206,17 @@ static inline void qusb2_clrbits(void __iomem *base, u32 offset, u32 val)
static inline
void qcom_qusb2_phy_configure(void __iomem *base,
+ const unsigned int *regs,
const struct qusb2_phy_init_tbl tbl[], int num)
{
int i;
- for (i = 0; i < num; i++)
- writel(tbl[i].val, base + tbl[i].offset);
+ for (i = 0; i < num; i++) {
+ if (tbl[i].in_layout)
+ writel(tbl[i].val, base + regs[tbl[i].offset]);
+ else
+ writel(tbl[i].val, base + tbl[i].offset);
+ }
}
/*
@@ -198,7 +249,8 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
static int qusb2_phy_init(struct phy *phy)
{
struct qusb2_phy *qphy = phy_get_drvdata(phy);
- unsigned int val;
+ const struct qusb2_phy_cfg *cfg = qphy->cfg;
+ unsigned int val = 0;
unsigned int clk_scheme;
int ret;
@@ -239,20 +291,23 @@ static int qusb2_phy_init(struct phy *phy)
}
/* Disable the PHY */
- qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN,
- CLAMP_N_EN | FREEZIO_N | POWER_DOWN);
+ qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_POWERDOWN],
+ qphy->cfg->disable_ctrl);
- /* save reset value to override reference clock scheme later */
- val = readl(qphy->base + QUSB2PHY_PLL_TEST);
+ if (cfg->has_pll_test) {
+ /* save reset value to override reference clock scheme later */
+ val = readl(qphy->base + QUSB2PHY_PLL_TEST);
+ }
- qcom_qusb2_phy_configure(qphy->base, qphy->cfg->tbl,
- qphy->cfg->tbl_num);
+ qcom_qusb2_phy_configure(qphy->base, cfg->regs, cfg->tbl,
+ cfg->tbl_num);
/* Set efuse value for tuning the PHY */
qusb2_phy_set_tune2_param(qphy);
/* Enable the PHY */
- qusb2_clrbits(qphy->base, QUSB2PHY_PORT_POWERDOWN, POWER_DOWN);
+ qusb2_clrbits(qphy->base, cfg->regs[QUSB2PHY_PORT_POWERDOWN],
+ POWER_DOWN);
/* Required to get phy pll lock successfully */
usleep_range(150, 160);
@@ -285,27 +340,31 @@ static int qusb2_phy_init(struct phy *phy)
}
if (!qphy->has_se_clk_scheme) {
- val &= ~CLK_REF_SEL;
ret = clk_prepare_enable(qphy->ref_clk);
if (ret) {
dev_err(&phy->dev, "failed to enable ref clk, %d\n",
ret);
goto assert_phy_reset;
}
- } else {
- val |= CLK_REF_SEL;
}
- writel(val, qphy->base + QUSB2PHY_PLL_TEST);
+ if (cfg->has_pll_test) {
+ if (!qphy->has_se_clk_scheme)
+ val &= ~CLK_REF_SEL;
+ else
+ val |= CLK_REF_SEL;
+
+ writel(val, qphy->base + QUSB2PHY_PLL_TEST);
- /* ensure above write is through */
- readl(qphy->base + QUSB2PHY_PLL_TEST);
+ /* ensure above write is through */
+ readl(qphy->base + QUSB2PHY_PLL_TEST);
+ }
/* Required to get phy pll lock successfully */
usleep_range(100, 110);
- val = readb(qphy->base + QUSB2PHY_PLL_STATUS);
- if (!(val & PLL_LOCKED)) {
+ val = readb(qphy->base + cfg->regs[QUSB2PHY_PLL_STATUS]);
+ if (!(val & cfg->mask_core_ready)) {
dev_err(&phy->dev,
"QUSB2PHY pll lock failed: status reg = %x\n", val);
ret = -EBUSY;
@@ -334,8 +393,8 @@ static int qusb2_phy_exit(struct phy *phy)
struct qusb2_phy *qphy = phy_get_drvdata(phy);
/* Disable the PHY */
- qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN,
- CLAMP_N_EN | FREEZIO_N | POWER_DOWN);
+ qusb2_setbits(qphy->base, qphy->cfg->regs[QUSB2PHY_PORT_POWERDOWN],
+ qphy->cfg->disable_ctrl);
if (!qphy->has_se_clk_scheme)
clk_disable_unprepare(qphy->ref_clk);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 07/17] phy: qcom-qusb2: Add support for different register layouts
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Jaehoon Chung, Heiko Stuebner,
open list:GENERIC PHY FRAMEWORK
New version of QUSB2 PHY has some registers offset changed.
Add support to have register layout for a target and update
the same in phy_configuration.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 131 ++++++++++++++++++++++++----------
1 file changed, 95 insertions(+), 36 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 4a5b2a1..c0c5358 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -37,17 +37,10 @@
#define QUSB2PHY_PLL_AUTOPGM_CTL1 0x1c
#define QUSB2PHY_PLL_PWR_CTRL 0x18
-#define QUSB2PHY_PLL_STATUS 0x38
+/* QUSB2PHY_PLL_STATUS register bits */
#define PLL_LOCKED BIT(5)
-#define QUSB2PHY_PORT_TUNE1 0x80
-#define QUSB2PHY_PORT_TUNE2 0x84
-#define QUSB2PHY_PORT_TUNE3 0x88
-#define QUSB2PHY_PORT_TUNE4 0x8c
-#define QUSB2PHY_PORT_TUNE5 0x90
-#define QUSB2PHY_PORT_TEST2 0x9c
-
-#define QUSB2PHY_PORT_POWERDOWN 0xb4
+/* QUSB2PHY_PORT_POWERDOWN register bits */
#define CLAMP_N_EN BIT(5)
#define FREEZIO_N BIT(1)
#define POWER_DOWN BIT(0)
@@ -59,6 +52,11 @@
struct qusb2_phy_init_tbl {
unsigned int offset;
unsigned int val;
+ /*
+ * register part of layout ?
+ * if yes, then offset gives index in the reg-layout
+ */
+ int in_layout;
};
#define QUSB2_PHY_INIT_CFG(o, v) \
@@ -67,15 +65,50 @@ struct qusb2_phy_init_tbl {
.val = v, \
}
+#define QUSB2_PHY_INIT_CFG_L(o, v) \
+ { \
+ .offset = o, \
+ .val = v, \
+ .in_layout = 1, \
+ }
+
+/* set of registers with offsets different per-PHY */
+enum qusb2phy_reg_layout {
+ QUSB2PHY_PLL_STATUS,
+ QUSB2PHY_PORT_TUNE1,
+ QUSB2PHY_PORT_TUNE2,
+ QUSB2PHY_PORT_TUNE3,
+ QUSB2PHY_PORT_TUNE4,
+ QUSB2PHY_PORT_TUNE5,
+ QUSB2PHY_PORT_TEST1,
+ QUSB2PHY_PORT_TEST2,
+ QUSB2PHY_PORT_POWERDOWN,
+ QUSB2PHY_INTR_CTRL,
+};
+
+static const unsigned int msm8996_regs_layout[] = {
+ [QUSB2PHY_PLL_STATUS] = 0x38,
+ [QUSB2PHY_PORT_TUNE1] = 0x80,
+ [QUSB2PHY_PORT_TUNE2] = 0x84,
+ [QUSB2PHY_PORT_TUNE3] = 0x88,
+ [QUSB2PHY_PORT_TUNE4] = 0x8c,
+ [QUSB2PHY_PORT_TUNE5] = 0x90,
+ [QUSB2PHY_PORT_TEST2] = 0x9c,
+ [QUSB2PHY_PORT_POWERDOWN] = 0xb4,
+};
+
static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = {
- QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE1, 0xf8),
- QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE2, 0xb3),
- QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE3, 0x83),
- QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TUNE4, 0xc0),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0xf8),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0xb3),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0x83),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0xc0),
+
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_TUNE, 0x30),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL1, 0x79),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_USER_CTL2, 0x21),
- QUSB2_PHY_INIT_CFG(QUSB2PHY_PORT_TEST2, 0x14),
+
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TEST2, 0x14),
+
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_AUTOPGM_CTL1, 0x9f),
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
};
@@ -86,11 +119,24 @@ struct qusb2_phy_cfg {
unsigned int tbl_num;
/* offset to PHY_CLK_SCHEME register in TCSR map */
unsigned int clk_scheme_offset;
+
+ /* array of registers with different offsets */
+ const unsigned int *regs;
+ unsigned int mask_core_ready;
+ unsigned int disable_ctrl;
+
+ /* true if PHY has PLL_TEST register to select clk_scheme */
+ bool has_pll_test;
};
static const struct qusb2_phy_cfg msm8996_phy_cfg = {
- .tbl = msm8996_init_tbl,
- .tbl_num = ARRAY_SIZE(msm8996_init_tbl),
+ .tbl = msm8996_init_tbl,
+ .tbl_num = ARRAY_SIZE(msm8996_init_tbl),
+ .regs = msm8996_regs_layout,
+
+ .has_pll_test = true,
+ .disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN),
+ .mask_core_ready = PLL_LOCKED,
};
static const char * const qusb2_phy_vreg_names[] = {
@@ -160,12 +206,17 @@ static inline void qusb2_clrbits(void __iomem *base, u32 offset, u32 val)
static inline
void qcom_qusb2_phy_configure(void __iomem *base,
+ const unsigned int *regs,
const struct qusb2_phy_init_tbl tbl[], int num)
{
int i;
- for (i = 0; i < num; i++)
- writel(tbl[i].val, base + tbl[i].offset);
+ for (i = 0; i < num; i++) {
+ if (tbl[i].in_layout)
+ writel(tbl[i].val, base + regs[tbl[i].offset]);
+ else
+ writel(tbl[i].val, base + tbl[i].offset);
+ }
}
/*
@@ -198,7 +249,8 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
static int qusb2_phy_init(struct phy *phy)
{
struct qusb2_phy *qphy = phy_get_drvdata(phy);
- unsigned int val;
+ const struct qusb2_phy_cfg *cfg = qphy->cfg;
+ unsigned int val = 0;
unsigned int clk_scheme;
int ret;
@@ -239,20 +291,23 @@ static int qusb2_phy_init(struct phy *phy)
}
/* Disable the PHY */
- qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN,
- CLAMP_N_EN | FREEZIO_N | POWER_DOWN);
+ qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_POWERDOWN],
+ qphy->cfg->disable_ctrl);
- /* save reset value to override reference clock scheme later */
- val = readl(qphy->base + QUSB2PHY_PLL_TEST);
+ if (cfg->has_pll_test) {
+ /* save reset value to override reference clock scheme later */
+ val = readl(qphy->base + QUSB2PHY_PLL_TEST);
+ }
- qcom_qusb2_phy_configure(qphy->base, qphy->cfg->tbl,
- qphy->cfg->tbl_num);
+ qcom_qusb2_phy_configure(qphy->base, cfg->regs, cfg->tbl,
+ cfg->tbl_num);
/* Set efuse value for tuning the PHY */
qusb2_phy_set_tune2_param(qphy);
/* Enable the PHY */
- qusb2_clrbits(qphy->base, QUSB2PHY_PORT_POWERDOWN, POWER_DOWN);
+ qusb2_clrbits(qphy->base, cfg->regs[QUSB2PHY_PORT_POWERDOWN],
+ POWER_DOWN);
/* Required to get phy pll lock successfully */
usleep_range(150, 160);
@@ -285,27 +340,31 @@ static int qusb2_phy_init(struct phy *phy)
}
if (!qphy->has_se_clk_scheme) {
- val &= ~CLK_REF_SEL;
ret = clk_prepare_enable(qphy->ref_clk);
if (ret) {
dev_err(&phy->dev, "failed to enable ref clk, %d\n",
ret);
goto assert_phy_reset;
}
- } else {
- val |= CLK_REF_SEL;
}
- writel(val, qphy->base + QUSB2PHY_PLL_TEST);
+ if (cfg->has_pll_test) {
+ if (!qphy->has_se_clk_scheme)
+ val &= ~CLK_REF_SEL;
+ else
+ val |= CLK_REF_SEL;
+
+ writel(val, qphy->base + QUSB2PHY_PLL_TEST);
- /* ensure above write is through */
- readl(qphy->base + QUSB2PHY_PLL_TEST);
+ /* ensure above write is through */
+ readl(qphy->base + QUSB2PHY_PLL_TEST);
+ }
/* Required to get phy pll lock successfully */
usleep_range(100, 110);
- val = readb(qphy->base + QUSB2PHY_PLL_STATUS);
- if (!(val & PLL_LOCKED)) {
+ val = readb(qphy->base + cfg->regs[QUSB2PHY_PLL_STATUS]);
+ if (!(val & cfg->mask_core_ready)) {
dev_err(&phy->dev,
"QUSB2PHY pll lock failed: status reg = %x\n", val);
ret = -EBUSY;
@@ -334,8 +393,8 @@ static int qusb2_phy_exit(struct phy *phy)
struct qusb2_phy *qphy = phy_get_drvdata(phy);
/* Disable the PHY */
- qusb2_setbits(qphy->base, QUSB2PHY_PORT_POWERDOWN,
- CLAMP_N_EN | FREEZIO_N | POWER_DOWN);
+ qusb2_setbits(qphy->base, qphy->cfg->regs[QUSB2PHY_PORT_POWERDOWN],
+ qphy->cfg->disable_ctrl);
if (!qphy->has_se_clk_scheme)
clk_disable_unprepare(qphy->ref_clk);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 08/17] dt-bindings: phy-qcom-qusb2: Update binding for QUSB2 V2 version
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam, Rob Herring,
Mark Rutland, Stephen Boyd, Vivek Gautam,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
Update generic compatible string for QUSB2 V2 PHY. This will allow
all targets using QUSB2 V2 use same string.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt
index aa0fcb0..42c9742 100644
--- a/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt
+++ b/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt
@@ -4,7 +4,10 @@ Qualcomm QUSB2 phy controller
QUSB2 controller supports LS/FS/HS usb connectivity on Qualcomm chipsets.
Required properties:
- - compatible: compatible list, contains "qcom,msm8996-qusb2-phy".
+ - compatible: compatible list, contains
+ "qcom,msm8996-qusb2-phy" for 14nm PHY on msm8996,
+ "qcom,qusb2-v2-phy" for QUSB2 V2 PHY.
+
- reg: offset and length of the PHY register set.
- #phy-cells: must be 0.
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 08/17] dt-bindings: phy-qcom-qusb2: Update binding for QUSB2 V2 version
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam, Rob Herring,
Mark Rutland, Stephen Boyd, Vivek Gautam,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
Update generic compatible string for QUSB2 V2 PHY. This will allow
all targets using QUSB2 V2 use same string.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt
index aa0fcb0..42c9742 100644
--- a/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt
+++ b/Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt
@@ -4,7 +4,10 @@ Qualcomm QUSB2 phy controller
QUSB2 controller supports LS/FS/HS usb connectivity on Qualcomm chipsets.
Required properties:
- - compatible: compatible list, contains "qcom,msm8996-qusb2-phy".
+ - compatible: compatible list, contains
+ "qcom,msm8996-qusb2-phy" for 14nm PHY on msm8996,
+ "qcom,qusb2-v2-phy" for QUSB2 V2 PHY.
+
- reg: offset and length of the PHY register set.
- #phy-cells: must be 0.
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 09/17] phy: qcom-qusb2: Add support for QUSB2 V2 version
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Jaehoon Chung, Stephen Boyd,
open list:GENERIC PHY FRAMEWORK
Use register layout to add additional registers present
on QUSB2 PHY V2 version for PHY initialization.
Other than new registers on V2, following two register's
offset and bit definitions are different: POWERDOWN control
and PLL_STATUS.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 64 +++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index c0c5358..bda1f4c 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -40,15 +40,34 @@
/* QUSB2PHY_PLL_STATUS register bits */
#define PLL_LOCKED BIT(5)
+/* QUSB2PHY_PLL_COMMON_STATUS_ONE register bits */
+#define CORE_READY_STATUS BIT(0)
+
/* QUSB2PHY_PORT_POWERDOWN register bits */
#define CLAMP_N_EN BIT(5)
#define FREEZIO_N BIT(1)
#define POWER_DOWN BIT(0)
+/* QUSB2PHY_PWR_CTRL1 register bits */
+#define PWR_CTRL1_VREF_SUPPLY_TRIM BIT(5)
+#define PWR_CTRL1_CLAMP_N_EN BIT(1)
+
#define QUSB2PHY_REFCLK_ENABLE BIT(0)
#define PHY_CLK_SCHEME_SEL BIT(0)
+#define QUSB2PHY_PLL_ANALOG_CONTROLS_TWO 0x04
+#define QUSB2PHY_PLL_CLOCK_INVERTERS 0x18c
+#define QUSB2PHY_PLL_CMODE 0x2c
+#define QUSB2PHY_PLL_LOCK_DELAY 0x184
+#define QUSB2PHY_PLL_DIGITAL_TIMERS_TWO 0xb4
+#define QUSB2PHY_PLL_BIAS_CONTROL_1 0x194
+#define QUSB2PHY_PLL_BIAS_CONTROL_2 0x198
+#define QUSB2PHY_PWR_CTRL2 0x214
+#define QUSB2PHY_IMP_CTRL1 0x220
+#define QUSB2PHY_IMP_CTRL2 0x224
+#define QUSB2PHY_CHG_CTRL2 0x23c
+
struct qusb2_phy_init_tbl {
unsigned int offset;
unsigned int val;
@@ -113,6 +132,38 @@ enum qusb2phy_reg_layout {
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
};
+static const unsigned int qusb2_v2_regs_layout[] = {
+ [QUSB2PHY_PLL_STATUS] = 0x1a0,
+ [QUSB2PHY_PORT_TUNE1] = 0x240,
+ [QUSB2PHY_PORT_TUNE2] = 0x244,
+ [QUSB2PHY_PORT_TUNE3] = 0x248,
+ [QUSB2PHY_PORT_TUNE4] = 0x24c,
+ [QUSB2PHY_PORT_TUNE5] = 0x250,
+ [QUSB2PHY_PORT_TEST2] = 0x258,
+ [QUSB2PHY_PORT_POWERDOWN] = 0x210,
+};
+
+static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = {
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CMODE, 0x80),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_LOCK_DELAY, 0x0a),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_DIGITAL_TIMERS_TWO, 0x19),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_BIAS_CONTROL_1, 0x40),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_BIAS_CONTROL_2, 0x20),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PWR_CTRL2, 0x21),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_IMP_CTRL1, 0x0),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_IMP_CTRL2, 0x58),
+
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0x30),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0x29),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0xca),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0x04),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE5, 0x03),
+
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_CHG_CTRL2, 0x0),
+};
+
struct qusb2_phy_cfg {
const struct qusb2_phy_init_tbl *tbl;
/* number of entries in the table */
@@ -139,6 +190,16 @@ struct qusb2_phy_cfg {
.mask_core_ready = PLL_LOCKED,
};
+static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = {
+ .tbl = qusb2_v2_init_tbl,
+ .tbl_num = ARRAY_SIZE(qusb2_v2_init_tbl),
+ .regs = qusb2_v2_regs_layout,
+
+ .disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN |
+ POWER_DOWN),
+ .mask_core_ready = CORE_READY_STATUS,
+};
+
static const char * const qusb2_phy_vreg_names[] = {
"vdda-pll", "vdda-phy-dpdm",
};
@@ -419,6 +480,9 @@ static int qusb2_phy_exit(struct phy *phy)
{
.compatible = "qcom,msm8996-qusb2-phy",
.data = &msm8996_phy_cfg,
+ }, {
+ .compatible = "qcom,qusb2-v2-phy",
+ .data = &qusb2_v2_phy_cfg,
},
{ },
};
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 09/17] phy: qcom-qusb2: Add support for QUSB2 V2 version
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Jaehoon Chung, Stephen Boyd,
open list:GENERIC PHY FRAMEWORK
Use register layout to add additional registers present
on QUSB2 PHY V2 version for PHY initialization.
Other than new registers on V2, following two register's
offset and bit definitions are different: POWERDOWN control
and PLL_STATUS.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 64 +++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index c0c5358..bda1f4c 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -40,15 +40,34 @@
/* QUSB2PHY_PLL_STATUS register bits */
#define PLL_LOCKED BIT(5)
+/* QUSB2PHY_PLL_COMMON_STATUS_ONE register bits */
+#define CORE_READY_STATUS BIT(0)
+
/* QUSB2PHY_PORT_POWERDOWN register bits */
#define CLAMP_N_EN BIT(5)
#define FREEZIO_N BIT(1)
#define POWER_DOWN BIT(0)
+/* QUSB2PHY_PWR_CTRL1 register bits */
+#define PWR_CTRL1_VREF_SUPPLY_TRIM BIT(5)
+#define PWR_CTRL1_CLAMP_N_EN BIT(1)
+
#define QUSB2PHY_REFCLK_ENABLE BIT(0)
#define PHY_CLK_SCHEME_SEL BIT(0)
+#define QUSB2PHY_PLL_ANALOG_CONTROLS_TWO 0x04
+#define QUSB2PHY_PLL_CLOCK_INVERTERS 0x18c
+#define QUSB2PHY_PLL_CMODE 0x2c
+#define QUSB2PHY_PLL_LOCK_DELAY 0x184
+#define QUSB2PHY_PLL_DIGITAL_TIMERS_TWO 0xb4
+#define QUSB2PHY_PLL_BIAS_CONTROL_1 0x194
+#define QUSB2PHY_PLL_BIAS_CONTROL_2 0x198
+#define QUSB2PHY_PWR_CTRL2 0x214
+#define QUSB2PHY_IMP_CTRL1 0x220
+#define QUSB2PHY_IMP_CTRL2 0x224
+#define QUSB2PHY_CHG_CTRL2 0x23c
+
struct qusb2_phy_init_tbl {
unsigned int offset;
unsigned int val;
@@ -113,6 +132,38 @@ enum qusb2phy_reg_layout {
QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_PWR_CTRL, 0x00),
};
+static const unsigned int qusb2_v2_regs_layout[] = {
+ [QUSB2PHY_PLL_STATUS] = 0x1a0,
+ [QUSB2PHY_PORT_TUNE1] = 0x240,
+ [QUSB2PHY_PORT_TUNE2] = 0x244,
+ [QUSB2PHY_PORT_TUNE3] = 0x248,
+ [QUSB2PHY_PORT_TUNE4] = 0x24c,
+ [QUSB2PHY_PORT_TUNE5] = 0x250,
+ [QUSB2PHY_PORT_TEST2] = 0x258,
+ [QUSB2PHY_PORT_POWERDOWN] = 0x210,
+};
+
+static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = {
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_ANALOG_CONTROLS_TWO, 0x03),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CLOCK_INVERTERS, 0x7c),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_CMODE, 0x80),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_LOCK_DELAY, 0x0a),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_DIGITAL_TIMERS_TWO, 0x19),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_BIAS_CONTROL_1, 0x40),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PLL_BIAS_CONTROL_2, 0x20),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_PWR_CTRL2, 0x21),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_IMP_CTRL1, 0x0),
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_IMP_CTRL2, 0x58),
+
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE1, 0x30),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE2, 0x29),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE3, 0xca),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE4, 0x04),
+ QUSB2_PHY_INIT_CFG_L(QUSB2PHY_PORT_TUNE5, 0x03),
+
+ QUSB2_PHY_INIT_CFG(QUSB2PHY_CHG_CTRL2, 0x0),
+};
+
struct qusb2_phy_cfg {
const struct qusb2_phy_init_tbl *tbl;
/* number of entries in the table */
@@ -139,6 +190,16 @@ struct qusb2_phy_cfg {
.mask_core_ready = PLL_LOCKED,
};
+static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = {
+ .tbl = qusb2_v2_init_tbl,
+ .tbl_num = ARRAY_SIZE(qusb2_v2_init_tbl),
+ .regs = qusb2_v2_regs_layout,
+
+ .disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN |
+ POWER_DOWN),
+ .mask_core_ready = CORE_READY_STATUS,
+};
+
static const char * const qusb2_phy_vreg_names[] = {
"vdda-pll", "vdda-phy-dpdm",
};
@@ -419,6 +480,9 @@ static int qusb2_phy_exit(struct phy *phy)
{
.compatible = "qcom,msm8996-qusb2-phy",
.data = &msm8996_phy_cfg,
+ }, {
+ .compatible = "qcom,qusb2-v2-phy",
+ .data = &qusb2_v2_phy_cfg,
},
{ },
};
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 10/17] phy: qcom-qmp: Move register offsets to header file
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Viresh Kumar, Fengguang Wu,
Wei Yongjun, open list
New revision (v3) of QMP PHY uses different offsets
for almost all of the registers. Hence, move these
definitions to header file so that updated offsets
can be added for QMP v3.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 119 +------------------------------
drivers/phy/qualcomm/phy-qcom-qmp.h | 137 ++++++++++++++++++++++++++++++++++++
2 files changed, 138 insertions(+), 118 deletions(-)
create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp.h
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 263cf50..15a734f 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -31,124 +31,7 @@
#include <dt-bindings/phy/phy.h>
-/* QMP PHY QSERDES COM registers */
-#define QSERDES_COM_BG_TIMER 0x00c
-#define QSERDES_COM_SSC_EN_CENTER 0x010
-#define QSERDES_COM_SSC_ADJ_PER1 0x014
-#define QSERDES_COM_SSC_ADJ_PER2 0x018
-#define QSERDES_COM_SSC_PER1 0x01c
-#define QSERDES_COM_SSC_PER2 0x020
-#define QSERDES_COM_SSC_STEP_SIZE1 0x024
-#define QSERDES_COM_SSC_STEP_SIZE2 0x028
-#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x034
-#define QSERDES_COM_CLK_ENABLE1 0x038
-#define QSERDES_COM_SYS_CLK_CTRL 0x03c
-#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x040
-#define QSERDES_COM_PLL_IVCO 0x048
-#define QSERDES_COM_LOCK_CMP1_MODE0 0x04c
-#define QSERDES_COM_LOCK_CMP2_MODE0 0x050
-#define QSERDES_COM_LOCK_CMP3_MODE0 0x054
-#define QSERDES_COM_LOCK_CMP1_MODE1 0x058
-#define QSERDES_COM_LOCK_CMP2_MODE1 0x05c
-#define QSERDES_COM_LOCK_CMP3_MODE1 0x060
-#define QSERDES_COM_BG_TRIM 0x070
-#define QSERDES_COM_CLK_EP_DIV 0x074
-#define QSERDES_COM_CP_CTRL_MODE0 0x078
-#define QSERDES_COM_CP_CTRL_MODE1 0x07c
-#define QSERDES_COM_PLL_RCTRL_MODE0 0x084
-#define QSERDES_COM_PLL_RCTRL_MODE1 0x088
-#define QSERDES_COM_PLL_CCTRL_MODE0 0x090
-#define QSERDES_COM_PLL_CCTRL_MODE1 0x094
-#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM 0x0a8
-#define QSERDES_COM_SYSCLK_EN_SEL 0x0ac
-#define QSERDES_COM_RESETSM_CNTRL 0x0b4
-#define QSERDES_COM_RESTRIM_CTRL 0x0bc
-#define QSERDES_COM_RESCODE_DIV_NUM 0x0c4
-#define QSERDES_COM_LOCK_CMP_EN 0x0c8
-#define QSERDES_COM_LOCK_CMP_CFG 0x0cc
-#define QSERDES_COM_DEC_START_MODE0 0x0d0
-#define QSERDES_COM_DEC_START_MODE1 0x0d4
-#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x0dc
-#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x0e0
-#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x0e4
-#define QSERDES_COM_DIV_FRAC_START1_MODE1 0x0e8
-#define QSERDES_COM_DIV_FRAC_START2_MODE1 0x0ec
-#define QSERDES_COM_DIV_FRAC_START3_MODE1 0x0f0
-#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x108
-#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x10c
-#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x110
-#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x114
-#define QSERDES_COM_VCO_TUNE_CTRL 0x124
-#define QSERDES_COM_VCO_TUNE_MAP 0x128
-#define QSERDES_COM_VCO_TUNE1_MODE0 0x12c
-#define QSERDES_COM_VCO_TUNE2_MODE0 0x130
-#define QSERDES_COM_VCO_TUNE1_MODE1 0x134
-#define QSERDES_COM_VCO_TUNE2_MODE1 0x138
-#define QSERDES_COM_VCO_TUNE_TIMER1 0x144
-#define QSERDES_COM_VCO_TUNE_TIMER2 0x148
-#define QSERDES_COM_BG_CTRL 0x170
-#define QSERDES_COM_CLK_SELECT 0x174
-#define QSERDES_COM_HSCLK_SEL 0x178
-#define QSERDES_COM_CORECLK_DIV 0x184
-#define QSERDES_COM_CORE_CLK_EN 0x18c
-#define QSERDES_COM_C_READY_STATUS 0x190
-#define QSERDES_COM_CMN_CONFIG 0x194
-#define QSERDES_COM_SVS_MODE_CLK_SEL 0x19c
-#define QSERDES_COM_DEBUG_BUS0 0x1a0
-#define QSERDES_COM_DEBUG_BUS1 0x1a4
-#define QSERDES_COM_DEBUG_BUS2 0x1a8
-#define QSERDES_COM_DEBUG_BUS3 0x1ac
-#define QSERDES_COM_DEBUG_BUS_SEL 0x1b0
-#define QSERDES_COM_CORECLK_DIV_MODE1 0x1bc
-
-/* QMP PHY TX registers */
-#define QSERDES_TX_RES_CODE_LANE_OFFSET 0x054
-#define QSERDES_TX_DEBUG_BUS_SEL 0x064
-#define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x068
-#define QSERDES_TX_LANE_MODE 0x094
-#define QSERDES_TX_RCV_DETECT_LVL_2 0x0ac
-
-/* QMP PHY RX registers */
-#define QSERDES_RX_UCDR_SO_GAIN_HALF 0x010
-#define QSERDES_RX_UCDR_SO_GAIN 0x01c
-#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN 0x040
-#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x048
-#define QSERDES_RX_RX_TERM_BW 0x090
-#define QSERDES_RX_RX_EQ_GAIN1_LSB 0x0c4
-#define QSERDES_RX_RX_EQ_GAIN1_MSB 0x0c8
-#define QSERDES_RX_RX_EQ_GAIN2_LSB 0x0cc
-#define QSERDES_RX_RX_EQ_GAIN2_MSB 0x0d0
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d8
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x0dc
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x0e0
-#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x108
-#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x10c
-#define QSERDES_RX_SIGDET_ENABLES 0x110
-#define QSERDES_RX_SIGDET_CNTRL 0x114
-#define QSERDES_RX_SIGDET_LVL 0x118
-#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x11c
-#define QSERDES_RX_RX_BAND 0x120
-#define QSERDES_RX_RX_INTERFACE_MODE 0x12c
-
-/* QMP PHY PCS registers */
-#define QPHY_POWER_DOWN_CONTROL 0x04
-#define QPHY_TXDEEMPH_M6DB_V0 0x24
-#define QPHY_TXDEEMPH_M3P5DB_V0 0x28
-#define QPHY_ENDPOINT_REFCLK_DRIVE 0x54
-#define QPHY_RX_IDLE_DTCT_CNTRL 0x58
-#define QPHY_POWER_STATE_CONFIG1 0x60
-#define QPHY_POWER_STATE_CONFIG2 0x64
-#define QPHY_POWER_STATE_CONFIG4 0x6c
-#define QPHY_LOCK_DETECT_CONFIG1 0x80
-#define QPHY_LOCK_DETECT_CONFIG2 0x84
-#define QPHY_LOCK_DETECT_CONFIG3 0x88
-#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0
-#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4
-#define QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB 0x1A8
-#define QPHY_OSC_DTCT_ACTIONS 0x1AC
-#define QPHY_RX_SIGDET_LVL 0x1D8
-#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1DC
-#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1E0
+#include "phy-qcom-qmp.h"
/* QPHY_SW_RESET bit */
#define SW_RESET BIT(0)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
new file mode 100644
index 0000000..d930ca7
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2017, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef QCOM_PHY_QMP_H_
+#define QCOM_PHY_QMP_H_
+
+/* Only for QMP V2 PHY - QSERDES COM registers */
+#define QSERDES_COM_BG_TIMER 0x00c
+#define QSERDES_COM_SSC_EN_CENTER 0x010
+#define QSERDES_COM_SSC_ADJ_PER1 0x014
+#define QSERDES_COM_SSC_ADJ_PER2 0x018
+#define QSERDES_COM_SSC_PER1 0x01c
+#define QSERDES_COM_SSC_PER2 0x020
+#define QSERDES_COM_SSC_STEP_SIZE1 0x024
+#define QSERDES_COM_SSC_STEP_SIZE2 0x028
+#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x034
+#define QSERDES_COM_CLK_ENABLE1 0x038
+#define QSERDES_COM_SYS_CLK_CTRL 0x03c
+#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x040
+#define QSERDES_COM_PLL_IVCO 0x048
+#define QSERDES_COM_LOCK_CMP1_MODE0 0x04c
+#define QSERDES_COM_LOCK_CMP2_MODE0 0x050
+#define QSERDES_COM_LOCK_CMP3_MODE0 0x054
+#define QSERDES_COM_LOCK_CMP1_MODE1 0x058
+#define QSERDES_COM_LOCK_CMP2_MODE1 0x05c
+#define QSERDES_COM_LOCK_CMP3_MODE1 0x060
+#define QSERDES_COM_BG_TRIM 0x070
+#define QSERDES_COM_CLK_EP_DIV 0x074
+#define QSERDES_COM_CP_CTRL_MODE0 0x078
+#define QSERDES_COM_CP_CTRL_MODE1 0x07c
+#define QSERDES_COM_PLL_RCTRL_MODE0 0x084
+#define QSERDES_COM_PLL_RCTRL_MODE1 0x088
+#define QSERDES_COM_PLL_CCTRL_MODE0 0x090
+#define QSERDES_COM_PLL_CCTRL_MODE1 0x094
+#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM 0x0a8
+#define QSERDES_COM_SYSCLK_EN_SEL 0x0ac
+#define QSERDES_COM_RESETSM_CNTRL 0x0b4
+#define QSERDES_COM_RESTRIM_CTRL 0x0bc
+#define QSERDES_COM_RESCODE_DIV_NUM 0x0c4
+#define QSERDES_COM_LOCK_CMP_EN 0x0c8
+#define QSERDES_COM_LOCK_CMP_CFG 0x0cc
+#define QSERDES_COM_DEC_START_MODE0 0x0d0
+#define QSERDES_COM_DEC_START_MODE1 0x0d4
+#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x0dc
+#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x0e0
+#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x0e4
+#define QSERDES_COM_DIV_FRAC_START1_MODE1 0x0e8
+#define QSERDES_COM_DIV_FRAC_START2_MODE1 0x0ec
+#define QSERDES_COM_DIV_FRAC_START3_MODE1 0x0f0
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x108
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x10c
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x110
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x114
+#define QSERDES_COM_VCO_TUNE_CTRL 0x124
+#define QSERDES_COM_VCO_TUNE_MAP 0x128
+#define QSERDES_COM_VCO_TUNE1_MODE0 0x12c
+#define QSERDES_COM_VCO_TUNE2_MODE0 0x130
+#define QSERDES_COM_VCO_TUNE1_MODE1 0x134
+#define QSERDES_COM_VCO_TUNE2_MODE1 0x138
+#define QSERDES_COM_VCO_TUNE_TIMER1 0x144
+#define QSERDES_COM_VCO_TUNE_TIMER2 0x148
+#define QSERDES_COM_BG_CTRL 0x170
+#define QSERDES_COM_CLK_SELECT 0x174
+#define QSERDES_COM_HSCLK_SEL 0x178
+#define QSERDES_COM_CORECLK_DIV 0x184
+#define QSERDES_COM_CORE_CLK_EN 0x18c
+#define QSERDES_COM_C_READY_STATUS 0x190
+#define QSERDES_COM_CMN_CONFIG 0x194
+#define QSERDES_COM_SVS_MODE_CLK_SEL 0x19c
+#define QSERDES_COM_DEBUG_BUS0 0x1a0
+#define QSERDES_COM_DEBUG_BUS1 0x1a4
+#define QSERDES_COM_DEBUG_BUS2 0x1a8
+#define QSERDES_COM_DEBUG_BUS3 0x1ac
+#define QSERDES_COM_DEBUG_BUS_SEL 0x1b0
+#define QSERDES_COM_CORECLK_DIV_MODE1 0x1bc
+
+/* Only for QMP V2 PHY - TX registers */
+#define QSERDES_TX_RES_CODE_LANE_OFFSET 0x054
+#define QSERDES_TX_DEBUG_BUS_SEL 0x064
+#define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x068
+#define QSERDES_TX_LANE_MODE 0x094
+#define QSERDES_TX_RCV_DETECT_LVL_2 0x0ac
+
+/* Only for QMP V2 PHY - RX registers */
+#define QSERDES_RX_UCDR_SO_GAIN_HALF 0x010
+#define QSERDES_RX_UCDR_SO_GAIN 0x01c
+#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN 0x040
+#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x048
+#define QSERDES_RX_RX_TERM_BW 0x090
+#define QSERDES_RX_RX_EQ_GAIN1_LSB 0x0c4
+#define QSERDES_RX_RX_EQ_GAIN1_MSB 0x0c8
+#define QSERDES_RX_RX_EQ_GAIN2_LSB 0x0cc
+#define QSERDES_RX_RX_EQ_GAIN2_MSB 0x0d0
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d8
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x0dc
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x0e0
+#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x108
+#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x10c
+#define QSERDES_RX_SIGDET_ENABLES 0x110
+#define QSERDES_RX_SIGDET_CNTRL 0x114
+#define QSERDES_RX_SIGDET_LVL 0x118
+#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x11c
+#define QSERDES_RX_RX_BAND 0x120
+#define QSERDES_RX_RX_INTERFACE_MODE 0x12c
+
+/* Only for QMP V2 PHY - PCS registers */
+#define QPHY_POWER_DOWN_CONTROL 0x04
+#define QPHY_TXDEEMPH_M6DB_V0 0x24
+#define QPHY_TXDEEMPH_M3P5DB_V0 0x28
+#define QPHY_ENDPOINT_REFCLK_DRIVE 0x54
+#define QPHY_RX_IDLE_DTCT_CNTRL 0x58
+#define QPHY_POWER_STATE_CONFIG1 0x60
+#define QPHY_POWER_STATE_CONFIG2 0x64
+#define QPHY_POWER_STATE_CONFIG4 0x6c
+#define QPHY_LOCK_DETECT_CONFIG1 0x80
+#define QPHY_LOCK_DETECT_CONFIG2 0x84
+#define QPHY_LOCK_DETECT_CONFIG3 0x88
+#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0
+#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4
+#define QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB 0x1A8
+#define QPHY_OSC_DTCT_ACTIONS 0x1AC
+#define QPHY_RX_SIGDET_LVL 0x1D8
+#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1DC
+#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1E0
+
+#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 10/17] phy: qcom-qmp: Move register offsets to header file
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Viresh Kumar, Fengguang Wu,
Wei Yongjun, open list
New revision (v3) of QMP PHY uses different offsets
for almost all of the registers. Hence, move these
definitions to header file so that updated offsets
can be added for QMP v3.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 119 +------------------------------
drivers/phy/qualcomm/phy-qcom-qmp.h | 137 ++++++++++++++++++++++++++++++++++++
2 files changed, 138 insertions(+), 118 deletions(-)
create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp.h
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 263cf50..15a734f 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -31,124 +31,7 @@
#include <dt-bindings/phy/phy.h>
-/* QMP PHY QSERDES COM registers */
-#define QSERDES_COM_BG_TIMER 0x00c
-#define QSERDES_COM_SSC_EN_CENTER 0x010
-#define QSERDES_COM_SSC_ADJ_PER1 0x014
-#define QSERDES_COM_SSC_ADJ_PER2 0x018
-#define QSERDES_COM_SSC_PER1 0x01c
-#define QSERDES_COM_SSC_PER2 0x020
-#define QSERDES_COM_SSC_STEP_SIZE1 0x024
-#define QSERDES_COM_SSC_STEP_SIZE2 0x028
-#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x034
-#define QSERDES_COM_CLK_ENABLE1 0x038
-#define QSERDES_COM_SYS_CLK_CTRL 0x03c
-#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x040
-#define QSERDES_COM_PLL_IVCO 0x048
-#define QSERDES_COM_LOCK_CMP1_MODE0 0x04c
-#define QSERDES_COM_LOCK_CMP2_MODE0 0x050
-#define QSERDES_COM_LOCK_CMP3_MODE0 0x054
-#define QSERDES_COM_LOCK_CMP1_MODE1 0x058
-#define QSERDES_COM_LOCK_CMP2_MODE1 0x05c
-#define QSERDES_COM_LOCK_CMP3_MODE1 0x060
-#define QSERDES_COM_BG_TRIM 0x070
-#define QSERDES_COM_CLK_EP_DIV 0x074
-#define QSERDES_COM_CP_CTRL_MODE0 0x078
-#define QSERDES_COM_CP_CTRL_MODE1 0x07c
-#define QSERDES_COM_PLL_RCTRL_MODE0 0x084
-#define QSERDES_COM_PLL_RCTRL_MODE1 0x088
-#define QSERDES_COM_PLL_CCTRL_MODE0 0x090
-#define QSERDES_COM_PLL_CCTRL_MODE1 0x094
-#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM 0x0a8
-#define QSERDES_COM_SYSCLK_EN_SEL 0x0ac
-#define QSERDES_COM_RESETSM_CNTRL 0x0b4
-#define QSERDES_COM_RESTRIM_CTRL 0x0bc
-#define QSERDES_COM_RESCODE_DIV_NUM 0x0c4
-#define QSERDES_COM_LOCK_CMP_EN 0x0c8
-#define QSERDES_COM_LOCK_CMP_CFG 0x0cc
-#define QSERDES_COM_DEC_START_MODE0 0x0d0
-#define QSERDES_COM_DEC_START_MODE1 0x0d4
-#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x0dc
-#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x0e0
-#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x0e4
-#define QSERDES_COM_DIV_FRAC_START1_MODE1 0x0e8
-#define QSERDES_COM_DIV_FRAC_START2_MODE1 0x0ec
-#define QSERDES_COM_DIV_FRAC_START3_MODE1 0x0f0
-#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x108
-#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x10c
-#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x110
-#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x114
-#define QSERDES_COM_VCO_TUNE_CTRL 0x124
-#define QSERDES_COM_VCO_TUNE_MAP 0x128
-#define QSERDES_COM_VCO_TUNE1_MODE0 0x12c
-#define QSERDES_COM_VCO_TUNE2_MODE0 0x130
-#define QSERDES_COM_VCO_TUNE1_MODE1 0x134
-#define QSERDES_COM_VCO_TUNE2_MODE1 0x138
-#define QSERDES_COM_VCO_TUNE_TIMER1 0x144
-#define QSERDES_COM_VCO_TUNE_TIMER2 0x148
-#define QSERDES_COM_BG_CTRL 0x170
-#define QSERDES_COM_CLK_SELECT 0x174
-#define QSERDES_COM_HSCLK_SEL 0x178
-#define QSERDES_COM_CORECLK_DIV 0x184
-#define QSERDES_COM_CORE_CLK_EN 0x18c
-#define QSERDES_COM_C_READY_STATUS 0x190
-#define QSERDES_COM_CMN_CONFIG 0x194
-#define QSERDES_COM_SVS_MODE_CLK_SEL 0x19c
-#define QSERDES_COM_DEBUG_BUS0 0x1a0
-#define QSERDES_COM_DEBUG_BUS1 0x1a4
-#define QSERDES_COM_DEBUG_BUS2 0x1a8
-#define QSERDES_COM_DEBUG_BUS3 0x1ac
-#define QSERDES_COM_DEBUG_BUS_SEL 0x1b0
-#define QSERDES_COM_CORECLK_DIV_MODE1 0x1bc
-
-/* QMP PHY TX registers */
-#define QSERDES_TX_RES_CODE_LANE_OFFSET 0x054
-#define QSERDES_TX_DEBUG_BUS_SEL 0x064
-#define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x068
-#define QSERDES_TX_LANE_MODE 0x094
-#define QSERDES_TX_RCV_DETECT_LVL_2 0x0ac
-
-/* QMP PHY RX registers */
-#define QSERDES_RX_UCDR_SO_GAIN_HALF 0x010
-#define QSERDES_RX_UCDR_SO_GAIN 0x01c
-#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN 0x040
-#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x048
-#define QSERDES_RX_RX_TERM_BW 0x090
-#define QSERDES_RX_RX_EQ_GAIN1_LSB 0x0c4
-#define QSERDES_RX_RX_EQ_GAIN1_MSB 0x0c8
-#define QSERDES_RX_RX_EQ_GAIN2_LSB 0x0cc
-#define QSERDES_RX_RX_EQ_GAIN2_MSB 0x0d0
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d8
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x0dc
-#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x0e0
-#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x108
-#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x10c
-#define QSERDES_RX_SIGDET_ENABLES 0x110
-#define QSERDES_RX_SIGDET_CNTRL 0x114
-#define QSERDES_RX_SIGDET_LVL 0x118
-#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x11c
-#define QSERDES_RX_RX_BAND 0x120
-#define QSERDES_RX_RX_INTERFACE_MODE 0x12c
-
-/* QMP PHY PCS registers */
-#define QPHY_POWER_DOWN_CONTROL 0x04
-#define QPHY_TXDEEMPH_M6DB_V0 0x24
-#define QPHY_TXDEEMPH_M3P5DB_V0 0x28
-#define QPHY_ENDPOINT_REFCLK_DRIVE 0x54
-#define QPHY_RX_IDLE_DTCT_CNTRL 0x58
-#define QPHY_POWER_STATE_CONFIG1 0x60
-#define QPHY_POWER_STATE_CONFIG2 0x64
-#define QPHY_POWER_STATE_CONFIG4 0x6c
-#define QPHY_LOCK_DETECT_CONFIG1 0x80
-#define QPHY_LOCK_DETECT_CONFIG2 0x84
-#define QPHY_LOCK_DETECT_CONFIG3 0x88
-#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0
-#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4
-#define QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB 0x1A8
-#define QPHY_OSC_DTCT_ACTIONS 0x1AC
-#define QPHY_RX_SIGDET_LVL 0x1D8
-#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1DC
-#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1E0
+#include "phy-qcom-qmp.h"
/* QPHY_SW_RESET bit */
#define SW_RESET BIT(0)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
new file mode 100644
index 0000000..d930ca7
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2017, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef QCOM_PHY_QMP_H_
+#define QCOM_PHY_QMP_H_
+
+/* Only for QMP V2 PHY - QSERDES COM registers */
+#define QSERDES_COM_BG_TIMER 0x00c
+#define QSERDES_COM_SSC_EN_CENTER 0x010
+#define QSERDES_COM_SSC_ADJ_PER1 0x014
+#define QSERDES_COM_SSC_ADJ_PER2 0x018
+#define QSERDES_COM_SSC_PER1 0x01c
+#define QSERDES_COM_SSC_PER2 0x020
+#define QSERDES_COM_SSC_STEP_SIZE1 0x024
+#define QSERDES_COM_SSC_STEP_SIZE2 0x028
+#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN 0x034
+#define QSERDES_COM_CLK_ENABLE1 0x038
+#define QSERDES_COM_SYS_CLK_CTRL 0x03c
+#define QSERDES_COM_SYSCLK_BUF_ENABLE 0x040
+#define QSERDES_COM_PLL_IVCO 0x048
+#define QSERDES_COM_LOCK_CMP1_MODE0 0x04c
+#define QSERDES_COM_LOCK_CMP2_MODE0 0x050
+#define QSERDES_COM_LOCK_CMP3_MODE0 0x054
+#define QSERDES_COM_LOCK_CMP1_MODE1 0x058
+#define QSERDES_COM_LOCK_CMP2_MODE1 0x05c
+#define QSERDES_COM_LOCK_CMP3_MODE1 0x060
+#define QSERDES_COM_BG_TRIM 0x070
+#define QSERDES_COM_CLK_EP_DIV 0x074
+#define QSERDES_COM_CP_CTRL_MODE0 0x078
+#define QSERDES_COM_CP_CTRL_MODE1 0x07c
+#define QSERDES_COM_PLL_RCTRL_MODE0 0x084
+#define QSERDES_COM_PLL_RCTRL_MODE1 0x088
+#define QSERDES_COM_PLL_CCTRL_MODE0 0x090
+#define QSERDES_COM_PLL_CCTRL_MODE1 0x094
+#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM 0x0a8
+#define QSERDES_COM_SYSCLK_EN_SEL 0x0ac
+#define QSERDES_COM_RESETSM_CNTRL 0x0b4
+#define QSERDES_COM_RESTRIM_CTRL 0x0bc
+#define QSERDES_COM_RESCODE_DIV_NUM 0x0c4
+#define QSERDES_COM_LOCK_CMP_EN 0x0c8
+#define QSERDES_COM_LOCK_CMP_CFG 0x0cc
+#define QSERDES_COM_DEC_START_MODE0 0x0d0
+#define QSERDES_COM_DEC_START_MODE1 0x0d4
+#define QSERDES_COM_DIV_FRAC_START1_MODE0 0x0dc
+#define QSERDES_COM_DIV_FRAC_START2_MODE0 0x0e0
+#define QSERDES_COM_DIV_FRAC_START3_MODE0 0x0e4
+#define QSERDES_COM_DIV_FRAC_START1_MODE1 0x0e8
+#define QSERDES_COM_DIV_FRAC_START2_MODE1 0x0ec
+#define QSERDES_COM_DIV_FRAC_START3_MODE1 0x0f0
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0 0x108
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0 0x10c
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1 0x110
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1 0x114
+#define QSERDES_COM_VCO_TUNE_CTRL 0x124
+#define QSERDES_COM_VCO_TUNE_MAP 0x128
+#define QSERDES_COM_VCO_TUNE1_MODE0 0x12c
+#define QSERDES_COM_VCO_TUNE2_MODE0 0x130
+#define QSERDES_COM_VCO_TUNE1_MODE1 0x134
+#define QSERDES_COM_VCO_TUNE2_MODE1 0x138
+#define QSERDES_COM_VCO_TUNE_TIMER1 0x144
+#define QSERDES_COM_VCO_TUNE_TIMER2 0x148
+#define QSERDES_COM_BG_CTRL 0x170
+#define QSERDES_COM_CLK_SELECT 0x174
+#define QSERDES_COM_HSCLK_SEL 0x178
+#define QSERDES_COM_CORECLK_DIV 0x184
+#define QSERDES_COM_CORE_CLK_EN 0x18c
+#define QSERDES_COM_C_READY_STATUS 0x190
+#define QSERDES_COM_CMN_CONFIG 0x194
+#define QSERDES_COM_SVS_MODE_CLK_SEL 0x19c
+#define QSERDES_COM_DEBUG_BUS0 0x1a0
+#define QSERDES_COM_DEBUG_BUS1 0x1a4
+#define QSERDES_COM_DEBUG_BUS2 0x1a8
+#define QSERDES_COM_DEBUG_BUS3 0x1ac
+#define QSERDES_COM_DEBUG_BUS_SEL 0x1b0
+#define QSERDES_COM_CORECLK_DIV_MODE1 0x1bc
+
+/* Only for QMP V2 PHY - TX registers */
+#define QSERDES_TX_RES_CODE_LANE_OFFSET 0x054
+#define QSERDES_TX_DEBUG_BUS_SEL 0x064
+#define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN 0x068
+#define QSERDES_TX_LANE_MODE 0x094
+#define QSERDES_TX_RCV_DETECT_LVL_2 0x0ac
+
+/* Only for QMP V2 PHY - RX registers */
+#define QSERDES_RX_UCDR_SO_GAIN_HALF 0x010
+#define QSERDES_RX_UCDR_SO_GAIN 0x01c
+#define QSERDES_RX_UCDR_FASTLOCK_FO_GAIN 0x040
+#define QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE 0x048
+#define QSERDES_RX_RX_TERM_BW 0x090
+#define QSERDES_RX_RX_EQ_GAIN1_LSB 0x0c4
+#define QSERDES_RX_RX_EQ_GAIN1_MSB 0x0c8
+#define QSERDES_RX_RX_EQ_GAIN2_LSB 0x0cc
+#define QSERDES_RX_RX_EQ_GAIN2_MSB 0x0d0
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d8
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3 0x0dc
+#define QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4 0x0e0
+#define QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x108
+#define QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x10c
+#define QSERDES_RX_SIGDET_ENABLES 0x110
+#define QSERDES_RX_SIGDET_CNTRL 0x114
+#define QSERDES_RX_SIGDET_LVL 0x118
+#define QSERDES_RX_SIGDET_DEGLITCH_CNTRL 0x11c
+#define QSERDES_RX_RX_BAND 0x120
+#define QSERDES_RX_RX_INTERFACE_MODE 0x12c
+
+/* Only for QMP V2 PHY - PCS registers */
+#define QPHY_POWER_DOWN_CONTROL 0x04
+#define QPHY_TXDEEMPH_M6DB_V0 0x24
+#define QPHY_TXDEEMPH_M3P5DB_V0 0x28
+#define QPHY_ENDPOINT_REFCLK_DRIVE 0x54
+#define QPHY_RX_IDLE_DTCT_CNTRL 0x58
+#define QPHY_POWER_STATE_CONFIG1 0x60
+#define QPHY_POWER_STATE_CONFIG2 0x64
+#define QPHY_POWER_STATE_CONFIG4 0x6c
+#define QPHY_LOCK_DETECT_CONFIG1 0x80
+#define QPHY_LOCK_DETECT_CONFIG2 0x84
+#define QPHY_LOCK_DETECT_CONFIG3 0x88
+#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0
+#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4
+#define QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB 0x1A8
+#define QPHY_OSC_DTCT_ACTIONS 0x1AC
+#define QPHY_RX_SIGDET_LVL 0x1D8
+#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1DC
+#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1E0
+
+#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 11/17] phy: qcom-qmp: Add register offsets for QMP V3 PHY
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
open list:GENERIC PHY FRAMEWORK
Registers offsets for QMP V3 PHY are changed from
previous versions (1/2), update same in header file.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.h | 149 ++++++++++++++++++++++++++++++++++++
1 file changed, 149 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index d930ca7..f7d4c2a 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -134,4 +134,153 @@
#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1DC
#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1E0
+/* Only for QMP V3 PHY - DP COM registers */
+#define QPHY_V3_DP_COM_PHY_MODE_CTRL 0x00
+#define QPHY_V3_DP_COM_SW_RESET 0x04
+#define QPHY_V3_DP_COM_POWER_DOWN_CTRL 0x08
+#define QPHY_V3_DP_COM_SWI_CTRL 0x0c
+#define QPHY_V3_DP_COM_TYPEC_CTRL 0x10
+#define QPHY_V3_DP_COM_TYPEC_PWRDN_CTRL 0x14
+#define QPHY_V3_DP_COM_RESET_OVRD_CTRL 0x1c
+
+/* Only for QMP V3 PHY - QSERDES COM registers */
+#define QSERDES_V3_COM_BG_TIMER 0x00c
+#define QSERDES_V3_COM_SSC_EN_CENTER 0x010
+#define QSERDES_V3_COM_SSC_ADJ_PER1 0x014
+#define QSERDES_V3_COM_SSC_ADJ_PER2 0x018
+#define QSERDES_V3_COM_SSC_PER1 0x01c
+#define QSERDES_V3_COM_SSC_PER2 0x020
+#define QSERDES_V3_COM_SSC_STEP_SIZE1 0x024
+#define QSERDES_V3_COM_SSC_STEP_SIZE2 0x028
+#define QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN 0x034
+#define QSERDES_V3_COM_CLK_ENABLE1 0x038
+#define QSERDES_V3_COM_SYS_CLK_CTRL 0x03c
+#define QSERDES_V3_COM_SYSCLK_BUF_ENABLE 0x040
+#define QSERDES_V3_COM_PLL_IVCO 0x048
+#define QSERDES_V3_COM_LOCK_CMP1_MODE0 0x098
+#define QSERDES_V3_COM_LOCK_CMP2_MODE0 0x09c
+#define QSERDES_V3_COM_LOCK_CMP3_MODE0 0x0a0
+#define QSERDES_V3_COM_LOCK_CMP1_MODE1 0x0a4
+#define QSERDES_V3_COM_LOCK_CMP2_MODE1 0x0a8
+#define QSERDES_V3_COM_LOCK_CMP3_MODE1 0x0ac
+#define QSERDES_V3_COM_CLK_EP_DIV 0x05c
+#define QSERDES_V3_COM_CP_CTRL_MODE0 0x060
+#define QSERDES_V3_COM_CP_CTRL_MODE1 0x064
+#define QSERDES_V3_COM_PLL_RCTRL_MODE0 0x068
+#define QSERDES_V3_COM_PLL_RCTRL_MODE1 0x06c
+#define QSERDES_V3_COM_PLL_CCTRL_MODE0 0x070
+#define QSERDES_V3_COM_PLL_CCTRL_MODE1 0x074
+#define QSERDES_V3_COM_SYSCLK_EN_SEL 0x080
+#define QSERDES_V3_COM_RESETSM_CNTRL 0x088
+#define QSERDES_V3_COM_RESETSM_CNTRL2 0x08c
+#define QSERDES_V3_COM_LOCK_CMP_EN 0x090
+#define QSERDES_V3_COM_LOCK_CMP_CFG 0x094
+#define QSERDES_V3_COM_DEC_START_MODE0 0x0b0
+#define QSERDES_V3_COM_DEC_START_MODE1 0x0b4
+#define QSERDES_V3_COM_DIV_FRAC_START1_MODE0 0x0b8
+#define QSERDES_V3_COM_DIV_FRAC_START2_MODE0 0x0bc
+#define QSERDES_V3_COM_DIV_FRAC_START3_MODE0 0x0c0
+#define QSERDES_V3_COM_DIV_FRAC_START1_MODE1 0x0c4
+#define QSERDES_V3_COM_DIV_FRAC_START2_MODE1 0x0c8
+#define QSERDES_V3_COM_DIV_FRAC_START3_MODE1 0x0cc
+#define QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0 0x0d8
+#define QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0 0x0dc
+#define QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1 0x0e0
+#define QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1 0x0e4
+#define QSERDES_V3_COM_VCO_TUNE_CTRL 0x0ec
+#define QSERDES_V3_COM_VCO_TUNE_MAP 0x0f0
+#define QSERDES_V3_COM_VCO_TUNE1_MODE0 0x0f4
+#define QSERDES_V3_COM_VCO_TUNE2_MODE0 0x0f8
+#define QSERDES_V3_COM_VCO_TUNE1_MODE1 0x0fc
+#define QSERDES_V3_COM_VCO_TUNE2_MODE1 0x100
+#define QSERDES_V3_COM_VCO_TUNE_TIMER1 0x11c
+#define QSERDES_V3_COM_VCO_TUNE_TIMER2 0x120
+#define QSERDES_V3_COM_CLK_SELECT 0x138
+#define QSERDES_V3_COM_HSCLK_SEL 0x13c
+#define QSERDES_V3_COM_CORECLK_DIV_MODE0 0x148
+#define QSERDES_V3_COM_CORECLK_DIV_MODE1 0x14c
+#define QSERDES_V3_COM_CORE_CLK_EN 0x154
+#define QSERDES_V3_COM_C_READY_STATUS 0x158
+#define QSERDES_V3_COM_CMN_CONFIG 0x15c
+#define QSERDES_V3_COM_SVS_MODE_CLK_SEL 0x164
+#define QSERDES_V3_COM_DEBUG_BUS0 0x168
+#define QSERDES_V3_COM_DEBUG_BUS1 0x16c
+#define QSERDES_V3_COM_DEBUG_BUS2 0x170
+#define QSERDES_V3_COM_DEBUG_BUS3 0x174
+#define QSERDES_V3_COM_DEBUG_BUS_SEL 0x178
+
+/* Only for QMP V3 PHY - TX registers */
+#define QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX 0x044
+#define QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX 0x048
+#define QSERDES_V3_TX_DEBUG_BUS_SEL 0x058
+#define QSERDES_V3_TX_HIGHZ_DRVR_EN 0x060
+#define QSERDES_V3_TX_LANE_MODE_1 0x08c
+#define QSERDES_V3_TX_RCV_DETECT_LVL_2 0x0a4
+
+/* Only for QMP V3 PHY - RX registers */
+#define QSERDES_V3_RX_UCDR_SO_GAIN_HALF 0x00c
+#define QSERDES_V3_RX_UCDR_SO_GAIN 0x014
+#define QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN 0x030
+#define QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034
+#define QSERDES_V3_RX_RX_TERM_BW 0x07c
+#define QSERDES_V3_RX_RX_EQ_GAIN2_LSB 0x0c8
+#define QSERDES_V3_RX_RX_EQ_GAIN2_MSB 0x0cc
+#define QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d4
+#define QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3 0x0d8
+#define QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4 0x0dc
+#define QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x0f8
+#define QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x0fc
+#define QSERDES_V3_RX_SIGDET_ENABLES 0x100
+#define QSERDES_V3_RX_SIGDET_CNTRL 0x104
+#define QSERDES_V3_RX_SIGDET_LVL 0x108
+#define QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL 0x10c
+#define QSERDES_V3_RX_RX_BAND 0x110
+#define QSERDES_V3_RX_RX_INTERFACE_MODE 0x11c
+
+/* Only for QMP V3 PHY - PCS registers */
+#define QPHY_V3_PCS_POWER_DOWN_CONTROL 0x004
+#define QPHY_V3_PCS_TXMGN_V0 0x00c
+#define QPHY_V3_PCS_TXMGN_V1 0x010
+#define QPHY_V3_PCS_TXMGN_V2 0x014
+#define QPHY_V3_PCS_TXMGN_V3 0x018
+#define QPHY_V3_PCS_TXMGN_V4 0x01c
+#define QPHY_V3_PCS_TXMGN_LS 0x020
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_V0 0x024
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0 0x028
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_V1 0x02c
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1 0x030
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_V2 0x034
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2 0x038
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_V3 0x03c
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3 0x040
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_V4 0x044
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4 0x048
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_LS 0x04c
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS 0x050
+#define QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE 0x054
+#define QPHY_V3_PCS_RX_IDLE_DTCT_CNTRL 0x058
+#define QPHY_V3_PCS_RATE_SLEW_CNTRL 0x05c
+#define QPHY_V3_PCS_POWER_STATE_CONFIG1 0x060
+#define QPHY_V3_PCS_POWER_STATE_CONFIG2 0x064
+#define QPHY_V3_PCS_POWER_STATE_CONFIG4 0x06c
+#define QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L 0x070
+#define QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H 0x074
+#define QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L 0x078
+#define QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H 0x07c
+#define QPHY_V3_PCS_LOCK_DETECT_CONFIG1 0x080
+#define QPHY_V3_PCS_LOCK_DETECT_CONFIG2 0x084
+#define QPHY_V3_PCS_LOCK_DETECT_CONFIG3 0x088
+#define QPHY_V3_PCS_TSYNC_RSYNC_TIME 0x08c
+#define QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK 0x0a0
+#define QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK 0x0a4
+#define QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK 0x0b0
+#define QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME 0x0b8
+#define QPHY_V3_PCS_RXEQTRAINING_RUN_TIME 0x0bc
+#define QPHY_V3_PCS_FLL_CNTRL1 0x0c4
+#define QPHY_V3_PCS_FLL_CNTRL2 0x0c8
+#define QPHY_V3_PCS_FLL_CNT_VAL_L 0x0cc
+#define QPHY_V3_PCS_FLL_CNT_VAL_H_TOL 0x0d0
+#define QPHY_V3_PCS_FLL_MAN_CODE 0x0d4
+#define QPHY_V3_PCS_RX_SIGDET_LVL 0x1d8
+
#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 11/17] phy: qcom-qmp: Add register offsets for QMP V3 PHY
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
open list:GENERIC PHY FRAMEWORK
Registers offsets for QMP V3 PHY are changed from
previous versions (1/2), update same in header file.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.h | 149 ++++++++++++++++++++++++++++++++++++
1 file changed, 149 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index d930ca7..f7d4c2a 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -134,4 +134,153 @@
#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1DC
#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1E0
+/* Only for QMP V3 PHY - DP COM registers */
+#define QPHY_V3_DP_COM_PHY_MODE_CTRL 0x00
+#define QPHY_V3_DP_COM_SW_RESET 0x04
+#define QPHY_V3_DP_COM_POWER_DOWN_CTRL 0x08
+#define QPHY_V3_DP_COM_SWI_CTRL 0x0c
+#define QPHY_V3_DP_COM_TYPEC_CTRL 0x10
+#define QPHY_V3_DP_COM_TYPEC_PWRDN_CTRL 0x14
+#define QPHY_V3_DP_COM_RESET_OVRD_CTRL 0x1c
+
+/* Only for QMP V3 PHY - QSERDES COM registers */
+#define QSERDES_V3_COM_BG_TIMER 0x00c
+#define QSERDES_V3_COM_SSC_EN_CENTER 0x010
+#define QSERDES_V3_COM_SSC_ADJ_PER1 0x014
+#define QSERDES_V3_COM_SSC_ADJ_PER2 0x018
+#define QSERDES_V3_COM_SSC_PER1 0x01c
+#define QSERDES_V3_COM_SSC_PER2 0x020
+#define QSERDES_V3_COM_SSC_STEP_SIZE1 0x024
+#define QSERDES_V3_COM_SSC_STEP_SIZE2 0x028
+#define QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN 0x034
+#define QSERDES_V3_COM_CLK_ENABLE1 0x038
+#define QSERDES_V3_COM_SYS_CLK_CTRL 0x03c
+#define QSERDES_V3_COM_SYSCLK_BUF_ENABLE 0x040
+#define QSERDES_V3_COM_PLL_IVCO 0x048
+#define QSERDES_V3_COM_LOCK_CMP1_MODE0 0x098
+#define QSERDES_V3_COM_LOCK_CMP2_MODE0 0x09c
+#define QSERDES_V3_COM_LOCK_CMP3_MODE0 0x0a0
+#define QSERDES_V3_COM_LOCK_CMP1_MODE1 0x0a4
+#define QSERDES_V3_COM_LOCK_CMP2_MODE1 0x0a8
+#define QSERDES_V3_COM_LOCK_CMP3_MODE1 0x0ac
+#define QSERDES_V3_COM_CLK_EP_DIV 0x05c
+#define QSERDES_V3_COM_CP_CTRL_MODE0 0x060
+#define QSERDES_V3_COM_CP_CTRL_MODE1 0x064
+#define QSERDES_V3_COM_PLL_RCTRL_MODE0 0x068
+#define QSERDES_V3_COM_PLL_RCTRL_MODE1 0x06c
+#define QSERDES_V3_COM_PLL_CCTRL_MODE0 0x070
+#define QSERDES_V3_COM_PLL_CCTRL_MODE1 0x074
+#define QSERDES_V3_COM_SYSCLK_EN_SEL 0x080
+#define QSERDES_V3_COM_RESETSM_CNTRL 0x088
+#define QSERDES_V3_COM_RESETSM_CNTRL2 0x08c
+#define QSERDES_V3_COM_LOCK_CMP_EN 0x090
+#define QSERDES_V3_COM_LOCK_CMP_CFG 0x094
+#define QSERDES_V3_COM_DEC_START_MODE0 0x0b0
+#define QSERDES_V3_COM_DEC_START_MODE1 0x0b4
+#define QSERDES_V3_COM_DIV_FRAC_START1_MODE0 0x0b8
+#define QSERDES_V3_COM_DIV_FRAC_START2_MODE0 0x0bc
+#define QSERDES_V3_COM_DIV_FRAC_START3_MODE0 0x0c0
+#define QSERDES_V3_COM_DIV_FRAC_START1_MODE1 0x0c4
+#define QSERDES_V3_COM_DIV_FRAC_START2_MODE1 0x0c8
+#define QSERDES_V3_COM_DIV_FRAC_START3_MODE1 0x0cc
+#define QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0 0x0d8
+#define QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0 0x0dc
+#define QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1 0x0e0
+#define QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1 0x0e4
+#define QSERDES_V3_COM_VCO_TUNE_CTRL 0x0ec
+#define QSERDES_V3_COM_VCO_TUNE_MAP 0x0f0
+#define QSERDES_V3_COM_VCO_TUNE1_MODE0 0x0f4
+#define QSERDES_V3_COM_VCO_TUNE2_MODE0 0x0f8
+#define QSERDES_V3_COM_VCO_TUNE1_MODE1 0x0fc
+#define QSERDES_V3_COM_VCO_TUNE2_MODE1 0x100
+#define QSERDES_V3_COM_VCO_TUNE_TIMER1 0x11c
+#define QSERDES_V3_COM_VCO_TUNE_TIMER2 0x120
+#define QSERDES_V3_COM_CLK_SELECT 0x138
+#define QSERDES_V3_COM_HSCLK_SEL 0x13c
+#define QSERDES_V3_COM_CORECLK_DIV_MODE0 0x148
+#define QSERDES_V3_COM_CORECLK_DIV_MODE1 0x14c
+#define QSERDES_V3_COM_CORE_CLK_EN 0x154
+#define QSERDES_V3_COM_C_READY_STATUS 0x158
+#define QSERDES_V3_COM_CMN_CONFIG 0x15c
+#define QSERDES_V3_COM_SVS_MODE_CLK_SEL 0x164
+#define QSERDES_V3_COM_DEBUG_BUS0 0x168
+#define QSERDES_V3_COM_DEBUG_BUS1 0x16c
+#define QSERDES_V3_COM_DEBUG_BUS2 0x170
+#define QSERDES_V3_COM_DEBUG_BUS3 0x174
+#define QSERDES_V3_COM_DEBUG_BUS_SEL 0x178
+
+/* Only for QMP V3 PHY - TX registers */
+#define QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX 0x044
+#define QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX 0x048
+#define QSERDES_V3_TX_DEBUG_BUS_SEL 0x058
+#define QSERDES_V3_TX_HIGHZ_DRVR_EN 0x060
+#define QSERDES_V3_TX_LANE_MODE_1 0x08c
+#define QSERDES_V3_TX_RCV_DETECT_LVL_2 0x0a4
+
+/* Only for QMP V3 PHY - RX registers */
+#define QSERDES_V3_RX_UCDR_SO_GAIN_HALF 0x00c
+#define QSERDES_V3_RX_UCDR_SO_GAIN 0x014
+#define QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN 0x030
+#define QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034
+#define QSERDES_V3_RX_RX_TERM_BW 0x07c
+#define QSERDES_V3_RX_RX_EQ_GAIN2_LSB 0x0c8
+#define QSERDES_V3_RX_RX_EQ_GAIN2_MSB 0x0cc
+#define QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2 0x0d4
+#define QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3 0x0d8
+#define QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4 0x0dc
+#define QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x0f8
+#define QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x0fc
+#define QSERDES_V3_RX_SIGDET_ENABLES 0x100
+#define QSERDES_V3_RX_SIGDET_CNTRL 0x104
+#define QSERDES_V3_RX_SIGDET_LVL 0x108
+#define QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL 0x10c
+#define QSERDES_V3_RX_RX_BAND 0x110
+#define QSERDES_V3_RX_RX_INTERFACE_MODE 0x11c
+
+/* Only for QMP V3 PHY - PCS registers */
+#define QPHY_V3_PCS_POWER_DOWN_CONTROL 0x004
+#define QPHY_V3_PCS_TXMGN_V0 0x00c
+#define QPHY_V3_PCS_TXMGN_V1 0x010
+#define QPHY_V3_PCS_TXMGN_V2 0x014
+#define QPHY_V3_PCS_TXMGN_V3 0x018
+#define QPHY_V3_PCS_TXMGN_V4 0x01c
+#define QPHY_V3_PCS_TXMGN_LS 0x020
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_V0 0x024
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0 0x028
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_V1 0x02c
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1 0x030
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_V2 0x034
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2 0x038
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_V3 0x03c
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3 0x040
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_V4 0x044
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4 0x048
+#define QPHY_V3_PCS_TXDEEMPH_M6DB_LS 0x04c
+#define QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS 0x050
+#define QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE 0x054
+#define QPHY_V3_PCS_RX_IDLE_DTCT_CNTRL 0x058
+#define QPHY_V3_PCS_RATE_SLEW_CNTRL 0x05c
+#define QPHY_V3_PCS_POWER_STATE_CONFIG1 0x060
+#define QPHY_V3_PCS_POWER_STATE_CONFIG2 0x064
+#define QPHY_V3_PCS_POWER_STATE_CONFIG4 0x06c
+#define QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L 0x070
+#define QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H 0x074
+#define QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L 0x078
+#define QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H 0x07c
+#define QPHY_V3_PCS_LOCK_DETECT_CONFIG1 0x080
+#define QPHY_V3_PCS_LOCK_DETECT_CONFIG2 0x084
+#define QPHY_V3_PCS_LOCK_DETECT_CONFIG3 0x088
+#define QPHY_V3_PCS_TSYNC_RSYNC_TIME 0x08c
+#define QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK 0x0a0
+#define QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK 0x0a4
+#define QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK 0x0b0
+#define QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME 0x0b8
+#define QPHY_V3_PCS_RXEQTRAINING_RUN_TIME 0x0bc
+#define QPHY_V3_PCS_FLL_CNTRL1 0x0c4
+#define QPHY_V3_PCS_FLL_CNTRL2 0x0c8
+#define QPHY_V3_PCS_FLL_CNT_VAL_L 0x0cc
+#define QPHY_V3_PCS_FLL_CNT_VAL_H_TOL 0x0d0
+#define QPHY_V3_PCS_FLL_MAN_CODE 0x0d4
+#define QPHY_V3_PCS_RX_SIGDET_LVL 0x1d8
+
#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 12/17] dt-bindings: phy-qcom-qmp: Update bindings for QMP V3 USB PHY
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam, Rob Herring,
Mark Rutland, Stephen Boyd, Vivek Gautam,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
Update compatible string and clock names for QMP version V3
USB PHY.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
index b6a9f2b..dcf1b8f 100644
--- a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
+++ b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
@@ -8,7 +8,8 @@ Required properties:
- compatible: compatible list, contains:
"qcom,ipq8074-qmp-pcie-phy" for PCIe phy on IPQ8074
"qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996,
- "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996.
+ "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996,
+ "qcom,qmp-v3-usb3-phy" for USB3 QMP V3 phy.
- reg: offset and length of register set for PHY's common serdes block.
@@ -25,10 +26,13 @@ Required properties:
- clock-names: "cfg_ahb" for phy config clock,
"aux" for phy aux clock,
"ref" for 19.2 MHz ref clk,
+ "com_aux" for phy common block aux clock,
For "qcom,msm8996-qmp-pcie-phy" must contain:
"aux", "cfg_ahb", "ref".
For "qcom,msm8996-qmp-usb3-phy" must contain:
"aux", "cfg_ahb", "ref".
+ For "qcom,qmp-v3-usb3-phy" must contain:
+ "aux", "cfg_ahb", "ref", "com_aux".
- resets: a list of phandles and reset controller specifier pairs,
one for each entry in reset-names.
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 12/17] dt-bindings: phy-qcom-qmp: Update bindings for QMP V3 USB PHY
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam, Rob Herring,
Mark Rutland, Stephen Boyd, Vivek Gautam,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
Update compatible string and clock names for QMP version V3
USB PHY.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
index b6a9f2b..dcf1b8f 100644
--- a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
+++ b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
@@ -8,7 +8,8 @@ Required properties:
- compatible: compatible list, contains:
"qcom,ipq8074-qmp-pcie-phy" for PCIe phy on IPQ8074
"qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996,
- "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996.
+ "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996,
+ "qcom,qmp-v3-usb3-phy" for USB3 QMP V3 phy.
- reg: offset and length of register set for PHY's common serdes block.
@@ -25,10 +26,13 @@ Required properties:
- clock-names: "cfg_ahb" for phy config clock,
"aux" for phy aux clock,
"ref" for 19.2 MHz ref clk,
+ "com_aux" for phy common block aux clock,
For "qcom,msm8996-qmp-pcie-phy" must contain:
"aux", "cfg_ahb", "ref".
For "qcom,msm8996-qmp-usb3-phy" must contain:
"aux", "cfg_ahb", "ref".
+ For "qcom,qmp-v3-usb3-phy" must contain:
+ "aux", "cfg_ahb", "ref", "com_aux".
- resets: a list of phandles and reset controller specifier pairs,
one for each entry in reset-names.
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 13/17] phy: qcom-qmp: Add support for QMP V3 USB3 PHY
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Viresh Kumar, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
QMP V3 USB3 PHY is a DP USB combo PHY with
dual RX/TX lanes to support type-c. There is a
separate block DP_COM for configuration related
to type-c or DP. Add support for dp_com region
and secondary rx/tx lanes initialization.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 222 +++++++++++++++++++++++++++++++++++-
1 file changed, 219 insertions(+), 3 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 15a734f..d4e1436 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -47,6 +47,21 @@
/* QPHY_COM_PCS_READY_STATUS bit */
#define PCS_READY BIT(0)
+/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
+/* DP PHY soft reset */
+#define SW_DPPHY_RESET BIT(0)
+/* mux to select DP PHY reset control, 0:HW control, 1: software reset */
+#define SW_DPPHY_RESET_MUX BIT(1)
+/* USB3 PHY soft reset */
+#define SW_USB3PHY_RESET BIT(2)
+/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */
+#define SW_USB3PHY_RESET_MUX BIT(3)
+
+/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */
+#define USB3_MODE BIT(0) /* enables USB3 mode */
+#define DP_MODE BIT(1) /* enables DP mode */
+
+
#define PHY_INIT_COMPLETE_TIMEOUT 1000
#define POWER_DOWN_DELAY_US_MIN 10
#define POWER_DOWN_DELAY_US_MAX 11
@@ -122,6 +137,12 @@ enum qphy_reg_layout {
[QPHY_PCS_READY_STATUS] = 0x17c,
};
+static const unsigned int qmp_v3_usb3phy_regs_layout[] = {
+ [QPHY_SW_RESET] = 0x00,
+ [QPHY_START_CTRL] = 0x08,
+ [QPHY_PCS_READY_STATUS] = 0x174,
+};
+
static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
@@ -350,6 +371,112 @@ enum qphy_reg_layout {
QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3),
};
+static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07),
+};
+
+static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06),
+};
+
+static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
+};
+
+static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = {
+ /* FLL settings */
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
+
+ /* Lock Det settings */
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b),
+
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d),
+
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
+};
+
/* struct qmp_phy_cfg - per-PHY initialization config */
struct qmp_phy_cfg {
/* phy-type - PCIE/UFS/USB */
@@ -394,6 +521,12 @@ struct qmp_phy_cfg {
/* power_down delay in usec */
int pwrdn_delay_min;
int pwrdn_delay_max;
+
+ /* true, if PHY has a separate DP_COM control block */
+ bool has_phy_dp_com_ctrl;
+ /* Register offset of secondary tx/rx lanes for USB DP combo PHY */
+ unsigned int tx_b_lane_offset;
+ unsigned int rx_b_lane_offset;
};
/**
@@ -424,6 +557,7 @@ struct qmp_phy {
*
* @dev: device
* @serdes: iomapped memory space for phy's serdes
+ * @dp_com: iomapped memory space for phy's dp_com control block
*
* @clks: array of clocks required by phy
* @resets: array of resets required by phy
@@ -437,6 +571,7 @@ struct qmp_phy {
struct qcom_qmp {
struct device *dev;
void __iomem *serdes;
+ void __iomem *dp_com;
struct clk_bulk_data *clks;
struct reset_control **resets;
@@ -478,6 +613,10 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
"aux", "cfg_ahb", "ref",
};
+static const char * const qmp_v3_phy_clk_l[] = {
+ "aux", "cfg_ahb", "ref", "com_aux",
+};
+
/* list of resets */
static const char * const msm8996_pciephy_reset_l[] = {
"phy", "common", "cfg",
@@ -584,6 +723,38 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
.pwrdn_delay_max = 1005, /* us */
};
+static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
+ .type = PHY_TYPE_USB3,
+ .nlanes = 1,
+
+ .serdes_tbl = qmp_v3_usb3_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl),
+ .tx_tbl = qmp_v3_usb3_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl),
+ .rx_tbl = qmp_v3_usb3_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl),
+ .pcs_tbl = qmp_v3_usb3_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl),
+ .clk_list = qmp_v3_phy_clk_l,
+ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l),
+ .reset_list = msm8996_usb3phy_reset_l,
+ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
+ .vreg_list = msm8996_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(msm8996_phy_vreg_l),
+ .regs = qmp_v3_usb3phy_regs_layout,
+
+ .start_ctrl = SERDES_START | PCS_START,
+ .pwrdn_ctrl = SW_PWRDN,
+ .mask_pcs_ready = PHYSTATUS,
+
+ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
+ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
+
+ .has_phy_dp_com_ctrl = true,
+ .tx_b_lane_offset = 0x400,
+ .rx_b_lane_offset = 0x400,
+};
+
static void qcom_qmp_phy_configure(void __iomem *base,
const unsigned int *regs,
const struct qmp_phy_init_tbl tbl[],
@@ -650,6 +821,23 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
SW_PWRDN);
+ if (cfg->has_phy_dp_com_ctrl) {
+ qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL,
+ SW_PWRDN);
+ /* override hardware control for reset of qmp phy */
+ qphy_setbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
+ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
+ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
+
+ qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL,
+ USB3_MODE | DP_MODE);
+
+ /* bring both QMP USB and QMP DP PHYs PCS block out of reset */
+ qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
+ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
+ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
+ }
+
/* Serdes configuration */
qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl,
cfg->serdes_tbl_num);
@@ -732,6 +920,7 @@ static int qcom_qmp_phy_init(struct phy *phy)
void __iomem *tx = qphy->tx;
void __iomem *rx = qphy->rx;
void __iomem *pcs = qphy->pcs;
+ void __iomem *dp_com = qmp->dp_com;
void __iomem *status;
unsigned int mask, val;
int ret;
@@ -753,7 +942,16 @@ static int qcom_qmp_phy_init(struct phy *phy)
/* Tx, Rx, and PCS configurations */
qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num);
+ /* Configuration for other LANE for USB-DP combo PHY */
+ if (cfg->has_phy_dp_com_ctrl)
+ qcom_qmp_phy_configure(tx + cfg->tx_b_lane_offset, cfg->regs,
+ cfg->tx_tbl, cfg->tx_tbl_num);
+
qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num);
+ if (cfg->has_phy_dp_com_ctrl)
+ qcom_qmp_phy_configure(rx + cfg->rx_b_lane_offset, cfg->regs,
+ cfg->rx_tbl, cfg->rx_tbl_num);
+
qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
/*
@@ -767,6 +965,8 @@ static int qcom_qmp_phy_init(struct phy *phy)
/* Pull PHY out of reset state */
qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
+ if (cfg->has_phy_dp_com_ctrl)
+ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET);
/* start SerDes and Phy-Coding-Sublayer */
qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
@@ -1023,6 +1223,9 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
}, {
.compatible = "qcom,ipq8074-qmp-pcie-phy",
.data = &ipq8074_pciephy_cfg,
+ }, {
+ .compatible = "qcom,qmp-v3-usb3-phy",
+ .data = &qmp_v3_usb3phy_cfg,
},
{ },
};
@@ -1046,6 +1249,11 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
qmp->dev = dev;
dev_set_drvdata(dev, qmp);
+ /* Get the specific init parameters of QMP phy */
+ qmp->cfg = of_device_get_match_data(dev);
+ if (!qmp->cfg)
+ return -EINVAL;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
@@ -1054,10 +1262,18 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
/* per PHY serdes; usually located at base address */
qmp->serdes = base;
- mutex_init(&qmp->phy_mutex);
+ /* per PHY dp_com; if PHY has dp_com control block */
+ if (qmp->cfg->has_phy_dp_com_ctrl) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "dp_com");
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
- /* Get the specific init parameters of QMP phy */
- qmp->cfg = of_device_get_match_data(dev);
+ qmp->dp_com = base;
+ }
+
+ mutex_init(&qmp->phy_mutex);
ret = qcom_qmp_phy_clk_init(dev);
if (ret)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 13/17] phy: qcom-qmp: Add support for QMP V3 USB3 PHY
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Viresh Kumar, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
QMP V3 USB3 PHY is a DP USB combo PHY with
dual RX/TX lanes to support type-c. There is a
separate block DP_COM for configuration related
to type-c or DP. Add support for dp_com region
and secondary rx/tx lanes initialization.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 222 +++++++++++++++++++++++++++++++++++-
1 file changed, 219 insertions(+), 3 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 15a734f..d4e1436 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -47,6 +47,21 @@
/* QPHY_COM_PCS_READY_STATUS bit */
#define PCS_READY BIT(0)
+/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
+/* DP PHY soft reset */
+#define SW_DPPHY_RESET BIT(0)
+/* mux to select DP PHY reset control, 0:HW control, 1: software reset */
+#define SW_DPPHY_RESET_MUX BIT(1)
+/* USB3 PHY soft reset */
+#define SW_USB3PHY_RESET BIT(2)
+/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */
+#define SW_USB3PHY_RESET_MUX BIT(3)
+
+/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */
+#define USB3_MODE BIT(0) /* enables USB3 mode */
+#define DP_MODE BIT(1) /* enables DP mode */
+
+
#define PHY_INIT_COMPLETE_TIMEOUT 1000
#define POWER_DOWN_DELAY_US_MIN 10
#define POWER_DOWN_DELAY_US_MAX 11
@@ -122,6 +137,12 @@ enum qphy_reg_layout {
[QPHY_PCS_READY_STATUS] = 0x17c,
};
+static const unsigned int qmp_v3_usb3phy_regs_layout[] = {
+ [QPHY_SW_RESET] = 0x00,
+ [QPHY_START_CTRL] = 0x08,
+ [QPHY_PCS_READY_STATUS] = 0x174,
+};
+
static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c),
QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
@@ -350,6 +371,112 @@ enum qphy_reg_layout {
QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3),
};
+static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85),
+ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07),
+};
+
+static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x09),
+ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06),
+};
+
+static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16),
+ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
+};
+
+static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = {
+ /* FLL settings */
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
+
+ /* Lock Det settings */
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b),
+
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d),
+
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
+};
+
/* struct qmp_phy_cfg - per-PHY initialization config */
struct qmp_phy_cfg {
/* phy-type - PCIE/UFS/USB */
@@ -394,6 +521,12 @@ struct qmp_phy_cfg {
/* power_down delay in usec */
int pwrdn_delay_min;
int pwrdn_delay_max;
+
+ /* true, if PHY has a separate DP_COM control block */
+ bool has_phy_dp_com_ctrl;
+ /* Register offset of secondary tx/rx lanes for USB DP combo PHY */
+ unsigned int tx_b_lane_offset;
+ unsigned int rx_b_lane_offset;
};
/**
@@ -424,6 +557,7 @@ struct qmp_phy {
*
* @dev: device
* @serdes: iomapped memory space for phy's serdes
+ * @dp_com: iomapped memory space for phy's dp_com control block
*
* @clks: array of clocks required by phy
* @resets: array of resets required by phy
@@ -437,6 +571,7 @@ struct qmp_phy {
struct qcom_qmp {
struct device *dev;
void __iomem *serdes;
+ void __iomem *dp_com;
struct clk_bulk_data *clks;
struct reset_control **resets;
@@ -478,6 +613,10 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
"aux", "cfg_ahb", "ref",
};
+static const char * const qmp_v3_phy_clk_l[] = {
+ "aux", "cfg_ahb", "ref", "com_aux",
+};
+
/* list of resets */
static const char * const msm8996_pciephy_reset_l[] = {
"phy", "common", "cfg",
@@ -584,6 +723,38 @@ static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
.pwrdn_delay_max = 1005, /* us */
};
+static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = {
+ .type = PHY_TYPE_USB3,
+ .nlanes = 1,
+
+ .serdes_tbl = qmp_v3_usb3_serdes_tbl,
+ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl),
+ .tx_tbl = qmp_v3_usb3_tx_tbl,
+ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl),
+ .rx_tbl = qmp_v3_usb3_rx_tbl,
+ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl),
+ .pcs_tbl = qmp_v3_usb3_pcs_tbl,
+ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl),
+ .clk_list = qmp_v3_phy_clk_l,
+ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l),
+ .reset_list = msm8996_usb3phy_reset_l,
+ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l),
+ .vreg_list = msm8996_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(msm8996_phy_vreg_l),
+ .regs = qmp_v3_usb3phy_regs_layout,
+
+ .start_ctrl = SERDES_START | PCS_START,
+ .pwrdn_ctrl = SW_PWRDN,
+ .mask_pcs_ready = PHYSTATUS,
+
+ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN,
+ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX,
+
+ .has_phy_dp_com_ctrl = true,
+ .tx_b_lane_offset = 0x400,
+ .rx_b_lane_offset = 0x400,
+};
+
static void qcom_qmp_phy_configure(void __iomem *base,
const unsigned int *regs,
const struct qmp_phy_init_tbl tbl[],
@@ -650,6 +821,23 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL],
SW_PWRDN);
+ if (cfg->has_phy_dp_com_ctrl) {
+ qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL,
+ SW_PWRDN);
+ /* override hardware control for reset of qmp phy */
+ qphy_setbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
+ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
+ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
+
+ qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL,
+ USB3_MODE | DP_MODE);
+
+ /* bring both QMP USB and QMP DP PHYs PCS block out of reset */
+ qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
+ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
+ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET);
+ }
+
/* Serdes configuration */
qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl,
cfg->serdes_tbl_num);
@@ -732,6 +920,7 @@ static int qcom_qmp_phy_init(struct phy *phy)
void __iomem *tx = qphy->tx;
void __iomem *rx = qphy->rx;
void __iomem *pcs = qphy->pcs;
+ void __iomem *dp_com = qmp->dp_com;
void __iomem *status;
unsigned int mask, val;
int ret;
@@ -753,7 +942,16 @@ static int qcom_qmp_phy_init(struct phy *phy)
/* Tx, Rx, and PCS configurations */
qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num);
+ /* Configuration for other LANE for USB-DP combo PHY */
+ if (cfg->has_phy_dp_com_ctrl)
+ qcom_qmp_phy_configure(tx + cfg->tx_b_lane_offset, cfg->regs,
+ cfg->tx_tbl, cfg->tx_tbl_num);
+
qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num);
+ if (cfg->has_phy_dp_com_ctrl)
+ qcom_qmp_phy_configure(rx + cfg->rx_b_lane_offset, cfg->regs,
+ cfg->rx_tbl, cfg->rx_tbl_num);
+
qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
/*
@@ -767,6 +965,8 @@ static int qcom_qmp_phy_init(struct phy *phy)
/* Pull PHY out of reset state */
qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
+ if (cfg->has_phy_dp_com_ctrl)
+ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET);
/* start SerDes and Phy-Coding-Sublayer */
qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl);
@@ -1023,6 +1223,9 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
}, {
.compatible = "qcom,ipq8074-qmp-pcie-phy",
.data = &ipq8074_pciephy_cfg,
+ }, {
+ .compatible = "qcom,qmp-v3-usb3-phy",
+ .data = &qmp_v3_usb3phy_cfg,
},
{ },
};
@@ -1046,6 +1249,11 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
qmp->dev = dev;
dev_set_drvdata(dev, qmp);
+ /* Get the specific init parameters of QMP phy */
+ qmp->cfg = of_device_get_match_data(dev);
+ if (!qmp->cfg)
+ return -EINVAL;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
@@ -1054,10 +1262,18 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
/* per PHY serdes; usually located at base address */
qmp->serdes = base;
- mutex_init(&qmp->phy_mutex);
+ /* per PHY dp_com; if PHY has dp_com control block */
+ if (qmp->cfg->has_phy_dp_com_ctrl) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "dp_com");
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
- /* Get the specific init parameters of QMP phy */
- qmp->cfg = of_device_get_match_data(dev);
+ qmp->dp_com = base;
+ }
+
+ mutex_init(&qmp->phy_mutex);
ret = qcom_qmp_phy_clk_init(dev);
if (ret)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Viresh Kumar, Krzysztof Kozlowski,
open list:GENERIC PHY FRAMEWORK
VBUS signal coming from PHY must be asserted in device for
controller to start operation or assert pull-up. For some
platforms where VBUS line is not connected to PHY there is
HS_PHY_CTRL register in QSCRATCH wrapper that can be used
by software to override VBUS signal going to controller.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 39 +++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index bda1f4c..0e9d88b 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -68,6 +68,11 @@
#define QUSB2PHY_IMP_CTRL2 0x224
#define QUSB2PHY_CHG_CTRL2 0x23c
+/* QSCRATCH register bits */
+#define QSCRATCH_HS_PHY_CTRL 0x10
+#define UTMI_OTG_VBUS_VALID BIT(20)
+#define SW_SESSVLD_SEL BIT(28)
+
struct qusb2_phy_init_tbl {
unsigned int offset;
unsigned int val;
@@ -211,6 +216,7 @@ struct qusb2_phy_cfg {
*
* @phy: generic phy
* @base: iomapped memory space for qubs2 phy
+ * @qscratch_base: iomapped memory space for qscratch region
*
* @cfg_ahb_clk: AHB2PHY interface clock
* @ref_clk: phy reference clock
@@ -223,10 +229,12 @@ struct qusb2_phy_cfg {
*
* @cfg: phy config data
* @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme
+ * @mode: indicate current PHY mode of operation e.g. HOST or DEVICE
*/
struct qusb2_phy {
struct phy *phy;
void __iomem *base;
+ void __iomem *qscratch_base;
struct clk *cfg_ahb_clk;
struct clk *ref_clk;
@@ -239,6 +247,7 @@ struct qusb2_phy {
const struct qusb2_phy_cfg *cfg;
bool has_se_clk_scheme;
+ enum phy_mode mode;
};
static inline void qusb2_setbits(void __iomem *base, u32 offset, u32 val)
@@ -307,6 +316,25 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
qusb2_setbits(qphy->base, QUSB2PHY_PORT_TUNE2, val[0] << 0x4);
}
+static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
+{
+ struct qusb2_phy *qphy = phy_get_drvdata(phy);
+
+ qphy->mode = mode;
+
+ /* Update VBUS override in qscratch register */
+ if (qphy->qscratch_base) {
+ if (mode == PHY_MODE_USB_DEVICE)
+ qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
+ UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
+ else
+ qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
+ UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
+ }
+
+ return 0;
+}
+
static int qusb2_phy_init(struct phy *phy)
{
struct qusb2_phy *qphy = phy_get_drvdata(phy);
@@ -473,6 +501,7 @@ static int qusb2_phy_exit(struct phy *phy)
static const struct phy_ops qusb2_phy_gen_ops = {
.init = qusb2_phy_init,
.exit = qusb2_phy_exit,
+ .set_mode = qusb2_phy_set_mode,
.owner = THIS_MODULE,
};
@@ -507,6 +536,16 @@ static int qusb2_phy_probe(struct platform_device *pdev)
if (IS_ERR(qphy->base))
return PTR_ERR(qphy->base);
+ /* Check if platform uses qscratch wrapper */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qscratch");
+ if (res) {
+ /* Can't request region as used by other phy and glue drivers */
+ qphy->qscratch_base = devm_ioremap(dev, res->start,
+ resource_size(res));
+ if (IS_ERR(qphy->qscratch_base))
+ return PTR_ERR(qphy->qscratch_base);
+ }
+
qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb");
if (IS_ERR(qphy->cfg_ahb_clk)) {
ret = PTR_ERR(qphy->cfg_ahb_clk);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Viresh Kumar, Krzysztof Kozlowski,
open list:GENERIC PHY FRAMEWORK
VBUS signal coming from PHY must be asserted in device for
controller to start operation or assert pull-up. For some
platforms where VBUS line is not connected to PHY there is
HS_PHY_CTRL register in QSCRATCH wrapper that can be used
by software to override VBUS signal going to controller.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 39 +++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index bda1f4c..0e9d88b 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -68,6 +68,11 @@
#define QUSB2PHY_IMP_CTRL2 0x224
#define QUSB2PHY_CHG_CTRL2 0x23c
+/* QSCRATCH register bits */
+#define QSCRATCH_HS_PHY_CTRL 0x10
+#define UTMI_OTG_VBUS_VALID BIT(20)
+#define SW_SESSVLD_SEL BIT(28)
+
struct qusb2_phy_init_tbl {
unsigned int offset;
unsigned int val;
@@ -211,6 +216,7 @@ struct qusb2_phy_cfg {
*
* @phy: generic phy
* @base: iomapped memory space for qubs2 phy
+ * @qscratch_base: iomapped memory space for qscratch region
*
* @cfg_ahb_clk: AHB2PHY interface clock
* @ref_clk: phy reference clock
@@ -223,10 +229,12 @@ struct qusb2_phy_cfg {
*
* @cfg: phy config data
* @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme
+ * @mode: indicate current PHY mode of operation e.g. HOST or DEVICE
*/
struct qusb2_phy {
struct phy *phy;
void __iomem *base;
+ void __iomem *qscratch_base;
struct clk *cfg_ahb_clk;
struct clk *ref_clk;
@@ -239,6 +247,7 @@ struct qusb2_phy {
const struct qusb2_phy_cfg *cfg;
bool has_se_clk_scheme;
+ enum phy_mode mode;
};
static inline void qusb2_setbits(void __iomem *base, u32 offset, u32 val)
@@ -307,6 +316,25 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
qusb2_setbits(qphy->base, QUSB2PHY_PORT_TUNE2, val[0] << 0x4);
}
+static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
+{
+ struct qusb2_phy *qphy = phy_get_drvdata(phy);
+
+ qphy->mode = mode;
+
+ /* Update VBUS override in qscratch register */
+ if (qphy->qscratch_base) {
+ if (mode == PHY_MODE_USB_DEVICE)
+ qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
+ UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
+ else
+ qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
+ UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
+ }
+
+ return 0;
+}
+
static int qusb2_phy_init(struct phy *phy)
{
struct qusb2_phy *qphy = phy_get_drvdata(phy);
@@ -473,6 +501,7 @@ static int qusb2_phy_exit(struct phy *phy)
static const struct phy_ops qusb2_phy_gen_ops = {
.init = qusb2_phy_init,
.exit = qusb2_phy_exit,
+ .set_mode = qusb2_phy_set_mode,
.owner = THIS_MODULE,
};
@@ -507,6 +536,16 @@ static int qusb2_phy_probe(struct platform_device *pdev)
if (IS_ERR(qphy->base))
return PTR_ERR(qphy->base);
+ /* Check if platform uses qscratch wrapper */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qscratch");
+ if (res) {
+ /* Can't request region as used by other phy and glue drivers */
+ qphy->qscratch_base = devm_ioremap(dev, res->start,
+ resource_size(res));
+ if (IS_ERR(qphy->qscratch_base))
+ return PTR_ERR(qphy->qscratch_base);
+ }
+
qphy->cfg_ahb_clk = devm_clk_get(dev, "cfg_ahb");
if (IS_ERR(qphy->cfg_ahb_clk)) {
ret = PTR_ERR(qphy->cfg_ahb_clk);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 15/17] phy: qcom-qusb2: Add support for runtime PM
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Yoshihiro Shimoda, Viresh Kumar,
open list:GENERIC PHY FRAMEWORK
Disable clocks and dp/dm asynchronous interrupts from
PHY as part of runtime suspend.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 159 ++++++++++++++++++++++++++++++++++
1 file changed, 159 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 0e9d88b..7414272 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -56,6 +56,18 @@
#define PHY_CLK_SCHEME_SEL BIT(0)
+/* QUSB2PHY_INTR_CTRL register bits */
+#define DMSE_INTR_HIGH_SEL BIT(4)
+#define DPSE_INTR_HIGH_SEL BIT(3)
+#define CHG_DET_INTR_EN BIT(2)
+#define DMSE_INTR_EN BIT(1)
+#define DPSE_INTR_EN BIT(0)
+
+/* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE register bits */
+#define CORE_PLL_EN_FROM_RESET BIT(4)
+#define CORE_RESET BIT(5)
+#define CORE_RESET_MUX BIT(6)
+
#define QUSB2PHY_PLL_ANALOG_CONTROLS_TWO 0x04
#define QUSB2PHY_PLL_CLOCK_INVERTERS 0x18c
#define QUSB2PHY_PLL_CMODE 0x2c
@@ -73,6 +85,10 @@
#define UTMI_OTG_VBUS_VALID BIT(20)
#define SW_SESSVLD_SEL BIT(28)
+#define QSCRATCH_CHARGING_DET_OUTPUT 0x1C
+#define LINESTATE_DP BIT(8)
+#define LINESTATE_DM BIT(9)
+
struct qusb2_phy_init_tbl {
unsigned int offset;
unsigned int val;
@@ -98,6 +114,7 @@ struct qusb2_phy_init_tbl {
/* set of registers with offsets different per-PHY */
enum qusb2phy_reg_layout {
+ QUSB2PHY_PLL_CORE_INPUT_OVERRIDE,
QUSB2PHY_PLL_STATUS,
QUSB2PHY_PORT_TUNE1,
QUSB2PHY_PORT_TUNE2,
@@ -117,8 +134,10 @@ enum qusb2phy_reg_layout {
[QUSB2PHY_PORT_TUNE3] = 0x88,
[QUSB2PHY_PORT_TUNE4] = 0x8c,
[QUSB2PHY_PORT_TUNE5] = 0x90,
+ [QUSB2PHY_PORT_TEST1] = 0xb8,
[QUSB2PHY_PORT_TEST2] = 0x9c,
[QUSB2PHY_PORT_POWERDOWN] = 0xb4,
+ [QUSB2PHY_INTR_CTRL] = 0xbc,
};
static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = {
@@ -138,14 +157,17 @@ enum qusb2phy_reg_layout {
};
static const unsigned int qusb2_v2_regs_layout[] = {
+ [QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8,
[QUSB2PHY_PLL_STATUS] = 0x1a0,
[QUSB2PHY_PORT_TUNE1] = 0x240,
[QUSB2PHY_PORT_TUNE2] = 0x244,
[QUSB2PHY_PORT_TUNE3] = 0x248,
[QUSB2PHY_PORT_TUNE4] = 0x24c,
[QUSB2PHY_PORT_TUNE5] = 0x250,
+ [QUSB2PHY_PORT_TEST1] = 0x254,
[QUSB2PHY_PORT_TEST2] = 0x258,
[QUSB2PHY_PORT_POWERDOWN] = 0x210,
+ [QUSB2PHY_INTR_CTRL] = 0x230,
};
static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = {
@@ -180,9 +202,13 @@ struct qusb2_phy_cfg {
const unsigned int *regs;
unsigned int mask_core_ready;
unsigned int disable_ctrl;
+ unsigned int autoresume_en;
/* true if PHY has PLL_TEST register to select clk_scheme */
bool has_pll_test;
+
+ /* true if PHY has PLL_CORE_INPUT_OVERRIDE register to reset PLL */
+ bool has_pll_override;
};
static const struct qusb2_phy_cfg msm8996_phy_cfg = {
@@ -193,6 +219,7 @@ struct qusb2_phy_cfg {
.has_pll_test = true,
.disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN),
.mask_core_ready = PLL_LOCKED,
+ .autoresume_en = BIT(3),
};
static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = {
@@ -203,6 +230,8 @@ struct qusb2_phy_cfg {
.disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN |
POWER_DOWN),
.mask_core_ready = CORE_READY_STATUS,
+ .has_pll_override = true,
+ .autoresume_en = BIT(0),
};
static const char * const qusb2_phy_vreg_names[] = {
@@ -229,6 +258,7 @@ struct qusb2_phy_cfg {
*
* @cfg: phy config data
* @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme
+ * @phy_initialized: indicate if PHY has been initialized
* @mode: indicate current PHY mode of operation e.g. HOST or DEVICE
*/
struct qusb2_phy {
@@ -247,6 +277,7 @@ struct qusb2_phy {
const struct qusb2_phy_cfg *cfg;
bool has_se_clk_scheme;
+ bool phy_initialized;
enum phy_mode mode;
};
@@ -335,6 +366,115 @@ static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
return 0;
}
+static int __maybe_unused qusb2_phy_runtime_suspend(struct device *dev)
+{
+ struct qusb2_phy *qphy = dev_get_drvdata(dev);
+ const struct qusb2_phy_cfg *cfg = qphy->cfg;
+ u32 linestate = 0, intr_mask;
+
+ dev_vdbg(dev, "Suspending QUSB2 Phy, mode:%d\n", qphy->mode);
+
+ if (!qphy->phy_initialized) {
+ dev_vdbg(dev, "PHY not initialized, bailing out\n");
+ return 0;
+ }
+
+ /*
+ * Enable DP/DM interrupts to detect line state changes based on current
+ * state. In other words, enable the triggers _opposite_ of what the
+ * current D+/D- levels are e.g. if currently D+ high, D- low
+ * (HS 'J'/Suspend), configure the mask to trigger on D+ low OR D- high
+ */
+ if (qphy->qscratch_base) {
+ linestate = readl(qphy->qscratch_base +
+ QSCRATCH_CHARGING_DET_OUTPUT);
+ intr_mask = DPSE_INTR_EN | DMSE_INTR_EN;
+ if (!(linestate & LINESTATE_DP)) /* D+ low */
+ intr_mask |= DPSE_INTR_HIGH_SEL;
+ if (!(linestate & LINESTATE_DM)) /* D- low */
+ intr_mask |= DMSE_INTR_HIGH_SEL;
+
+ writel(intr_mask, qphy->base + cfg->regs[QUSB2PHY_INTR_CTRL]);
+ }
+
+ /* hold core PLL into reset */
+ if (cfg->has_pll_override) {
+ qusb2_setbits(qphy->base,
+ cfg->regs[QUSB2PHY_PLL_CORE_INPUT_OVERRIDE],
+ CORE_PLL_EN_FROM_RESET | CORE_RESET |
+ CORE_RESET_MUX);
+ }
+
+ /* enable phy auto-resume */
+ if (linestate & (LINESTATE_DP | LINESTATE_DM)) {
+ qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TEST1],
+ cfg->autoresume_en);
+ /* Autoresume bit has to be toggled in order to enable it */
+ qusb2_clrbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TEST1],
+ cfg->autoresume_en);
+ }
+
+ if (!qphy->has_se_clk_scheme)
+ clk_disable_unprepare(qphy->ref_clk);
+
+ clk_disable_unprepare(qphy->cfg_ahb_clk);
+ clk_disable_unprepare(qphy->iface_clk);
+
+ return 0;
+}
+
+static int __maybe_unused qusb2_phy_runtime_resume(struct device *dev)
+{
+ struct qusb2_phy *qphy = dev_get_drvdata(dev);
+ const struct qusb2_phy_cfg *cfg = qphy->cfg;
+ int ret;
+
+ dev_vdbg(dev, "Resuming QUSB2 phy, mode:%d\n", qphy->mode);
+
+ if (!qphy->phy_initialized) {
+ dev_vdbg(dev, "PHY not initialized, bailing out\n");
+ return 0;
+ }
+
+ ret = clk_prepare_enable(qphy->iface_clk);
+ if (ret) {
+ dev_err(dev, "failed to enable iface_clk, %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(qphy->cfg_ahb_clk);
+ if (ret) {
+ dev_err(dev, "failed to enable cfg ahb clock, %d\n", ret);
+ goto disable_iface_clk;
+ }
+
+ if (!qphy->has_se_clk_scheme) {
+ clk_prepare_enable(qphy->ref_clk);
+ if (ret) {
+ dev_err(dev, "failed to enable ref clk, %d\n", ret);
+ goto disable_ahb_clk;
+ }
+ }
+
+ writel(0x0, qphy->base + cfg->regs[QUSB2PHY_INTR_CTRL]);
+
+ /* bring core PLL out of reset */
+ if (cfg->has_pll_override) {
+ qusb2_clrbits(qphy->base,
+ cfg->regs[QUSB2PHY_PLL_CORE_INPUT_OVERRIDE],
+ CORE_RESET | CORE_RESET_MUX);
+ }
+
+ return 0;
+
+disable_ahb_clk:
+ clk_disable_unprepare(qphy->cfg_ahb_clk);
+disable_iface_clk:
+ clk_disable_unprepare(qphy->iface_clk);
+
+ return ret;
+}
+
static int qusb2_phy_init(struct phy *phy)
{
struct qusb2_phy *qphy = phy_get_drvdata(phy);
@@ -459,6 +599,7 @@ static int qusb2_phy_init(struct phy *phy)
ret = -EBUSY;
goto disable_ref_clk;
}
+ qphy->phy_initialized = true;
return 0;
@@ -495,6 +636,8 @@ static int qusb2_phy_exit(struct phy *phy)
regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
+ qphy->phy_initialized = false;
+
return 0;
}
@@ -517,6 +660,11 @@ static int qusb2_phy_exit(struct phy *phy)
};
MODULE_DEVICE_TABLE(of, qusb2_phy_of_match_table);
+static const struct dev_pm_ops qusb2_phy_pm_ops = {
+ SET_RUNTIME_PM_OPS(qusb2_phy_runtime_suspend,
+ qusb2_phy_runtime_resume, NULL)
+};
+
static int qusb2_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -604,11 +752,19 @@ static int qusb2_phy_probe(struct platform_device *pdev)
qphy->cell = NULL;
dev_dbg(dev, "failed to lookup tune2 hstx trim value\n");
}
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ /*
+ * Prevent runtime pm from being ON by default. Users can enable
+ * it using power/control in sysfs.
+ */
+ pm_runtime_forbid(dev);
generic_phy = devm_phy_create(dev, NULL, &qusb2_phy_gen_ops);
if (IS_ERR(generic_phy)) {
ret = PTR_ERR(generic_phy);
dev_err(dev, "failed to create phy, %d\n", ret);
+ pm_runtime_disable(dev);
return ret;
}
qphy->phy = generic_phy;
@@ -619,6 +775,8 @@ static int qusb2_phy_probe(struct platform_device *pdev)
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (!IS_ERR(phy_provider))
dev_info(dev, "Registered Qcom-QUSB2 phy\n");
+ else
+ pm_runtime_disable(dev);
return PTR_ERR_OR_ZERO(phy_provider);
}
@@ -627,6 +785,7 @@ static int qusb2_phy_probe(struct platform_device *pdev)
.probe = qusb2_phy_probe,
.driver = {
.name = "qcom-qusb2-phy",
+ .pm = &qusb2_phy_pm_ops,
.of_match_table = qusb2_phy_of_match_table,
},
};
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 15/17] phy: qcom-qusb2: Add support for runtime PM
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Yoshihiro Shimoda, Viresh Kumar,
open list:GENERIC PHY FRAMEWORK
Disable clocks and dp/dm asynchronous interrupts from
PHY as part of runtime suspend.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qusb2.c | 159 ++++++++++++++++++++++++++++++++++
1 file changed, 159 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c
index 0e9d88b..7414272 100644
--- a/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -56,6 +56,18 @@
#define PHY_CLK_SCHEME_SEL BIT(0)
+/* QUSB2PHY_INTR_CTRL register bits */
+#define DMSE_INTR_HIGH_SEL BIT(4)
+#define DPSE_INTR_HIGH_SEL BIT(3)
+#define CHG_DET_INTR_EN BIT(2)
+#define DMSE_INTR_EN BIT(1)
+#define DPSE_INTR_EN BIT(0)
+
+/* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE register bits */
+#define CORE_PLL_EN_FROM_RESET BIT(4)
+#define CORE_RESET BIT(5)
+#define CORE_RESET_MUX BIT(6)
+
#define QUSB2PHY_PLL_ANALOG_CONTROLS_TWO 0x04
#define QUSB2PHY_PLL_CLOCK_INVERTERS 0x18c
#define QUSB2PHY_PLL_CMODE 0x2c
@@ -73,6 +85,10 @@
#define UTMI_OTG_VBUS_VALID BIT(20)
#define SW_SESSVLD_SEL BIT(28)
+#define QSCRATCH_CHARGING_DET_OUTPUT 0x1C
+#define LINESTATE_DP BIT(8)
+#define LINESTATE_DM BIT(9)
+
struct qusb2_phy_init_tbl {
unsigned int offset;
unsigned int val;
@@ -98,6 +114,7 @@ struct qusb2_phy_init_tbl {
/* set of registers with offsets different per-PHY */
enum qusb2phy_reg_layout {
+ QUSB2PHY_PLL_CORE_INPUT_OVERRIDE,
QUSB2PHY_PLL_STATUS,
QUSB2PHY_PORT_TUNE1,
QUSB2PHY_PORT_TUNE2,
@@ -117,8 +134,10 @@ enum qusb2phy_reg_layout {
[QUSB2PHY_PORT_TUNE3] = 0x88,
[QUSB2PHY_PORT_TUNE4] = 0x8c,
[QUSB2PHY_PORT_TUNE5] = 0x90,
+ [QUSB2PHY_PORT_TEST1] = 0xb8,
[QUSB2PHY_PORT_TEST2] = 0x9c,
[QUSB2PHY_PORT_POWERDOWN] = 0xb4,
+ [QUSB2PHY_INTR_CTRL] = 0xbc,
};
static const struct qusb2_phy_init_tbl msm8996_init_tbl[] = {
@@ -138,14 +157,17 @@ enum qusb2phy_reg_layout {
};
static const unsigned int qusb2_v2_regs_layout[] = {
+ [QUSB2PHY_PLL_CORE_INPUT_OVERRIDE] = 0xa8,
[QUSB2PHY_PLL_STATUS] = 0x1a0,
[QUSB2PHY_PORT_TUNE1] = 0x240,
[QUSB2PHY_PORT_TUNE2] = 0x244,
[QUSB2PHY_PORT_TUNE3] = 0x248,
[QUSB2PHY_PORT_TUNE4] = 0x24c,
[QUSB2PHY_PORT_TUNE5] = 0x250,
+ [QUSB2PHY_PORT_TEST1] = 0x254,
[QUSB2PHY_PORT_TEST2] = 0x258,
[QUSB2PHY_PORT_POWERDOWN] = 0x210,
+ [QUSB2PHY_INTR_CTRL] = 0x230,
};
static const struct qusb2_phy_init_tbl qusb2_v2_init_tbl[] = {
@@ -180,9 +202,13 @@ struct qusb2_phy_cfg {
const unsigned int *regs;
unsigned int mask_core_ready;
unsigned int disable_ctrl;
+ unsigned int autoresume_en;
/* true if PHY has PLL_TEST register to select clk_scheme */
bool has_pll_test;
+
+ /* true if PHY has PLL_CORE_INPUT_OVERRIDE register to reset PLL */
+ bool has_pll_override;
};
static const struct qusb2_phy_cfg msm8996_phy_cfg = {
@@ -193,6 +219,7 @@ struct qusb2_phy_cfg {
.has_pll_test = true,
.disable_ctrl = (CLAMP_N_EN | FREEZIO_N | POWER_DOWN),
.mask_core_ready = PLL_LOCKED,
+ .autoresume_en = BIT(3),
};
static const struct qusb2_phy_cfg qusb2_v2_phy_cfg = {
@@ -203,6 +230,8 @@ struct qusb2_phy_cfg {
.disable_ctrl = (PWR_CTRL1_VREF_SUPPLY_TRIM | PWR_CTRL1_CLAMP_N_EN |
POWER_DOWN),
.mask_core_ready = CORE_READY_STATUS,
+ .has_pll_override = true,
+ .autoresume_en = BIT(0),
};
static const char * const qusb2_phy_vreg_names[] = {
@@ -229,6 +258,7 @@ struct qusb2_phy_cfg {
*
* @cfg: phy config data
* @has_se_clk_scheme: indicate if PHY has single-ended ref clock scheme
+ * @phy_initialized: indicate if PHY has been initialized
* @mode: indicate current PHY mode of operation e.g. HOST or DEVICE
*/
struct qusb2_phy {
@@ -247,6 +277,7 @@ struct qusb2_phy {
const struct qusb2_phy_cfg *cfg;
bool has_se_clk_scheme;
+ bool phy_initialized;
enum phy_mode mode;
};
@@ -335,6 +366,115 @@ static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
return 0;
}
+static int __maybe_unused qusb2_phy_runtime_suspend(struct device *dev)
+{
+ struct qusb2_phy *qphy = dev_get_drvdata(dev);
+ const struct qusb2_phy_cfg *cfg = qphy->cfg;
+ u32 linestate = 0, intr_mask;
+
+ dev_vdbg(dev, "Suspending QUSB2 Phy, mode:%d\n", qphy->mode);
+
+ if (!qphy->phy_initialized) {
+ dev_vdbg(dev, "PHY not initialized, bailing out\n");
+ return 0;
+ }
+
+ /*
+ * Enable DP/DM interrupts to detect line state changes based on current
+ * state. In other words, enable the triggers _opposite_ of what the
+ * current D+/D- levels are e.g. if currently D+ high, D- low
+ * (HS 'J'/Suspend), configure the mask to trigger on D+ low OR D- high
+ */
+ if (qphy->qscratch_base) {
+ linestate = readl(qphy->qscratch_base +
+ QSCRATCH_CHARGING_DET_OUTPUT);
+ intr_mask = DPSE_INTR_EN | DMSE_INTR_EN;
+ if (!(linestate & LINESTATE_DP)) /* D+ low */
+ intr_mask |= DPSE_INTR_HIGH_SEL;
+ if (!(linestate & LINESTATE_DM)) /* D- low */
+ intr_mask |= DMSE_INTR_HIGH_SEL;
+
+ writel(intr_mask, qphy->base + cfg->regs[QUSB2PHY_INTR_CTRL]);
+ }
+
+ /* hold core PLL into reset */
+ if (cfg->has_pll_override) {
+ qusb2_setbits(qphy->base,
+ cfg->regs[QUSB2PHY_PLL_CORE_INPUT_OVERRIDE],
+ CORE_PLL_EN_FROM_RESET | CORE_RESET |
+ CORE_RESET_MUX);
+ }
+
+ /* enable phy auto-resume */
+ if (linestate & (LINESTATE_DP | LINESTATE_DM)) {
+ qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TEST1],
+ cfg->autoresume_en);
+ /* Autoresume bit has to be toggled in order to enable it */
+ qusb2_clrbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TEST1],
+ cfg->autoresume_en);
+ }
+
+ if (!qphy->has_se_clk_scheme)
+ clk_disable_unprepare(qphy->ref_clk);
+
+ clk_disable_unprepare(qphy->cfg_ahb_clk);
+ clk_disable_unprepare(qphy->iface_clk);
+
+ return 0;
+}
+
+static int __maybe_unused qusb2_phy_runtime_resume(struct device *dev)
+{
+ struct qusb2_phy *qphy = dev_get_drvdata(dev);
+ const struct qusb2_phy_cfg *cfg = qphy->cfg;
+ int ret;
+
+ dev_vdbg(dev, "Resuming QUSB2 phy, mode:%d\n", qphy->mode);
+
+ if (!qphy->phy_initialized) {
+ dev_vdbg(dev, "PHY not initialized, bailing out\n");
+ return 0;
+ }
+
+ ret = clk_prepare_enable(qphy->iface_clk);
+ if (ret) {
+ dev_err(dev, "failed to enable iface_clk, %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(qphy->cfg_ahb_clk);
+ if (ret) {
+ dev_err(dev, "failed to enable cfg ahb clock, %d\n", ret);
+ goto disable_iface_clk;
+ }
+
+ if (!qphy->has_se_clk_scheme) {
+ clk_prepare_enable(qphy->ref_clk);
+ if (ret) {
+ dev_err(dev, "failed to enable ref clk, %d\n", ret);
+ goto disable_ahb_clk;
+ }
+ }
+
+ writel(0x0, qphy->base + cfg->regs[QUSB2PHY_INTR_CTRL]);
+
+ /* bring core PLL out of reset */
+ if (cfg->has_pll_override) {
+ qusb2_clrbits(qphy->base,
+ cfg->regs[QUSB2PHY_PLL_CORE_INPUT_OVERRIDE],
+ CORE_RESET | CORE_RESET_MUX);
+ }
+
+ return 0;
+
+disable_ahb_clk:
+ clk_disable_unprepare(qphy->cfg_ahb_clk);
+disable_iface_clk:
+ clk_disable_unprepare(qphy->iface_clk);
+
+ return ret;
+}
+
static int qusb2_phy_init(struct phy *phy)
{
struct qusb2_phy *qphy = phy_get_drvdata(phy);
@@ -459,6 +599,7 @@ static int qusb2_phy_init(struct phy *phy)
ret = -EBUSY;
goto disable_ref_clk;
}
+ qphy->phy_initialized = true;
return 0;
@@ -495,6 +636,8 @@ static int qusb2_phy_exit(struct phy *phy)
regulator_bulk_disable(ARRAY_SIZE(qphy->vregs), qphy->vregs);
+ qphy->phy_initialized = false;
+
return 0;
}
@@ -517,6 +660,11 @@ static int qusb2_phy_exit(struct phy *phy)
};
MODULE_DEVICE_TABLE(of, qusb2_phy_of_match_table);
+static const struct dev_pm_ops qusb2_phy_pm_ops = {
+ SET_RUNTIME_PM_OPS(qusb2_phy_runtime_suspend,
+ qusb2_phy_runtime_resume, NULL)
+};
+
static int qusb2_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -604,11 +752,19 @@ static int qusb2_phy_probe(struct platform_device *pdev)
qphy->cell = NULL;
dev_dbg(dev, "failed to lookup tune2 hstx trim value\n");
}
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ /*
+ * Prevent runtime pm from being ON by default. Users can enable
+ * it using power/control in sysfs.
+ */
+ pm_runtime_forbid(dev);
generic_phy = devm_phy_create(dev, NULL, &qusb2_phy_gen_ops);
if (IS_ERR(generic_phy)) {
ret = PTR_ERR(generic_phy);
dev_err(dev, "failed to create phy, %d\n", ret);
+ pm_runtime_disable(dev);
return ret;
}
qphy->phy = generic_phy;
@@ -619,6 +775,8 @@ static int qusb2_phy_probe(struct platform_device *pdev)
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (!IS_ERR(phy_provider))
dev_info(dev, "Registered Qcom-QUSB2 phy\n");
+ else
+ pm_runtime_disable(dev);
return PTR_ERR_OR_ZERO(phy_provider);
}
@@ -627,6 +785,7 @@ static int qusb2_phy_probe(struct platform_device *pdev)
.probe = qusb2_phy_probe,
.driver = {
.name = "qcom-qusb2-phy",
+ .pm = &qusb2_phy_pm_ops,
.of_match_table = qusb2_phy_of_match_table,
},
};
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 16/17] phy: qcom-qmp: Override lane0_power_present signal in device mode
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Jaehoon Chung, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
lane0_power_present signal must be asserted of hardware to
operate properly in SS device mode. On some platforms where VBUS
line is not connected to SS QMP PHY there is SS_PHY_CTRL register
in QSCRATCH wrapper that can be used by software to override VBUS.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 38 +++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index d4e1436..1403de3 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -61,6 +61,9 @@
#define USB3_MODE BIT(0) /* enables USB3 mode */
#define DP_MODE BIT(1) /* enables DP mode */
+/* QSCRATCH register bits */
+#define QSCRATCH_SS_PHY_CTRL 0x30
+#define LANE0_PWR_PRESENT BIT(24)
#define PHY_INIT_COMPLETE_TIMEOUT 1000
#define POWER_DOWN_DELAY_US_MIN 10
@@ -558,6 +561,7 @@ struct qmp_phy {
* @dev: device
* @serdes: iomapped memory space for phy's serdes
* @dp_com: iomapped memory space for phy's dp_com control block
+ * @qscratch_base: iomapped memory space for qscratch region
*
* @clks: array of clocks required by phy
* @resets: array of resets required by phy
@@ -572,6 +576,7 @@ struct qcom_qmp {
struct device *dev;
void __iomem *serdes;
void __iomem *dp_com;
+ void __iomem *qscratch_base;
struct clk_bulk_data *clks;
struct reset_control **resets;
@@ -582,6 +587,7 @@ struct qcom_qmp {
struct mutex phy_mutex;
int init_count;
+ enum phy_mode mode;
};
static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
@@ -1024,6 +1030,26 @@ static int qcom_qmp_phy_exit(struct phy *phy)
return 0;
}
+static int qcom_qmp_phy_set_mode(struct phy *phy, enum phy_mode mode)
+{
+ struct qmp_phy *qphy = phy_get_drvdata(phy);
+ struct qcom_qmp *qmp = qphy->qmp;
+
+ qmp->mode = mode;
+
+ /* Update VBUS override in qscratch register */
+ if (qmp->qscratch_base) {
+ if (mode == PHY_MODE_USB_DEVICE)
+ qphy_setbits(qmp->qscratch_base, QSCRATCH_SS_PHY_CTRL,
+ LANE0_PWR_PRESENT);
+ else
+ qphy_clrbits(qmp->qscratch_base, QSCRATCH_SS_PHY_CTRL,
+ LANE0_PWR_PRESENT);
+ }
+
+ return 0;
+}
+
static int qcom_qmp_phy_vreg_init(struct device *dev)
{
struct qcom_qmp *qmp = dev_get_drvdata(dev);
@@ -1133,6 +1159,7 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np)
static const struct phy_ops qcom_qmp_phy_gen_ops = {
.init = qcom_qmp_phy_init,
.exit = qcom_qmp_phy_exit,
+ .set_mode = qcom_qmp_phy_set_mode,
.owner = THIS_MODULE,
};
@@ -1273,7 +1300,18 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
qmp->dp_com = base;
}
+ /* Check if platform uses qscratch wrapper */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qscratch");
+ if (res) {
+ /* Can't request region as used by other phy and glue drivers */
+ qmp->qscratch_base = devm_ioremap(dev, res->start,
+ resource_size(res));
+ if (IS_ERR(qmp->qscratch_base))
+ return PTR_ERR(qmp->qscratch_base);
+ }
+
mutex_init(&qmp->phy_mutex);
+ qmp->mode = PHY_MODE_INVALID;
ret = qcom_qmp_phy_clk_init(dev);
if (ret)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 16/17] phy: qcom-qmp: Override lane0_power_present signal in device mode
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Jaehoon Chung, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
lane0_power_present signal must be asserted of hardware to
operate properly in SS device mode. On some platforms where VBUS
line is not connected to SS QMP PHY there is SS_PHY_CTRL register
in QSCRATCH wrapper that can be used by software to override VBUS.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 38 +++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index d4e1436..1403de3 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -61,6 +61,9 @@
#define USB3_MODE BIT(0) /* enables USB3 mode */
#define DP_MODE BIT(1) /* enables DP mode */
+/* QSCRATCH register bits */
+#define QSCRATCH_SS_PHY_CTRL 0x30
+#define LANE0_PWR_PRESENT BIT(24)
#define PHY_INIT_COMPLETE_TIMEOUT 1000
#define POWER_DOWN_DELAY_US_MIN 10
@@ -558,6 +561,7 @@ struct qmp_phy {
* @dev: device
* @serdes: iomapped memory space for phy's serdes
* @dp_com: iomapped memory space for phy's dp_com control block
+ * @qscratch_base: iomapped memory space for qscratch region
*
* @clks: array of clocks required by phy
* @resets: array of resets required by phy
@@ -572,6 +576,7 @@ struct qcom_qmp {
struct device *dev;
void __iomem *serdes;
void __iomem *dp_com;
+ void __iomem *qscratch_base;
struct clk_bulk_data *clks;
struct reset_control **resets;
@@ -582,6 +587,7 @@ struct qcom_qmp {
struct mutex phy_mutex;
int init_count;
+ enum phy_mode mode;
};
static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
@@ -1024,6 +1030,26 @@ static int qcom_qmp_phy_exit(struct phy *phy)
return 0;
}
+static int qcom_qmp_phy_set_mode(struct phy *phy, enum phy_mode mode)
+{
+ struct qmp_phy *qphy = phy_get_drvdata(phy);
+ struct qcom_qmp *qmp = qphy->qmp;
+
+ qmp->mode = mode;
+
+ /* Update VBUS override in qscratch register */
+ if (qmp->qscratch_base) {
+ if (mode == PHY_MODE_USB_DEVICE)
+ qphy_setbits(qmp->qscratch_base, QSCRATCH_SS_PHY_CTRL,
+ LANE0_PWR_PRESENT);
+ else
+ qphy_clrbits(qmp->qscratch_base, QSCRATCH_SS_PHY_CTRL,
+ LANE0_PWR_PRESENT);
+ }
+
+ return 0;
+}
+
static int qcom_qmp_phy_vreg_init(struct device *dev)
{
struct qcom_qmp *qmp = dev_get_drvdata(dev);
@@ -1133,6 +1159,7 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np)
static const struct phy_ops qcom_qmp_phy_gen_ops = {
.init = qcom_qmp_phy_init,
.exit = qcom_qmp_phy_exit,
+ .set_mode = qcom_qmp_phy_set_mode,
.owner = THIS_MODULE,
};
@@ -1273,7 +1300,18 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
qmp->dp_com = base;
}
+ /* Check if platform uses qscratch wrapper */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qscratch");
+ if (res) {
+ /* Can't request region as used by other phy and glue drivers */
+ qmp->qscratch_base = devm_ioremap(dev, res->start,
+ resource_size(res));
+ if (IS_ERR(qmp->qscratch_base))
+ return PTR_ERR(qmp->qscratch_base);
+ }
+
mutex_init(&qmp->phy_mutex);
+ qmp->mode = PHY_MODE_INVALID;
ret = qcom_qmp_phy_clk_init(dev);
if (ret)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 17/17] phy: qcom-qmp: Add support for runtime PM
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
@ 2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:58 ` Manu Gautam
` (15 subsequent siblings)
16 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Jaehoon Chung, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
Disable clocks as part of PHY suspend. This also requires enabling
PHY autonomous mode to detect lfps/rx_det in suspend state.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 182 +++++++++++++++++++++++++++++++++++-
drivers/phy/qualcomm/phy-qcom-qmp.h | 3 +
2 files changed, 184 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 1403de3..a04ba28 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -61,6 +61,20 @@
#define USB3_MODE BIT(0) /* enables USB3 mode */
#define DP_MODE BIT(1) /* enables DP mode */
+/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */
+#define ARCVR_DTCT_EN BIT(0)
+#define ALFPS_DTCT_EN BIT(1)
+#define ARCVR_DTCT_EVENT_SEL BIT(4)
+
+/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */
+#define IRQ_CLEAR BIT(0)
+
+/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */
+#define RCVR_DETECT BIT(0)
+
+/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
+#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
+
/* QSCRATCH register bits */
#define QSCRATCH_SS_PHY_CTRL 0x30
#define LANE0_PWR_PRESENT BIT(24)
@@ -111,6 +125,9 @@ enum qphy_reg_layout {
QPHY_SW_RESET,
QPHY_START_CTRL,
QPHY_PCS_READY_STATUS,
+ QPHY_PCS_AUTONOMOUS_MODE_CTRL,
+ QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR,
+ QPHY_PCS_LFPS_RXTERM_IRQ_STATUS,
};
static const unsigned int pciephy_regs_layout[] = {
@@ -138,12 +155,18 @@ enum qphy_reg_layout {
[QPHY_SW_RESET] = 0x00,
[QPHY_START_CTRL] = 0x08,
[QPHY_PCS_READY_STATUS] = 0x17c,
+ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d4,
+ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0d8,
+ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178,
};
static const unsigned int qmp_v3_usb3phy_regs_layout[] = {
[QPHY_SW_RESET] = 0x00,
[QPHY_START_CTRL] = 0x08,
[QPHY_PCS_READY_STATUS] = 0x174,
+ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d8,
+ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0dc,
+ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170,
};
static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = {
@@ -539,6 +562,7 @@ struct qmp_phy_cfg {
* @tx: iomapped memory space for lane's tx
* @rx: iomapped memory space for lane's rx
* @pcs: iomapped memory space for lane's pcs
+ * @pcs_misc: iomapped memory space for lane's pcs_misc
* @pipe_clk: pipe lock
* @index: lane index
* @qmp: QMP phy to which this lane belongs
@@ -549,6 +573,7 @@ struct qmp_phy {
void __iomem *tx;
void __iomem *rx;
void __iomem *pcs;
+ void __iomem *pcs_misc;
struct clk *pipe_clk;
unsigned int index;
struct qcom_qmp *qmp;
@@ -587,6 +612,7 @@ struct qcom_qmp {
struct mutex phy_mutex;
int init_count;
+ bool phy_initialized;
enum phy_mode mode;
};
@@ -784,6 +810,7 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
void __iomem *serdes = qmp->serdes;
+ void __iomem *dp_com = qmp->dp_com;
int ret, i;
mutex_lock(&qmp->phy_mutex);
@@ -993,6 +1020,7 @@ static int qcom_qmp_phy_init(struct phy *phy)
dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret);
goto err_pcs_ready;
}
+ qmp->phy_initialized = true;
return 0;
@@ -1027,6 +1055,135 @@ static int qcom_qmp_phy_exit(struct phy *phy)
qcom_qmp_phy_com_exit(qmp);
+ qmp->phy_initialized = false;
+
+ return 0;
+}
+
+static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy)
+{
+ struct qcom_qmp *qmp = qphy->qmp;
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ void __iomem *pcs = qphy->pcs;
+ void __iomem *pcs_misc = qphy->pcs_misc;
+ unsigned int reg;
+
+ /* Clear previous PHY int_status before checking rx_det */
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+ /* Writing 1 followed by 0 clears the interrupt */
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+
+ /* Enable PHY autonomous mode to detect lfps and rx_det detach */
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
+ ARCVR_DTCT_EN | ALFPS_DTCT_EN);
+
+ /* Enable i/o clamp_n for autonomous mode */
+ if (pcs_misc)
+ qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN);
+
+ /* Add delay for int_status to reflect current rx_det state */
+ usleep_range(10000, 12000);
+ reg = readl(pcs + cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_STATUS]);
+
+ /*
+ * Get rx_det state to know if SS device not connected. If so
+ * then enable RX_DET attach interrupt.
+ */
+ if (reg & RCVR_DETECT) {
+ dev_dbg(qmp->dev, "Enable rx_det attach interrupt\n");
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
+ ARCVR_DTCT_EN | ALFPS_DTCT_EN);
+
+ /* Clear previous PHY interrupt status before re-enabling */
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR],
+ IRQ_CLEAR);
+ /* Writing 1 followed by 0 clears the interrupt */
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR],
+ IRQ_CLEAR);
+
+ /* Enable rx_det attach interrupt */
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
+ ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL);
+ }
+}
+
+static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy)
+{
+ struct qcom_qmp *qmp = qphy->qmp;
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ void __iomem *pcs = qphy->pcs;
+ void __iomem *pcs_misc = qphy->pcs_misc;
+
+ /* Disable i/o clamp_n on resume for normal mode */
+ if (pcs_misc)
+ qphy_setbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN);
+
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
+ ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN);
+
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+ /* Writing 1 followed by 0 clears the interrupt */
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+}
+
+static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev)
+{
+ struct qcom_qmp *qmp = dev_get_drvdata(dev);
+ struct qmp_phy *qphy = qmp->phys[0];
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+
+ dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode);
+
+ /* Supported only for USB3 PHY */
+ if (cfg->type != PHY_TYPE_USB3)
+ return 0;
+
+ if (!qmp->phy_initialized) {
+ dev_vdbg(dev, "PHY not initialized, bailing out\n");
+ return 0;
+ }
+
+ qcom_qmp_phy_enable_autonomous_mode(qphy);
+
+ clk_disable_unprepare(qphy->pipe_clk);
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
+
+ return 0;
+}
+
+static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev)
+{
+ struct qcom_qmp *qmp = dev_get_drvdata(dev);
+ struct qmp_phy *qphy = qmp->phys[0];
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ int ret = 0;
+
+ dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode);
+
+ /* Supported only for USB3 PHY */
+ if (cfg->type != PHY_TYPE_USB3)
+ return 0;
+
+ if (!qmp->phy_initialized) {
+ dev_vdbg(dev, "PHY not initialized, bailing out\n");
+ return 0;
+ }
+
+ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
+ if (ret) {
+ dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(qphy->pipe_clk);
+ if (ret) {
+ dev_err(dev, "pipe_clk enable failed, err=%d\n", ret);
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
+ return ret;
+ }
+
+ qcom_qmp_phy_disable_autonomous_mode(qphy);
+
return 0;
}
@@ -1178,7 +1335,8 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
/*
* Get memory resources for each phy lane:
- * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
+ * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2; and
+ * pcs_misc (optional) -> 3.
*/
qphy->tx = of_iomap(np, 0);
if (!qphy->tx)
@@ -1192,6 +1350,10 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
if (!qphy->pcs)
return -ENOMEM;
+ qphy->pcs_misc = of_iomap(np, 3);
+ if (!qphy->pcs_misc)
+ dev_vdbg(dev, "PHY pcs_misc-reg not used\n");
+
/*
* Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3
* based phys, so they essentially have pipe clock. So,
@@ -1258,6 +1420,11 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
};
MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table);
+static const struct dev_pm_ops qcom_qmp_phy_pm_ops = {
+ SET_RUNTIME_PM_OPS(qcom_qmp_phy_runtime_suspend,
+ qcom_qmp_phy_runtime_resume, NULL)
+};
+
static int qcom_qmp_phy_probe(struct platform_device *pdev)
{
struct qcom_qmp *qmp;
@@ -1337,12 +1504,21 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
return -ENOMEM;
id = 0;
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ /*
+ * Prevent runtime pm from being ON by default. Users can enable
+ * it using power/control in sysfs.
+ */
+ pm_runtime_forbid(dev);
+
for_each_available_child_of_node(dev->of_node, child) {
/* Create per-lane phy */
ret = qcom_qmp_phy_create(dev, child, id);
if (ret) {
dev_err(dev, "failed to create lane%d phy, %d\n",
id, ret);
+ pm_runtime_disable(dev);
return ret;
}
@@ -1354,6 +1530,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
if (ret) {
dev_err(qmp->dev,
"failed to register pipe clock source\n");
+ pm_runtime_disable(dev);
return ret;
}
id++;
@@ -1362,6 +1539,8 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (!IS_ERR(phy_provider))
dev_info(dev, "Registered Qcom-QMP phy\n");
+ else
+ pm_runtime_disable(dev);
return PTR_ERR_OR_ZERO(phy_provider);
}
@@ -1370,6 +1549,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
.probe = qcom_qmp_phy_probe,
.driver = {
.name = "qcom-qmp-phy",
+ .pm = &qcom_qmp_phy_pm_ops,
.of_match_table = qcom_qmp_phy_of_match_table,
},
};
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index f7d4c2a..264b5c4 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -283,4 +283,7 @@
#define QPHY_V3_PCS_FLL_MAN_CODE 0x0d4
#define QPHY_V3_PCS_RX_SIGDET_LVL 0x1d8
+/* Only for QMP V3 PHY - PCS_MISC registers */
+#define QPHY_V3_PCS_MISC_CLAMP_ENABLE 0x0c
+
#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v2 17/17] phy: qcom-qmp: Add support for runtime PM
@ 2017-09-27 8:59 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-09-27 8:59 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Manu Gautam,
Vivek Gautam, Varadarajan Narayanan, Jaehoon Chung, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
Disable clocks as part of PHY suspend. This also requires enabling
PHY autonomous mode to detect lfps/rx_det in suspend state.
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
---
drivers/phy/qualcomm/phy-qcom-qmp.c | 182 +++++++++++++++++++++++++++++++++++-
drivers/phy/qualcomm/phy-qcom-qmp.h | 3 +
2 files changed, 184 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 1403de3..a04ba28 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -61,6 +61,20 @@
#define USB3_MODE BIT(0) /* enables USB3 mode */
#define DP_MODE BIT(1) /* enables DP mode */
+/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */
+#define ARCVR_DTCT_EN BIT(0)
+#define ALFPS_DTCT_EN BIT(1)
+#define ARCVR_DTCT_EVENT_SEL BIT(4)
+
+/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */
+#define IRQ_CLEAR BIT(0)
+
+/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */
+#define RCVR_DETECT BIT(0)
+
+/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
+#define CLAMP_EN BIT(0) /* enables i/o clamp_n */
+
/* QSCRATCH register bits */
#define QSCRATCH_SS_PHY_CTRL 0x30
#define LANE0_PWR_PRESENT BIT(24)
@@ -111,6 +125,9 @@ enum qphy_reg_layout {
QPHY_SW_RESET,
QPHY_START_CTRL,
QPHY_PCS_READY_STATUS,
+ QPHY_PCS_AUTONOMOUS_MODE_CTRL,
+ QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR,
+ QPHY_PCS_LFPS_RXTERM_IRQ_STATUS,
};
static const unsigned int pciephy_regs_layout[] = {
@@ -138,12 +155,18 @@ enum qphy_reg_layout {
[QPHY_SW_RESET] = 0x00,
[QPHY_START_CTRL] = 0x08,
[QPHY_PCS_READY_STATUS] = 0x17c,
+ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d4,
+ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0d8,
+ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178,
};
static const unsigned int qmp_v3_usb3phy_regs_layout[] = {
[QPHY_SW_RESET] = 0x00,
[QPHY_START_CTRL] = 0x08,
[QPHY_PCS_READY_STATUS] = 0x174,
+ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d8,
+ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0dc,
+ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170,
};
static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = {
@@ -539,6 +562,7 @@ struct qmp_phy_cfg {
* @tx: iomapped memory space for lane's tx
* @rx: iomapped memory space for lane's rx
* @pcs: iomapped memory space for lane's pcs
+ * @pcs_misc: iomapped memory space for lane's pcs_misc
* @pipe_clk: pipe lock
* @index: lane index
* @qmp: QMP phy to which this lane belongs
@@ -549,6 +573,7 @@ struct qmp_phy {
void __iomem *tx;
void __iomem *rx;
void __iomem *pcs;
+ void __iomem *pcs_misc;
struct clk *pipe_clk;
unsigned int index;
struct qcom_qmp *qmp;
@@ -587,6 +612,7 @@ struct qcom_qmp {
struct mutex phy_mutex;
int init_count;
+ bool phy_initialized;
enum phy_mode mode;
};
@@ -784,6 +810,7 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
void __iomem *serdes = qmp->serdes;
+ void __iomem *dp_com = qmp->dp_com;
int ret, i;
mutex_lock(&qmp->phy_mutex);
@@ -993,6 +1020,7 @@ static int qcom_qmp_phy_init(struct phy *phy)
dev_err(qmp->dev, "pipe_clk enable failed, err=%d\n", ret);
goto err_pcs_ready;
}
+ qmp->phy_initialized = true;
return 0;
@@ -1027,6 +1055,135 @@ static int qcom_qmp_phy_exit(struct phy *phy)
qcom_qmp_phy_com_exit(qmp);
+ qmp->phy_initialized = false;
+
+ return 0;
+}
+
+static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy)
+{
+ struct qcom_qmp *qmp = qphy->qmp;
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ void __iomem *pcs = qphy->pcs;
+ void __iomem *pcs_misc = qphy->pcs_misc;
+ unsigned int reg;
+
+ /* Clear previous PHY int_status before checking rx_det */
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+ /* Writing 1 followed by 0 clears the interrupt */
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+
+ /* Enable PHY autonomous mode to detect lfps and rx_det detach */
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
+ ARCVR_DTCT_EN | ALFPS_DTCT_EN);
+
+ /* Enable i/o clamp_n for autonomous mode */
+ if (pcs_misc)
+ qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN);
+
+ /* Add delay for int_status to reflect current rx_det state */
+ usleep_range(10000, 12000);
+ reg = readl(pcs + cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_STATUS]);
+
+ /*
+ * Get rx_det state to know if SS device not connected. If so
+ * then enable RX_DET attach interrupt.
+ */
+ if (reg & RCVR_DETECT) {
+ dev_dbg(qmp->dev, "Enable rx_det attach interrupt\n");
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
+ ARCVR_DTCT_EN | ALFPS_DTCT_EN);
+
+ /* Clear previous PHY interrupt status before re-enabling */
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR],
+ IRQ_CLEAR);
+ /* Writing 1 followed by 0 clears the interrupt */
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR],
+ IRQ_CLEAR);
+
+ /* Enable rx_det attach interrupt */
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
+ ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL);
+ }
+}
+
+static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy)
+{
+ struct qcom_qmp *qmp = qphy->qmp;
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ void __iomem *pcs = qphy->pcs;
+ void __iomem *pcs_misc = qphy->pcs_misc;
+
+ /* Disable i/o clamp_n on resume for normal mode */
+ if (pcs_misc)
+ qphy_setbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN);
+
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
+ ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN);
+
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+ /* Writing 1 followed by 0 clears the interrupt */
+ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
+}
+
+static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev)
+{
+ struct qcom_qmp *qmp = dev_get_drvdata(dev);
+ struct qmp_phy *qphy = qmp->phys[0];
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+
+ dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode);
+
+ /* Supported only for USB3 PHY */
+ if (cfg->type != PHY_TYPE_USB3)
+ return 0;
+
+ if (!qmp->phy_initialized) {
+ dev_vdbg(dev, "PHY not initialized, bailing out\n");
+ return 0;
+ }
+
+ qcom_qmp_phy_enable_autonomous_mode(qphy);
+
+ clk_disable_unprepare(qphy->pipe_clk);
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
+
+ return 0;
+}
+
+static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev)
+{
+ struct qcom_qmp *qmp = dev_get_drvdata(dev);
+ struct qmp_phy *qphy = qmp->phys[0];
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ int ret = 0;
+
+ dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode);
+
+ /* Supported only for USB3 PHY */
+ if (cfg->type != PHY_TYPE_USB3)
+ return 0;
+
+ if (!qmp->phy_initialized) {
+ dev_vdbg(dev, "PHY not initialized, bailing out\n");
+ return 0;
+ }
+
+ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks);
+ if (ret) {
+ dev_err(qmp->dev, "failed to enable clks, err=%d\n", ret);
+ return ret;
+ }
+
+ ret = clk_prepare_enable(qphy->pipe_clk);
+ if (ret) {
+ dev_err(dev, "pipe_clk enable failed, err=%d\n", ret);
+ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks);
+ return ret;
+ }
+
+ qcom_qmp_phy_disable_autonomous_mode(qphy);
+
return 0;
}
@@ -1178,7 +1335,8 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
/*
* Get memory resources for each phy lane:
- * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
+ * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2; and
+ * pcs_misc (optional) -> 3.
*/
qphy->tx = of_iomap(np, 0);
if (!qphy->tx)
@@ -1192,6 +1350,10 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
if (!qphy->pcs)
return -ENOMEM;
+ qphy->pcs_misc = of_iomap(np, 3);
+ if (!qphy->pcs_misc)
+ dev_vdbg(dev, "PHY pcs_misc-reg not used\n");
+
/*
* Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3
* based phys, so they essentially have pipe clock. So,
@@ -1258,6 +1420,11 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
};
MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table);
+static const struct dev_pm_ops qcom_qmp_phy_pm_ops = {
+ SET_RUNTIME_PM_OPS(qcom_qmp_phy_runtime_suspend,
+ qcom_qmp_phy_runtime_resume, NULL)
+};
+
static int qcom_qmp_phy_probe(struct platform_device *pdev)
{
struct qcom_qmp *qmp;
@@ -1337,12 +1504,21 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
return -ENOMEM;
id = 0;
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ /*
+ * Prevent runtime pm from being ON by default. Users can enable
+ * it using power/control in sysfs.
+ */
+ pm_runtime_forbid(dev);
+
for_each_available_child_of_node(dev->of_node, child) {
/* Create per-lane phy */
ret = qcom_qmp_phy_create(dev, child, id);
if (ret) {
dev_err(dev, "failed to create lane%d phy, %d\n",
id, ret);
+ pm_runtime_disable(dev);
return ret;
}
@@ -1354,6 +1530,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
if (ret) {
dev_err(qmp->dev,
"failed to register pipe clock source\n");
+ pm_runtime_disable(dev);
return ret;
}
id++;
@@ -1362,6 +1539,8 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (!IS_ERR(phy_provider))
dev_info(dev, "Registered Qcom-QMP phy\n");
+ else
+ pm_runtime_disable(dev);
return PTR_ERR_OR_ZERO(phy_provider);
}
@@ -1370,6 +1549,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
.probe = qcom_qmp_phy_probe,
.driver = {
.name = "qcom-qmp-phy",
+ .pm = &qcom_qmp_phy_pm_ops,
.of_match_table = qcom_qmp_phy_of_match_table,
},
};
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
index f7d4c2a..264b5c4 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -283,4 +283,7 @@
#define QPHY_V3_PCS_FLL_MAN_CODE 0x0d4
#define QPHY_V3_PCS_RX_SIGDET_LVL 0x1d8
+/* Only for QMP V3 PHY - PCS_MISC registers */
+#define QPHY_V3_PCS_MISC_CLAMP_ENABLE 0x0c
+
#endif
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* Re: [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
2017-09-27 8:59 ` Manu Gautam
(?)
@ 2017-09-27 17:57 ` Jack Pham
2017-09-27 19:16 ` Jack Pham
-1 siblings, 1 reply; 48+ messages in thread
From: Jack Pham @ 2017-09-27 17:57 UTC (permalink / raw)
To: Manu Gautam
Cc: Kishon Vijay Abraham I, Felipe Balbi, linux-arm-msm, linux-usb,
Vivek Gautam, Viresh Kumar, Krzysztof Kozlowski,
open list:GENERIC PHY FRAMEWORK
Hi Manu,
On Wed, Sep 27, 2017 at 02:29:10PM +0530, Manu Gautam wrote:
> VBUS signal coming from PHY must be asserted in device for
> controller to start operation or assert pull-up. For some
> platforms where VBUS line is not connected to PHY there is
> HS_PHY_CTRL register in QSCRATCH wrapper that can be used
> by software to override VBUS signal going to controller.
>
> Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
> ---
>
> +static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
> +{
> + struct qusb2_phy *qphy = phy_get_drvdata(phy);
> +
> + qphy->mode = mode;
> +
> + /* Update VBUS override in qscratch register */
> + if (qphy->qscratch_base) {
> + if (mode == PHY_MODE_USB_DEVICE)
> + qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
> + else
> + qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
Wouldn't this be better off handled in the controller glue driver? Two
reasons I think this patch is unattractive:
- qscratch_base is part of the controller's register space. Your later
patch 16/17 ("phy: qcom-qmp: Override lane0_power_present signal in
device mode") does a similar thing and hence both drivers have to
ioremap() the same register resource while at the same time avoiding
request_mem_region() (called by devm_ioremap_resource) to allow it to
be mapped in both places.
- VBUS override bit becomes asserted simply because the mode is changed
to device mode but this is irrespective of the actual VBUS state. This
could break some test setups which perform a logical disconnect by
switching off/on VBUS while leaving data lines connected. Controller
would go merrily along thinking it is still attached to the host.
Instead maybe this could be tied to EXTCON_USB handling in the glue
driver; though it would need to be an additional notifier on top of
dwc3/drd.c which already handles extcon for host/device mode.
Jack
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v2 13/17] phy: qcom-qmp: Add support for QMP V3 USB3 PHY
2017-09-27 8:59 ` Manu Gautam
(?)
@ 2017-09-27 17:59 ` Jack Pham
2017-10-05 6:30 ` Manu Gautam
-1 siblings, 1 reply; 48+ messages in thread
From: Jack Pham @ 2017-09-27 17:59 UTC (permalink / raw)
To: Manu Gautam
Cc: Kishon Vijay Abraham I, Felipe Balbi, linux-arm-msm, linux-usb,
Vivek Gautam, Varadarajan Narayanan, Viresh Kumar, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
On Wed, Sep 27, 2017 at 02:29:09PM +0530, Manu Gautam wrote:
> QMP V3 USB3 PHY is a DP USB combo PHY with
> dual RX/TX lanes to support type-c. There is a
> separate block DP_COM for configuration related
> to type-c or DP. Add support for dp_com region
> and secondary rx/tx lanes initialization.
Clarify "DP" as DisplayPort here?
Jack
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
2017-09-27 17:57 ` Jack Pham
@ 2017-09-27 19:16 ` Jack Pham
2017-09-28 4:00 ` Manu Gautam
0 siblings, 1 reply; 48+ messages in thread
From: Jack Pham @ 2017-09-27 19:16 UTC (permalink / raw)
To: Manu Gautam
Cc: Kishon Vijay Abraham I, Felipe Balbi, linux-arm-msm, linux-usb,
Vivek Gautam, Viresh Kumar, Krzysztof Kozlowski,
open list:GENERIC PHY FRAMEWORK
On Wed, Sep 27, 2017 at 10:57:41AM -0700, Jack Pham wrote:
> Hi Manu,
>
> On Wed, Sep 27, 2017 at 02:29:10PM +0530, Manu Gautam wrote:
> > VBUS signal coming from PHY must be asserted in device for
> > controller to start operation or assert pull-up. For some
> > platforms where VBUS line is not connected to PHY there is
> > HS_PHY_CTRL register in QSCRATCH wrapper that can be used
> > by software to override VBUS signal going to controller.
> >
> > Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
> > ---
> >
> > +static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
> > +{
> > + struct qusb2_phy *qphy = phy_get_drvdata(phy);
> > +
> > + qphy->mode = mode;
> > +
> > + /* Update VBUS override in qscratch register */
> > + if (qphy->qscratch_base) {
> > + if (mode == PHY_MODE_USB_DEVICE)
> > + qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
> > + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
> > + else
> > + qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
> > + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
>
> Wouldn't this be better off handled in the controller glue driver? Two
> reasons I think this patch is unattractive:
>
> - qscratch_base is part of the controller's register space. Your later
> patch 16/17 ("phy: qcom-qmp: Override lane0_power_present signal in
> device mode") does a similar thing and hence both drivers have to
> ioremap() the same register resource while at the same time avoiding
> request_mem_region() (called by devm_ioremap_resource) to allow it to
> be mapped in both places.
>
> - VBUS override bit becomes asserted simply because the mode is changed
> to device mode but this is irrespective of the actual VBUS state. This
> could break some test setups which perform a logical disconnect by
> switching off/on VBUS while leaving data lines connected. Controller
> would go merrily along thinking it is still attached to the host.
>
> Instead maybe this could be tied to EXTCON_USB handling in the glue
> driver; though it would need to be an additional notifier on top of
> dwc3/drd.c which already handles extcon for host/device mode.
That is to say, we'd probably need to split out dwc3-qcom from
dwc3-of-simple.c into its own driver (again) in order to add this.
Jack
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
2017-09-27 19:16 ` Jack Pham
@ 2017-09-28 4:00 ` Manu Gautam
2017-09-28 16:53 ` Jack Pham
0 siblings, 1 reply; 48+ messages in thread
From: Manu Gautam @ 2017-09-28 4:00 UTC (permalink / raw)
To: Jack Pham
Cc: Kishon Vijay Abraham I, Felipe Balbi, linux-arm-msm, linux-usb,
Vivek Gautam, Krzysztof Kozlowski,
open list:GENERIC PHY FRAMEWORK
Hi Jack,
On 9/28/2017 12:46 AM, Jack Pham wrote:
> On Wed, Sep 27, 2017 at 10:57:41AM -0700, Jack Pham wrote:
>> Hi Manu,
>>
>> On Wed, Sep 27, 2017 at 02:29:10PM +0530, Manu Gautam wrote:
>>> VBUS signal coming from PHY must be asserted in device for
>>> controller to start operation or assert pull-up. For some
>>> platforms where VBUS line is not connected to PHY there is
>>> HS_PHY_CTRL register in QSCRATCH wrapper that can be used
>>> by software to override VBUS signal going to controller.
>>>
>>> Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
>>> ---
>>>
>>> +static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
>>> +{
>>> + struct qusb2_phy *qphy = phy_get_drvdata(phy);
>>> +
>>> + qphy->mode = mode;
>>> +
>>> + /* Update VBUS override in qscratch register */
>>> + if (qphy->qscratch_base) {
>>> + if (mode == PHY_MODE_USB_DEVICE)
>>> + qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
>>> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
>>> + else
>>> + qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
>>> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
>> Wouldn't this be better off handled in the controller glue driver? Two
>> reasons I think this patch is unattractive:
>>
>> - qscratch_base is part of the controller's register space. Your later
>> patch 16/17 ("phy: qcom-qmp: Override lane0_power_present signal in
>> device mode") does a similar thing and hence both drivers have to
>> ioremap() the same register resource while at the same time avoiding
>> request_mem_region() (called by devm_ioremap_resource) to allow it to
>> be mapped in both places.
Right. There is one more reason why qusb2 driver needs qscratch:
- During runtime suspend, it has to check linestate to set correct polarity for dp/dm
wakeup interrupt in order to detect disconnect/resume ion LS and FS/HS modes.
>> - VBUS override bit becomes asserted simply because the mode is changed
>> to device mode but this is irrespective of the actual VBUS state. This
>> could break some test setups which perform a logical disconnect by
>> switching off/on VBUS while leaving data lines connected. Controller
>> would go merrily along thinking it is still attached to the host.
>>
>> Instead maybe this could be tied to EXTCON_USB handling in the glue
>> driver; though it would need to be an additional notifier on top of
>> dwc3/drd.c which already handles extcon for host/device mode.
Yes, dwc3/drd.c currently deals with only EXTCON_USB_HOST. So, for platforms
where role swap happens using only Vbus or single GPIO this should take care of.
> That is to say, we'd probably need to split out dwc3-qcom from
> dwc3-of-simple.c into its own driver (again) in order to add this.
>
> Jack
However, I agree that more appropriate place for lane0-pwr-present and
vbus override update is dwc3 glue driver. Since we don't have one right now,
IMO once we have dwc3-qcom driver in place, this handling can be moved from
PHY to glue driver. Until then we can use this approach to get USB device mode
working on qcom platforms which are using dwc3-of-simple.c e.g. sdm820
dragonboard.
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
2017-09-28 4:00 ` Manu Gautam
@ 2017-09-28 16:53 ` Jack Pham
2017-10-05 9:08 ` Manu Gautam
0 siblings, 1 reply; 48+ messages in thread
From: Jack Pham @ 2017-09-28 16:53 UTC (permalink / raw)
To: Manu Gautam
Cc: Kishon Vijay Abraham I, Felipe Balbi, linux-arm-msm, linux-usb,
Vivek Gautam, Krzysztof Kozlowski,
open list:GENERIC PHY FRAMEWORK
Hi Manu,
On Thu, Sep 28, 2017 at 09:30:38AM +0530, Manu Gautam wrote:
> On 9/28/2017 12:46 AM, Jack Pham wrote:
> > On Wed, Sep 27, 2017 at 10:57:41AM -0700, Jack Pham wrote:
> >> On Wed, Sep 27, 2017 at 02:29:10PM +0530, Manu Gautam wrote:
> >>> VBUS signal coming from PHY must be asserted in device for
> >>> controller to start operation or assert pull-up. For some
> >>> platforms where VBUS line is not connected to PHY there is
> >>> HS_PHY_CTRL register in QSCRATCH wrapper that can be used
> >>> by software to override VBUS signal going to controller.
> >>>
> >>> Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
> >>> ---
> >>>
> >>> +static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
> >>> +{
> >>> + struct qusb2_phy *qphy = phy_get_drvdata(phy);
> >>> +
> >>> + qphy->mode = mode;
> >>> +
> >>> + /* Update VBUS override in qscratch register */
> >>> + if (qphy->qscratch_base) {
> >>> + if (mode == PHY_MODE_USB_DEVICE)
> >>> + qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
> >>> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
> >>> + else
> >>> + qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
> >>> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
> >> Wouldn't this be better off handled in the controller glue driver? Two
> >> reasons I think this patch is unattractive:
> >>
> >> - qscratch_base is part of the controller's register space. Your later
> >> patch 16/17 ("phy: qcom-qmp: Override lane0_power_present signal in
> >> device mode") does a similar thing and hence both drivers have to
> >> ioremap() the same register resource while at the same time avoiding
> >> request_mem_region() (called by devm_ioremap_resource) to allow it to
> >> be mapped in both places.
>
> Right. There is one more reason why qusb2 driver needs qscratch:
> - During runtime suspend, it has to check linestate to set correct polarity for dp/dm
> wakeup interrupt in order to detect disconnect/resume ion LS and FS/HS modes.
Ugh, oh yeah. The way I understand we did it in our downstream driver
is still to have the controller driver read the linestate but then pass
the information via additional set_mode() flags which the PHY driver
could use to correctly arm the interrupt trigger polarity.
An alternative would be to access a couple of the debug QUSB2PHY
registers that also provide a reading of the current UTMI linestate. The
HPG mentions them vaguely, and I can't remember if we tested that
interface or not. Assuming it works, would that be preferable to reading
a non-PHY register here?
> >> - VBUS override bit becomes asserted simply because the mode is changed
> >> to device mode but this is irrespective of the actual VBUS state. This
> >> could break some test setups which perform a logical disconnect by
> >> switching off/on VBUS while leaving data lines connected. Controller
> >> would go merrily along thinking it is still attached to the host.
> >>
> >> Instead maybe this could be tied to EXTCON_USB handling in the glue
> >> driver; though it would need to be an additional notifier on top of
> >> dwc3/drd.c which already handles extcon for host/device mode.
>
> Yes, dwc3/drd.c currently deals with only EXTCON_USB_HOST. So, for platforms
> where role swap happens using only Vbus or single GPIO this should take care of.
>
>
> > That is to say, we'd probably need to split out dwc3-qcom from
> > dwc3-of-simple.c into its own driver (again) in order to add this.
> >
> > Jack
>
> However, I agree that more appropriate place for lane0-pwr-present and
> vbus override update is dwc3 glue driver. Since we don't have one right now,
>
> IMO once we have dwc3-qcom driver in place, this handling can be moved from
> PHY to glue driver. Until then we can use this approach to get USB device mode
> working on qcom platforms which are using dwc3-of-simple.c e.g. sdm820
> dragonboard.
Could that be done in this series too? IMO better to get it right in one
shot. Is this aimed for 4.15?
Jack
--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v2 13/17] phy: qcom-qmp: Add support for QMP V3 USB3 PHY
2017-09-27 17:59 ` Jack Pham
@ 2017-10-05 6:30 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-10-05 6:30 UTC (permalink / raw)
To: Jack Pham
Cc: Kishon Vijay Abraham I, Felipe Balbi, linux-arm-msm, linux-usb,
Vivek Gautam, Varadarajan Narayanan, Viresh Kumar, Fengguang Wu,
Wei Yongjun, open list:GENERIC PHY FRAMEWORK
On 9/27/2017 11:29 PM, Jack Pham wrote:
> On Wed, Sep 27, 2017 at 02:29:09PM +0530, Manu Gautam wrote:
>> QMP V3 USB3 PHY is a DP USB combo PHY with
>> dual RX/TX lanes to support type-c. There is a
>> separate block DP_COM for configuration related
>> to type-c or DP. Add support for dp_com region
>> and secondary rx/tx lanes initialization.
> Clarify "DP" as DisplayPort here?
Yes, DP implies DisplayPort. I will update commit text.
> Jack
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
2017-09-28 16:53 ` Jack Pham
@ 2017-10-05 9:08 ` Manu Gautam
2017-10-09 8:03 ` Manu Gautam
0 siblings, 1 reply; 48+ messages in thread
From: Manu Gautam @ 2017-10-05 9:08 UTC (permalink / raw)
To: Jack Pham
Cc: Kishon Vijay Abraham I, Felipe Balbi, linux-arm-msm, linux-usb,
Vivek Gautam, Krzysztof Kozlowski,
open list:GENERIC PHY FRAMEWORK
Hi Jack,
On 9/28/2017 10:23 PM, Jack Pham wrote:
> Hi Manu,
>
> On Thu, Sep 28, 2017 at 09:30:38AM +0530, Manu Gautam wrote:
>> On 9/28/2017 12:46 AM, Jack Pham wrote:
>>> On Wed, Sep 27, 2017 at 10:57:41AM -0700, Jack Pham wrote:
>>>> On Wed, Sep 27, 2017 at 02:29:10PM +0530, Manu Gautam wrote:
>>>>> VBUS signal coming from PHY must be asserted in device for
>>>>> controller to start operation or assert pull-up. For some
>>>>> platforms where VBUS line is not connected to PHY there is
>>>>> HS_PHY_CTRL register in QSCRATCH wrapper that can be used
>>>>> by software to override VBUS signal going to controller.
>>>>>
>>>>> Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
>>>>> ---
>>>>>
>>>>> +static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
>>>>> +{
>>>>> + struct qusb2_phy *qphy = phy_get_drvdata(phy);
>>>>> +
>>>>> + qphy->mode = mode;
>>>>> +
>>>>> + /* Update VBUS override in qscratch register */
>>>>> + if (qphy->qscratch_base) {
>>>>> + if (mode == PHY_MODE_USB_DEVICE)
>>>>> + qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
>>>>> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
>>>>> + else
>>>>> + qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
>>>>> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
>>>> Wouldn't this be better off handled in the controller glue driver? Two
>>>> reasons I think this patch is unattractive:
>>>>
>>>> - qscratch_base is part of the controller's register space. Your later
>>>> patch 16/17 ("phy: qcom-qmp: Override lane0_power_present signal in
>>>> device mode") does a similar thing and hence both drivers have to
>>>> ioremap() the same register resource while at the same time avoiding
>>>> request_mem_region() (called by devm_ioremap_resource) to allow it to
>>>> be mapped in both places.
>> Right. There is one more reason why qusb2 driver needs qscratch:
>> - During runtime suspend, it has to check linestate to set correct polarity for dp/dm
>> wakeup interrupt in order to detect disconnect/resume ion LS and FS/HS modes.
> Ugh, oh yeah. The way I understand we did it in our downstream driver
> is still to have the controller driver read the linestate but then pass
> the information via additional set_mode() flags which the PHY driver
> could use to correctly arm the interrupt trigger polarity.
>
> An alternative would be to access a couple of the debug QUSB2PHY
> registers that also provide a reading of the current UTMI linestate. The
> HPG mentions them vaguely, and I can't remember if we tested that
> interface or not. Assuming it works, would that be preferable to reading
> a non-PHY register here?
it looks like newer QUSB2 PHY doesn't have a register to read linestate.
QSCRATCH is the only option.
However, setting dp/dm wakeup interrupt polarity based on current linestate
isn't perfect either. It could race with any change in linestate while it was being
read, resulting in missed wakeup interrupt.
Same is the case with QMP PHY when trying to check for RX terminations on
suspend.
IMO PHY driver should get this info from platform glue or controller driver.
E.g. current speed -> SS, HS/FS, LS or NONE (if not in session).
Kishon,
What would you suggest here?
Should we add new calls e.g. phy_get/set_current_speed like::
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 78bb0d7..41d9ec2 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -29,6 +29,14 @@ enum phy_mode {
PHY_MODE_USB_OTG,
};
+enum phy_speed {
+ PHY_SPEED_INVALID,
+ PHY_SPEED_USB_LS,
+ PHY_SPEED_USB_FS_HS,
+ PHY_SPEED_USB_SS,
+};
+
/**
* struct phy_ops - set of function pointers for performing phy operations
* @init: operation to be performed for initializing phy
@@ -45,6 +53,7 @@ struct phy_ops {
int (*power_on)(struct phy *phy);
int (*power_off)(struct phy *phy);
int (*set_mode)(struct phy *phy, enum phy_mode mode);
+ int (*set_speed)(struct phy *phy, enum phy_speed speed);
int (*reset)(struct phy *phy);
struct module *owner;
};
>>>> - VBUS override bit becomes asserted simply because the mode is changed
>>>> to device mode but this is irrespective of the actual VBUS state. This
>>>> could break some test setups which perform a logical disconnect by
>>>> switching off/on VBUS while leaving data lines connected. Controller
>>>> would go merrily along thinking it is still attached to the host.
>>>>
>>>> Instead maybe this could be tied to EXTCON_USB handling in the glue
>>>> driver; though it would need to be an additional notifier on top of
>>>> dwc3/drd.c which already handles extcon for host/device mode.
>> Yes, dwc3/drd.c currently deals with only EXTCON_USB_HOST. So, for platforms
>> where role swap happens using only Vbus or single GPIO this should take care of.
>>
>>
>>> That is to say, we'd probably need to split out dwc3-qcom from
>>> dwc3-of-simple.c into its own driver (again) in order to add this.
>>>
>>> Jack
>> However, I agree that more appropriate place for lane0-pwr-present and
>> vbus override update is dwc3 glue driver. Since we don't have one right now,
>>
>> IMO once we have dwc3-qcom driver in place, this handling can be moved from
>> PHY to glue driver. Until then we can use this approach to get USB device mode
>> working on qcom platforms which are using dwc3-of-simple.c e.g. sdm820
>> dragonboard.
> Could that be done in this series too? IMO better to get it right in one
> shot. Is this aimed for 4.15?
I was aiming 4.15 for PHY drivers at least.
This will be further simplified if dwc3 glue driver can pass current speed as well
to PHY drivers.
> Jack
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply related [flat|nested] 48+ messages in thread
* Re: [PATCH v2 08/17] dt-bindings: phy-qcom-qusb2: Update binding for QUSB2 V2 version
2017-09-27 8:59 ` Manu Gautam
@ 2017-10-05 22:10 ` Rob Herring
-1 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2017-10-05 22:10 UTC (permalink / raw)
To: Manu Gautam
Cc: Kishon Vijay Abraham I, Felipe Balbi, linux-arm-msm, linux-usb,
Mark Rutland, Stephen Boyd, Vivek Gautam,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
On Wed, Sep 27, 2017 at 02:29:04PM +0530, Manu Gautam wrote:
> Update generic compatible string for QUSB2 V2 PHY. This will allow
> all targets using QUSB2 V2 use same string.
>
> Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
> ---
> Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v2 08/17] dt-bindings: phy-qcom-qusb2: Update binding for QUSB2 V2 version
@ 2017-10-05 22:10 ` Rob Herring
0 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2017-10-05 22:10 UTC (permalink / raw)
To: Manu Gautam
Cc: Kishon Vijay Abraham I, Felipe Balbi, linux-arm-msm, linux-usb,
Mark Rutland, Stephen Boyd, Vivek Gautam,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
On Wed, Sep 27, 2017 at 02:29:04PM +0530, Manu Gautam wrote:
> Update generic compatible string for QUSB2 V2 PHY. This will allow
> all targets using QUSB2 V2 use same string.
>
> Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
> ---
> Documentation/devicetree/bindings/phy/qcom-qusb2-phy.txt | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
Acked-by: Rob Herring <robh@kernel.org>
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v2 12/17] dt-bindings: phy-qcom-qmp: Update bindings for QMP V3 USB PHY
2017-09-27 8:59 ` Manu Gautam
@ 2017-10-05 22:14 ` Rob Herring
-1 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2017-10-05 22:14 UTC (permalink / raw)
To: Manu Gautam
Cc: Kishon Vijay Abraham I, Felipe Balbi, linux-arm-msm, linux-usb,
Mark Rutland, Stephen Boyd, Vivek Gautam,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
On Wed, Sep 27, 2017 at 02:29:08PM +0530, Manu Gautam wrote:
> Update compatible string and clock names for QMP version V3
> USB PHY.
>
> Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
> ---
> Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
> index b6a9f2b..dcf1b8f 100644
> --- a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
> +++ b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
> @@ -8,7 +8,8 @@ Required properties:
> - compatible: compatible list, contains:
> "qcom,ipq8074-qmp-pcie-phy" for PCIe phy on IPQ8074
> "qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996,
> - "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996.
> + "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996,
> + "qcom,qmp-v3-usb3-phy" for USB3 QMP V3 phy.
This is fine, but you will still need an SoC specific compatible in
addition to this.
Acked-by: Rob Herring <robh@kernel.org>
Rob
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v2 12/17] dt-bindings: phy-qcom-qmp: Update bindings for QMP V3 USB PHY
@ 2017-10-05 22:14 ` Rob Herring
0 siblings, 0 replies; 48+ messages in thread
From: Rob Herring @ 2017-10-05 22:14 UTC (permalink / raw)
To: Manu Gautam
Cc: Kishon Vijay Abraham I, Felipe Balbi, linux-arm-msm, linux-usb,
Mark Rutland, Stephen Boyd, Vivek Gautam,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list
On Wed, Sep 27, 2017 at 02:29:08PM +0530, Manu Gautam wrote:
> Update compatible string and clock names for QMP version V3
> USB PHY.
>
> Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
> ---
> Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
> index b6a9f2b..dcf1b8f 100644
> --- a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
> +++ b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
> @@ -8,7 +8,8 @@ Required properties:
> - compatible: compatible list, contains:
> "qcom,ipq8074-qmp-pcie-phy" for PCIe phy on IPQ8074
> "qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996,
> - "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996.
> + "qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996,
> + "qcom,qmp-v3-usb3-phy" for USB3 QMP V3 phy.
This is fine, but you will still need an SoC specific compatible in
addition to this.
Acked-by: Rob Herring <robh@kernel.org>
Rob
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
2017-10-05 9:08 ` Manu Gautam
@ 2017-10-09 8:03 ` Manu Gautam
2017-10-23 10:49 ` Manu Gautam
0 siblings, 1 reply; 48+ messages in thread
From: Manu Gautam @ 2017-10-09 8:03 UTC (permalink / raw)
To: Jack Pham, Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Vivek Gautam,
Krzysztof Kozlowski, open list:GENERIC PHY FRAMEWORK
Hi Kishon
On 10/5/2017 2:38 PM, Manu Gautam wrote:
> Hi Jack,
>
> On 9/28/2017 10:23 PM, Jack Pham wrote:
>>
>>>>>> +static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
>>>>>> +{
>>>>>> + struct qusb2_phy *qphy = phy_get_drvdata(phy);
>>>>>> +
>>>>>> + qphy->mode = mode;
>>>>>> +
>>>>>> + /* Update VBUS override in qscratch register */
>>>>>> + if (qphy->qscratch_base) {
>>>>>> + if (mode == PHY_MODE_USB_DEVICE)
>>>>>> + qusb2_setbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
>>>>>> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
>>>>>> + else
>>>>>> + qusb2_clrbits(qphy->qscratch_base, QSCRATCH_HS_PHY_CTRL,
>>>>>> + UTMI_OTG_VBUS_VALID | SW_SESSVLD_SEL);
>>>>> Wouldn't this be better off handled in the controller glue driver? Two
>>>>> reasons I think this patch is unattractive:
>>>>>
>>>>> - qscratch_base is part of the controller's register space. Your later
>>>>> patch 16/17 ("phy: qcom-qmp: Override lane0_power_present signal in
>>>>> device mode") does a similar thing and hence both drivers have to
>>>>> ioremap() the same register resource while at the same time avoiding
>>>>> request_mem_region() (called by devm_ioremap_resource) to allow it to
>>>>> be mapped in both places.
>>> Right. There is one more reason why qusb2 driver needs qscratch:
>>> - During runtime suspend, it has to check linestate to set correct polarity for dp/dm
>>> wakeup interrupt in order to detect disconnect/resume ion LS and FS/HS modes.
>> Ugh, oh yeah. The way I understand we did it in our downstream driver
>> is still to have the controller driver read the linestate but then pass
>> the information via additional set_mode() flags which the PHY driver
>> could use to correctly arm the interrupt trigger polarity.
>>
>> An alternative would be to access a couple of the debug QUSB2PHY
>> registers that also provide a reading of the current UTMI linestate. The
>> HPG mentions them vaguely, and I can't remember if we tested that
>> interface or not. Assuming it works, would that be preferable to reading
>> a non-PHY register here?
> it looks like newer QUSB2 PHY doesn't have a register to read linestate.
> QSCRATCH is the only option.
> However, setting dp/dm wakeup interrupt polarity based on current linestate
> isn't perfect either. It could race with any change in linestate while it was being
> read, resulting in missed wakeup interrupt.
> Same is the case with QMP PHY when trying to check for RX terminations on
> suspend.
> IMO PHY driver should get this info from platform glue or controller driver.
> E.g. current speed -> SS, HS/FS, LS or NONE (if not in session).
>
> Kishon,
> What would you suggest here?
> Should we add new calls e.g. phy_get/set_current_speed like::
>
> diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
> index 78bb0d7..41d9ec2 100644
> --- a/include/linux/phy/phy.h
> +++ b/include/linux/phy/phy.h
> @@ -29,6 +29,14 @@ enum phy_mode {
> PHY_MODE_USB_OTG,
> };
>
> +enum phy_speed {
> + PHY_SPEED_INVALID,
> + PHY_SPEED_USB_LS,
> + PHY_SPEED_USB_FS_HS,
> + PHY_SPEED_USB_SS,
> +};
> +
> /**
> * struct phy_ops - set of function pointers for performing phy operations
> * @init: operation to be performed for initializing phy
> @@ -45,6 +53,7 @@ struct phy_ops {
> int (*power_on)(struct phy *phy);
> int (*power_off)(struct phy *phy);
> int (*set_mode)(struct phy *phy, enum phy_mode mode);
> + int (*set_speed)(struct phy *phy, enum phy_speed speed);
> int (*reset)(struct phy *phy);
> struct module *owner;
> };
>
@Kishon,
Let me know if we can add set_speed to phy_ops. We need this for glue
driver to notify PHY of current connection speed to enable appropriate
wakeup interrupts.
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode
2017-10-09 8:03 ` Manu Gautam
@ 2017-10-23 10:49 ` Manu Gautam
0 siblings, 0 replies; 48+ messages in thread
From: Manu Gautam @ 2017-10-23 10:49 UTC (permalink / raw)
To: Jack Pham, Kishon Vijay Abraham I
Cc: Felipe Balbi, linux-arm-msm, linux-usb, Vivek Gautam,
Krzysztof Kozlowski, open list:GENERIC PHY FRAMEWORK
Hi Kishon,
Please review this so that I can re-submit patch-set based on this approach.
On 10/9/2017 1:33 PM, Manu Gautam wrote:
> Hi Kishon
>
> On 10/5/2017 2:38 PM, Manu Gautam wrote:
>> Kishon,
>> What would you suggest here?
>> Should we add new calls e.g. phy_get/set_current_speed like::
>>
>> diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
>> index 78bb0d7..41d9ec2 100644
>> --- a/include/linux/phy/phy.h
>> +++ b/include/linux/phy/phy.h
>> @@ -29,6 +29,14 @@ enum phy_mode {
>> PHY_MODE_USB_OTG,
>> };
>>
>> +enum phy_speed {
>> + PHY_SPEED_INVALID,
>> + PHY_SPEED_USB_LS,
>> + PHY_SPEED_USB_FS_HS,
>> + PHY_SPEED_USB_SS,
>> +};
>> +
>> /**
>> * struct phy_ops - set of function pointers for performing phy operations
>> * @init: operation to be performed for initializing phy
>> @@ -45,6 +53,7 @@ struct phy_ops {
>> int (*power_on)(struct phy *phy);
>> int (*power_off)(struct phy *phy);
>> int (*set_mode)(struct phy *phy, enum phy_mode mode);
>> + int (*set_speed)(struct phy *phy, enum phy_speed speed);
>> int (*reset)(struct phy *phy);
>> struct module *owner;
>> };
>>
> @Kishon,
> Let me know if we can add set_speed to phy_ops. We need this for glue
> driver to notify PHY of current connection speed to enable appropriate
> wakeup interrupts.
>
>
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply [flat|nested] 48+ messages in thread
end of thread, other threads:[~2017-10-23 10:49 UTC | newest]
Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-27 8:58 [PATCH v2 00/17] Support for Qualcomm QUSBv2 and QMPv3 USB PHYs Manu Gautam
2017-09-27 8:58 ` [PATCH v2 01/17] phy: qcom-qmp: Fix phy pipe clock gating Manu Gautam
2017-09-27 8:58 ` Manu Gautam
2017-09-27 8:58 ` [PATCH v2 02/17] phy: qcom-qmp: Adapt to clk_bulk_* APIs Manu Gautam
2017-09-27 8:58 ` Manu Gautam
2017-09-27 8:58 ` [PATCH v2 03/17] phy: qcom-qmp: Power-on PHY before initialization Manu Gautam
2017-09-27 8:58 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 04/17] phy: qcom-qusb2: " Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 05/17] phy: qcom-qmp: Fix PHY block reset sequence Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 06/17] phy: qcom-qmp: Move SERDES/PCS START after PHY reset Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 07/17] phy: qcom-qusb2: Add support for different register layouts Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 08/17] dt-bindings: phy-qcom-qusb2: Update binding for QUSB2 V2 version Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-10-05 22:10 ` Rob Herring
2017-10-05 22:10 ` Rob Herring
2017-09-27 8:59 ` [PATCH v2 09/17] phy: qcom-qusb2: Add support " Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 10/17] phy: qcom-qmp: Move register offsets to header file Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 11/17] phy: qcom-qmp: Add register offsets for QMP V3 PHY Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 12/17] dt-bindings: phy-qcom-qmp: Update bindings for QMP V3 USB PHY Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-10-05 22:14 ` Rob Herring
2017-10-05 22:14 ` Rob Herring
2017-09-27 8:59 ` [PATCH v2 13/17] phy: qcom-qmp: Add support for QMP V3 USB3 PHY Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-09-27 17:59 ` Jack Pham
2017-10-05 6:30 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 14/17] phy: qcom-qusb2: Set vbus sw-override signal in device mode Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-09-27 17:57 ` Jack Pham
2017-09-27 19:16 ` Jack Pham
2017-09-28 4:00 ` Manu Gautam
2017-09-28 16:53 ` Jack Pham
2017-10-05 9:08 ` Manu Gautam
2017-10-09 8:03 ` Manu Gautam
2017-10-23 10:49 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 15/17] phy: qcom-qusb2: Add support for runtime PM Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 16/17] phy: qcom-qmp: Override lane0_power_present signal in device mode Manu Gautam
2017-09-27 8:59 ` Manu Gautam
2017-09-27 8:59 ` [PATCH v2 17/17] phy: qcom-qmp: Add support for runtime PM Manu Gautam
2017-09-27 8:59 ` Manu Gautam
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.