lkml.org 
[lkml]   [2021]   [Jul]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH 6/9] phy: phy-rockchip-inno-usb2: support muxed interrupts
    Date
    The rk3568 usb2phy has a single muxed interrupt that handles all
    interrupts.
    Allow the driver to plug in only a single interrupt as necessary.

    This currently only supports the host configuration for the new phy.

    Signed-off-by: Peter Geis <pgwipeout@gmail.com>
    ---
    drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 168 +++++++++++++-----
    1 file changed, 119 insertions(+), 49 deletions(-)

    diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
    index 84a0c1d697da..fdeb2e7c937a 100644
    --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
    +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
    @@ -204,6 +204,7 @@ struct rockchip_usb2phy_port {
    * @dcd_retries: The retry count used to track Data contact
    * detection process.
    * @edev: extcon device for notification registration
    + * @irq: muxed interrupt for single irq configuration
    * @phy_cfg: phy register configuration, assigned by driver data.
    * @ports: phy port instance.
    */
    @@ -218,6 +219,7 @@ struct rockchip_usb2phy {
    enum power_supply_type chg_type;
    u8 dcd_retries;
    struct extcon_dev *edev;
    + int irq;
    const struct rockchip_usb2phy_cfg *phy_cfg;
    struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS];
    };
    @@ -934,6 +936,102 @@ static irqreturn_t rockchip_usb2phy_otg_mux_irq(int irq, void *data)
    return IRQ_NONE;
    }

    +static irqreturn_t rockchip_usb2phy_irq(int irq, void *data)
    +{
    + struct rockchip_usb2phy *rphy = data;
    + struct rockchip_usb2phy_port *rport;
    + irqreturn_t ret = IRQ_NONE;
    + unsigned int index;
    +
    + for (index = 0; index < rphy->phy_cfg->num_ports; index++) {
    + rport = &rphy->ports[index];
    + if (!rport->phy)
    + continue;
    +
    + /* Handle linestate irq for both otg port and host port */
    + ret = rockchip_usb2phy_linestate_irq(irq, rport);
    + }
    +
    + 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;
    +
    + switch (rport->port_id) {
    + case USB2PHY_PORT_HOST:
    + 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);
    + if (ret) {
    + dev_err(rphy->dev, "failed to request linestate irq handle\n");
    + return ret;
    + }
    + break;
    + case USB2PHY_PORT_OTG:
    + /*
    + * 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");
    + return ret;
    + }
    + } 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 = rport->bvalid_irq;
    + return ret;
    + }
    +
    + 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;
    + }
    + }
    + break;
    + default:
    + return -EINVAL;
    + }
    +
    + return 0;
    +}
    +
    static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
    struct rockchip_usb2phy_port *rport,
    struct device_node *child_np)
    @@ -947,18 +1045,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 setup host irq\n");
    return ret;
    }

    @@ -1007,44 +1096,10 @@ 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 out;
    - }
    - } 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 = rport->bvalid_irq;
    - goto out;
    - }
    -
    - 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 out;
    - }
    - }
    + ret = rockchip_usb2phy_port_irq_init(rphy, rport, child_np);
    + if (ret) {
    + dev_err(rphy->dev, "failed to init irq for host port\n");
    + goto out;

    if (!IS_ERR(rphy->edev)) {
    rport->event_nb.notifier_call = rockchip_otg_event;
    @@ -1124,6 +1179,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
    phy_cfgs = match->data;
    rphy->chg_state = USB_CHG_STATE_UNDEFINED;
    rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
    + rphy->irq = platform_get_irq(pdev, 0);
    platform_set_drvdata(pdev, rphy);

    ret = rockchip_usb2phy_extcon_register(rphy);
    @@ -1201,6 +1257,20 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
    }

    provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
    +
    + if (rphy->irq > 0) {
    + ret = devm_request_threaded_irq(rphy->dev, rphy->irq, NULL,
    + rockchip_usb2phy_irq,
    + IRQF_ONESHOT,
    + "rockchip_usb2phy",
    + rphy);
    + if (ret) {
    + dev_err(rphy->dev,
    + "failed to request usb2phy irq handle\n");
    + goto put_child;
    + }
    + }
    +
    return PTR_ERR_OR_ZERO(provider);

    put_child:
    --
    2.25.1
    \
     
     \ /
      Last update: 2021-07-28 14:27    [W:3.436 / U:1.420 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site