mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
phy: rockchip: inno-usb2: refactor irq init for otg and host ports
Add common helper function rockchip_usb2phy_port_irq_init() for both otg port and host port to init their own irqs. It can help to reduce redundant code, and also fix a issue that the id irq isn't enabled for otg port if the vbus_always_on flag is true. This patch introduces a combined irq for some inno usb2 phys which combined the irqs of otg port and host port. We will used it for RK3568 later. Change-Id: Ifa74ec72e2b9d4ed62ee69e916b8ab2e8ae665b3 Signed-off-by: William Wu <william.wu@rock-chips.com> Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
This commit is contained in:
@@ -268,6 +268,8 @@ struct rockchip_usb2phy_port {
|
||||
* @dcd_retries: The retry count used to track Data contact
|
||||
* detection process.
|
||||
* @edev_self: represent the source of extcon.
|
||||
* @irq: IRQ number assigned for phy which combined irqs of
|
||||
* otg port and host port.
|
||||
* @edev: extcon device for notification registration
|
||||
* @phy_cfg: phy register configuration, assigned by driver data.
|
||||
* @ports: phy port instance.
|
||||
@@ -284,6 +286,7 @@ struct rockchip_usb2phy {
|
||||
u8 dcd_retries;
|
||||
u8 primary_retries;
|
||||
bool edev_self;
|
||||
int irq;
|
||||
struct extcon_dev *edev;
|
||||
const struct rockchip_usb2phy_cfg *phy_cfg;
|
||||
struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS];
|
||||
@@ -625,18 +628,9 @@ static int rockchip_usb2phy_init(struct phy *phy)
|
||||
|
||||
mutex_lock(&rport->mutex);
|
||||
|
||||
if (rport->port_id == USB2PHY_PORT_OTG &&
|
||||
rport->bvalid_irq > 0) {
|
||||
/* clear bvalid status and enable bvalid detect irq */
|
||||
ret = rockchip_usb2phy_enable_vbus_irq(rphy, rport, true);
|
||||
if (ret) {
|
||||
dev_err(rphy->dev,
|
||||
"failed to enable bvalid irq\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rport->port_id == USB2PHY_PORT_OTG) {
|
||||
/* clear id status and enable id detect irq */
|
||||
if (rport->id_irq > 0) {
|
||||
if (rport->id_irq > 0 || rport->otg_mux_irq > 0) {
|
||||
ret = rockchip_usb2phy_enable_id_irq(rphy, rport,
|
||||
true);
|
||||
if (ret) {
|
||||
@@ -646,8 +640,20 @@ static int rockchip_usb2phy_init(struct phy *phy)
|
||||
}
|
||||
}
|
||||
|
||||
schedule_delayed_work(&rport->otg_sm_work,
|
||||
OTG_SCHEDULE_DELAY);
|
||||
/* clear bvalid status and enable bvalid detect irq */
|
||||
if ((rport->bvalid_irq > 0 || rport->otg_mux_irq > 0) &&
|
||||
!rport->vbus_always_on) {
|
||||
ret = rockchip_usb2phy_enable_vbus_irq(rphy, rport,
|
||||
true);
|
||||
if (ret) {
|
||||
dev_err(rphy->dev,
|
||||
"failed to enable bvalid irq\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
schedule_delayed_work(&rport->otg_sm_work,
|
||||
OTG_SCHEDULE_DELAY);
|
||||
}
|
||||
} else if (rport->port_id == USB2PHY_PORT_HOST) {
|
||||
/* clear linestate and enable linestate detect irq */
|
||||
ret = rockchip_usb2phy_enable_line_irq(rphy, rport, true);
|
||||
@@ -1459,17 +1465,6 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t rockchip_usb2phy_otg_mux_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->grf, &rport->port_cfg->bvalid_det_st))
|
||||
return rockchip_usb2phy_bvalid_irq(irq, data);
|
||||
else
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static irqreturn_t rockchip_usb2phy_id_irq(int irq, void *data)
|
||||
{
|
||||
struct rockchip_usb2phy_port *rport = data;
|
||||
@@ -1507,6 +1502,123 @@ static irqreturn_t rockchip_usb2phy_id_irq(int irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t rockchip_usb2phy_otg_mux_irq(int irq, void *data)
|
||||
{
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
ret = rockchip_usb2phy_id_irq(irq, data);
|
||||
ret |= rockchip_usb2phy_bvalid_irq(irq, data);
|
||||
ret |= rockchip_usb2phy_linestate_irq(irq, data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rockchip_usb2phy_port_irq_init(struct rockchip_usb2phy *rphy,
|
||||
struct rockchip_usb2phy_port *rport,
|
||||
struct device_node *child_np)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If the usb2 phy used combined irq for otg and host port,
|
||||
* don't need to init otg and host port irq separately.
|
||||
*/
|
||||
if (rphy->irq > 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Some SoCs (e.g. RV1108) use one combined irq for all of
|
||||
* the irqs of otg port. So probe the otg-mux interrupt first,
|
||||
* if not found, then init the regular irqs one by one.
|
||||
*/
|
||||
rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux");
|
||||
if (rport->otg_mux_irq > 0) {
|
||||
ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq,
|
||||
NULL,
|
||||
rockchip_usb2phy_otg_mux_irq,
|
||||
IRQF_ONESHOT,
|
||||
"rockchip_usb2phy_otg",
|
||||
rport);
|
||||
if (ret)
|
||||
dev_err(rphy->dev,
|
||||
"failed to request otg-mux irq handle\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Init linestate irq for both otg port and host port */
|
||||
rport->ls_irq = of_irq_get_byname(child_np, "linestate");
|
||||
if (rport->ls_irq <= 0) {
|
||||
dev_err(rphy->dev, "no linestate irq provided\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL,
|
||||
rockchip_usb2phy_linestate_irq,
|
||||
IRQF_ONESHOT,
|
||||
"rockchip_usb2phy", rport);
|
||||
if (ret) {
|
||||
dev_err(rphy->dev, "failed to request linestate irq handle\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's host port or it's otg port but only support
|
||||
* host mode, return immediately without init the bvalid
|
||||
* and id irqs/
|
||||
*/
|
||||
if (rport->port_id == USB2PHY_PORT_HOST ||
|
||||
rport->mode == USB_DR_MODE_HOST ||
|
||||
rport->mode == USB_DR_MODE_UNKNOWN)
|
||||
return ret;
|
||||
|
||||
/* Init the bvalid irq for otg port */
|
||||
if (!rport->vbus_always_on) {
|
||||
rport->bvalid_irq = of_irq_get_byname(child_np,
|
||||
"otg-bvalid");
|
||||
if (rport->bvalid_irq <= 0) {
|
||||
dev_err(rphy->dev, "no bvalid irq provided\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(rphy->dev,
|
||||
rport->bvalid_irq,
|
||||
NULL,
|
||||
rockchip_usb2phy_bvalid_irq,
|
||||
IRQF_ONESHOT,
|
||||
"rockchip_usb2phy_bvalid",
|
||||
rport);
|
||||
if (ret) {
|
||||
dev_err(rphy->dev,
|
||||
"failed to request otg-bvalid irq handle\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Init the id irq for otg port */
|
||||
if (rphy->edev_self) {
|
||||
rport->id_irq = of_irq_get_byname(child_np, "otg-id");
|
||||
if (rport->id_irq <= 0) {
|
||||
dev_err(rphy->dev, "no otg id irq provided\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(rphy->dev,
|
||||
rport->id_irq, NULL,
|
||||
rockchip_usb2phy_id_irq,
|
||||
IRQF_ONESHOT,
|
||||
"rockchip_usb2phy_id",
|
||||
rport);
|
||||
if (ret) {
|
||||
dev_err(rphy->dev,
|
||||
"failed to request otg-id irq handle\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
|
||||
struct rockchip_usb2phy_port *rport,
|
||||
struct device_node *child_np)
|
||||
@@ -1524,18 +1636,9 @@ static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
|
||||
mutex_init(&rport->mutex);
|
||||
INIT_DELAYED_WORK(&rport->sm_work, rockchip_usb2phy_sm_work);
|
||||
|
||||
rport->ls_irq = of_irq_get_byname(child_np, "linestate");
|
||||
if (rport->ls_irq < 0) {
|
||||
dev_err(rphy->dev, "no linestate irq provided\n");
|
||||
return rport->ls_irq;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL,
|
||||
rockchip_usb2phy_linestate_irq,
|
||||
IRQF_ONESHOT,
|
||||
"rockchip_usb2phy", rport);
|
||||
ret = rockchip_usb2phy_port_irq_init(rphy, rport, child_np);
|
||||
if (ret) {
|
||||
dev_err(rphy->dev, "failed to request linestate irq handle\n");
|
||||
dev_err(rphy->dev, "failed to init irq for host port\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1600,26 +1703,31 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
|
||||
dev_warn(&rport->phy->dev, "Failed to get VBUS supply regulator\n");
|
||||
dev_warn(&rport->phy->dev, "No vbus specified for otg port\n");
|
||||
rport->vbus = NULL;
|
||||
}
|
||||
|
||||
rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
|
||||
if (rport->mode == USB_DR_MODE_HOST ||
|
||||
rport->mode == USB_DR_MODE_UNKNOWN) {
|
||||
if (rphy->edev_self) {
|
||||
extcon_set_state(rphy->edev, EXTCON_USB, false);
|
||||
extcon_set_state(rphy->edev, EXTCON_USB_HOST, true);
|
||||
/* Enable VBUS supply */
|
||||
extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, true);
|
||||
ret = rockchip_set_vbus_power(rport, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
goto out;
|
||||
iddig = property_enabled(rphy->grf, &rport->port_cfg->utmi_iddig);
|
||||
if (rphy->edev_self && (rport->mode == USB_DR_MODE_HOST ||
|
||||
rport->mode == USB_DR_MODE_UNKNOWN || !iddig)) {
|
||||
/* Enable VBUS supply for otg port */
|
||||
extcon_set_state(rphy->edev, EXTCON_USB, false);
|
||||
extcon_set_state(rphy->edev, EXTCON_USB_HOST, true);
|
||||
extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, true);
|
||||
ret = rockchip_set_vbus_power(rport, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rport->vbus_always_on)
|
||||
ret = rockchip_usb2phy_port_irq_init(rphy, rport, child_np);
|
||||
if (ret) {
|
||||
dev_err(rphy->dev, "failed to init irq for otg port\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (rport->vbus_always_on || rport->mode == USB_DR_MODE_HOST ||
|
||||
rport->mode == USB_DR_MODE_UNKNOWN)
|
||||
goto out;
|
||||
|
||||
wake_lock_init(&rport->wakelock, WAKE_LOCK_SUSPEND, "rockchip_otg");
|
||||
@@ -1628,90 +1736,6 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
|
||||
INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
|
||||
INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work);
|
||||
|
||||
/*
|
||||
* Some SoCs use one interrupt with otg-id/otg-bvalid/linestate
|
||||
* interrupts muxed together, so probe the otg-mux interrupt first,
|
||||
* if not found, then look for the regular interrupts one by one.
|
||||
*/
|
||||
rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux");
|
||||
if (rport->otg_mux_irq > 0) {
|
||||
ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq,
|
||||
NULL,
|
||||
rockchip_usb2phy_otg_mux_irq,
|
||||
IRQF_ONESHOT,
|
||||
"rockchip_usb2phy_otg",
|
||||
rport);
|
||||
if (ret) {
|
||||
dev_err(rphy->dev,
|
||||
"failed to request otg-mux irq handle\n");
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
|
||||
if (rport->bvalid_irq < 0) {
|
||||
dev_err(rphy->dev, "no vbus valid irq provided\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq,
|
||||
NULL,
|
||||
rockchip_usb2phy_bvalid_irq,
|
||||
IRQF_ONESHOT,
|
||||
"rockchip_usb2phy_bvalid",
|
||||
rport);
|
||||
if (ret) {
|
||||
dev_err(rphy->dev,
|
||||
"failed to request otg-bvalid irq handle\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
rport->ls_irq = of_irq_get_byname(child_np, "linestate");
|
||||
if (rport->ls_irq < 0) {
|
||||
dev_err(rphy->dev, "no linestate irq provided\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(rphy->dev, rport->ls_irq, NULL,
|
||||
rockchip_usb2phy_linestate_irq,
|
||||
IRQF_ONESHOT,
|
||||
"rockchip_usb2phy", rport);
|
||||
if (ret) {
|
||||
dev_err(rphy->dev, "failed to request linestate irq handle\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (rphy->edev_self) {
|
||||
rport->id_irq = of_irq_get_byname(child_np, "otg-id");
|
||||
if (rport->id_irq < 0) {
|
||||
dev_err(rphy->dev, "no otg id irq provided\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(rphy->dev, rport->id_irq, NULL,
|
||||
rockchip_usb2phy_id_irq,
|
||||
IRQF_ONESHOT,
|
||||
"rockchip_usb2phy_id", rport);
|
||||
if (ret) {
|
||||
dev_err(rphy->dev, "failed to request otg-id irq handle\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
iddig = property_enabled(rphy->grf, &rport->port_cfg->utmi_iddig);
|
||||
if (!iddig) {
|
||||
extcon_set_state(rphy->edev, EXTCON_USB, false);
|
||||
extcon_set_state(rphy->edev, EXTCON_USB_HOST, true);
|
||||
extcon_set_state(rphy->edev, EXTCON_USB_VBUS_EN, true);
|
||||
/* Enable VBUS supply */
|
||||
ret = rockchip_set_vbus_power(rport, true);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_ERR(rphy->edev)) {
|
||||
rport->event_nb.notifier_call = rockchip_otg_event;
|
||||
|
||||
@@ -1792,6 +1816,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
|
||||
rphy->chg_state = USB_CHG_STATE_UNDEFINED;
|
||||
rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
|
||||
rphy->edev_self = false;
|
||||
rphy->irq = platform_get_irq(pdev, 0);
|
||||
platform_set_drvdata(pdev, rphy);
|
||||
|
||||
ret = rockchip_usb2phy_extcon_register(rphy);
|
||||
|
||||
Reference in New Issue
Block a user