linux/arch/arm/mach-s5pv210/setup-usb-phy.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 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
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundationr
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/delay.h>
  12#include <linux/err.h>
  13#include <linux/io.h>
  14#include <linux/platform_device.h>
  15
  16#include <mach/map.h>
  17
  18#include <plat/cpu.h>
  19#include <plat/regs-usb-hsotg-phy.h>
  20#include <plat/usb-phy.h>
  21
  22#define S5PV210_USB_PHY_CON     (S3C_VA_SYS + 0xE80C)
  23#define S5PV210_USB_PHY0_EN     (1 << 0)
  24#define S5PV210_USB_PHY1_EN     (1 << 1)
  25
  26static int s5pv210_usb_otgphy_init(struct platform_device *pdev)
  27{
  28        struct clk *xusbxti;
  29        u32 phyclk;
  30
  31        writel(readl(S5PV210_USB_PHY_CON) | S5PV210_USB_PHY0_EN,
  32                        S5PV210_USB_PHY_CON);
  33
  34        /* set clock frequency for PLL */
  35        phyclk = readl(S3C_PHYCLK) & ~S3C_PHYCLK_CLKSEL_MASK;
  36
  37        xusbxti = clk_get(&pdev->dev, "xusbxti");
  38        if (xusbxti && !IS_ERR(xusbxti)) {
  39                switch (clk_get_rate(xusbxti)) {
  40                case 12 * MHZ:
  41                        phyclk |= S3C_PHYCLK_CLKSEL_12M;
  42                        break;
  43                case 24 * MHZ:
  44                        phyclk |= S3C_PHYCLK_CLKSEL_24M;
  45                        break;
  46                default:
  47                case 48 * MHZ:
  48                        /* default reference clock */
  49                        break;
  50                }
  51                clk_put(xusbxti);
  52        }
  53
  54        /* TODO: select external clock/oscillator */
  55        writel(phyclk | S3C_PHYCLK_CLK_FORCE, S3C_PHYCLK);
  56
  57        /* set to normal OTG PHY */
  58        writel((readl(S3C_PHYPWR) & ~S3C_PHYPWR_NORMAL_MASK), S3C_PHYPWR);
  59        mdelay(1);
  60
  61        /* reset OTG PHY and Link */
  62        writel(S3C_RSTCON_PHY | S3C_RSTCON_HCLK | S3C_RSTCON_PHYCLK,
  63                        S3C_RSTCON);
  64        udelay(20);     /* at-least 10uS */
  65        writel(0, S3C_RSTCON);
  66
  67        return 0;
  68}
  69
  70static int s5pv210_usb_otgphy_exit(struct platform_device *pdev)
  71{
  72        writel((readl(S3C_PHYPWR) | S3C_PHYPWR_ANALOG_POWERDOWN |
  73                                S3C_PHYPWR_OTG_DISABLE), S3C_PHYPWR);
  74
  75        writel(readl(S5PV210_USB_PHY_CON) & ~S5PV210_USB_PHY0_EN,
  76                        S5PV210_USB_PHY_CON);
  77
  78        return 0;
  79}
  80
  81int s5p_usb_phy_init(struct platform_device *pdev, int type)
  82{
  83        if (type == USB_PHY_TYPE_DEVICE)
  84                return s5pv210_usb_otgphy_init(pdev);
  85
  86        return -EINVAL;
  87}
  88
  89int s5p_usb_phy_exit(struct platform_device *pdev, int type)
  90{
  91        if (type == USB_PHY_TYPE_DEVICE)
  92                return s5pv210_usb_otgphy_exit(pdev);
  93
  94        return -EINVAL;
  95}
  96