Path: blob/master/arch/arm/mach-exynos4/setup-usb-phy.c
10817 views
/*1* Copyright (C) 2011 Samsung Electronics Co.Ltd2* Author: Joonyoung Shim <[email protected]>3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License as published by the6* Free Software Foundation; either version 2 of the License, or (at your7* option) any later version.8*9*/1011#include <linux/clk.h>12#include <linux/delay.h>13#include <linux/err.h>14#include <linux/io.h>15#include <linux/platform_device.h>16#include <mach/regs-pmu.h>17#include <mach/regs-usb-phy.h>18#include <plat/cpu.h>19#include <plat/usb-phy.h>2021static int exynos4_usb_phy1_init(struct platform_device *pdev)22{23struct clk *otg_clk;24struct clk *xusbxti_clk;25u32 phyclk;26u32 rstcon;27int err;2829otg_clk = clk_get(&pdev->dev, "otg");30if (IS_ERR(otg_clk)) {31dev_err(&pdev->dev, "Failed to get otg clock\n");32return PTR_ERR(otg_clk);33}3435err = clk_enable(otg_clk);36if (err) {37clk_put(otg_clk);38return err;39}4041writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,42S5P_USBHOST_PHY_CONTROL);4344/* set clock frequency for PLL */45phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;4647xusbxti_clk = clk_get(&pdev->dev, "xusbxti");48if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {49switch (clk_get_rate(xusbxti_clk)) {50case 12 * MHZ:51phyclk |= CLKSEL_12M;52break;53case 24 * MHZ:54phyclk |= CLKSEL_24M;55break;56default:57case 48 * MHZ:58/* default reference clock */59break;60}61clk_put(xusbxti_clk);62}6364writel(phyclk, EXYNOS4_PHYCLK);6566/* floating prevention logic: disable */67writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);6869/* set to normal HSIC 0 and 1 of PHY1 */70writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK),71EXYNOS4_PHYPWR);7273/* set to normal standard USB of PHY1 */74writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR);7576/* reset all ports of both PHY and Link */77rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK |78PHY1_SWRST_MASK;79writel(rstcon, EXYNOS4_RSTCON);80udelay(10);8182rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);83writel(rstcon, EXYNOS4_RSTCON);84udelay(50);8586clk_disable(otg_clk);87clk_put(otg_clk);8889return 0;90}9192static int exynos4_usb_phy1_exit(struct platform_device *pdev)93{94struct clk *otg_clk;95int err;9697otg_clk = clk_get(&pdev->dev, "otg");98if (IS_ERR(otg_clk)) {99dev_err(&pdev->dev, "Failed to get otg clock\n");100return PTR_ERR(otg_clk);101}102103err = clk_enable(otg_clk);104if (err) {105clk_put(otg_clk);106return err;107}108109writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),110EXYNOS4_PHYPWR);111112writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,113S5P_USBHOST_PHY_CONTROL);114115clk_disable(otg_clk);116clk_put(otg_clk);117118return 0;119}120121int s5p_usb_phy_init(struct platform_device *pdev, int type)122{123if (type == S5P_USB_PHY_HOST)124return exynos4_usb_phy1_init(pdev);125126return -EINVAL;127}128129int s5p_usb_phy_exit(struct platform_device *pdev, int type)130{131if (type == S5P_USB_PHY_HOST)132return exynos4_usb_phy1_exit(pdev);133134return -EINVAL;135}136137138