diff mbox

[1/3] phy: rockchip-inno-usb2: add companion grf quirk

Message ID 1501575133-20953-2-git-send-email-frank.wang@rock-chips.com (mailing list archive)
State New, archived
Headers show

Commit Message

Frank Wang Aug. 1, 2017, 8:12 a.m. UTC
The registers of usb-phy are distributed in grf and usbgrf on some
Rockchip SoCs (e.g RV1108), this patch add a quirk to support this
companion grf design.

Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
---
 .../bindings/phy/phy-rockchip-inno-usb2.txt        |   4 +
 drivers/phy/rockchip/phy-rockchip-inno-usb2.c      | 112 ++++++++++++++-------
 2 files changed, 78 insertions(+), 38 deletions(-)

Comments

Kishon Vijay Abraham I Aug. 2, 2017, 5:03 a.m. UTC | #1
Hi,

On Tuesday 01 August 2017 01:42 PM, Frank Wang wrote:
> The registers of usb-phy are distributed in grf and usbgrf on some
> Rockchip SoCs (e.g RV1108), this patch add a quirk to support this
> companion grf design.
> 
> Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
> ---
>  .../bindings/phy/phy-rockchip-inno-usb2.txt        |   4 +
>  drivers/phy/rockchip/phy-rockchip-inno-usb2.c      | 112 ++++++++++++++-------
>  2 files changed, 78 insertions(+), 38 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt
> index 84d59b0..ddf868a 100644
> --- a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt
> +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt
> @@ -18,6 +18,10 @@ Optional properties:
>  		 usb-phy output 480m and xin24m.
>  		 Refer to clk/clock-bindings.txt for generic clock
>  		 consumer properties.
> + - rockchip,usbgrf : phandle to the syscon managing the "usb general
> +		 register files".
> + - rockchip,companion_grf_quirk : when set driver will request
> +		 "rockchip,usbgrf" phandle as one companion-grf.

please send the dt-bindings as a separate patch and cc devicetree list.

