summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2012-06-05 11:08:29 +0800
committerPeter Chen <peter.chen@freescale.com>2012-06-08 16:24:55 +0800
commitc515c3b8a220a8c1c398b21d2773435d9011b1f0 (patch)
treeaa70c510850d708ede47490ce13597ad7f15b3bb
parent276671467aaff55a2896648de418caf28138bae5 (diff)
ENGR00212322-1: usb: add usb charger support for i.mx6x
- USB charger function is embedded in usb device driver, and only for i.mx6x - SDP and DCP charger are tested - Need to enable usb device function (insmod one gadget driver) to use usb charger detect function - The power supply interface for usb charger is: /sys/class/power_supply/imx_usb_charger/ Some useful entries for power supply interface: - present: whether usb charger is present or not - type: usb charger type - current_max: the max charger current for this charger - online: whether vbus is on or not Signed-off-by: Peter Chen <peter.chen@freescale.com>
-rwxr-xr-xdrivers/usb/gadget/Kconfig7
-rwxr-xr-xdrivers/usb/gadget/arcotg_udc.c45
-rwxr-xr-xdrivers/usb/gadget/arcotg_udc.h4
-rw-r--r--drivers/usb/gadget/imx_usb_charger.c319
-rw-r--r--drivers/usb/gadget/imx_usb_charger.h194
5 files changed, 562 insertions, 7 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 0ffd11012cfb..6c7b401fe6b1 100755
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -173,6 +173,13 @@ config USB_STATIC_IRAM_PPH
help
Apply static IRAM patch to peripheral driver.
+config IMX_USB_CHARGER
+ bool "Use i.MX SoC USB charger detect function"
+ depends on USB_GADGET_ARC && ARCH_MX6
+ help
+ Say "y" will enable i.mx usb charger detect function
+ (only for i.mx6x currently).
+
config USB_ARC
tristate
depends on USB_GADGET_ARC
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index ea81802a3ca6..8def72278d19 100755
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -38,10 +38,10 @@
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
#include <linux/dmapool.h>
+#include <linux/io.h>
#include <asm/processor.h>
#include <asm/byteorder.h>
-#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/mach-types.h>
@@ -78,6 +78,8 @@ static const char driver_desc[] = DRIVER_DESC;
volatile static struct usb_dr_device *dr_regs;
volatile static struct usb_sys_interface *usb_sys_regs;
+#include "imx_usb_charger.c" /* support for usb charger detect */
+
/* it is initialized in probe() */
static struct fsl_udc *udc_controller;
@@ -488,6 +490,8 @@ static void dr_controller_run(struct fsl_udc *udc)
/* If vbus not on and used low power mode */
if (!(temp & OTGSC_B_SESSION_VALID)) {
/* Set stopped before low power mode */
+ udc->vbus_active = false;
+ imx_usb_vbus_disconnect(&udc->charger); /* charger disconnect */
udc->stopped = 1;
/* enable wake up */
dr_wake_up_enable(udc, true);
@@ -508,10 +512,8 @@ static void dr_controller_run(struct fsl_udc *udc)
/* disable pulldown dp and dm */
dr_discharge_line(udc->pdata, false);
- /* The usb line has already been connected to pc */
- temp = fsl_readl(&dr_regs->usbcmd);
- temp |= USB_CMD_RUN_STOP;
- fsl_writel(temp, &dr_regs->usbcmd);
+ udc->vbus_active = true;
+ imx_usb_vbus_connect(&udc->charger); /* charger detect */
printk(KERN_DEBUG "%s: udc out low power mode\n", __func__);
}
@@ -1467,6 +1469,15 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on)
return 0;
}
+/*
+ * The USB PHY/Charger driver can't visit usb_gadget directly, so
+ * supply a wrapped function for usb charger visiting.
+ */
+static void usb_charger_pullup_dp(bool enable)
+{
+ fsl_pullup(&udc_controller->gadget, (int)enable);
+}
+
/* defined in gadget.h */
static struct usb_gadget_ops fsl_gadget_ops = {
.get_frame = fsl_get_frame,
@@ -2227,13 +2238,15 @@ bool try_wake_up_udc(struct fsl_udc *udc)
if (irq_src & OTGSC_B_SESSION_VALID) {
if (udc->suspended) /*let the system pm resume the udc */
return true;
+ udc->vbus_active = true;
udc->stopped = 0;
/* disable pulldown dp and dm */
dr_discharge_line(pdata, false);
- fsl_writel(tmp | USB_CMD_RUN_STOP, &dr_regs->usbcmd);
+ imx_usb_vbus_connect(&udc->charger); /* charger detect */
printk(KERN_DEBUG "%s: udc out low power mode\n", __func__);
} else {
- fsl_writel(tmp & ~USB_CMD_RUN_STOP, &dr_regs->usbcmd);
+ udc->vbus_active = false;
+ imx_usb_vbus_disconnect(&udc->charger); /* charger disconnect */
/* here we need disable B_SESSION_IRQ, after
* schedule_work finished, it need to be enabled again.
* Doing like this can avoid conflicting between rapid
@@ -3178,6 +3191,20 @@ static int __devinit fsl_udc_probe(struct platform_device *pdev)
create_proc_file();
+ /* create usb charger */
+#ifdef CONFIG_IMX_USB_CHARGER
+ udc_controller->charger.dev = &pdev->dev;
+ udc_controller->charger.dp_pullup = usb_charger_pullup_dp;
+ udc_controller->charger.enable = true;
+ if (pdata->charger_base_addr)
+ udc_controller->charger.charger_base_addr = pdata->charger_base_addr;
+ if (imx_usb_create_charger(&udc_controller->charger, "imx_usb_charger"))
+ dev_err(&pdev->dev, "Can't create usb charger\n");
+#else
+ udc_controller->charger.dp_pullup = usb_charger_pullup_dp;
+ udc_controller->charger.enable = false;
+#endif
+
return 0;
err4:
@@ -3234,6 +3261,10 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
free_irq(udc_controller->irq, udc_controller);
iounmap((u8 __iomem *)dr_regs);
+#ifdef CONFIG_IMX_USB_CHARGER
+ imx_usb_remove_charger(&udc_controller->charger);
+#endif
+
#ifndef CONFIG_USB_OTG
{
struct resource *res;
diff --git a/drivers/usb/gadget/arcotg_udc.h b/drivers/usb/gadget/arcotg_udc.h
index 8f4b88ebc283..35a2790828a9 100755
--- a/drivers/usb/gadget/arcotg_udc.h
+++ b/drivers/usb/gadget/arcotg_udc.h
@@ -25,6 +25,9 @@
#ifndef __ARCOTG_UDC_H
#define __ARCOTG_UDC_H
+/* delete below include when charger code moves to phy driver */
+#include "imx_usb_charger.h"
+
#define TRUE 1
#define FALSE 0
@@ -621,6 +624,7 @@ struct fsl_udc {
u32 iram_buffer[IRAM_PPH_NTD];
void *iram_buffer_v[IRAM_PPH_NTD];
struct work_struct gadget_disconnect_schedule;
+ struct usb_charger charger; /* usb charger for this udc */
};
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/imx_usb_charger.c b/drivers/usb/gadget/imx_usb_charger.c
new file mode 100644
index 000000000000..41043b432102
--- /dev/null
+++ b/drivers/usb/gadget/imx_usb_charger.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2004-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * NOTICE: Currently, it only supports i.mx6q usb charger detect
+ */
+
+static int usb_charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct usb_charger *charger =
+ container_of(psy, struct usb_charger, psy);
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = charger->present;
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = charger->online;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ val->intval = charger->max_current;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void usb_charger_work(struct work_struct *data)
+{
+ int ret;
+ struct usb_charger *charger =
+ container_of(data, struct usb_charger, work);
+
+ if (!charger->online)
+ return;
+
+ mutex_lock(&charger->lock);
+
+ /* Start the primary charger detection. */
+ if (charger->detect) {
+ ret = charger->detect(charger);
+ if (ret <= 0)
+ dev_err(charger->dev, "Error occurs during usb charger \
+ detection\n");
+ else
+ charger->present = ret;
+ }
+
+ switch (charger->psy.type) {
+ case POWER_SUPPLY_TYPE_USB_DCP:
+ charger->max_current = 1500;
+ break;
+ case POWER_SUPPLY_TYPE_USB_CDP:
+ charger->max_current = 900;
+ break;
+ case POWER_SUPPLY_TYPE_USB: /* SDP */
+ charger->max_current = 500;
+ default:
+ if (charger->dp_pullup)
+ charger->dp_pullup(true);
+ break;
+ }
+
+ power_supply_changed(&charger->psy);
+
+ mutex_unlock(&charger->lock);
+}
+
+/* Return value if the charger is present */
+static int usb_charger_detect(struct usb_charger *charger)
+{
+ void __iomem *addr = charger->charger_base_addr;
+ int i;
+
+ BUG_ON(!addr);
+
+ /* Enable the vdd3p0 curret limiter */
+ writel(BM_ANADIG_REG_3P0_ENABLE_LINREG |
+ BM_ANADIG_REG_3P0_ENABLE_ILIMIT,
+ addr + HW_ANADIG_REG_3P0_SET);
+
+ /* check if vbus is valid */
+ if (!(readl(addr + HW_ANADIG_USB1_VBUS_DET_STAT) &
+ BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)) {
+ dev_err(charger->dev, "vbus is error\n");
+ return 0;
+ }
+
+ /* Enable charger detector */
+ writel(BM_ANADIG_USB1_CHRG_DETECT_EN_B,
+ addr + HW_ANADIG_USB1_CHRG_DETECT_CLR);
+ /*
+ * - Do not check whether a charger is connected to the USB port
+ * - Check whether the USB plug has been in contact with each other
+ */
+ writel(BM_ANADIG_USB1_CHRG_DETECT_CHK_CONTACT
+ | BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B,
+ addr + HW_ANADIG_USB1_CHRG_DETECT_SET);
+
+ /* Check if plug is connected */
+ for (i = 0; i < 1000; i = i + 1) {
+ if (readl(addr + HW_ANADIG_USB1_CHRG_DET_STAT) &
+ BM_ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT) {
+ dev_dbg(charger->dev, "Plug Contact = 1\n");
+ break;
+ } else if (i > 800) {
+ dev_err(charger->dev, "VBUS is coming from a dedicated power supply.\n");
+ return 0;
+ } else
+ msleep(1);
+ }
+
+ /*
+ * - Do check whether a charger is connected to the USB port
+ * - Do not Check whether the USB plug has been in contact with each other
+ */
+ writel(BM_ANADIG_USB1_CHRG_DETECT_CHK_CONTACT
+ | BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B,
+ addr + HW_ANADIG_USB1_CHRG_DETECT_CLR);
+
+ msleep(40);
+
+ /* Check if it is a charger */
+ if (!(readl(addr + HW_ANADIG_USB1_CHRG_DET_STAT) &
+ BM_ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED)) {
+ dev_info(charger->dev, "It is a stardard downstream port\n");
+ charger->psy.type = POWER_SUPPLY_TYPE_USB;
+
+ /* Disable Charger detector */
+ writel(BM_ANADIG_USB1_CHRG_DETECT_EN_B
+ | BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B,
+ addr + HW_ANADIG_USB1_CHRG_DETECT);
+
+ /* Disable the vdd3p0 curret limiter */
+ writel(BM_ANADIG_REG_3P0_ENABLE_ILIMIT,
+ addr + HW_ANADIG_REG_3P0_CLR);
+ return 1;
+ }
+
+ /* Begin to detect CDP and DCP */
+
+ /* Disable Charger detector */
+ writel(BM_ANADIG_USB1_CHRG_DETECT_EN_B
+ | BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B,
+ addr + HW_ANADIG_USB1_CHRG_DETECT);
+
+ msleep(40);
+
+ /* Disable the vdd3p0 curret limiter */
+ writel(BM_ANADIG_REG_3P0_ENABLE_ILIMIT,
+ addr + HW_ANADIG_REG_3P0_CLR);
+
+ /* pull up dp */
+ if (charger->dp_pullup)
+ charger->dp_pullup(true);
+
+ msleep(40);
+
+ if ((readl(&dr_regs->portsc1) & PORTSCX_LINE_STATUS_KSTATE)) {
+ dev_info(charger->dev, "It is a dedicate charging port\n");
+ charger->psy.type = POWER_SUPPLY_TYPE_USB_DCP;
+ } else {
+ dev_info(charger->dev, "It is a charging downstream port\n");
+ charger->psy.type = POWER_SUPPLY_TYPE_USB_CDP;
+ }
+
+ return 1;
+}
+
+void usb_charger_init(struct usb_charger *charger)
+{
+ charger->bc = BATTERY_CHARGING_SPEC_1_2;
+ charger->detect = usb_charger_detect;
+}
+
+/*
+ * imx_usb_create_charger - create a USB charger
+ * @charger: the charger to be initialized
+ * @name: name for the power supply
+
+ * Registers a power supply for the charger. The PHY/UDC driver will
+ * call this after filling struct usb_charger. All the users are
+ * expected to be in the supplied_to parameter.
+ */
+int imx_usb_create_charger(struct usb_charger *charger,
+ const char *name)
+{
+ int ret = 0;
+ struct power_supply *psy = &charger->psy;
+
+ if (!charger->dev)
+ return -EINVAL;
+
+ if (name)
+ psy->name = name;
+ else
+ psy->name = "usb_charger";
+
+ usb_charger_init(charger);
+
+ psy->type = POWER_SUPPLY_TYPE_USB;
+ psy->properties = power_props;
+ psy->num_properties = ARRAY_SIZE(power_props);
+ psy->get_property = usb_charger_get_property;
+
+ psy->supplied_to = usb_charger_supplied_to;
+ psy->num_supplicants = sizeof(usb_charger_supplied_to)/sizeof(char *);
+
+ ret = power_supply_register(charger->dev, psy);
+ if (ret)
+ goto fail;
+
+ mutex_init(&charger->lock);
+ INIT_WORK(&charger->work, usb_charger_work);
+
+fail:
+ return ret;
+}
+EXPORT_SYMBOL(imx_usb_create_charger);
+
+/*
+ * imx_usb_remove_charger - remove a USB charger
+ * @charger: the charger to be removed
+ *
+ * Unregister the chargers power supply.
+ */
+void imx_usb_remove_charger(struct usb_charger *charger)
+{
+ power_supply_unregister(&charger->psy);
+}
+EXPORT_SYMBOL(imx_usb_remove_charger);
+
+/*
+ * imx_usb_set_power - Set the maximum power allowed to draw
+ * @charger: the usb charger
+ * @mA: maximum current in milliamps
+ *
+ * Called from the controller after enumeration to inform the maximum
+ * power from the configuration, and after bus suspend and resume.
+ */
+int imx_usb_set_power(struct usb_charger *charger, unsigned mA)
+{
+ if (!charger->online)
+ return 0;
+
+ if (charger->max_current == mA)
+ return 0;
+
+ charger->max_current = mA;
+
+ power_supply_changed(&charger->psy);
+
+ return 0;
+}
+EXPORT_SYMBOL(imx_usb_set_power);
+
+/*
+ * imx_usb_vbus_connect - inform about VBUS connection
+ * @charger: the usb charger
+ *
+ * Inform the charger VBUS is connected. The USB device controller is
+ * expected to keep the dataline pullups disabled until dp_pullup()
+ * is called.
+ */
+int imx_usb_vbus_connect(struct usb_charger *charger)
+{
+ /* if charger is disabled, set usbcmd.rs=1 and return directly */
+ if (!charger->enable) {
+ if (charger->dp_pullup)
+ charger->dp_pullup(true);
+ return 0;
+ }
+
+ charger->online = 1;
+ schedule_work(&charger->work);
+
+ return 0;
+}
+EXPORT_SYMBOL(imx_usb_vbus_connect);
+
+/*
+ * imx_usb_vbus_disconnect - inform about VBUS disconnection
+ * @charger: the usb charger
+ *
+ * Inform the charger that VBUS is disconnected. The charging will be
+ * stopped and the charger properties cleared.
+ */
+int imx_usb_vbus_disconnect(struct usb_charger *charger)
+{
+ if (charger->dp_pullup)
+ charger->dp_pullup(false); /* usbcmd.rs = 0 */
+
+ if (!charger->enable)
+ return 0;
+
+ charger->online = 0;
+ charger->present = 0;
+ charger->max_current = 0;
+ charger->psy.type = POWER_SUPPLY_TYPE_USB;
+
+ if (charger->disconnect)
+ charger->disconnect(charger);
+
+ power_supply_changed(&charger->psy);
+
+ return 0;
+}
+EXPORT_SYMBOL(imx_usb_vbus_disconnect);
diff --git a/drivers/usb/gadget/imx_usb_charger.h b/drivers/usb/gadget/imx_usb_charger.h
new file mode 100644
index 000000000000..5417743a5118
--- /dev/null
+++ b/drivers/usb/gadget/imx_usb_charger.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2004-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * NOTICE: Currently, it only supports i.mx6q usb charger detect
+ */
+
+#ifndef __IMXUSB_CHARGER_H
+#define __IMXUSB_CHARGER_H
+
+#define HW_ANADIG_REG_3P0 (0x00000120)
+#define HW_ANADIG_REG_3P0_SET (0x00000124)
+#define HW_ANADIG_REG_3P0_CLR (0x00000128)
+#define HW_ANADIG_REG_3P0_TOG (0x0000012c)
+#define BM_ANADIG_REG_3P0_ENABLE_ILIMIT 0x00000004
+#define BM_ANADIG_REG_3P0_ENABLE_LINREG 0x00000001
+
+#define HW_ANADIG_USB1_VBUS_DETECT (0x000001a0)
+#define HW_ANADIG_USB1_VBUS_DETECT_SET (0x000001a4)
+#define HW_ANADIG_USB1_VBUS_DETECT_CLR (0x000001a8)
+#define HW_ANADIG_USB1_VBUS_DETECT_TOG (0x000001ac)
+
+#define BM_ANADIG_USB1_VBUS_DETECT_EN_CHARGER_RESISTOR 0x80000000
+#define BP_ANADIG_USB1_VBUS_DETECT_RSVD2 28
+#define BM_ANADIG_USB1_VBUS_DETECT_RSVD2 0x70000000
+#define BF_ANADIG_USB1_VBUS_DETECT_RSVD2(v) \
+ (((v) << 28) & BM_ANADIG_USB1_VBUS_DETECT_RSVD2)
+#define BM_ANADIG_USB1_VBUS_DETECT_CHARGE_VBUS 0x08000000
+#define BM_ANADIG_USB1_VBUS_DETECT_DISCHARGE_VBUS 0x04000000
+#define BP_ANADIG_USB1_VBUS_DETECT_RSVD1 21
+#define BM_ANADIG_USB1_VBUS_DETECT_RSVD1 0x03E00000
+#define BF_ANADIG_USB1_VBUS_DETECT_RSVD1(v) \
+ (((v) << 21) & BM_ANADIG_USB1_VBUS_DETECT_RSVD1)
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_PWRUP_CMPS 0x00100000
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_5VDETECT 0x00080000
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_TO_B 0x00040000
+#define BP_ANADIG_USB1_VBUS_DETECT_RSVD0 8
+#define BM_ANADIG_USB1_VBUS_DETECT_RSVD0 0x0003FF00
+#define BF_ANADIG_USB1_VBUS_DETECT_RSVD0(v) \
+ (((v) << 8) & BM_ANADIG_USB1_VBUS_DETECT_RSVD0)
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_OVERRIDE 0x00000080
+#define BM_ANADIG_USB1_VBUS_DETECT_AVALID_OVERRIDE 0x00000040
+#define BM_ANADIG_USB1_VBUS_DETECT_BVALID_OVERRIDE 0x00000020
+#define BM_ANADIG_USB1_VBUS_DETECT_SESSEND_OVERRIDE 0x00000010
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUS_OVERRIDE_EN 0x00000008
+#define BP_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH 0
+#define BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH 0x00000007
+#define BF_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH(v) \
+ (((v) << 0) & BM_ANADIG_USB1_VBUS_DETECT_VBUSVALID_THRESH)
+
+#define HW_ANADIG_USB1_CHRG_DETECT (0x000001b0)
+#define HW_ANADIG_USB1_CHRG_DETECT_SET (0x000001b4)
+#define HW_ANADIG_USB1_CHRG_DETECT_CLR (0x000001b8)
+#define HW_ANADIG_USB1_CHRG_DETECT_TOG (0x000001bc)
+
+#define BP_ANADIG_USB1_CHRG_DETECT_RSVD2 24
+#define BM_ANADIG_USB1_CHRG_DETECT_RSVD2 0xFF000000
+#define BF_ANADIG_USB1_CHRG_DETECT_RSVD2(v) \
+ (((v) << 24) & BM_ANADIG_USB1_CHRG_DETECT_RSVD2)
+#define BM_ANADIG_USB1_CHRG_DETECT_BGR_BIAS 0x00800000
+#define BP_ANADIG_USB1_CHRG_DETECT_RSVD1 21
+#define BM_ANADIG_USB1_CHRG_DETECT_RSVD1 0x00600000
+#define BF_ANADIG_USB1_CHRG_DETECT_RSVD1(v) \
+ (((v) << 21) & BM_ANADIG_USB1_CHRG_DETECT_RSVD1)
+#define BM_ANADIG_USB1_CHRG_DETECT_EN_B 0x00100000
+#define BM_ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B 0x00080000
+#define BM_ANADIG_USB1_CHRG_DETECT_CHK_CONTACT 0x00040000
+#define BP_ANADIG_USB1_CHRG_DETECT_RSVD0 1
+#define BM_ANADIG_USB1_CHRG_DETECT_RSVD0 0x0003FFFE
+#define BF_ANADIG_USB1_CHRG_DETECT_RSVD0(v) \
+ (((v) << 1) & BM_ANADIG_USB1_CHRG_DETECT_RSVD0)
+#define BM_ANADIG_USB1_CHRG_DETECT_FORCE_DETECT 0x00000001
+
+#define HW_ANADIG_USB1_VBUS_DET_STAT (0x000001c0)
+#define HW_ANADIG_USB1_VBUS_DET_STAT_SET (0x000001c4)
+#define HW_ANADIG_USB1_VBUS_DET_STAT_CLR (0x000001c8)
+#define HW_ANADIG_USB1_VBUS_DET_STAT_TOG (0x000001cc)
+
+#define BP_ANADIG_USB1_VBUS_DET_STAT_RSVD0 4
+#define BM_ANADIG_USB1_VBUS_DET_STAT_RSVD0 0xFFFFFFF0
+#define BF_ANADIG_USB1_VBUS_DET_STAT_RSVD0(v) \
+ (((v) << 4) & BM_ANADIG_USB1_VBUS_DET_STAT_RSVD0)
+#define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID 0x00000008
+#define BM_ANADIG_USB1_VBUS_DET_STAT_AVALID 0x00000004
+#define BM_ANADIG_USB1_VBUS_DET_STAT_BVALID 0x00000002
+#define BM_ANADIG_USB1_VBUS_DET_STAT_SESSEND 0x00000001
+
+#define HW_ANADIG_USB1_CHRG_DET_STAT (0x000001d0)
+#define HW_ANADIG_USB1_CHRG_DET_STAT_SET (0x000001d4)
+#define HW_ANADIG_USB1_CHRG_DET_STAT_CLR (0x000001d8)
+#define HW_ANADIG_USB1_CHRG_DET_STAT_TOG (0x000001dc)
+
+#define BP_ANADIG_USB1_CHRG_DET_STAT_RSVD0 4
+#define BM_ANADIG_USB1_CHRG_DET_STAT_RSVD0 0xFFFFFFF0
+#define BF_ANADIG_USB1_CHRG_DET_STAT_RSVD0(v) \
+ (((v) << 4) & BM_ANADIG_USB1_CHRG_DET_STAT_RSVD0)
+#define BM_ANADIG_USB1_CHRG_DET_STAT_DP_STATE 0x00000008
+#define BM_ANADIG_USB1_CHRG_DET_STAT_DM_STATE 0x00000004
+#define BM_ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED 0x00000002
+#define BM_ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT 0x00000001
+
+#define HW_ANADIG_USB1_LOOPBACK (0x000001e0)
+#define HW_ANADIG_USB1_LOOPBACK_SET (0x000001e4)
+#define HW_ANADIG_USB1_LOOPBACK_CLR (0x000001e8)
+#define HW_ANADIG_USB1_LOOPBACK_TOG (0x000001ec)
+
+#define BP_ANADIG_USB1_LOOPBACK_RSVD0 9
+#define BM_ANADIG_USB1_LOOPBACK_RSVD0 0xFFFFFE00
+#define BF_ANADIG_USB1_LOOPBACK_RSVD0(v) \
+ (((v) << 9) & BM_ANADIG_USB1_LOOPBACK_RSVD0)
+#define BM_ANADIG_USB1_LOOPBACK_UTMO_DIG_TST1 0x00000100
+#define BM_ANADIG_USB1_LOOPBACK_UTMO_DIG_TST0 0x00000080
+#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_HIZ 0x00000040
+#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN 0x00000020
+#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_LS_MODE 0x00000010
+#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_HS_MODE 0x00000008
+#define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 0x00000004
+#define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST0 0x00000002
+#define BM_ANADIG_USB1_LOOPBACK_UTMI_TESTSTART 0x00000001
+
+#define HW_ANADIG_USB1_MISC (0x000001f0)
+#define HW_ANADIG_USB1_MISC_SET (0x000001f4)
+#define HW_ANADIG_USB1_MISC_CLR (0x000001f8)
+#define HW_ANADIG_USB1_MISC_TOG (0x000001fc)
+
+#define BM_ANADIG_USB1_MISC_RSVD1 0x80000000
+#define BM_ANADIG_USB1_MISC_EN_CLK_UTMI 0x40000000
+#define BM_ANADIG_USB1_MISC_RX_VPIN_FS 0x20000000
+#define BM_ANADIG_USB1_MISC_RX_VMIN_FS 0x10000000
+#define BM_ANADIG_USB1_MISC_RX_RXD_FS 0x08000000
+#define BM_ANADIG_USB1_MISC_RX_SQUELCH 0x04000000
+#define BM_ANADIG_USB1_MISC_RX_DISCON_DET 0x02000000
+#define BM_ANADIG_USB1_MISC_RX_HS_DATA 0x01000000
+#define BP_ANADIG_USB1_MISC_RSVD0 2
+#define BM_ANADIG_USB1_MISC_RSVD0 0x00FFFFFC
+#define BF_ANADIG_USB1_MISC_RSVD0(v) \
+ (((v) << 2) & BM_ANADIG_USB1_MISC_RSVD0)
+#define BM_ANADIG_USB1_MISC_EN_DEGLITCH 0x00000002
+#define BM_ANADIG_USB1_MISC_HS_USE_EXTERNAL_R 0x00000001
+
+#include <linux/power_supply.h>
+enum battery_charging_spec {
+ BATTERY_CHARGING_SPEC_NONE = 0,
+ BATTERY_CHARGING_SPEC_UNKNOWN,
+ BATTERY_CHARGING_SPEC_1_0,
+ BATTERY_CHARGING_SPEC_1_1,
+ BATTERY_CHARGING_SPEC_1_2,
+};
+
+struct usb_charger {
+ void __iomem *charger_base_addr; /* Get from MSL if exists */
+ struct device *dev; /* udc supplies */
+ /* charger detect can be enabled/disabled by kernel config */
+ bool enable;
+
+ struct power_supply psy;
+ struct work_struct work;
+ struct mutex lock;
+
+ /* Compliant with Battery Charging Specification version (if any) */
+ enum battery_charging_spec bc;
+
+ /* properties */
+ unsigned present:1;
+ unsigned online:1;
+ unsigned max_current;
+ /* pull up/down dp during the charger detect, udc supplies */
+ void (*dp_pullup)(bool);
+ int (*connect)(struct usb_charger *charger);
+ int (*disconnect)(struct usb_charger *charger);
+ int (*set_power)(struct usb_charger *charger, unsigned mA);
+
+ int (*detect)(struct usb_charger *charger);
+};
+
+static char *usb_charger_supplied_to[] = {
+ "main-battery",
+};
+
+static enum power_supply_property power_props[] = {
+ POWER_SUPPLY_PROP_PRESENT, /* Charger detected */
+ POWER_SUPPLY_PROP_ONLINE, /* VBUS online */
+ POWER_SUPPLY_PROP_CURRENT_MAX, /* Maximum current in mA */
+};
+
+#endif /* __IMXUSB_CHARGER_H */