2010-12-07 17:54:03 +05:30
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation .
*/
# include <linux/module.h>
# include <linux/platform_device.h>
2010-12-07 17:54:05 +05:30
# include <linux/pm_runtime.h>
2010-12-07 17:54:03 +05:30
# include <linux/usb/msm_hsusb_hw.h>
# include <linux/usb/ulpi.h>
2012-05-08 23:29:01 +03:00
# include <linux/usb/gadget.h>
2012-05-11 17:25:46 +03:00
# include <linux/usb/chipidea.h>
2010-12-07 17:54:03 +05:30
2012-05-11 17:25:46 +03:00
# include "ci.h"
2010-12-07 17:54:03 +05:30
2012-07-07 22:56:40 +08:00
# define MSM_USB_BASE (ci->hw_bank.abs)
2010-12-07 17:54:03 +05:30
2012-07-07 22:56:40 +08:00
static void ci13xxx_msm_notify_event ( struct ci13xxx * ci , unsigned event )
2010-12-07 17:54:03 +05:30
{
2012-07-07 22:56:40 +08:00
struct device * dev = ci - > gadget . dev . parent ;
2010-12-07 17:54:03 +05:30
int val ;
switch ( event ) {
case CI13XXX_CONTROLLER_RESET_EVENT :
dev_dbg ( dev , " CI13XXX_CONTROLLER_RESET_EVENT received \n " ) ;
writel ( 0 , USB_AHBBURST ) ;
writel ( 0 , USB_AHBMODE ) ;
break ;
case CI13XXX_CONTROLLER_STOPPED_EVENT :
dev_dbg ( dev , " CI13XXX_CONTROLLER_STOPPED_EVENT received \n " ) ;
/*
* Put the transceiver in non - driving mode . Otherwise host
* may not detect soft - disconnection .
*/
2012-07-07 22:56:40 +08:00
val = usb_phy_io_read ( ci - > transceiver , ULPI_FUNC_CTRL ) ;
2010-12-07 17:54:03 +05:30
val & = ~ ULPI_FUNC_CTRL_OPMODE_MASK ;
val | = ULPI_FUNC_CTRL_OPMODE_NONDRIVING ;
2012-07-07 22:56:40 +08:00
usb_phy_io_write ( ci - > transceiver , val , ULPI_FUNC_CTRL ) ;
2010-12-07 17:54:03 +05:30
break ;
default :
2012-07-07 22:56:40 +08:00
dev_dbg ( dev , " unknown ci13xxx event \n " ) ;
2010-12-07 17:54:03 +05:30
break ;
}
}
2012-06-29 17:48:53 +08:00
static struct ci13xxx_platform_data ci13xxx_msm_platdata = {
2010-12-07 17:54:03 +05:30
. name = " ci13xxx_msm " ,
. flags = CI13XXX_REGS_SHARED |
CI13XXX_REQUIRE_TRANSCEIVER |
CI13XXX_PULLUP_ON_VBUS |
CI13XXX_DISABLE_STREAMING ,
. notify_event = ci13xxx_msm_notify_event ,
} ;
2012-11-19 13:21:48 -05:00
static int ci13xxx_msm_probe ( struct platform_device * pdev )
2010-12-07 17:54:03 +05:30
{
2012-05-08 23:29:01 +03:00
struct platform_device * plat_ci ;
2010-12-07 17:54:03 +05:30
dev_dbg ( & pdev - > dev , " ci13xxx_msm_probe \n " ) ;
2012-07-07 22:56:41 +08:00
plat_ci = ci13xxx_add_device ( & pdev - > dev ,
pdev - > resource , pdev - > num_resources ,
& ci13xxx_msm_platdata ) ;
if ( IS_ERR ( plat_ci ) ) {
dev_err ( & pdev - > dev , " ci13xxx_add_device failed! \n " ) ;
return PTR_ERR ( plat_ci ) ;
2010-12-07 17:54:03 +05:30
}
2012-06-29 17:48:52 +08:00
platform_set_drvdata ( pdev , plat_ci ) ;
2010-12-07 17:54:05 +05:30
pm_runtime_no_callbacks ( & pdev - > dev ) ;
pm_runtime_enable ( & pdev - > dev ) ;
2010-12-07 17:54:03 +05:30
return 0 ;
}
2012-11-19 13:26:20 -05:00
static int ci13xxx_msm_remove ( struct platform_device * pdev )
2012-06-29 17:48:52 +08:00
{
struct platform_device * plat_ci = platform_get_drvdata ( pdev ) ;
pm_runtime_disable ( & pdev - > dev ) ;
2012-07-07 22:56:41 +08:00
ci13xxx_remove_device ( plat_ci ) ;
2012-06-29 17:48:52 +08:00
return 0 ;
}
2010-12-07 17:54:03 +05:30
static struct platform_driver ci13xxx_msm_driver = {
. probe = ci13xxx_msm_probe ,
2012-11-19 13:21:08 -05:00
. remove = ci13xxx_msm_remove ,
2010-12-07 17:54:03 +05:30
. driver = { . name = " msm_hsusb " , } ,
} ;
2012-06-29 17:48:52 +08:00
module_platform_driver ( ci13xxx_msm_driver ) ;
2011-10-10 18:38:11 +02:00
2012-06-29 17:48:52 +08:00
MODULE_ALIAS ( " platform:msm_hsusb " ) ;
2011-10-10 18:38:11 +02:00
MODULE_LICENSE ( " GPL v2 " ) ;