phy: rockchip-inno-usb2: Handle ID IRQ
authorSamuel Holland <samuel@sholland.org>
Thu, 14 Apr 2022 03:22:57 +0000 (22:22 -0500)
committerVinod Koul <vkoul@kernel.org>
Wed, 20 Apr 2022 09:14:04 +0000 (14:44 +0530)
This supports detecting host mode for the OTG port without an extcon.

The rv1108 properties are not updated due to lack of documentation.

Signed-off-by: Samuel Holland <samuel@sholland.org>
Tested-by: Michael Riesch <michael.riesch@wolfvision.net>
Link: https://lore.kernel.org/r/20220414032258.40984-7-samuel@sholland.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/phy/rockchip/phy-rockchip-inno-usb2.c

index 2b29f5dd88736b7781994b1e774d2f4c6169e3a4..e377b958d9b644ef1782cf3ebcf15217c2d7cec4 100644 (file)
@@ -116,11 +116,15 @@ struct rockchip_chg_det_reg {
  * @bvalid_det_en: vbus valid rise detection enable register.
  * @bvalid_det_st: vbus valid rise detection status register.
  * @bvalid_det_clr: vbus valid rise detection clear register.
+ * @id_det_en: id detection enable register.
+ * @id_det_st: id detection state register.
+ * @id_det_clr: id detection clear register.
  * @ls_det_en: linestate detection enable register.
  * @ls_det_st: linestate detection state register.
  * @ls_det_clr: linestate detection clear register.
  * @utmi_avalid: utmi vbus avalid status register.
  * @utmi_bvalid: utmi vbus bvalid status register.
+ * @utmi_id: utmi id state register.
  * @utmi_ls: utmi linestate state register.
  * @utmi_hstdet: utmi host disconnect register.
  */
@@ -129,11 +133,15 @@ struct rockchip_usb2phy_port_cfg {
        struct usb2phy_reg      bvalid_det_en;
        struct usb2phy_reg      bvalid_det_st;
        struct usb2phy_reg      bvalid_det_clr;
+       struct usb2phy_reg      id_det_en;
+       struct usb2phy_reg      id_det_st;
+       struct usb2phy_reg      id_det_clr;
        struct usb2phy_reg      ls_det_en;
        struct usb2phy_reg      ls_det_st;
        struct usb2phy_reg      ls_det_clr;
        struct usb2phy_reg      utmi_avalid;
        struct usb2phy_reg      utmi_bvalid;
+       struct usb2phy_reg      utmi_id;
        struct usb2phy_reg      utmi_ls;
        struct usb2phy_reg      utmi_hstdet;
 };
@@ -161,6 +169,7 @@ struct rockchip_usb2phy_cfg {
  * @suspended: phy suspended flag.
  * @vbus_attached: otg device vbus status.
  * @bvalid_irq: IRQ number assigned for vbus valid rise detection.
+ * @id_irq: IRQ number assigned for ID pin detection.
  * @ls_irq: IRQ number assigned for linestate detection.
  * @otg_mux_irq: IRQ number which multiplex otg-id/otg-bvalid/linestate
  *              irqs to one irq in otg-port.
@@ -179,6 +188,7 @@ struct rockchip_usb2phy_port {
        bool            suspended;
        bool            vbus_attached;
        int             bvalid_irq;
+       int             id_irq;
        int             ls_irq;
        int             otg_mux_irq;
        struct mutex    mutex;
@@ -419,6 +429,19 @@ static int rockchip_usb2phy_init(struct phy *phy)
                        if (ret)
                                goto out;
 
+                       /* clear id status and enable id detect irq */
+                       ret = property_enable(rphy->grf,
+                                             &rport->port_cfg->id_det_clr,
+                                             true);
+                       if (ret)
+                               goto out;
+
+                       ret = property_enable(rphy->grf,
+                                             &rport->port_cfg->id_det_en,
+                                             true);
+                       if (ret)
+                               goto out;
+
                        schedule_delayed_work(&rport->otg_sm_work,
                                              OTG_SCHEDULE_DELAY * 3);
                } else {
@@ -913,11 +936,30 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static irqreturn_t rockchip_usb2phy_id_irq(int irq, void *data)
+{
+       struct rockchip_usb2phy_port *rport = data;
+       struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
+       bool id;
+
+       if (!property_enabled(rphy->grf, &rport->port_cfg->id_det_st))
+               return IRQ_NONE;
+
+       /* clear id detect irq pending status */
+       property_enable(rphy->grf, &rport->port_cfg->id_det_clr, true);
+
+       id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id);
+       extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id);
+
+       return IRQ_HANDLED;
+}
+
 static irqreturn_t rockchip_usb2phy_otg_mux_irq(int irq, void *data)
 {
        irqreturn_t ret = IRQ_NONE;
 
        ret |= rockchip_usb2phy_bvalid_irq(irq, data);
+       ret |= rockchip_usb2phy_id_irq(irq, data);
 
        return ret;
 }
@@ -1015,6 +1057,25 @@ static int rockchip_usb2phy_port_irq_init(struct rockchip_usb2phy *rphy,
                                        "failed to request otg-bvalid irq handle\n");
                                return ret;
                        }
