From: Jiebing Li <[email protected]>

This patch implements ACA device detection in transceiver driver.
There's no real ACA device yet so the function has not been
fully tested.

Signed-off-by: Jiebing Li <[email protected]>
---
 drivers/usb/otg/penwell_otg.c   |  102 +++++++++++++++++++++++++++++++++++++++
 include/linux/usb/penwell_otg.h |    5 ++
 2 files changed, 107 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/otg/penwell_otg.c b/drivers/usb/otg/penwell_otg.c
index 724a516..229a1ee 100644
--- a/drivers/usb/otg/penwell_otg.c
+++ b/drivers/usb/otg/penwell_otg.c
@@ -1077,6 +1077,10 @@ static irqreturn_t otg_irq(int irq, void *_dev)
        struct intel_mid_otg_xceiv      *iotg = &pnw->iotg;
        int                             flag = 0;
        u32                             int_sts, int_en, int_mask = 0;
+       u8                              int_vs4_aca = 0;
+       u8                              int_vs5_aca = 0;
+       u8                              int_vs2_aca = 0;
+       struct iotg_ulpi_access_ops     *ops;
 
        /* Check VBUS/SRP interrup */
        int_sts = readl(pnw->iotg.base + CI_OTGSC);
@@ -1132,6 +1136,49 @@ static irqreturn_t otg_irq(int irq, void *_dev)
                                pnw->iotg.base + CI_OTGSC);
        }
 
+       /* ACA device detection */
+       ops = &iotg->ulpi_ops;
+
+       ops->read(iotg, ULPI_TI_VS4, &int_vs4_aca);
+
+       if (int_vs4_aca & TI_ACA_DET_EN) {
+               ops->read(iotg, ULPI_TI_VS5, &int_vs5_aca);
+
+               /* ulpi read will clear related bits according to TI spec*/
+               ops->read(iotg, ULPI_TI_VS2_LATCH, &int_vs2_aca);
+
+               /*
+                * not sure if OTGSC_IDIS can cover this
+                * when no charger is attached
+               if (int_vs5_aca & TI_ID_FLOAT_EN) {
+                       iotg->hsm.id =
+                       (int_vs2_aca & TI_ID_FLOAT_STS) ? ID_B : ID_A;
+                       flag = 1;
+               }
+               */
+
+               if (int_vs5_aca & TI_ID_RES_EN)
+                       switch (TI_ID_RARBRC_STS(int_vs2_aca)) {
+                       case TI_ID_RARBRC_A:
+                               iotg->hsm.id = ID_ACA_A;
+                               flag = 1;
+                               break;
+                       case TI_ID_RARBRC_B:
+                               iotg->hsm.id = ID_ACA_B;
+                               flag = 1;
+                               break;
+                       case TI_ID_RARBRC_C:
+                               iotg->hsm.id = ID_ACA_C;
+                               flag = 1;
+                               break;
+                       default:
+                               break;
+                       }
+
+               dev_dbg(pnw->dev, "%s: id change int = %d\n",
+                                       __func__, iotg->hsm.id);
+       }
+
        if (flag)
                penwell_update_transceiver();
 
@@ -2487,6 +2534,55 @@ static struct attribute_group debug_dev_attr_group = {
        .attrs = inputs_attrs,
 };
 
+static int penwell_otg_aca_enable(void)
+{
+       int                     retval = 0;
+       struct penwell_otg      *pnw = the_transceiver;
+
+       penwell_otg_msic_spi_access(true);
+
+       retval = intel_scu_ipc_update_register(SPI_TI_VS4,
+               TI_ACA_DET_EN, TI_ACA_DET_EN);
+       if (retval)
+               goto done;
+
+       retval = intel_scu_ipc_update_register(SPI_TI_VS5,
+               TI_ID_FLOAT_EN | TI_ID_RES_EN,
+               TI_ID_FLOAT_EN | TI_ID_RES_EN);
+
+done:
+       penwell_otg_msic_spi_access(false);
+
+       if (retval)
+               dev_warn(pnw->dev, "Failed to enable ACA device detection\n");
+
+       return retval;
+}
+
+static int penwell_otg_aca_disable(void)
+{
+       int                     retval = 0;
+       struct penwell_otg      *pnw = the_transceiver;
+
+       penwell_otg_msic_spi_access(true);
+
+       retval = intel_scu_ipc_update_register(SPI_TI_VS5,
+               0, TI_ID_FLOAT_EN | TI_ID_RES_EN);
+       if (retval)
+               goto done;
+
+       retval = intel_scu_ipc_update_register(SPI_TI_VS4,
+               0, TI_ACA_DET_EN);
+
+done:
+       penwell_otg_msic_spi_access(false);
+
+       if (retval)
+               dev_warn(pnw->dev, "Failed to disable ACA device detection\n");
+
+       return retval;
+}
+
 static int penwell_otg_probe(struct pci_dev *pdev,
                const struct pci_device_id *id)
 {
@@ -2592,6 +2688,9 @@ static int penwell_otg_probe(struct pci_dev *pdev,
        mutex_init(&pnw->msic_mutex);
        pnw->msic = penwell_otg_check_msic();
 
+       /* enable ACA device detection */
+       penwell_otg_aca_enable();
+
        penwell_otg_phy_enable(1);
 
        reset_otg();
@@ -2658,6 +2757,9 @@ static void penwell_otg_remove(struct pci_dev *pdev)
 {
        struct penwell_otg *pnw = the_transceiver;
 
+       /* ACA device detection disable */
+       penwell_otg_aca_disable();
+
        if (pnw->qwork) {
                flush_workqueue(pnw->qwork);
                destroy_workqueue(pnw->qwork);
diff --git a/include/linux/usb/penwell_otg.h b/include/linux/usb/penwell_otg.h
index 77776ca..f4e8d5b 100644
--- a/include/linux/usb/penwell_otg.h
+++ b/include/linux/usb/penwell_otg.h
@@ -143,7 +143,12 @@
 #      define SPIMODE                  BIT(0)
 
 /* MSIC TI implementation for ADP/ACA */
+#define SPI_TI_VS2             0x3B7
+#define SPI_TI_VS2_LATCH       0x3B8
+#define SPI_TI_VS4             0x3BA
+#define SPI_TI_VS5             0x3BB
 #define ULPI_TI_VS2            0x83
+#define ULPI_TI_VS2_LATCH      0x84
 #      define TI_ID_FLOAT_STS          BIT(4)
 #      define TI_ID_RARBRC_STS(d)      (((d)>>2)&3)
 #      define TI_ID_RARBRC_STS_MASK    (BIT(3) | BIT(2))
-- 
1.6.0.6

_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to