Thanks
Kishon
>  
>  Required nodes : a sub-node is required for each port the phy provides.
>  		 The sub-node name is used to identify host or otg port,
> diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
> index 626883d..669e5f6 100644
> --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
> +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
> @@ -202,6 +202,7 @@ struct rockchip_usb2phy_port {
>  /**
>   * struct rockchip_usb2phy: usb2.0 phy driver data.
>   * @grf: General Register Files regmap.
> + * @usbgrf: USB General Register Files regmap.
>   * @clk: clock struct of phy input clk.
>   * @clk480m: clock struct of phy output clk.
>   * @clk_hw: clock struct of phy output clk management.
> @@ -216,6 +217,7 @@ struct rockchip_usb2phy_port {
>  struct rockchip_usb2phy {
>  	struct device	*dev;
>  	struct regmap	*grf;
> +	struct regmap	*usbgrf;
>  	struct clk	*clk;
>  	struct clk	*clk480m;
>  	struct clk_hw	clk480m_hw;
> @@ -225,9 +227,15 @@ struct rockchip_usb2phy {
>  	struct extcon_dev	*edev;
>  	const struct rockchip_usb2phy_cfg	*phy_cfg;
>  	struct rockchip_usb2phy_port	ports[USB2PHY_NUM_PORTS];
> +	unsigned int	companion_grf_quirk:1;
>  };
>  
> -static inline int property_enable(struct rockchip_usb2phy *rphy,
> +static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy)
> +{
> +	return rphy->companion_grf_quirk ? rphy->usbgrf : rphy->grf;
> +}
> +
> +static inline int property_enable(struct regmap *base,
>  				  const struct usb2phy_reg *reg, bool en)
>  {
>  	unsigned int val, mask, tmp;
> @@ -236,17 +244,17 @@ static inline int property_enable(struct rockchip_usb2phy *rphy,
>  	mask = GENMASK(reg->bitend, reg->bitstart);
>  	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)
>  {
>  	int ret;
>  	unsigned int tmp, orig;
>  	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)
>  		return false;
>  
> @@ -258,11 +266,12 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
>  {
>  	struct rockchip_usb2phy *rphy =
>  		container_of(hw, struct rockchip_usb2phy, clk480m_hw);
> +	struct regmap *base = get_reg_base(rphy);
>  	int ret;
>  
>  	/* turn on 480m clk output if it is off */
> -	if (!property_enabled(rphy, &rphy->phy_cfg->clkout_ctl)) {
> -		ret = property_enable(rphy, &rphy->phy_cfg->clkout_ctl, true);
> +	if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
> +		ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true);
>  		if (ret)
>  			return ret;
>  
> @@ -277,17 +286,19 @@ static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
>  {
>  	struct rockchip_usb2phy *rphy =
>  		container_of(hw, struct rockchip_usb2phy, clk480m_hw);
> +	struct regmap *base = get_reg_base(rphy);
>  
>  	/* 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)
>  {
>  	struct rockchip_usb2phy *rphy =
>  		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
> @@ -409,13 +420,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
>  		if (rport->mode != USB_DR_MODE_HOST &&
>  		    rport->mode != USB_DR_MODE_UNKNOWN) {
>  			/* clear bvalid status and enable bvalid detect irq */
> -			ret = property_enable(rphy,
> +			ret = property_enable(rphy->grf,
>  					      &rport->port_cfg->bvalid_det_clr,
>  					      true);
>  			if (ret)
>  				goto out;
>  
> -			ret = property_enable(rphy,
> +			ret = property_enable(rphy->grf,
>  					      &rport->port_cfg->bvalid_det_en,
>  					      true);
>  			if (ret)
> @@ -429,11 +440,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
>  		}
>  	} else if (rport->port_id == USB2PHY_PORT_HOST) {
>  		/* 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)
>  			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)
>  			goto out;
>  
> @@ -449,6 +462,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
>  {
>  	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
>  	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
> +	struct regmap *base = get_reg_base(rphy);
>  	int ret;
>  
>  	dev_dbg(&rport->phy->dev, "port power on\n");
> @@ -460,7 +474,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
>  	if (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)
>  		return ret;
>  
> @@ -475,6 +489,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
>  {
>  	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
>  	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
> +	struct regmap *base = get_reg_base(rphy);
>  	int ret;
>  
>  	dev_dbg(&rport->phy->dev, "port power off\n");
> @@ -482,7 +497,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
>  	if (rport->suspended)
>  		return 0;
>  
> -	ret = property_enable(rphy, &rport->port_cfg->phy_sus, true);
> +	ret = property_enable(base, &rport->port_cfg->phy_sus, true);
>  	if (ret)
>  		return ret;
>  
> @@ -526,11 +541,11 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
>  	bool vbus_attach, sch_work, notify_charger;
>  
>  	if (rport->utmi_avalid)
> -		vbus_attach =
> -			property_enabled(rphy, &rport->port_cfg->utmi_avalid);
> +		vbus_attach = property_enabled(rphy->grf,
> +					       &rport->port_cfg->utmi_avalid);
>  	else
> -		vbus_attach =
> -			property_enabled(rphy, &rport->port_cfg->utmi_bvalid);
> +		vbus_attach = property_enabled(rphy->grf,
> +					       &rport->port_cfg->utmi_bvalid);
>  
>  	sch_work = false;
>  	notify_charger = false;
> @@ -650,22 +665,28 @@ static const char *chg_to_string(enum power_supply_type chg_type)
>  static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
>  				    bool en)
>  {
> -	property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
> -	property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
> +	struct regmap *base = get_reg_base(rphy);
> +
> +	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,
>  					    bool en)
>  {
> -	property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en);
> -	property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
> +	struct regmap *base = get_reg_base(rphy);
> +
> +	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,
>  					      bool en)
>  {
> -	property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en);
> -	property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
> +	struct regmap *base = get_reg_base(rphy);
> +
> +	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)
> @@ -677,6 +698,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>  	struct rockchip_usb2phy_port *rport =
>  		container_of(work, struct rockchip_usb2phy_port, chg_work.work);
>  	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
> +	struct regmap *base = get_reg_base(rphy);
>  	bool is_dcd, tmout, vout;
>  	unsigned long delay;
>  
> @@ -687,7 +709,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>  		if (!rport->suspended)
>  			rockchip_usb2phy_power_off(rport->phy);
>  		/* 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 */
>  		rockchip_chg_enable_dcd(rphy, true);
>  		rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
> @@ -696,7 +718,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>  		break;
>  	case USB_CHG_STATE_WAIT_FOR_DCD:
>  		/* 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;
>  		/* stage 2 */
>  		if (is_dcd || tmout) {
> @@ -713,7 +736,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>  		}
>  		break;
>  	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);
>  		if (vout) {
>  			/* Voltage Source on DM, Probe on DP  */
> @@ -734,7 +758,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>  		}
>  		break;
>  	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 */
>  		rockchip_chg_enable_secondary_det(rphy, false);
>  		if (vout)
> @@ -748,7 +773,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>  		/* fall through */
>  	case USB_CHG_STATE_DETECTED:
>  		/* 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);
>  		dev_info(&rport->phy->dev, "charger = %s\n",
>  			 chg_to_string(rphy->chg_type));
> @@ -790,8 +815,7 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
>  	if (ret < 0)
>  		goto next_schedule;
>  
> -	ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset,
> -			  &uhd);
> +	ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd);
>  	if (ret < 0)
>  		goto next_schedule;
>  
> @@ -845,8 +869,8 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
>  		 * activate the linestate detection to get the next device
>  		 * plug-in irq.
>  		 */
> -		property_enable(rphy, &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_clr, 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
> @@ -869,14 +893,14 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
>  	struct rockchip_usb2phy_port *rport = data;
>  	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;
>  
>  	mutex_lock(&rport->mutex);
>  
>  	/* disable linestate detect irq and clear its status */
> -	property_enable(rphy, &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_en, false);
> +	property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
>  
>  	mutex_unlock(&rport->mutex);
>  
> @@ -896,13 +920,13 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
>  	struct rockchip_usb2phy_port *rport = data;
>  	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;
>  
>  	mutex_lock(&rport->mutex);
>  
>  	/* 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);
>  
> @@ -1045,6 +1069,18 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>  	if (IS_ERR(rphy->grf))
>  		return PTR_ERR(rphy->grf);
>  
> +	rphy->companion_grf_quirk =
> +		device_property_read_bool(dev, "rockchip,companion_grf_quirk");
> +	if (rphy->companion_grf_quirk) {
> +		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)) {
>  		dev_err(dev, "the reg property is not assigned in %s node\n",
>  			np->name);
>
Frank Wang Aug. 2, 2017, 6:50 a.m. UTC | #2
Hi Kishon,

On 2017/8/2 13:03, Kishon Vijay Abraham I wrote:
> Hi,
>
> On Tuesday 01 August 2017 01:42 PM, Frank Wang wrote:
>> The registers of usb-phy are distributed in grf and usbgrf on some
>> Rockchip SoCs (e.g RV1108), this patch add a quirk to support this
>> companion grf design.
>>
>> Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
>> ---
>>   .../bindings/phy/phy-rockchip-inno-usb2.txt        |   4 +
>>   drivers/phy/rockchip/phy-rockchip-inno-usb2.c      | 112 ++++++++++++++-------
>>   2 files changed, 78 insertions(+), 38 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt
>> index 84d59b0..ddf868a 100644
>> --- a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt
>> +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt
>> @@ -18,6 +18,10 @@ Optional properties:
>>   		 usb-phy output 480m and xin24m.
>>   		 Refer to clk/clock-bindings.txt for generic clock
>>   		 consumer properties.
>> + - rockchip,usbgrf : phandle to the syscon managing the "usb general
>> +		 register files".
>> + - rockchip,companion_grf_quirk : when set driver will request
>> +		 "rockchip,usbgrf" phandle as one companion-grf.
> please send the dt-bindings as a separate patch and cc devicetree list.

Noted and thanks for your comments, I will fix it.


BR.
Frank

> Thanks
> Kishon
>>   
>>   Required nodes : a sub-node is required for each port the phy provides.
>>   		 The sub-node name is used to identify host or otg port,
>> diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
>> index 626883d..669e5f6 100644
>> --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
>> +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
>> @@ -202,6 +202,7 @@ struct rockchip_usb2phy_port {
>>   /**
>>    * struct rockchip_usb2phy: usb2.0 phy driver data.
>>    * @grf: General Register Files regmap.
>> + * @usbgrf: USB General Register Files regmap.
>>    * @clk: clock struct of phy input clk.
>>    * @clk480m: clock struct of phy output clk.
>>    * @clk_hw: clock struct of phy output clk management.
>> @@ -216,6 +217,7 @@ struct rockchip_usb2phy_port {
>>   struct rockchip_usb2phy {
>>   	struct device	*dev;
>>   	struct regmap	*grf;
>> +	struct regmap	*usbgrf;
>>   	struct clk	*clk;
>>   	struct clk	*clk480m;
>>   	struct clk_hw	clk480m_hw;
>> @@ -225,9 +227,15 @@ struct rockchip_usb2phy {
>>   	struct extcon_dev	*edev;
>>   	const struct rockchip_usb2phy_cfg	*phy_cfg;
>>   	struct rockchip_usb2phy_port	ports[USB2PHY_NUM_PORTS];
>> +	unsigned int	companion_grf_quirk:1;
>>   };
>>   
>> -static inline int property_enable(struct rockchip_usb2phy *rphy,
>> +static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy)
>> +{
>> +	return rphy->companion_grf_quirk ? rphy->usbgrf : rphy->grf;
>> +}
>> +
>> +static inline int property_enable(struct regmap *base,
>>   				  const struct usb2phy_reg *reg, bool en)
>>   {
>>   	unsigned int val, mask, tmp;
>> @@ -236,17 +244,17 @@ static inline int property_enable(struct rockchip_usb2phy *rphy,
>>   	mask = GENMASK(reg->bitend, reg->bitstart);
>>   	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)
>>   {
>>   	int ret;
>>   	unsigned int tmp, orig;
>>   	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)
>>   		return false;
>>   
>> @@ -258,11 +266,12 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
>>   {
>>   	struct rockchip_usb2phy *rphy =
>>   		container_of(hw, struct rockchip_usb2phy, clk480m_hw);
>> +	struct regmap *base = get_reg_base(rphy);
>>   	int ret;
>>   
>>   	/* turn on 480m clk output if it is off */
>> -	if (!property_enabled(rphy, &rphy->phy_cfg->clkout_ctl)) {
>> -		ret = property_enable(rphy, &rphy->phy_cfg->clkout_ctl, true);
>> +	if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
>> +		ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true);
>>   		if (ret)
>>   			return ret;
>>   
>> @@ -277,17 +286,19 @@ static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
>>   {
>>   	struct rockchip_usb2phy *rphy =
>>   		container_of(hw, struct rockchip_usb2phy, clk480m_hw);
>> +	struct regmap *base = get_reg_base(rphy);
>>   
>>   	/* 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)
>>   {
>>   	struct rockchip_usb2phy *rphy =
>>   		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
>> @@ -409,13 +420,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
>>   		if (rport->mode != USB_DR_MODE_HOST &&
>>   		    rport->mode != USB_DR_MODE_UNKNOWN) {
>>   			/* clear bvalid status and enable bvalid detect irq */
>> -			ret = property_enable(rphy,
>> +			ret = property_enable(rphy->grf,
>>   					      &rport->port_cfg->bvalid_det_clr,
>>   					      true);
>>   			if (ret)
>>   				goto out;
>>   
>> -			ret = property_enable(rphy,
>> +			ret = property_enable(rphy->grf,
>>   					      &rport->port_cfg->bvalid_det_en,
>>   					      true);
>>   			if (ret)
>> @@ -429,11 +440,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
>>   		}
>>   	} else if (rport->port_id == USB2PHY_PORT_HOST) {
>>   		/* 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)
>>   			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)
>>   			goto out;
>>   
>> @@ -449,6 +462,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
>>   {
>>   	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
>>   	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
>> +	struct regmap *base = get_reg_base(rphy);
>>   	int ret;
>>   
>>   	dev_dbg(&rport->phy->dev, "port power on\n");
>> @@ -460,7 +474,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
>>   	if (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)
>>   		return ret;
>>   
>> @@ -475,6 +489,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
>>   {
>>   	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
>>   	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
>> +	struct regmap *base = get_reg_base(rphy);
>>   	int ret;
>>   
>>   	dev_dbg(&rport->phy->dev, "port power off\n");
>> @@ -482,7 +497,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
>>   	if (rport->suspended)
>>   		return 0;
>>   
>> -	ret = property_enable(rphy, &rport->port_cfg->phy_sus, true);
>> +	ret = property_enable(base, &rport->port_cfg->phy_sus, true);
>>   	if (ret)
>>   		return ret;
>>   
>> @@ -526,11 +541,11 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
>>   	bool vbus_attach, sch_work, notify_charger;
>>   
>>   	if (rport->utmi_avalid)
>> -		vbus_attach =
>> -			property_enabled(rphy, &rport->port_cfg->utmi_avalid);
>> +		vbus_attach = property_enabled(rphy->grf,
>> +					       &rport->port_cfg->utmi_avalid);
>>   	else
>> -		vbus_attach =
>> -			property_enabled(rphy, &rport->port_cfg->utmi_bvalid);
>> +		vbus_attach = property_enabled(rphy->grf,
>> +					       &rport->port_cfg->utmi_bvalid);
>>   
>>   	sch_work = false;
>>   	notify_charger = false;
>> @@ -650,22 +665,28 @@ static const char *chg_to_string(enum power_supply_type chg_type)
>>   static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
>>   				    bool en)
>>   {
>> -	property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
>> -	property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
>> +	struct regmap *base = get_reg_base(rphy);
>> +
>> +	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,
>>   					    bool en)
>>   {
>> -	property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en);
>> -	property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
>> +	struct regmap *base = get_reg_base(rphy);
>> +
>> +	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,
>>   					      bool en)
>>   {
>> -	property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en);
>> -	property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
>> +	struct regmap *base = get_reg_base(rphy);
>> +
>> +	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)
>> @@ -677,6 +698,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>>   	struct rockchip_usb2phy_port *rport =
>>   		container_of(work, struct rockchip_usb2phy_port, chg_work.work);
>>   	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
>> +	struct regmap *base = get_reg_base(rphy);
>>   	bool is_dcd, tmout, vout;
>>   	unsigned long delay;
>>   
>> @@ -687,7 +709,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>>   		if (!rport->suspended)
>>   			rockchip_usb2phy_power_off(rport->phy);
>>   		/* 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 */
>>   		rockchip_chg_enable_dcd(rphy, true);
>>   		rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
>> @@ -696,7 +718,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>>   		break;
>>   	case USB_CHG_STATE_WAIT_FOR_DCD:
>>   		/* 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;
>>   		/* stage 2 */
>>   		if (is_dcd || tmout) {
>> @@ -713,7 +736,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>>   		}
>>   		break;
>>   	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);
>>   		if (vout) {
>>   			/* Voltage Source on DM, Probe on DP  */
>> @@ -734,7 +758,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>>   		}
>>   		break;
>>   	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 */
>>   		rockchip_chg_enable_secondary_det(rphy, false);
>>   		if (vout)
>> @@ -748,7 +773,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
>>   		/* fall through */
>>   	case USB_CHG_STATE_DETECTED:
>>   		/* 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);
>>   		dev_info(&rport->phy->dev, "charger = %s\n",
>>   			 chg_to_string(rphy->chg_type));
>> @@ -790,8 +815,7 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
>>   	if (ret < 0)
>>   		goto next_schedule;
>>   
>> -	ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset,
>> -			  &uhd);
>> +	ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd);
>>   	if (ret < 0)
>>   		goto next_schedule;
>>   
>> @@ -845,8 +869,8 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
>>   		 * activate the linestate detection to get the next device
>>   		 * plug-in irq.
>>   		 */
>> -		property_enable(rphy, &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_clr, 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
>> @@ -869,14 +893,14 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
>>   	struct rockchip_usb2phy_port *rport = data;
>>   	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;
>>   
>>   	mutex_lock(&rport->mutex);
>>   
>>   	/* disable linestate detect irq and clear its status */
>> -	property_enable(rphy, &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_en, false);
>> +	property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
>>   
>>   	mutex_unlock(&rport->mutex);
>>   
>> @@ -896,13 +920,13 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
>>   	struct rockchip_usb2phy_port *rport = data;
>>   	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;
>>   
>>   	mutex_lock(&rport->mutex);
>>   
>>   	/* 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);
>>   
>> @@ -1045,6 +1069,18 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>>   	if (IS_ERR(rphy->grf))
>>   		return PTR_ERR(rphy->grf);
>>   
>> +	rphy->companion_grf_quirk =
>> +		device_property_read_bool(dev, "rockchip,companion_grf_quirk");
>> +	if (rphy->companion_grf_quirk) {
>> +		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)) {
>>   		dev_err(dev, "the reg property is not assigned in %s node\n",
>>   			np->name);
>>
>
>
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt
index 84d59b0..ddf868a 100644
--- a/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt
+++ b/Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.txt
@@ -18,6 +18,10 @@  Optional properties:
 		 usb-phy output 480m and xin24m.
 		 Refer to clk/clock-bindings.txt for generic clock
 		 consumer properties.
+ - rockchip,usbgrf : phandle to the syscon managing the "usb general
+		 register files".
+ - rockchip,companion_grf_quirk : when set driver will request
+		 "rockchip,usbgrf" phandle as one companion-grf.
 
 Required nodes : a sub-node is required for each port the phy provides.
 		 The sub-node name is used to identify host or otg port,
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
index 626883d..669e5f6 100644
--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -202,6 +202,7 @@  struct rockchip_usb2phy_port {
 /**
  * struct rockchip_usb2phy: usb2.0 phy driver data.
  * @grf: General Register Files regmap.
+ * @usbgrf: USB General Register Files regmap.
  * @clk: clock struct of phy input clk.
  * @clk480m: clock struct of phy output clk.
  * @clk_hw: clock struct of phy output clk management.
@@ -216,6 +217,7 @@  struct rockchip_usb2phy_port {
 struct rockchip_usb2phy {
 	struct device	*dev;
 	struct regmap	*grf;
+	struct regmap	*usbgrf;
 	struct clk	*clk;
 	struct clk	*clk480m;
 	struct clk_hw	clk480m_hw;
@@ -225,9 +227,15 @@  struct rockchip_usb2phy {
 	struct extcon_dev	*edev;
 	const struct rockchip_usb2phy_cfg	*phy_cfg;
 	struct rockchip_usb2phy_port	ports[USB2PHY_NUM_PORTS];
+	unsigned int	companion_grf_quirk:1;
 };
 
-static inline int property_enable(struct rockchip_usb2phy *rphy,
+static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy)
+{
+	return rphy->companion_grf_quirk ? rphy->usbgrf : rphy->grf;
+}
+
+static inline int property_enable(struct regmap *base,
 				  const struct usb2phy_reg *reg, bool en)
 {
 	unsigned int val, mask, tmp;
@@ -236,17 +244,17 @@  static inline int property_enable(struct rockchip_usb2phy *rphy,
 	mask = GENMASK(reg->bitend, reg->bitstart);
 	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)
 {
 	int ret;
 	unsigned int tmp, orig;
 	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)
 		return false;
 
@@ -258,11 +266,12 @@  static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
 {
 	struct rockchip_usb2phy *rphy =
 		container_of(hw, struct rockchip_usb2phy, clk480m_hw);
+	struct regmap *base = get_reg_base(rphy);
 	int ret;
 
 	/* turn on 480m clk output if it is off */
-	if (!property_enabled(rphy, &rphy->phy_cfg->clkout_ctl)) {
-		ret = property_enable(rphy, &rphy->phy_cfg->clkout_ctl, true);
+	if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
+		ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true);
 		if (ret)
 			return ret;
 
@@ -277,17 +286,19 @@  static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
 {
 	struct rockchip_usb2phy *rphy =
 		container_of(hw, struct rockchip_usb2phy, clk480m_hw);
+	struct regmap *base = get_reg_base(rphy);
 
 	/* 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)
 {
 	struct rockchip_usb2phy *rphy =
 		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
@@ -409,13 +420,13 @@  static int rockchip_usb2phy_init(struct phy *phy)
 		if (rport->mode != USB_DR_MODE_HOST &&
 		    rport->mode != USB_DR_MODE_UNKNOWN) {
 			/* clear bvalid status and enable bvalid detect irq */
-			ret = property_enable(rphy,
+			ret = property_enable(rphy->grf,
 					      &rport->port_cfg->bvalid_det_clr,
 					      true);
 			if (ret)
 				goto out;
 
-			ret = property_enable(rphy,
+			ret = property_enable(rphy->grf,
 					      &rport->port_cfg->bvalid_det_en,
 					      true);
 			if (ret)
@@ -429,11 +440,13 @@  static int rockchip_usb2phy_init(struct phy *phy)
 		}
 	} else if (rport->port_id == USB2PHY_PORT_HOST) {
 		/* 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)
 			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)
 			goto out;
 
@@ -449,6 +462,7 @@  static int rockchip_usb2phy_power_on(struct phy *phy)
 {
 	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
 	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
+	struct regmap *base = get_reg_base(rphy);
 	int ret;
 
 	dev_dbg(&rport->phy->dev, "port power on\n");
@@ -460,7 +474,7 @@  static int rockchip_usb2phy_power_on(struct phy *phy)
 	if (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)
 		return ret;
 
@@ -475,6 +489,7 @@  static int rockchip_usb2phy_power_off(struct phy *phy)
 {
 	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
 	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
+	struct regmap *base = get_reg_base(rphy);
 	int ret;
 
 	dev_dbg(&rport->phy->dev, "port power off\n");
@@ -482,7 +497,7 @@  static int rockchip_usb2phy_power_off(struct phy *phy)
 	if (rport->suspended)
 		return 0;
 
-	ret = property_enable(rphy, &rport->port_cfg->phy_sus, true);
+	ret = property_enable(base, &rport->port_cfg->phy_sus, true);
 	if (ret)
 		return ret;
 
@@ -526,11 +541,11 @@  static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
 	bool vbus_attach, sch_work, notify_charger;
 
 	if (rport->utmi_avalid)
-		vbus_attach =
-			property_enabled(rphy, &rport->port_cfg->utmi_avalid);
+		vbus_attach = property_enabled(rphy->grf,
+					       &rport->port_cfg->utmi_avalid);
 	else
-		vbus_attach =
-			property_enabled(rphy, &rport->port_cfg->utmi_bvalid);
+		vbus_attach = property_enabled(rphy->grf,
+					       &rport->port_cfg->utmi_bvalid);
 
 	sch_work = false;
 	notify_charger = false;
@@ -650,22 +665,28 @@  static const char *chg_to_string(enum power_supply_type chg_type)
 static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
 				    bool en)
 {
-	property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
-	property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
+	struct regmap *base = get_reg_base(rphy);
+
+	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,
 					    bool en)
 {
-	property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en);
-	property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
+	struct regmap *base = get_reg_base(rphy);
+
+	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,
 					      bool en)
 {
-	property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en);
-	property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
+	struct regmap *base = get_reg_base(rphy);
+
+	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)
@@ -677,6 +698,7 @@  static void rockchip_chg_detect_work(struct work_struct *work)
 	struct rockchip_usb2phy_port *rport =
 		container_of(work, struct rockchip_usb2phy_port, chg_work.work);
 	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
+	struct regmap *base = get_reg_base(rphy);
 	bool is_dcd, tmout, vout;
 	unsigned long delay;
 
@@ -687,7 +709,7 @@  static void rockchip_chg_detect_work(struct work_struct *work)
 		if (!rport->suspended)
 			rockchip_usb2phy_power_off(rport->phy);
 		/* 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 */
 		rockchip_chg_enable_dcd(rphy, true);
 		rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
@@ -696,7 +718,8 @@  static void rockchip_chg_detect_work(struct work_struct *work)
 		break;
 	case USB_CHG_STATE_WAIT_FOR_DCD:
 		/* 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;
 		/* stage 2 */
 		if (is_dcd || tmout) {
@@ -713,7 +736,8 @@  static void rockchip_chg_detect_work(struct work_struct *work)
 		}
 		break;
 	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);
 		if (vout) {
 			/* Voltage Source on DM, Probe on DP  */
@@ -734,7 +758,8 @@  static void rockchip_chg_detect_work(struct work_struct *work)
 		}
 		break;
 	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 */
 		rockchip_chg_enable_secondary_det(rphy, false);
 		if (vout)
@@ -748,7 +773,7 @@  static void rockchip_chg_detect_work(struct work_struct *work)
 		/* fall through */
 	case USB_CHG_STATE_DETECTED:
 		/* 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);
 		dev_info(&rport->phy->dev, "charger = %s\n",
 			 chg_to_string(rphy->chg_type));
@@ -790,8 +815,7 @@  static void rockchip_usb2phy_sm_work(struct work_struct *work)
 	if (ret < 0)
 		goto next_schedule;
 
-	ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset,
-			  &uhd);
+	ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd);
 	if (ret < 0)
 		goto next_schedule;
 
@@ -845,8 +869,8 @@  static void rockchip_usb2phy_sm_work(struct work_struct *work)
 		 * activate the linestate detection to get the next device
 		 * plug-in irq.
 		 */
-		property_enable(rphy, &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_clr, 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
@@ -869,14 +893,14 @@  static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
 	struct rockchip_usb2phy_port *rport = data;
 	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;
 
 	mutex_lock(&rport->mutex);
 
 	/* disable linestate detect irq and clear its status */
-	property_enable(rphy, &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_en, false);
+	property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
 
 	mutex_unlock(&rport->mutex);
 
@@ -896,13 +920,13 @@  static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
 	struct rockchip_usb2phy_port *rport = data;
 	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;
 
 	mutex_lock(&rport->mutex);
 
 	/* 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);
 
@@ -1045,6 +1069,18 @@  static int rockchip_usb2phy_probe(struct platform_device *pdev)
 	if (IS_ERR(rphy->grf))
 		return PTR_ERR(rphy->grf);
 
+	rphy->companion_grf_quirk =
+		device_property_read_bool(dev, "rockchip,companion_grf_quirk");
+	if (rphy->companion_grf_quirk) {
+		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)) {
 		dev_err(dev, "the reg property is not assigned in %s node\n",
 			np->name);