[PATCH v2 19/25] usb: penwell_otg: add ACA device support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jiebing Li <jiebing.li@xxxxxxxxx>

ACA (Accessory Charger Adapter) is one kind of USB adapter which
is defined in Battery Charging Spec 1.1.
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 <jiebing.li@xxxxxxxxx>
---
 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 1c6212e..e26393c 100644
--- a/drivers/usb/otg/penwell_otg.c
+++ b/drivers/usb/otg/penwell_otg.c
@@ -1045,6 +1045,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);
@@ -1100,6 +1104,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();
 
@@ -2449,6 +2496,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)
 {
@@ -2546,6 +2642,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();
@@ -2608,6 +2707,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

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux