Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.8-rc4 111 lines 2.9 kB view raw
1/* 2 * Copyright (C) 2009 3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de> 4 * 5 * Description: 6 * Helper routines for i.MX3x SoCs from Freescale, needed by the fsl_usb2_udc.c 7 * driver to function correctly on these systems. 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. 13 */ 14#include <linux/clk.h> 15#include <linux/delay.h> 16#include <linux/err.h> 17#include <linux/fsl_devices.h> 18#include <linux/platform_device.h> 19#include <linux/io.h> 20 21#include <mach/hardware.h> 22 23static struct clk *mxc_ahb_clk; 24static struct clk *mxc_per_clk; 25static struct clk *mxc_ipg_clk; 26 27/* workaround ENGcm09152 for i.MX35 */ 28#define USBPHYCTRL_OTGBASE_OFFSET 0x608 29#define USBPHYCTRL_EVDO (1 << 23) 30 31int fsl_udc_clk_init(struct platform_device *pdev) 32{ 33 struct fsl_usb2_platform_data *pdata; 34 unsigned long freq; 35 int ret; 36 37 pdata = pdev->dev.platform_data; 38 39 mxc_ipg_clk = devm_clk_get(&pdev->dev, "ipg"); 40 if (IS_ERR(mxc_ipg_clk)) { 41 dev_err(&pdev->dev, "clk_get(\"ipg\") failed\n"); 42 return PTR_ERR(mxc_ipg_clk); 43 } 44 45 mxc_ahb_clk = devm_clk_get(&pdev->dev, "ahb"); 46 if (IS_ERR(mxc_ahb_clk)) { 47 dev_err(&pdev->dev, "clk_get(\"ahb\") failed\n"); 48 return PTR_ERR(mxc_ahb_clk); 49 } 50 51 mxc_per_clk = devm_clk_get(&pdev->dev, "per"); 52 if (IS_ERR(mxc_per_clk)) { 53 dev_err(&pdev->dev, "clk_get(\"per\") failed\n"); 54 return PTR_ERR(mxc_per_clk); 55 } 56 57 clk_prepare_enable(mxc_ipg_clk); 58 clk_prepare_enable(mxc_ahb_clk); 59 clk_prepare_enable(mxc_per_clk); 60 61 /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */ 62 if (!cpu_is_mx51()) { 63 freq = clk_get_rate(mxc_per_clk); 64 if (pdata->phy_mode != FSL_USB2_PHY_ULPI && 65 (freq < 59999000 || freq > 60001000)) { 66 dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq); 67 ret = -EINVAL; 68 goto eclkrate; 69 } 70 } 71 72 return 0; 73 74eclkrate: 75 clk_disable_unprepare(mxc_ipg_clk); 76 clk_disable_unprepare(mxc_ahb_clk); 77 clk_disable_unprepare(mxc_per_clk); 78 mxc_per_clk = NULL; 79 return ret; 80} 81 82void fsl_udc_clk_finalize(struct platform_device *pdev) 83{ 84 struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; 85 if (cpu_is_mx35()) { 86 unsigned int v; 87 88 /* workaround ENGcm09152 for i.MX35 */ 89 if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) { 90 v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + 91 USBPHYCTRL_OTGBASE_OFFSET)); 92 writel(v | USBPHYCTRL_EVDO, 93 MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + 94 USBPHYCTRL_OTGBASE_OFFSET)); 95 } 96 } 97 98 /* ULPI transceivers don't need usbpll */ 99 if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { 100 clk_disable_unprepare(mxc_per_clk); 101 mxc_per_clk = NULL; 102 } 103} 104 105void fsl_udc_clk_release(void) 106{ 107 if (mxc_per_clk) 108 clk_disable_unprepare(mxc_per_clk); 109 clk_disable_unprepare(mxc_ahb_clk); 110 clk_disable_unprepare(mxc_ipg_clk); 111}