Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // Copyright (C) 2011 Samsung Electronics Co.Ltd
0004 // Author: Joonyoung Shim <jy0922.shim@samsung.com>
0005 
0006 #include <linux/clk.h>
0007 #include <linux/delay.h>
0008 #include <linux/err.h>
0009 #include <linux/io.h>
0010 #include <linux/platform_device.h>
0011 #include "map.h"
0012 #include "cpu.h"
0013 #include "usb-phy.h"
0014 
0015 #include "regs-sys-s3c64xx.h"
0016 #include "regs-usb-hsotg-phy-s3c64xx.h"
0017 
0018 enum samsung_usb_phy_type {
0019     USB_PHY_TYPE_DEVICE,
0020     USB_PHY_TYPE_HOST,
0021 };
0022 
0023 static int s3c_usb_otgphy_init(struct platform_device *pdev)
0024 {
0025     struct clk *xusbxti;
0026     u32 phyclk;
0027 
0028     writel(readl(S3C64XX_OTHERS) | S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS);
0029 
0030     /* set clock frequency for PLL */
0031     phyclk = readl(S3C_PHYCLK) & ~S3C_PHYCLK_CLKSEL_MASK;
0032 
0033     xusbxti = clk_get(&pdev->dev, "xusbxti");
0034     if (!IS_ERR(xusbxti)) {
0035         switch (clk_get_rate(xusbxti)) {
0036         case 12 * MHZ:
0037             phyclk |= S3C_PHYCLK_CLKSEL_12M;
0038             break;
0039         case 24 * MHZ:
0040             phyclk |= S3C_PHYCLK_CLKSEL_24M;
0041             break;
0042         default:
0043         case 48 * MHZ:
0044             /* default reference clock */
0045             break;
0046         }
0047         clk_put(xusbxti);
0048     }
0049 
0050     /* TODO: select external clock/oscillator */
0051     writel(phyclk | S3C_PHYCLK_CLK_FORCE, S3C_PHYCLK);
0052 
0053     /* set to normal OTG PHY */
0054     writel((readl(S3C_PHYPWR) & ~S3C_PHYPWR_NORMAL_MASK), S3C_PHYPWR);
0055     mdelay(1);
0056 
0057     /* reset OTG PHY and Link */
0058     writel(S3C_RSTCON_PHY | S3C_RSTCON_HCLK | S3C_RSTCON_PHYCLK,
0059             S3C_RSTCON);
0060     udelay(20); /* at-least 10uS */
0061     writel(0, S3C_RSTCON);
0062 
0063     return 0;
0064 }
0065 
0066 static int s3c_usb_otgphy_exit(struct platform_device *pdev)
0067 {
0068     writel((readl(S3C_PHYPWR) | S3C_PHYPWR_ANALOG_POWERDOWN |
0069                 S3C_PHYPWR_OTG_DISABLE), S3C_PHYPWR);
0070 
0071     writel(readl(S3C64XX_OTHERS) & ~S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS);
0072 
0073     return 0;
0074 }
0075 
0076 int s3c_usb_phy_init(struct platform_device *pdev, int type)
0077 {
0078     if (type == USB_PHY_TYPE_DEVICE)
0079         return s3c_usb_otgphy_init(pdev);
0080 
0081     return -EINVAL;
0082 }
0083 
0084 int s3c_usb_phy_exit(struct platform_device *pdev, int type)
0085 {
0086     if (type == USB_PHY_TYPE_DEVICE)
0087         return s3c_usb_otgphy_exit(pdev);
0088 
0089     return -EINVAL;
0090 }