/*
* USB transceiver driver for AB8500 family chips
*
* Copyright (C) 2010-2013 ST-Ericsson AB
* Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
* Avinash Kumar <avinash.kumar@stericsson.com>
* Thirupathi Chippakurthy <thirupathi.chippakurthy@stericsson.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/usb/otg.h>
#include <linux/slab.h>
#include <linux/notifier.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/usb/musb-ux500.h>
#include <linux/regulator/consumer.h>
#include <linux/pinctrl/consumer.h>
/* Bank AB8500_SYS_CTRL2_BLOCK */
#define AB8500_MAIN_WD_CTRL_REG 0x01
/* Bank AB8500_USB */
#define AB8500_USB_LINE_STAT_REG 0x80
#define AB8505_USB_LINE_STAT_REG 0x94
#define AB8540_USB_LINK_STAT_REG 0x94
#define AB9540_USB_LINK_STAT_REG 0x94
#define AB8540_USB_OTG_CTL_REG 0x87
#define AB8500_USB_PHY_CTRL_REG 0x8A
#define AB8540_VBUS_CTRL_REG 0x82
/* Bank AB8500_DEVELOPMENT */
#define AB8500_BANK12_ACCESS 0x00
/* Bank AB8500_DEBUG */
#define AB8540_DEBUG 0x32
#define AB8500_USB_PHY_TUNE1 0x05
#define AB8500_USB_PHY_TUNE2 0x06
#define AB8500_USB_PHY_TUNE3 0x07
/* Bank AB8500_INTERRUPT */
#define AB8500_IT_SOURCE2_REG 0x01
#define AB8500_BIT_OTG_STAT_ID (1 << 0)
#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0)
#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1)
#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0)
#define AB8500_BIT_WD_CTRL_KICK (1 << 1)
#define AB8500_BIT_SOURCE2_VBUSDET (1 << 7)
#define AB8540_BIT_OTG_CTL_VBUS_VALID_ENA (1 << 0)
#define AB8540_BIT_OTG_CTL_ID_HOST_ENA (1 << 1)
#define AB8540_BIT_OTG_CTL_ID_DEV_ENA (1 << 5)
#define AB8540_BIT_VBUS_CTRL_CHARG_DET_ENA (1 << 0)
#define AB8500_WD_KICK_DELAY_US 100 /* usec */
#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */
#define AB8500_V20_31952_DISABLE_DELAY_US 100 /* usec */
/* Usb line status register */
enum ab8500_usb_link_status {
USB_LINK_NOT_CONFIGURED_8500 = 0,
USB_LINK_STD_HOST_NC_8500,
USB_LINK_STD_HOST_C_NS_8500,
USB_LINK_STD_HOST_C_S_8500,
USB_LINK_HOST_CHG_NM_8500,
USB_LINK_HOST_CHG_HS_8500,
USB_LINK_HOST_CHG_HS_CHIRP_8500,
USB_LINK_DEDICATED_CHG_8500,
USB_LINK_ACA_RID_A_8500,
USB_LINK_ACA_RID_B_8500,
USB_LINK_ACA_RID_C_NM_8500,
USB_LINK_ACA_RID_C_HS_8500,
USB_LINK_ACA_RID_C_HS_CHIRP_8500,
USB_LINK_HM_IDGND_8500,
USB_LINK_RESERVED_8500,
USB_LINK_NOT_VALID_LINK_8500,
};
enum ab8505_usb_link_status {
USB_LINK_NOT_CONFIGURED_8505 = 0,
USB_LINK_STD_HOST_NC_8505,
USB_LINK_STD_HOST_C_NS_8505,
USB_LINK_STD_HOST_C_S_8505,
USB_LINK_CDP_8505,
USB_LINK_RESERVED0_8505,
USB_LINK_RESERVED1_8505,
USB_LINK_DEDICATED_CHG_8505,
USB_LINK_ACA_RID_A_8505,
USB_LINK_ACA_RID_B_8505,
USB_LINK_ACA_RID_C_NM_8505,
USB_LINK_RESERVED2_8505,
USB_LINK_RESERVED3_8505,
USB_LINK_HM_IDGND_8505,
USB_LINK_CHARGERPORT_NOT_OK_8505,
USB_LINK_CHARGER_DM_HIGH_8505,
USB_LINK_PHYEN_NO_VBUS_NO_IDGND_8505,
USB_LINK_STD_UPSTREAM_NO_IDGNG_NO_VBUS_8505,
USB_LINK_STD_UPSTREAM_8505,
USB_LINK_CHARGER_SE1_8505,
USB_LINK_CARKIT_CHGR_1_8505,
USB_LINK_CARKIT_CHGR_2_8505,
USB_LINK_ACA_DOCK_CHGR_8505,
USB_LINK_SAMSUNG_BOOT_CBL_PHY_EN_8505,
USB_LINK_SAMSUNG_BOOT_CBL_PHY_DISB_8505,
USB_LINK_SAMSUNG_UART_CBL_PHY_EN_8505,
USB_LINK_SAMSUNG_UART_CBL_PHY_DISB_8505,
USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_8505,
};
enum ab8540_usb_link_status {
USB_LINK_NOT_CONFIGURED_8540 = 0,
USB_LINK_STD_HOST_NC_8540,
USB_LINK_STD_HOST_C_NS_8540,
USB_LINK_STD_HOST_C_S_8540,
USB_LINK_CDP_8540,
USB_LINK_RESERVED0_8540,
USB_LINK_RESERVED1_8540,
USB_LINK_DEDICATED_CHG_8540,
USB_LINK_ACA_RID_A_8540,
USB_LINK_ACA_RID_B_8540,
USB_LINK_ACA_RID_C_NM_8540,
USB_LINK_RESERVED2_8540,
USB_LINK_RESERVED3_8540,
USB_LINK_HM_IDGND_8540,
USB_LINK_CHARGERPORT_NOT_OK_8540,
USB_LINK_CHARGER_DM_HIGH_8540,
USB_LINK_PHYEN_NO_VBUS_NO_IDGND_8540,
USB_LINK_STD_UPSTREAM_NO_IDGNG_VBUS_8540,
USB_LINK_STD_UPSTREAM_8540,
USB_LINK_CHARGER_SE1_8540,
USB_LINK_CARKIT_CHGR_1_8540,
USB_LINK_CARKIT_CHGR_2_8540,
USB_LINK_ACA_DOCK_CHGR_8540,
USB_LINK_SAMSUNG_BOOT_CBL_PHY_EN_8540,
USB_LINK_SAMSUNG_BOOT_CBL_PHY_DISB_8540,
USB_LINK_SAMSUNG_UART_CBL_PHY_EN_8540,
USB_LINK_SAMSUNG_UART_CBL_PHY_DISB_8540,
USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_8540
};
enum ab9540_usb_link_status {
USB_LINK_NOT_CONFIGURED_9540 = 0,
USB_LINK_STD_HOST_NC_9540,
USB_LINK_STD_HOST_C_NS_9540,
USB_LINK_STD_HOST_C_S_9540,
USB_LINK_CDP_9540,
USB_LINK_RESERVED0_9540,
USB_LINK_RESERVED1_9540,
USB_LINK_DEDICATED_CHG_9540,
USB_LINK_ACA_RID_A_9540,
USB_LINK_ACA_RID_B_9540,
USB_LINK_ACA_RID_C_NM_9540,
USB_LINK_RESERVED2_9540,
USB_LINK_RESERVED3_9540,
USB_LINK_HM_IDGND_9540,
USB_LINK_CHARGERPORT_NOT_OK_9540,
USB_LINK_CHARGER_DM_HIGH_9540,
USB_LINK_PHYEN_NO_VBUS_NO_IDGND_9540,
USB_LINK_STD_UPSTREAM_NO_IDGNG_VBUS_9540,
USB_LINK_STD_UPSTREAM_9540,
USB_LINK_CHARGER_SE1_9540,
USB_LINK_CARKIT_CHGR_1_9540,
USB_LINK_CARKIT_CHGR_2_9540,
USB_LINK_ACA_DOCK_CHGR_9540,
USB_LINK_SAMSUNG_BOOT_CBL_PHY_EN_9540,
USB_LINK_SAMSUNG_BOOT_CBL_PHY_DISB_9540,
USB_LINK_SAMSUNG_UART_CBL_PHY_EN_9540,
USB_LINK_SAMSUNG_UART_CBL_PHY_DISB_9540,
USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_9540
};
enum ab8500_usb_mode {
USB_IDLE = 0,
USB_PERIPHERAL,
USB_HOST,
USB_DEDICATED_CHG
};
/* Register USB_LINK_STATUS interrupt */
#define AB8500_USB_FLAG_USE_LINK_STATUS_IRQ (1 << 0)
/* Register ID_WAKEUP_F interrupt */
#define AB8500_USB_FLAG_USE_ID_WAKEUP_IRQ (1 << 1)
/* Register VBUS_DET_F interrupt */
#define AB8500_USB_FLAG_USE_VBUS_DET_IRQ (1 << 2)
/* Driver is using the ab-iddet driver*/
#define AB8500_USB_FLAG_USE_AB_IDDET (1 << 3)
/* Enable setting regulators voltage */
#define AB8500_USB_FLAG_REGULATOR_SET_VOLTAGE (1 << 4)
/* Enable the check_vbus_status workaround */
#define AB8500_USB_FLAG_USE_CHECK_VBUS_STATUS (1 << 5)
/* Enable the vbus host workaround */
#define AB8500_USB_FLAG_USE_VBUS_HOST_QUIRK (1 << 6)
struct ab8500_usb {
struct usb_phy phy;
struct device *dev;
struct ab8500 *ab8500;
unsigned vbus_draw;
struct work_struct phy_dis_work;
struct work_struct vbus_event_work;
enum ab8500_usb_mode mode;
struct clk *sysclk;
struct regulator *v_ape;
struc
|