171b9114dSArnd Bergmann // SPDX-License-Identifier: GPL-2.0+ 271b9114dSArnd Bergmann // 371b9114dSArnd Bergmann // Copyright (C) 2011 Samsung Electronics Co.Ltd 471b9114dSArnd Bergmann // Author: Joonyoung Shim <jy0922.shim@samsung.com> 571b9114dSArnd Bergmann 671b9114dSArnd Bergmann #include <linux/clk.h> 771b9114dSArnd Bergmann #include <linux/delay.h> 871b9114dSArnd Bergmann #include <linux/err.h> 971b9114dSArnd Bergmann #include <linux/io.h> 1071b9114dSArnd Bergmann #include <linux/platform_device.h> 11*c6ff132dSArnd Bergmann #include "map.h" 12*c6ff132dSArnd Bergmann #include "cpu.h" 13*c6ff132dSArnd Bergmann #include "usb-phy.h" 1471b9114dSArnd Bergmann 1571b9114dSArnd Bergmann #include "regs-sys-s3c64xx.h" 1671b9114dSArnd Bergmann #include "regs-usb-hsotg-phy-s3c64xx.h" 1771b9114dSArnd Bergmann 1871b9114dSArnd Bergmann enum samsung_usb_phy_type { 1971b9114dSArnd Bergmann USB_PHY_TYPE_DEVICE, 2071b9114dSArnd Bergmann USB_PHY_TYPE_HOST, 2171b9114dSArnd Bergmann }; 2271b9114dSArnd Bergmann 2371b9114dSArnd Bergmann static int s3c_usb_otgphy_init(struct platform_device *pdev) 2471b9114dSArnd Bergmann { 2571b9114dSArnd Bergmann struct clk *xusbxti; 2671b9114dSArnd Bergmann u32 phyclk; 2771b9114dSArnd Bergmann 2871b9114dSArnd Bergmann writel(readl(S3C64XX_OTHERS) | S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS); 2971b9114dSArnd Bergmann 3071b9114dSArnd Bergmann /* set clock frequency for PLL */ 3171b9114dSArnd Bergmann phyclk = readl(S3C_PHYCLK) & ~S3C_PHYCLK_CLKSEL_MASK; 3271b9114dSArnd Bergmann 3371b9114dSArnd Bergmann xusbxti = clk_get(&pdev->dev, "xusbxti"); 3471b9114dSArnd Bergmann if (!IS_ERR(xusbxti)) { 3571b9114dSArnd Bergmann switch (clk_get_rate(xusbxti)) { 3671b9114dSArnd Bergmann case 12 * MHZ: 3771b9114dSArnd Bergmann phyclk |= S3C_PHYCLK_CLKSEL_12M; 3871b9114dSArnd Bergmann break; 3971b9114dSArnd Bergmann case 24 * MHZ: 4071b9114dSArnd Bergmann phyclk |= S3C_PHYCLK_CLKSEL_24M; 4171b9114dSArnd Bergmann break; 4271b9114dSArnd Bergmann default: 4371b9114dSArnd Bergmann case 48 * MHZ: 4471b9114dSArnd Bergmann /* default reference clock */ 4571b9114dSArnd Bergmann break; 4671b9114dSArnd Bergmann } 4771b9114dSArnd Bergmann clk_put(xusbxti); 4871b9114dSArnd Bergmann } 4971b9114dSArnd Bergmann 5071b9114dSArnd Bergmann /* TODO: select external clock/oscillator */ 5171b9114dSArnd Bergmann writel(phyclk | S3C_PHYCLK_CLK_FORCE, S3C_PHYCLK); 5271b9114dSArnd Bergmann 5371b9114dSArnd Bergmann /* set to normal OTG PHY */ 5471b9114dSArnd Bergmann writel((readl(S3C_PHYPWR) & ~S3C_PHYPWR_NORMAL_MASK), S3C_PHYPWR); 5571b9114dSArnd Bergmann mdelay(1); 5671b9114dSArnd Bergmann 5771b9114dSArnd Bergmann /* reset OTG PHY and Link */ 5871b9114dSArnd Bergmann writel(S3C_RSTCON_PHY | S3C_RSTCON_HCLK | S3C_RSTCON_PHYCLK, 5971b9114dSArnd Bergmann S3C_RSTCON); 6071b9114dSArnd Bergmann udelay(20); /* at-least 10uS */ 6171b9114dSArnd Bergmann writel(0, S3C_RSTCON); 6271b9114dSArnd Bergmann 6371b9114dSArnd Bergmann return 0; 6471b9114dSArnd Bergmann } 6571b9114dSArnd Bergmann 6671b9114dSArnd Bergmann static int s3c_usb_otgphy_exit(struct platform_device *pdev) 6771b9114dSArnd Bergmann { 6871b9114dSArnd Bergmann writel((readl(S3C_PHYPWR) | S3C_PHYPWR_ANALOG_POWERDOWN | 6971b9114dSArnd Bergmann S3C_PHYPWR_OTG_DISABLE), S3C_PHYPWR); 7071b9114dSArnd Bergmann 7171b9114dSArnd Bergmann writel(readl(S3C64XX_OTHERS) & ~S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS); 7271b9114dSArnd Bergmann 7371b9114dSArnd Bergmann return 0; 7471b9114dSArnd Bergmann } 7571b9114dSArnd Bergmann 7671b9114dSArnd Bergmann int s3c_usb_phy_init(struct platform_device *pdev, int type) 7771b9114dSArnd Bergmann { 7871b9114dSArnd Bergmann if (type == USB_PHY_TYPE_DEVICE) 7971b9114dSArnd Bergmann return s3c_usb_otgphy_init(pdev); 8071b9114dSArnd Bergmann 8171b9114dSArnd Bergmann return -EINVAL; 8271b9114dSArnd Bergmann } 8371b9114dSArnd Bergmann 8471b9114dSArnd Bergmann int s3c_usb_phy_exit(struct platform_device *pdev, int type) 8571b9114dSArnd Bergmann { 8671b9114dSArnd Bergmann if (type == USB_PHY_TYPE_DEVICE) 8771b9114dSArnd Bergmann return s3c_usb_otgphy_exit(pdev); 8871b9114dSArnd Bergmann 8971b9114dSArnd Bergmann return -EINVAL; 9071b9114dSArnd Bergmann } 91