2011-01-18 11:22:50 +05:30
/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
2010-02-25 11:38:39 -08:00
*
* 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 .
*
* 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 . , 51 Franklin Street , Fifth Floor , Boston , MA
* 02110 - 1301 , USA .
*/
2011-07-26 10:53:52 +01:00
# include <linux/gpio.h>
2010-02-25 11:38:39 -08:00
# include <linux/kernel.h>
# include <linux/irq.h>
# include <linux/platform_device.h>
# include <linux/delay.h>
2010-12-08 13:37:07 +05:30
# include <linux/usb/msm_hsusb.h>
2011-01-18 11:22:50 +05:30
# include <linux/err.h>
2011-02-23 09:37:42 -08:00
# include <linux/clkdev.h>
2010-02-25 11:38:39 -08:00
# include <asm/mach-types.h>
# include <asm/mach/arch.h>
# include <asm/io.h>
# include <asm/setup.h>
2010-05-05 07:17:31 -07:00
# include <mach/irqs.h>
# include <mach/sirc.h>
2011-01-18 11:22:50 +05:30
# include <mach/vreg.h>
2013-12-30 13:15:27 -08:00
# include <mach/clk.h>
2012-08-24 15:14:41 +02:00
# include <linux/platform_data/mmc-msm_sdcc.h>
2010-02-25 11:38:39 -08:00
# include "devices.h"
2012-09-05 12:28:52 -07:00
# include "common.h"
2010-02-25 11:38:39 -08:00
2012-10-04 17:11:28 -07:00
static const resource_size_t qsd8x50_surf_smc91x_base __initconst = 0x70000300 ;
static const unsigned qsd8x50_surf_smc91x_gpio __initconst = 156 ;
2010-09-29 13:46:45 -07:00
/* Leave smc91x resources empty here, as we'll fill them in
* at run - time : they vary from board to board , and the true
* configuration won ' t be known until boot .
*/
2010-12-20 15:00:17 -08:00
static struct resource smc91x_resources [ ] = {
2010-09-29 13:46:45 -07:00
[ 0 ] = {
. flags = IORESOURCE_MEM ,
} ,
[ 1 ] = {
. flags = IORESOURCE_IRQ ,
} ,
} ;
2010-12-20 15:00:17 -08:00
static struct platform_device smc91x_device = {
2010-09-29 13:46:45 -07:00
. name = " smc91x " ,
. id = 0 ,
. num_resources = ARRAY_SIZE ( smc91x_resources ) ,
. resource = smc91x_resources ,
} ;
static int __init msm_init_smc91x ( void )
{
if ( machine_is_qsd8x50_surf ( ) ) {
smc91x_resources [ 0 ] . start = qsd8x50_surf_smc91x_base ;
smc91x_resources [ 0 ] . end = qsd8x50_surf_smc91x_base + 0xff ;
smc91x_resources [ 1 ] . start =
gpio_to_irq ( qsd8x50_surf_smc91x_gpio ) ;
smc91x_resources [ 1 ] . end =
gpio_to_irq ( qsd8x50_surf_smc91x_gpio ) ;
platform_device_register ( & smc91x_device ) ;
}
return 0 ;
}
module_init ( msm_init_smc91x ) ;
2010-12-08 13:37:07 +05:30
static int hsusb_phy_init_seq [ ] = {
0x08 , 0x31 , /* Increase HS Driver Amplitude */
0x20 , 0x32 , /* Enable and set Pre-Emphasis Depth to 10% */
- 1
} ;
2013-12-30 13:15:27 -08:00
static int hsusb_link_clk_reset ( struct clk * link_clk , bool assert )
{
int ret ;
if ( assert ) {
ret = clk_reset ( link_clk , CLK_RESET_ASSERT ) ;
if ( ret )
pr_err ( " usb hs_clk assert failed \n " ) ;
} else {
ret = clk_reset ( link_clk , CLK_RESET_DEASSERT ) ;
if ( ret )
pr_err ( " usb hs_clk deassert failed \n " ) ;
}
return ret ;
}
static int hsusb_phy_clk_reset ( struct clk * phy_clk )
{
int ret ;
ret = clk_reset ( phy_clk , CLK_RESET_ASSERT ) ;
if ( ret ) {
pr_err ( " usb phy clk assert failed \n " ) ;
return ret ;
}
usleep_range ( 10000 , 12000 ) ;
ret = clk_reset ( phy_clk , CLK_RESET_DEASSERT ) ;
if ( ret )
pr_err ( " usb phy clk deassert failed \n " ) ;
return ret ;
}
2010-12-08 13:37:07 +05:30
static struct msm_otg_platform_data msm_otg_pdata = {
. phy_init_seq = hsusb_phy_init_seq ,
2014-04-28 16:34:11 +03:00
. mode = USB_DR_MODE_PERIPHERAL ,
2010-12-08 13:37:07 +05:30
. otg_control = OTG_PHY_CONTROL ,
2013-12-30 13:15:27 -08:00
. link_clk_reset = hsusb_link_clk_reset ,
. phy_clk_reset = hsusb_phy_clk_reset ,
2010-12-08 13:37:07 +05:30
} ;
2010-02-25 11:38:39 -08:00
static struct platform_device * devices [ ] __initdata = {
2013-06-17 10:43:18 -07:00
& msm_clock_8x50 ,
2013-03-04 15:08:27 -08:00
& msm_device_gpio_8x50 ,
2010-05-05 07:17:31 -07:00
& msm_device_uart3 ,
2010-10-06 13:52:11 -07:00
& msm_device_smd ,
2010-12-08 13:37:07 +05:30
& msm_device_otg ,
& msm_device_hsusb ,
& msm_device_hsusb_host ,
2010-02-25 11:38:39 -08:00
} ;
2011-01-18 11:22:50 +05:30
static struct msm_mmc_gpio sdc1_gpio_cfg [ ] = {
{ 51 , " sdc1_dat_3 " } ,
{ 52 , " sdc1_dat_2 " } ,
{ 53 , " sdc1_dat_1 " } ,
{ 54 , " sdc1_dat_0 " } ,
{ 55 , " sdc1_cmd " } ,
{ 56 , " sdc1_clk " }
} ;
static struct vreg * vreg_mmc ;
static unsigned long vreg_sts ;
static uint32_t msm_sdcc_setup_power ( struct device * dv , unsigned int vdd )
{
int rc = 0 ;
struct platform_device * pdev ;
pdev = container_of ( dv , struct platform_device , dev ) ;
if ( vdd = = 0 ) {
if ( ! vreg_sts )
return 0 ;
clear_bit ( pdev - > id , & vreg_sts ) ;
if ( ! vreg_sts ) {
rc = vreg_disable ( vreg_mmc ) ;
if ( rc )
pr_err ( " vreg_mmc disable failed for slot "
" %d: %d \n " , pdev - > id , rc ) ;
}
return 0 ;
}
if ( ! vreg_sts ) {
rc = vreg_set_level ( vreg_mmc , 2900 ) ;
if ( rc )
pr_err ( " vreg_mmc set level failed for slot %d: %d \n " ,
pdev - > id , rc ) ;
rc = vreg_enable ( vreg_mmc ) ;
if ( rc )
pr_err ( " vreg_mmc enable failed for slot %d: %d \n " ,
pdev - > id , rc ) ;
}
set_bit ( pdev - > id , & vreg_sts ) ;
return 0 ;
}
static struct msm_mmc_gpio_data sdc1_gpio = {
. gpio = sdc1_gpio_cfg ,
. size = ARRAY_SIZE ( sdc1_gpio_cfg ) ,
} ;
static struct msm_mmc_platform_data qsd8x50_sdc1_data = {
. ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 ,
. translate_vdd = msm_sdcc_setup_power ,
. gpio_data = & sdc1_gpio ,
} ;
static void __init qsd8x50_init_mmc ( void )
{
2011-03-29 11:48:45 -07:00
vreg_mmc = vreg_get ( NULL , " gp5 " ) ;
2011-01-18 11:22:50 +05:30
if ( IS_ERR ( vreg_mmc ) ) {
pr_err ( " vreg get for vreg_mmc failed (%ld) \n " ,
PTR_ERR ( vreg_mmc ) ) ;
return ;
}
msm_add_sdcc ( 1 , & qsd8x50_sdc1_data , 0 , 0 ) ;
}
2010-05-05 07:17:31 -07:00
static void __init qsd8x50_map_io ( void )
2010-02-25 11:38:39 -08:00
{
2010-05-05 07:17:31 -07:00
msm_map_qsd8x50_io ( ) ;
2010-02-25 11:38:39 -08:00
}
2010-05-05 07:17:31 -07:00
static void __init qsd8x50_init_irq ( void )
2010-02-25 11:38:39 -08:00
{
2010-05-05 07:17:31 -07:00
msm_init_irq ( ) ;
msm_init_sirc ( ) ;
2010-02-25 11:38:39 -08:00
}
static void __init qsd8x50_init ( void )
{
2010-12-08 13:37:07 +05:30
msm_device_otg . dev . platform_data = & msm_otg_pdata ;
msm_device_hsusb . dev . parent = & msm_device_otg . dev ;
msm_device_hsusb_host . dev . parent = & msm_device_otg . dev ;
2010-02-25 11:38:39 -08:00
platform_add_devices ( devices , ARRAY_SIZE ( devices ) ) ;
2011-01-18 11:22:50 +05:30
qsd8x50_init_mmc ( ) ;
2010-02-25 11:38:39 -08:00
}
2012-05-02 15:53:20 +08:00
static void __init qsd8x50_init_late ( void )
{
smd_debugfs_init ( ) ;
}
2010-02-25 11:38:39 -08:00
MACHINE_START ( QSD8X50_SURF , " QCT QSD8X50 SURF " )
2011-07-05 22:38:14 -04:00
. atag_offset = 0x100 ,
2010-02-25 11:38:39 -08:00
. map_io = qsd8x50_map_io ,
. init_irq = qsd8x50_init_irq ,
. init_machine = qsd8x50_init ,
2012-05-02 15:53:20 +08:00
. init_late = qsd8x50_init_late ,
2012-11-08 12:40:59 -07:00
. init_time = qsd8x50_timer_init ,
2010-02-25 11:38:39 -08:00
MACHINE_END
2010-05-05 07:17:31 -07:00
MACHINE_START ( QSD8X50A_ST1_5 , " QCT QSD8X50A ST1.5 " )
2011-07-05 22:38:14 -04:00
. atag_offset = 0x100 ,
2010-02-25 11:38:39 -08:00
. map_io = qsd8x50_map_io ,
. init_irq = qsd8x50_init_irq ,
. init_machine = qsd8x50_init ,
2012-05-02 15:53:20 +08:00
. init_late = qsd8x50_init_late ,
2012-11-08 12:40:59 -07:00
. init_time = qsd8x50_timer_init ,
2010-02-25 11:38:39 -08:00
MACHINE_END