/drivers/usb/otg/isp1301_omap.c
C | 1646 lines | 1186 code | 269 blank | 191 comment | 170 complexity | 5a07ee6f8d67e4011941c9a272e2e451 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * isp1301_omap - ISP 1301 USB transceiver, talking to OMAP OTG controller
- *
- * Copyright (C) 2004 Texas Instruments
- * Copyright (C) 2004 David Brownell
- *
- * 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/kernel.h>
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/slab.h>
- #include <linux/interrupt.h>
- #include <linux/platform_device.h>
- #include <linux/gpio.h>
- #include <linux/usb/ch9.h>
- #include <linux/usb/gadget.h>
- #include <linux/usb.h>
- #include <linux/usb/otg.h>
- #include <linux/i2c.h>
- #include <linux/workqueue.h>
- #include <asm/irq.h>
- #include <asm/mach-types.h>
- #include <plat/usb.h>
- #include <plat/mux.h>
- #ifndef DEBUG
- #undef VERBOSE
- #endif
- #define DRIVER_VERSION "24 August 2004"
- #define DRIVER_NAME (isp1301_driver.driver.name)
- MODULE_DESCRIPTION("ISP1301 USB OTG Transceiver Driver");
- MODULE_LICENSE("GPL");
- struct isp1301 {
- struct otg_transceiver otg;
- struct i2c_client *client;
- void (*i2c_release)(struct device *dev);
- int irq_type;
- u32 last_otg_ctrl;
- unsigned working:1;
- struct timer_list timer;
- /* use keventd context to change the state for us */
- struct work_struct work;
- unsigned long todo;
- # define WORK_UPDATE_ISP 0 /* update ISP from OTG */
- # define WORK_UPDATE_OTG 1 /* update OTG from ISP */
- # define WORK_HOST_RESUME 4 /* resume host */
- # define WORK_TIMER 6 /* timer fired */
- # define WORK_STOP 7 /* don't resubmit */
- };
- /* bits in OTG_CTRL */
- #define OTG_XCEIV_OUTPUTS \
- (OTG_ASESSVLD|OTG_BSESSEND|OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID)
- #define OTG_XCEIV_INPUTS \
- (OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID)
- #define OTG_CTRL_BITS \
- (OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|OTG_B_HNPEN|OTG_BUSDROP)
- /* and OTG_PULLUP is sometimes written */
- #define OTG_CTRL_MASK (OTG_DRIVER_SEL| \
- OTG_XCEIV_OUTPUTS|OTG_XCEIV_INPUTS| \
- OTG_CTRL_BITS)
- /*-------------------------------------------------------------------------*/
- /* board-specific PM hooks */
- #if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
- #if defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
- #include <linux/i2c/tps65010.h>
- #else
- static inline int tps65010_set_vbus_draw(unsigned mA)
- {
- pr_debug("tps65010: draw %d mA (STUB)\n", mA);
- return 0;
- }
- #endif
- static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
- {
- int status = tps65010_set_vbus_draw(mA);
- if (status < 0)
- pr_debug(" VBUS %d mA error %d\n", mA, status);
- }
- #else
- static void enable_vbus_draw(struct isp1301 *isp, unsigned mA)
- {
- /* H4 controls this by DIP switch S2.4; no soft control.
- * ON means the charger is always enabled. Leave it OFF
- * unless the OTG port is used only in B-peripheral mode.
- */
- }
- #endif
- static void enable_vbus_source(struct isp1301 *isp)
- {
- /* this board won't supply more than 8mA vbus power.
- * some boards can switch a 100ma "unit load" (or more).
- */
- }
- /* products will deliver OTG messages with LEDs, GUI, etc */
- static inline void notresponding(struct isp1301 *isp)
- {
- printk(KERN_NOTICE "OTG device not responding.\n");
- }
- /*-------------------------------------------------------------------------*/
- static struct i2c_driver isp1301_driver;
- /* smbus apis are used for portability */
- static inline u8
- isp1301_get_u8(struct isp1301 *isp, u8 reg)
- {
- return i2c_smbus_read_byte_data(isp->client, reg + 0);
- }
- static inline int
- isp1301_get_u16(struct isp1301 *isp, u8 reg)
- {
- return i2c_smbus_read_word_data(isp->client, reg);
- }
- static inline int
- isp1301_set_bits(struct isp1301 *isp, u8 reg, u8 bits)
- {
- return i2c_smbus_write_byte_data(isp->client, reg + 0, bits);
- }
- static inline int
- isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits)
- {
- return i2c_smbus_write_byte_data(isp->client, reg + 1, bits);
- }
- /*-------------------------------------------------------------------------*/
- /* identification */
- #define ISP1301_VENDOR_ID 0x00 /* u16 read */
- #define ISP1301_PRODUCT_ID 0x02 /* u16 read */
- #define ISP1301_BCD_DEVICE 0x14 /* u16 read */
- #define I2C_VENDOR_ID_PHILIPS 0x04cc
- #define I2C_PRODUCT_ID_PHILIPS_1301 0x1301
- /* operational registers */
- #define ISP1301_MODE_CONTROL_1 0x04 /* u8 read, set, +1 clear */
- # define MC1_SPEED (1 << 0)
- # define MC1_SUSPEND (1 << 1)
- # define MC1_DAT_SE0 (1 << 2)
- # define MC1_TRANSPARENT (1 << 3)
- # define MC1_BDIS_ACON_EN (1 << 4)
- # define MC1_OE_INT_EN (1 << 5)
- # define MC1_UART_EN (1 << 6)
- # define MC1_MASK 0x7f
- #define ISP1301_MODE_CONTROL_2 0x12 /* u8 read, set, +1 clear */
- # define MC2_GLOBAL_PWR_DN (1 << 0)
- # define MC2_SPD_SUSP_CTRL (1 << 1)
- # define MC2_BI_DI (1 << 2)
- # define MC2_TRANSP_BDIR0 (1 << 3)
- # define MC2_TRANSP_BDIR1 (1 << 4)
- # define MC2_AUDIO_EN (1 << 5)
- # define MC2_PSW_EN (1 << 6)
- # define MC2_EN2V7 (1 << 7)
- #define ISP1301_OTG_CONTROL_1 0x06 /* u8 read, set, +1 clear */
- # define OTG1_DP_PULLUP (1 << 0)
- # define OTG1_DM_PULLUP (1 << 1)
- # define OTG1_DP_PULLDOWN (1 << 2)
- # define OTG1_DM_PULLDOWN (1 << 3)
- # define OTG1_ID_PULLDOWN (1 << 4)
- # define OTG1_VBUS_DRV (1 << 5)
- # define OTG1_VBUS_DISCHRG (1 << 6)
- # define OTG1_VBUS_CHRG (1 << 7)
- #define ISP1301_OTG_STATUS 0x10 /* u8 readonly */
- # define OTG_B_SESS_END (1 << 6)
- # define OTG_B_SESS_VLD (1 << 7)
- #define ISP1301_INTERRUPT_SOURCE 0x08 /* u8 read */
- #define ISP1301_INTERRUPT_LATCH 0x0A /* u8 read, set, +1 clear */
- #define ISP1301_INTERRUPT_FALLING 0x0C /* u8 read, set, +1 clear */
- #define ISP1301_INTERRUPT_RISING 0x0E /* u8 read, set, +1 clear */
- /* same bitfields in all interrupt registers */
- # define INTR_VBUS_VLD (1 << 0)
- # define INTR_SESS_VLD (1 << 1)
- # define INTR_DP_HI (1 << 2)
- # define INTR_ID_GND (1 << 3)
- # define INTR_DM_HI (1 << 4)
- # define INTR_ID_FLOAT (1 << 5)
- # define INTR_BDIS_ACON (1 << 6)
- # define INTR_CR_INT (1 << 7)
- /*-------------------------------------------------------------------------*/
- static inline const char *state_name(struct isp1301 *isp)
- {
- return otg_state_string(isp->otg.state);
- }
- /*-------------------------------------------------------------------------*/
- /* NOTE: some of this ISP1301 setup is specific to H2 boards;
- * not everything is guarded by board-specific checks, or even using
- * omap_usb_config data to deduce MC1_DAT_SE0 and MC2_BI_DI.
- *