162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// Copyright (C) 2011 Samsung Electronics Co.Ltd 462306a36Sopenharmony_ci// Author: Joonyoung Shim <jy0922.shim@samsung.com> 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/clk.h> 762306a36Sopenharmony_ci#include <linux/delay.h> 862306a36Sopenharmony_ci#include <linux/err.h> 962306a36Sopenharmony_ci#include <linux/io.h> 1062306a36Sopenharmony_ci#include <linux/platform_device.h> 1162306a36Sopenharmony_ci#include "map.h" 1262306a36Sopenharmony_ci#include "cpu.h" 1362306a36Sopenharmony_ci#include "usb-phy.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "regs-sys-s3c64xx.h" 1662306a36Sopenharmony_ci#include "regs-usb-hsotg-phy-s3c64xx.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cienum samsung_usb_phy_type { 1962306a36Sopenharmony_ci USB_PHY_TYPE_DEVICE, 2062306a36Sopenharmony_ci USB_PHY_TYPE_HOST, 2162306a36Sopenharmony_ci}; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic int s3c_usb_otgphy_init(struct platform_device *pdev) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci struct clk *xusbxti; 2662306a36Sopenharmony_ci u32 phyclk; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci writel(readl(S3C64XX_OTHERS) | S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci /* set clock frequency for PLL */ 3162306a36Sopenharmony_ci phyclk = readl(S3C_PHYCLK) & ~S3C_PHYCLK_CLKSEL_MASK; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci xusbxti = clk_get(&pdev->dev, "xusbxti"); 3462306a36Sopenharmony_ci if (!IS_ERR(xusbxti)) { 3562306a36Sopenharmony_ci switch (clk_get_rate(xusbxti)) { 3662306a36Sopenharmony_ci case 12 * MHZ: 3762306a36Sopenharmony_ci phyclk |= S3C_PHYCLK_CLKSEL_12M; 3862306a36Sopenharmony_ci break; 3962306a36Sopenharmony_ci case 24 * MHZ: 4062306a36Sopenharmony_ci phyclk |= S3C_PHYCLK_CLKSEL_24M; 4162306a36Sopenharmony_ci break; 4262306a36Sopenharmony_ci default: 4362306a36Sopenharmony_ci case 48 * MHZ: 4462306a36Sopenharmony_ci /* default reference clock */ 4562306a36Sopenharmony_ci break; 4662306a36Sopenharmony_ci } 4762306a36Sopenharmony_ci clk_put(xusbxti); 4862306a36Sopenharmony_ci } 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci /* TODO: select external clock/oscillator */ 5162306a36Sopenharmony_ci writel(phyclk | S3C_PHYCLK_CLK_FORCE, S3C_PHYCLK); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci /* set to normal OTG PHY */ 5462306a36Sopenharmony_ci writel((readl(S3C_PHYPWR) & ~S3C_PHYPWR_NORMAL_MASK), S3C_PHYPWR); 5562306a36Sopenharmony_ci mdelay(1); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /* reset OTG PHY and Link */ 5862306a36Sopenharmony_ci writel(S3C_RSTCON_PHY | S3C_RSTCON_HCLK | S3C_RSTCON_PHYCLK, 5962306a36Sopenharmony_ci S3C_RSTCON); 6062306a36Sopenharmony_ci udelay(20); /* at-least 10uS */ 6162306a36Sopenharmony_ci writel(0, S3C_RSTCON); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci return 0; 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic int s3c_usb_otgphy_exit(struct platform_device *pdev) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci writel((readl(S3C_PHYPWR) | S3C_PHYPWR_ANALOG_POWERDOWN | 6962306a36Sopenharmony_ci S3C_PHYPWR_OTG_DISABLE), S3C_PHYPWR); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci writel(readl(S3C64XX_OTHERS) & ~S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci return 0; 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ciint s3c_usb_phy_init(struct platform_device *pdev, int type) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci if (type == USB_PHY_TYPE_DEVICE) 7962306a36Sopenharmony_ci return s3c_usb_otgphy_init(pdev); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci return -EINVAL; 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ciint s3c_usb_phy_exit(struct platform_device *pdev, int type) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci if (type == USB_PHY_TYPE_DEVICE) 8762306a36Sopenharmony_ci return s3c_usb_otgphy_exit(pdev); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci return -EINVAL; 9062306a36Sopenharmony_ci} 91