2012-03-07 16:23:47 +04:00
/*
* Copyright ( C ) 2011 Samsung Electronics Co . Ltd
* Author : Joonyoung Shim < jy0922 . shim @ samsung . 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 .
*
*/
# include <linux/clk.h>
# include <linux/delay.h>
# include <linux/err.h>
# include <linux/io.h>
# include <linux/platform_device.h>
# include <mach/map.h>
# include <plat/cpu.h>
# include <plat/usb-phy.h>
2013-01-03 01:31:15 +04:00
# include "regs-sys.h"
2015-07-29 20:00:36 +03:00
# include "regs-usb-hsotg-phy.h"
2013-01-03 01:31:15 +04:00
2012-03-07 16:23:47 +04:00
static int s3c_usb_otgphy_init ( struct platform_device * pdev )
{
struct clk * xusbxti ;
u32 phyclk ;
writel ( readl ( S3C64XX_OTHERS ) | S3C64XX_OTHERS_USBMASK , S3C64XX_OTHERS ) ;
/* set clock frequency for PLL */
phyclk = readl ( S3C_PHYCLK ) & ~ S3C_PHYCLK_CLKSEL_MASK ;
xusbxti = clk_get ( & pdev - > dev , " xusbxti " ) ;
if ( xusbxti & & ! IS_ERR ( xusbxti ) ) {
switch ( clk_get_rate ( xusbxti ) ) {
case 12 * MHZ :
phyclk | = S3C_PHYCLK_CLKSEL_12M ;
break ;
case 24 * MHZ :
phyclk | = S3C_PHYCLK_CLKSEL_24M ;
break ;
default :
case 48 * MHZ :
/* default reference clock */
break ;
}
clk_put ( xusbxti ) ;
}
/* TODO: select external clock/oscillator */
writel ( phyclk | S3C_PHYCLK_CLK_FORCE , S3C_PHYCLK ) ;
/* set to normal OTG PHY */
writel ( ( readl ( S3C_PHYPWR ) & ~ S3C_PHYPWR_NORMAL_MASK ) , S3C_PHYPWR ) ;
mdelay ( 1 ) ;
/* reset OTG PHY and Link */
writel ( S3C_RSTCON_PHY | S3C_RSTCON_HCLK | S3C_RSTCON_PHYCLK ,
S3C_RSTCON ) ;
udelay ( 20 ) ; /* at-least 10uS */
writel ( 0 , S3C_RSTCON ) ;
return 0 ;
}
static int s3c_usb_otgphy_exit ( struct platform_device * pdev )
{
writel ( ( readl ( S3C_PHYPWR ) | S3C_PHYPWR_ANALOG_POWERDOWN |
S3C_PHYPWR_OTG_DISABLE ) , S3C_PHYPWR ) ;
writel ( readl ( S3C64XX_OTHERS ) & ~ S3C64XX_OTHERS_USBMASK , S3C64XX_OTHERS ) ;
return 0 ;
}
int s5p_usb_phy_init ( struct platform_device * pdev , int type )
{
2013-04-12 00:49:39 +04:00
if ( type = = USB_PHY_TYPE_DEVICE )
2012-03-07 16:23:47 +04:00
return s3c_usb_otgphy_init ( pdev ) ;
return - EINVAL ;
}
int s5p_usb_phy_exit ( struct platform_device * pdev , int type )
{
2013-04-12 00:49:39 +04:00
if ( type = = USB_PHY_TYPE_DEVICE )
2012-03-07 16:23:47 +04:00
return s3c_usb_otgphy_exit ( pdev ) ;
return - EINVAL ;
}