+
+                       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 = rport->id_irq;
+                               return ret;
+                       }
+
+                       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;
+                       }
                }
                break;
        default:
@@ -1289,10 +1350,14 @@ static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = {
                                .bvalid_det_en  = { 0x0680, 3, 3, 0, 1 },
                                .bvalid_det_st  = { 0x0690, 3, 3, 0, 1 },
                                .bvalid_det_clr = { 0x06a0, 3, 3, 0, 1 },
+                               .id_det_en      = { 0x0680, 6, 5, 0, 3 },
+                               .id_det_st      = { 0x0690, 6, 5, 0, 3 },
+                               .id_det_clr     = { 0x06a0, 6, 5, 0, 3 },
                                .ls_det_en      = { 0x0680, 2, 2, 0, 1 },
                                .ls_det_st      = { 0x0690, 2, 2, 0, 1 },
                                .ls_det_clr     = { 0x06a0, 2, 2, 0, 1 },
                                .utmi_bvalid    = { 0x0480, 4, 4, 0, 1 },
+                               .utmi_id        = { 0x0480, 1, 1, 0, 1 },
                                .utmi_ls        = { 0x0480, 3, 2, 0, 1 },
                        },
                        [USB2PHY_PORT_HOST] = {
@@ -1348,11 +1413,15 @@ static const struct rockchip_usb2phy_cfg rk3308_phy_cfgs[] = {
                                .bvalid_det_en  = { 0x3020, 3, 2, 0, 3 },
                                .bvalid_det_st  = { 0x3024, 3, 2, 0, 3 },
                                .bvalid_det_clr = { 0x3028, 3, 2, 0, 3 },
+                               .id_det_en      = { 0x3020, 5, 4, 0, 3 },
+                               .id_det_st      = { 0x3024, 5, 4, 0, 3 },
+                               .id_det_clr     = { 0x3028, 5, 4, 0, 3 },
                                .ls_det_en      = { 0x3020, 0, 0, 0, 1 },
                                .ls_det_st      = { 0x3024, 0, 0, 0, 1 },
                                .ls_det_clr     = { 0x3028, 0, 0, 0, 1 },
                                .utmi_avalid    = { 0x0120, 10, 10, 0, 1 },
                                .utmi_bvalid    = { 0x0120, 9, 9, 0, 1 },
+                               .utmi_id        = { 0x0120, 6, 6, 0, 1 },
                                .utmi_ls        = { 0x0120, 5, 4, 0, 1 },
                        },
                        [USB2PHY_PORT_HOST] = {
@@ -1391,11 +1460,15 @@ static const struct rockchip_usb2phy_cfg rk3328_phy_cfgs[] = {
                                .bvalid_det_en  = { 0x0110, 3, 2, 0, 3 },
                                .bvalid_det_st  = { 0x0114, 3, 2, 0, 3 },
                                .bvalid_det_clr = { 0x0118, 3, 2, 0, 3 },
+                               .id_det_en      = { 0x0110, 5, 4, 0, 3 },
+                               .id_det_st      = { 0x0114, 5, 4, 0, 3 },
+                               .id_det_clr     = { 0x0118, 5, 4, 0, 3 },
                                .ls_det_en      = { 0x0110, 0, 0, 0, 1 },
                                .ls_det_st      = { 0x0114, 0, 0, 0, 1 },
                                .ls_det_clr     = { 0x0118, 0, 0, 0, 1 },
                                .utmi_avalid    = { 0x0120, 10, 10, 0, 1 },
                                .utmi_bvalid    = { 0x0120, 9, 9, 0, 1 },
+                               .utmi_id        = { 0x0120, 6, 6, 0, 1 },
                                .utmi_ls        = { 0x0120, 5, 4, 0, 1 },
                        },
                        [USB2PHY_PORT_HOST] = {
@@ -1453,8 +1526,12 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
                                .bvalid_det_en  = { 0xe3c0, 3, 3, 0, 1 },
                                .bvalid_det_st  = { 0xe3e0, 3, 3, 0, 1 },
                                .bvalid_det_clr = { 0xe3d0, 3, 3, 0, 1 },
+                               .id_det_en      = { 0xe3c0, 5, 4, 0, 3 },
+                               .id_det_st      = { 0xe3e0, 5, 4, 0, 3 },
+                               .id_det_clr     = { 0xe3d0, 5, 4, 0, 3 },
                                .utmi_avalid    = { 0xe2ac, 7, 7, 0, 1 },
                                .utmi_bvalid    = { 0xe2ac, 12, 12, 0, 1 },
+                               .utmi_id        = { 0xe2ac, 8, 8, 0, 1 },
                        },
                        [USB2PHY_PORT_HOST] = {
                                .phy_sus        = { 0xe458, 1, 0, 0x2, 0x1 },
@@ -1488,8 +1565,12 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
                                .bvalid_det_en  = { 0xe3c0, 8, 8, 0, 1 },
                                .bvalid_det_st  = { 0xe3e0, 8, 8, 0, 1 },
                                .bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 },
+                               .id_det_en      = { 0xe3c0, 10, 9, 0, 3 },
+                               .id_det_st      = { 0xe3e0, 10, 9, 0, 3 },
+                               .id_det_clr     = { 0xe3d0, 10, 9, 0, 3 },
                                .utmi_avalid    = { 0xe2ac, 10, 10, 0, 1 },
                                .utmi_bvalid    = { 0xe2ac, 16, 16, 0, 1 },
+                               .utmi_id        = { 0xe2ac, 11, 11, 0, 1 },
                        },
                        [USB2PHY_PORT_HOST] = {
                                .phy_sus        = { 0xe468, 1, 0, 0x2, 0x1 },
@@ -1515,8 +1596,12 @@ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = {
                                .bvalid_det_en  = { 0x0080, 3, 2, 0, 3 },
                                .bvalid_det_st  = { 0x0084, 3, 2, 0, 3 },
                                .bvalid_det_clr = { 0x0088, 3, 2, 0, 3 },
+                               .id_det_en      = { 0x0080, 5, 4, 0, 3 },
+                               .id_det_st      = { 0x0084, 5, 4, 0, 3 },
+                               .id_det_clr     = { 0x0088, 5, 4, 0, 3 },
                                .utmi_avalid    = { 0x00c0, 10, 10, 0, 1 },
                                .utmi_bvalid    = { 0x00c0, 9, 9, 0, 1 },
+                               .utmi_id        = { 0x00c0, 6, 6, 0, 1 },
                        },
                        [USB2PHY_PORT_HOST] = {
                                /* Select suspend control from controller */