Commit 1543645c authored by Frank Wang's avatar Frank Wang Committed by Kishon Vijay Abraham I

phy: rockchip-inno-usb2: add support for rockchip,usbgrf property

The registers of usb-phy are distributed in grf and usbgrf on some
Rockchip SoCs (e.g RV1108), this patch add a new rockchip,usbgrf
property to support this companion grf design.
Signed-off-by: default avatarFrank Wang <frank.wang@rock-chips.com>
Signed-off-by: default avatarKishon Vijay Abraham I <kishon@ti.com>
parent 4b63743c
...@@ -202,6 +202,7 @@ struct rockchip_usb2phy_port { ...@@ -202,6 +202,7 @@ struct rockchip_usb2phy_port {
/** /**
* struct rockchip_usb2phy: usb2.0 phy driver data. * struct rockchip_usb2phy: usb2.0 phy driver data.
* @grf: General Register Files regmap. * @grf: General Register Files regmap.
* @usbgrf: USB General Register Files regmap.
* @clk: clock struct of phy input clk. * @clk: clock struct of phy input clk.
* @clk480m: clock struct of phy output clk. * @clk480m: clock struct of phy output clk.
* @clk_hw: clock struct of phy output clk management. * @clk_hw: clock struct of phy output clk management.
...@@ -216,6 +217,7 @@ struct rockchip_usb2phy_port { ...@@ -216,6 +217,7 @@ struct rockchip_usb2phy_port {
struct rockchip_usb2phy { struct rockchip_usb2phy {
struct device *dev; struct device *dev;
struct regmap *grf; struct regmap *grf;
struct regmap *usbgrf;
struct clk *clk; struct clk *clk;
struct clk *clk480m; struct clk *clk480m;
struct clk_hw clk480m_hw; struct clk_hw clk480m_hw;
...@@ -227,7 +229,12 @@ struct rockchip_usb2phy { ...@@ -227,7 +229,12 @@ struct rockchip_usb2phy {
struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS]; struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS];
}; };
static inline int property_enable(struct rockchip_usb2phy *rphy, static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy)
{
return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf;
}
static inline int property_enable(struct regmap *base,
const struct usb2phy_reg *reg, bool en) const struct usb2phy_reg *reg, bool en)
{ {
unsigned int val, mask, tmp; unsigned int val, mask, tmp;
...@@ -236,17 +243,17 @@ static inline int property_enable(struct rockchip_usb2phy *rphy, ...@@ -236,17 +243,17 @@ static inline int property_enable(struct rockchip_usb2phy *rphy,
mask = GENMASK(reg->bitend, reg->bitstart); mask = GENMASK(reg->bitend, reg->bitstart);
val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
return regmap_write(rphy->grf, reg->offset, val); return regmap_write(base, reg->offset, val);
} }
static inline bool property_enabled(struct rockchip_usb2phy *rphy, static inline bool property_enabled(struct regmap *base,
const struct usb2phy_reg *reg) const struct usb2phy_reg *reg)
{ {
int ret; int ret;
unsigned int tmp, orig; unsigned int tmp, orig;
unsigned int mask = GENMASK(reg->bitend, reg->bitstart); unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
ret = regmap_read(rphy->grf, reg->offset, &orig); ret = regmap_read(base, reg->offset, &orig);
if (ret) if (ret)
return false; return false;
...@@ -258,11 +265,12 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw) ...@@ -258,11 +265,12 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
{ {
struct rockchip_usb2phy *rphy = struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw); container_of(hw, struct rockchip_usb2phy, clk480m_hw);
struct regmap *base = get_reg_base(rphy);
int ret; int ret;
/* turn on 480m clk output if it is off */ /* turn on 480m clk output if it is off */
if (!property_enabled(rphy, &rphy->phy_cfg->clkout_ctl)) { if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
ret = property_enable(rphy, &rphy->phy_cfg->clkout_ctl, true); ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true);
if (ret) if (ret)
return ret; return ret;
...@@ -277,17 +285,19 @@ static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw) ...@@ -277,17 +285,19 @@ static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
{ {
struct rockchip_usb2phy *rphy = struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw); container_of(hw, struct rockchip_usb2phy, clk480m_hw);
struct regmap *base = get_reg_base(rphy);
/* turn off 480m clk output */ /* turn off 480m clk output */
property_enable(rphy, &rphy->phy_cfg->clkout_ctl, false); property_enable(base, &rphy->phy_cfg->clkout_ctl, false);
} }
static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw) static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
{ {
struct rockchip_usb2phy *rphy = struct rockchip_usb2phy *rphy =
container_of(hw, struct rockchip_usb2phy, clk480m_hw); container_of(hw, struct rockchip_usb2phy, clk480m_hw);
struct regmap *base = get_reg_base(rphy);
return property_enabled(rphy, &rphy->phy_cfg->clkout_ctl); return property_enabled(base, &rphy->phy_cfg->clkout_ctl);
} }
static unsigned long static unsigned long
...@@ -409,13 +419,13 @@ static int rockchip_usb2phy_init(struct phy *phy) ...@@ -409,13 +419,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
if (rport->mode != USB_DR_MODE_HOST && if (rport->mode != USB_DR_MODE_HOST &&
rport->mode != USB_DR_MODE_UNKNOWN) { rport->mode != USB_DR_MODE_UNKNOWN) {
/* clear bvalid status and enable bvalid detect irq */ /* clear bvalid status and enable bvalid detect irq */
ret = property_enable(rphy, ret = property_enable(rphy->grf,
&rport->port_cfg->bvalid_det_clr, &rport->port_cfg->bvalid_det_clr,
true); true);
if (ret) if (ret)
goto out; goto out;
ret = property_enable(rphy, ret = property_enable(rphy->grf,
&rport->port_cfg->bvalid_det_en, &rport->port_cfg->bvalid_det_en,
true); true);
if (ret) if (ret)
...@@ -429,11 +439,13 @@ static int rockchip_usb2phy_init(struct phy *phy) ...@@ -429,11 +439,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
} }
} else if (rport->port_id == USB2PHY_PORT_HOST) { } else if (rport->port_id == USB2PHY_PORT_HOST) {
/* clear linestate and enable linestate detect irq */ /* clear linestate and enable linestate detect irq */
ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true); ret = property_enable(rphy->grf,
&rport->port_cfg->ls_det_clr, true);
if (ret) if (ret)
goto out; goto out;
ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true); ret = property_enable(rphy->grf,
&rport->port_cfg->ls_det_en, true);
if (ret) if (ret)
goto out; goto out;
...@@ -449,6 +461,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy) ...@@ -449,6 +461,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
{ {
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
struct regmap *base = get_reg_base(rphy);
int ret; int ret;
dev_dbg(&rport->phy->dev, "port power on\n"); dev_dbg(&rport->phy->dev, "port power on\n");
...@@ -460,7 +473,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy) ...@@ -460,7 +473,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
if (ret) if (ret)
return ret; return ret;
ret = property_enable(rphy, &rport->port_cfg->phy_sus, false); ret = property_enable(base, &rport->port_cfg->phy_sus, false);
if (ret) if (ret)
return ret; return ret;
...@@ -475,6 +488,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy) ...@@ -475,6 +488,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
{ {
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent); struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
struct regmap *base = get_reg_base(rphy);
int ret; int ret;
dev_dbg(&rport->phy->dev, "port power off\n"); dev_dbg(&rport->phy->dev, "port power off\n");
...@@ -482,7 +496,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy) ...@@ -482,7 +496,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
if (rport->suspended) if (rport->suspended)
return 0; return 0;
ret = property_enable(rphy, &rport->port_cfg->phy_sus, true); ret = property_enable(base, &rport->port_cfg->phy_sus, true);
if (ret) if (ret)
return ret; return ret;
...@@ -526,11 +540,11 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) ...@@ -526,11 +540,11 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
bool vbus_attach, sch_work, notify_charger; bool vbus_attach, sch_work, notify_charger;
if (rport->utmi_avalid) if (rport->utmi_avalid)
vbus_attach = vbus_attach = property_enabled(rphy->grf,
property_enabled(rphy, &rport->port_cfg->utmi_avalid); &rport->port_cfg->utmi_avalid);
else else
vbus_attach = vbus_attach = property_enabled(rphy->grf,
property_enabled(rphy, &rport->port_cfg->utmi_bvalid); &rport->port_cfg->utmi_bvalid);
sch_work = false; sch_work = false;
notify_charger = false; notify_charger = false;
...@@ -650,22 +664,28 @@ static const char *chg_to_string(enum power_supply_type chg_type) ...@@ -650,22 +664,28 @@ static const char *chg_to_string(enum power_supply_type chg_type)
static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy, static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
bool en) bool en)
{ {
property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en); struct regmap *base = get_reg_base(rphy);
property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en);
} }
static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy, static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
bool en) bool en)
{ {
property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en); struct regmap *base = get_reg_base(rphy);
property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en);
property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en);
} }
static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy, static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
bool en) bool en)
{ {
property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en); struct regmap *base = get_reg_base(rphy);
property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en);
property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en);
} }
#define CHG_DCD_POLL_TIME (100 * HZ / 1000) #define CHG_DCD_POLL_TIME (100 * HZ / 1000)
...@@ -677,6 +697,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -677,6 +697,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
struct rockchip_usb2phy_port *rport = struct rockchip_usb2phy_port *rport =
container_of(work, struct rockchip_usb2phy_port, chg_work.work); container_of(work, struct rockchip_usb2phy_port, chg_work.work);
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
struct regmap *base = get_reg_base(rphy);
bool is_dcd, tmout, vout; bool is_dcd, tmout, vout;
unsigned long delay; unsigned long delay;
...@@ -687,7 +708,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -687,7 +708,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
if (!rport->suspended) if (!rport->suspended)
rockchip_usb2phy_power_off(rport->phy); rockchip_usb2phy_power_off(rport->phy);
/* put the controller in non-driving mode */ /* put the controller in non-driving mode */
property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, false); property_enable(base, &rphy->phy_cfg->chg_det.opmode, false);
/* Start DCD processing stage 1 */ /* Start DCD processing stage 1 */
rockchip_chg_enable_dcd(rphy, true); rockchip_chg_enable_dcd(rphy, true);
rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
...@@ -696,7 +717,8 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -696,7 +717,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
break; break;
case USB_CHG_STATE_WAIT_FOR_DCD: case USB_CHG_STATE_WAIT_FOR_DCD:
/* get data contact detection status */ /* get data contact detection status */
is_dcd = property_enabled(rphy, &rphy->phy_cfg->chg_det.dp_det); is_dcd = property_enabled(rphy->grf,
&rphy->phy_cfg->chg_det.dp_det);
tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES; tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
/* stage 2 */ /* stage 2 */
if (is_dcd || tmout) { if (is_dcd || tmout) {
...@@ -713,7 +735,8 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -713,7 +735,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
} }
break; break;
case USB_CHG_STATE_DCD_DONE: case USB_CHG_STATE_DCD_DONE:
vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.cp_det); vout = property_enabled(rphy->grf,
&rphy->phy_cfg->chg_det.cp_det);
rockchip_chg_enable_primary_det(rphy, false); rockchip_chg_enable_primary_det(rphy, false);
if (vout) { if (vout) {
/* Voltage Source on DM, Probe on DP */ /* Voltage Source on DM, Probe on DP */
...@@ -734,7 +757,8 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -734,7 +757,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
} }
break; break;
case USB_CHG_STATE_PRIMARY_DONE: case USB_CHG_STATE_PRIMARY_DONE:
vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.dcp_det); vout = property_enabled(rphy->grf,
&rphy->phy_cfg->chg_det.dcp_det);
/* Turn off voltage source */ /* Turn off voltage source */
rockchip_chg_enable_secondary_det(rphy, false); rockchip_chg_enable_secondary_det(rphy, false);
if (vout) if (vout)
...@@ -748,7 +772,7 @@ static void rockchip_chg_detect_work(struct work_struct *work) ...@@ -748,7 +772,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
/* fall through */ /* fall through */
case USB_CHG_STATE_DETECTED: case USB_CHG_STATE_DETECTED:
/* put the controller in normal mode */ /* put the controller in normal mode */
property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, true); property_enable(base, &rphy->phy_cfg->chg_det.opmode, true);
rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work); rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
dev_info(&rport->phy->dev, "charger = %s\n", dev_info(&rport->phy->dev, "charger = %s\n",
chg_to_string(rphy->chg_type)); chg_to_string(rphy->chg_type));
...@@ -790,8 +814,7 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work) ...@@ -790,8 +814,7 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
if (ret < 0) if (ret < 0)
goto next_schedule; goto next_schedule;
ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd);
&uhd);
if (ret < 0) if (ret < 0)
goto next_schedule; goto next_schedule;
...@@ -845,8 +868,8 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work) ...@@ -845,8 +868,8 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
* activate the linestate detection to get the next device * activate the linestate detection to get the next device
* plug-in irq. * plug-in irq.
*/ */
property_enable(rphy, &rport->port_cfg->ls_det_clr, true); property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
property_enable(rphy, &rport->port_cfg->ls_det_en, true); property_enable(rphy->grf, &rport->port_cfg->ls_det_en, true);
/* /*
* we don't need to rearm the delayed work when the phy port * we don't need to rearm the delayed work when the phy port
...@@ -869,14 +892,14 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data) ...@@ -869,14 +892,14 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
struct rockchip_usb2phy_port *rport = data; struct rockchip_usb2phy_port *rport = data;
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
if (!property_enabled(rphy, &rport->port_cfg->ls_det_st)) if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st))
return IRQ_NONE; return IRQ_NONE;
mutex_lock(&rport->mutex); mutex_lock(&rport->mutex);
/* disable linestate detect irq and clear its status */ /* disable linestate detect irq and clear its status */
property_enable(rphy, &rport->port_cfg->ls_det_en, false); property_enable(rphy->grf, &rport->port_cfg->ls_det_en, false);
property_enable(rphy, &rport->port_cfg->ls_det_clr, true); property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
mutex_unlock(&rport->mutex); mutex_unlock(&rport->mutex);
...@@ -896,13 +919,13 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data) ...@@ -896,13 +919,13 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
struct rockchip_usb2phy_port *rport = data; struct rockchip_usb2phy_port *rport = data;
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
if (!property_enabled(rphy, &rport->port_cfg->bvalid_det_st)) if (!property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st))
return IRQ_NONE; return IRQ_NONE;
mutex_lock(&rport->mutex); mutex_lock(&rport->mutex);
/* clear bvalid detect irq pending status */ /* clear bvalid detect irq pending status */
property_enable(rphy, &rport->port_cfg->bvalid_det_clr, true); property_enable(rphy->grf, &rport->port_cfg->bvalid_det_clr, true);
mutex_unlock(&rport->mutex); mutex_unlock(&rport->mutex);
...@@ -1045,6 +1068,16 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev) ...@@ -1045,6 +1068,16 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
if (IS_ERR(rphy->grf)) if (IS_ERR(rphy->grf))
return PTR_ERR(rphy->grf); return PTR_ERR(rphy->grf);
if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) {
rphy->usbgrf =
syscon_regmap_lookup_by_phandle(dev->of_node,
"rockchip,usbgrf");
if (IS_ERR(rphy->usbgrf))
return PTR_ERR(rphy->usbgrf);
} else {
rphy->usbgrf = NULL;
}
if (of_property_read_u32(np, "reg", &reg)) { if (of_property_read_u32(np, "reg", &reg)) {
dev_err(dev, "the reg property is not assigned in %s node\n", dev_err(dev, "the reg property is not assigned in %s node\n",
np->name); np->name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment