1/* 2 * Copyright (C) 2011 Samsung Electronics Co.Ltd 3 * Author: Joonyoung Shim <jy0922.shim@samsung.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the 7 * Free Software Foundation; either version 2 of the License, or (at your 8 * option) any later version. 9 * 10 */ 11 12#include <linux/clk.h> 13#include <linux/delay.h> 14#include <linux/err.h> 15#include <linux/io.h> 16#include <linux/platform_device.h> 17#include <mach/map.h> 18#include <plat/cpu.h> 19#include <plat/regs-usb-hsotg-phy.h> 20#include <plat/usb-phy.h> 21 22#include "regs-sys.h" 23 24static int s3c_usb_otgphy_init(struct platform_device *pdev) 25{ 26 struct clk *xusbxti; 27 u32 phyclk; 28 29 writel(readl(S3C64XX_OTHERS) | S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS); 30 31 /* set clock frequency for PLL */ 32 phyclk = readl(S3C_PHYCLK) & ~S3C_PHYCLK_CLKSEL_MASK; 33 34 xusbxti = clk_get(&pdev->dev, "xusbxti"); 35 if (xusbxti && !IS_ERR(xusbxti)) { 36 switch (clk_get_rate(xusbxti)) { 37 case 12 * MHZ: 38 phyclk |= S3C_PHYCLK_CLKSEL_12M; 39 break; 40 case 24 * MHZ: 41 phyclk |= S3C_PHYCLK_CLKSEL_24M; 42 break; 43 default: 44 case 48 * MHZ: 45 /* default reference clock */ 46 break; 47 } 48 clk_put(xusbxti); 49 } 50 51 /* TODO: select external clock/oscillator */ 52 writel(phyclk | S3C_PHYCLK_CLK_FORCE, S3C_PHYCLK); 53 54 /* set to normal OTG PHY */ 55 writel((readl(S3C_PHYPWR) & ~S3C_PHYPWR_NORMAL_MASK), S3C_PHYPWR); 56 mdelay(1); 57 58 /* reset OTG PHY and Link */ 59 writel(S3C_RSTCON_PHY | S3C_RSTCON_HCLK | S3C_RSTCON_PHYCLK, 60 S3C_RSTCON); 61 udelay(20); /* at-least 10uS */ 62 writel(0, S3C_RSTCON); 63 64 return 0; 65} 66 67static int s3c_usb_otgphy_exit(struct platform_device *pdev) 68{ 69 writel((readl(S3C_PHYPWR) | S3C_PHYPWR_ANALOG_POWERDOWN | 70 S3C_PHYPWR_OTG_DISABLE), S3C_PHYPWR); 71 72 writel(readl(S3C64XX_OTHERS) & ~S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS); 73 74 return 0; 75} 76 77int s5p_usb_phy_init(struct platform_device *pdev, int type) 78{ 79 if (type == USB_PHY_TYPE_DEVICE) 80 return s3c_usb_otgphy_init(pdev); 81 82 return -EINVAL; 83} 84 85int s5p_usb_phy_exit(struct platform_device *pdev, int type) 86{ 87 if (type == USB_PHY_TYPE_DEVICE) 88 return s3c_usb_otgphy_exit(pdev); 89 90 return -EINVAL; 91} 92