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