Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1/*
  2 * Copyright (C) 2011 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 it
  6 *  under  the terms of  the GNU General  Public License as published by the
  7 *  Free Software Foundation;  either version 2 of the  License, or (at your
  8 *  option) any later version.
  9 *
 10 */
 11
 12#include <linux/clk.h>
 13#include <linux/delay.h>
 14#include <linux/err.h>
 15#include <linux/io.h>
 16#include <linux/platform_device.h>
 17#include <mach/regs-pmu.h>
 18#include <mach/regs-usb-phy.h>
 19#include <plat/cpu.h>
 20#include <plat/usb-phy.h>
 21
 22static int exynos4_usb_phy1_init(struct platform_device *pdev)
 23{
 24	struct clk *otg_clk;
 25	struct clk *xusbxti_clk;
 26	u32 phyclk;
 27	u32 rstcon;
 28	int err;
 29
 30	otg_clk = clk_get(&pdev->dev, "otg");
 31	if (IS_ERR(otg_clk)) {
 32		dev_err(&pdev->dev, "Failed to get otg clock\n");
 33		return PTR_ERR(otg_clk);
 34	}
 35
 36	err = clk_enable(otg_clk);
 37	if (err) {
 38		clk_put(otg_clk);
 39		return err;
 40	}
 41
 42	writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
 43			S5P_USBHOST_PHY_CONTROL);
 44
 45	/* set clock frequency for PLL */
 46	phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
 47
 48	xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
 49	if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
 50		switch (clk_get_rate(xusbxti_clk)) {
 51		case 12 * MHZ:
 52			phyclk |= CLKSEL_12M;
 53			break;
 54		case 24 * MHZ:
 55			phyclk |= CLKSEL_24M;
 56			break;
 57		default:
 58		case 48 * MHZ:
 59			/* default reference clock */
 60			break;
 61		}
 62		clk_put(xusbxti_clk);
 63	}
 64
 65	writel(phyclk, EXYNOS4_PHYCLK);
 66
 67	/* floating prevention logic: disable */
 68	writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
 69
 70	/* set to normal HSIC 0 and 1 of PHY1 */
 71	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK),
 72			EXYNOS4_PHYPWR);
 73
 74	/* set to normal standard USB of PHY1 */
 75	writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR);
 76
 77	/* reset all ports of both PHY and Link */
 78	rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK |
 79		PHY1_SWRST_MASK;
 80	writel(rstcon, EXYNOS4_RSTCON);
 81	udelay(10);
 82
 83	rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);
 84	writel(rstcon, EXYNOS4_RSTCON);
 85	udelay(80);
 86
 87	clk_disable(otg_clk);
 88	clk_put(otg_clk);
 89
 90	return 0;
 91}
 92
 93static int exynos4_usb_phy1_exit(struct platform_device *pdev)
 94{
 95	struct clk *otg_clk;
 96	int err;
 97
 98	otg_clk = clk_get(&pdev->dev, "otg");
 99	if (IS_ERR(otg_clk)) {
100		dev_err(&pdev->dev, "Failed to get otg clock\n");
101		return PTR_ERR(otg_clk);
102	}
103
104	err = clk_enable(otg_clk);
105	if (err) {
106		clk_put(otg_clk);
107		return err;
108	}
109
110	writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
111			EXYNOS4_PHYPWR);
112
113	writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,
114			S5P_USBHOST_PHY_CONTROL);
115
116	clk_disable(otg_clk);
117	clk_put(otg_clk);
118
119	return 0;
120}
121
122int s5p_usb_phy_init(struct platform_device *pdev, int type)
123{
124	if (type == S5P_USB_PHY_HOST)
125		return exynos4_usb_phy1_init(pdev);
126
127	return -EINVAL;
128}
129
130int s5p_usb_phy_exit(struct platform_device *pdev, int type)
131{
132	if (type == S5P_USB_PHY_HOST)
133		return exynos4_usb_phy1_exit(pdev);
134
135	return -EINVAL;
136}