forked from Minki/linux
97e7292ab5
Clock support is moving to the clk subsystem. These tegra, omap and imx changes are for code that is still platform specific and not (yet) part of that subsystem. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIVAwUAUA2dh2CrR//JCVInAQLm6g//UD7Q6xc/1I9/k0c/V35o4FRgmOt9xIp2 ofsB801AnYOOusFWkcBa8xb6zFQuNQwR6OflkYBBV+31Zp2cNHgF9SVxaYlh43MD iptUnCh8VzSEFFZGy1Vi3sdrKY5fw5dyffPjgv8HtWQzs4r8H+98UnNQFbkTwPft 9TxAeH73LRm4uNI/E8OerYN78TOefBK8p6HXyNW//MCzb59aG73/iD3EACrAmvyY gtyhLMtPeZTUWh3Fy5vXd9cfCmzQOAH/ADeMxVyx2QFyb3vCcPoS8Z5plh3zIjMt Ze0KlhHkB5lfBGBOB3gA/7ItlclhL2qLNkuhM2CBgYg+WTZ4OqaJCv80+OK8X4i5 XCVjuDG++CFH09jDnMPXeUBM6UHwRV3f/HIRhaL8nH+nq1mU5HzEGrvBZTnOIklI XNoOpAMVPih64vH8PIQL/8oXT+cNHyVkmKA2uqRKq+mgqC+FIjG7EKBmIVORr7eI HmDHtHpRZY9EpK/cfgykDl4ELDITEaaitxvk0uqchSj3SXjfmbBXNKKcInQhDKaZ TKRMCgzeTu4NXSrRyHAP2toKUQNSziB7mwL7aHD6LMloqP1jBVOyZpxAIVwt19lZ qBAAatYGYocbssypI/E4CptTn3uC3dQiXDHRNJkZC/4o5suZoW9wpT77yvQNR/YQ GBO0bhQCI0Y= =Cvpa -----END PGP SIGNATURE----- Merge tag 'clk' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc Pull arm-soc clk changes from Arnd Bergmann: "Clock support is moving to the clk subsystem. These tegra, omap and imx changes are for code that is still platform specific and not (yet) part of that subsystem." Fix up conflicts in arch/arm/mach-{imx/clk-imx51-imx53.c,omap2/Makefile} * tag 'clk' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (23 commits) ARM: imx: clk-imx31: Fix clock id for rnga driver ARM: imx: add missing item to the list of clock event modes ARM: i.MX5x CSPI: Fixed clock name for CSPI ARM: i.MX5x clocks: Fix GPT clocks ARM: i.MX5x clocks: Fix parent for PWM clocks ARM: i.MX5x clocks: Add EPIT support ARM: mx27: Reenable silicon version print ARM: clk-imx27: Fix rtc clock id ARM: tegra: Provide clock for only one PWM controller ARM: tegra: Fix PWM clock programming ARM: OMAP3+: clock33xx: Add AM33XX clock tree data ARM: OMAP3+: clock: Move common clksel_rate & clock data to common file ARM: tegra: dma: rename driver name for clock to "tegra-apbdma" ARM: tegra: Remove second instance of uart clk crypto: add clk_prepare/clk_unprepare ASoC: tegra: add clk_prepare/clk_unprepare staging: nvec: add clk_prepare/clk_unprepare spi/tegra: add clk_prepare/clk_unprepare Input: tegra-kbc - add clk_prepare/clk_unprepare USB: ehci-tegra: add clk_prepare/clk_unprepare ...
201 lines
10 KiB
C
201 lines
10 KiB
C
/*
|
|
* Copyright (C) 2012 Sascha Hauer <kernel@pengutronix.de>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/clkdev.h>
|
|
#include <linux/io.h>
|
|
#include <linux/err.h>
|
|
#include <linux/of.h>
|
|
|
|
#include <mach/hardware.h>
|
|
#include <mach/mx31.h>
|
|
#include <mach/common.h>
|
|
|
|
#include "clk.h"
|
|
#include "crmregs-imx3.h"
|
|
|
|
static const char *mcu_main_sel[] = { "spll", "mpll", };
|
|
static const char *per_sel[] = { "per_div", "ipg", };
|
|
static const char *csi_sel[] = { "upll", "spll", };
|
|
static const char *fir_sel[] = { "mcu_main", "upll", "spll" };
|
|
|
|
enum mx31_clks {
|
|
ckih, ckil, mpll, spll, upll, mcu_main, hsp, ahb, nfc, ipg, per_div,
|
|
per, csi, fir, csi_div, usb_div_pre, usb_div_post, fir_div_pre,
|
|
fir_div_post, sdhc1_gate, sdhc2_gate, gpt_gate, epit1_gate, epit2_gate,
|
|
iim_gate, ata_gate, sdma_gate, cspi3_gate, rng_gate, uart1_gate,
|
|
uart2_gate, ssi1_gate, i2c1_gate, i2c2_gate, i2c3_gate, hantro_gate,
|
|
mstick1_gate, mstick2_gate, csi_gate, rtc_gate, wdog_gate, pwm_gate,
|
|
sim_gate, ect_gate, usb_gate, kpp_gate, ipu_gate, uart3_gate,
|
|
uart4_gate, uart5_gate, owire_gate, ssi2_gate, cspi1_gate, cspi2_gate,
|
|
gacc_gate, emi_gate, rtic_gate, firi_gate, clk_max
|
|
};
|
|
|
|
static struct clk *clk[clk_max];
|
|
|
|
int __init mx31_clocks_init(unsigned long fref)
|
|
{
|
|
void __iomem *base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR);
|
|
int i;
|
|
|
|
clk[ckih] = imx_clk_fixed("ckih", fref);
|
|
clk[ckil] = imx_clk_fixed("ckil", 32768);
|
|
clk[mpll] = imx_clk_pllv1("mpll", "ckih", base + MXC_CCM_MPCTL);
|
|
clk[spll] = imx_clk_pllv1("spll", "ckih", base + MXC_CCM_SRPCTL);
|
|
clk[upll] = imx_clk_pllv1("upll", "ckih", base + MXC_CCM_UPCTL);
|
|
clk[mcu_main] = imx_clk_mux("mcu_main", base + MXC_CCM_PMCR0, 31, 1, mcu_main_sel, ARRAY_SIZE(mcu_main_sel));
|
|
clk[hsp] = imx_clk_divider("hsp", "mcu_main", base + MXC_CCM_PDR0, 11, 3);
|
|
clk[ahb] = imx_clk_divider("ahb", "mcu_main", base + MXC_CCM_PDR0, 3, 3);
|
|
clk[nfc] = imx_clk_divider("nfc", "ahb", base + MXC_CCM_PDR0, 8, 3);
|
|
clk[ipg] = imx_clk_divider("ipg", "ahb", base + MXC_CCM_PDR0, 6, 2);
|
|
clk[per_div] = imx_clk_divider("per_div", "upll", base + MXC_CCM_PDR0, 16, 5);
|
|
clk[per] = imx_clk_mux("per", base + MXC_CCM_CCMR, 24, 1, per_sel, ARRAY_SIZE(per_sel));
|
|
clk[csi] = imx_clk_mux("csi_sel", base + MXC_CCM_CCMR, 25, 1, csi_sel, ARRAY_SIZE(csi_sel));
|
|
clk[fir] = imx_clk_mux("fir_sel", base + MXC_CCM_CCMR, 11, 2, fir_sel, ARRAY_SIZE(fir_sel));
|
|
clk[csi_div] = imx_clk_divider("csi_div", "csi_sel", base + MXC_CCM_PDR0, 23, 9);
|
|
clk[usb_div_pre] = imx_clk_divider("usb_div_pre", "upll", base + MXC_CCM_PDR1, 30, 2);
|
|
clk[usb_div_post] = imx_clk_divider("usb_div_post", "usb_div_pre", base + MXC_CCM_PDR1, 27, 3);
|
|
clk[fir_div_pre] = imx_clk_divider("fir_div_pre", "fir_sel", base + MXC_CCM_PDR1, 24, 3);
|
|
clk[fir_div_post] = imx_clk_divider("fir_div_post", "fir_div_pre", base + MXC_CCM_PDR1, 23, 6);
|
|
clk[sdhc1_gate] = imx_clk_gate2("sdhc1_gate", "per", base + MXC_CCM_CGR0, 0);
|
|
clk[sdhc2_gate] = imx_clk_gate2("sdhc2_gate", "per", base + MXC_CCM_CGR0, 2);
|
|
clk[gpt_gate] = imx_clk_gate2("gpt_gate", "per", base + MXC_CCM_CGR0, 4);
|
|
clk[epit1_gate] = imx_clk_gate2("epit1_gate", "per", base + MXC_CCM_CGR0, 6);
|
|
clk[epit2_gate] = imx_clk_gate2("epit2_gate", "per", base + MXC_CCM_CGR0, 8);
|
|
clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", base + MXC_CCM_CGR0, 10);
|
|
clk[ata_gate] = imx_clk_gate2("ata_gate", "ipg", base + MXC_CCM_CGR0, 12);
|
|
clk[sdma_gate] = imx_clk_gate2("sdma_gate", "ahb", base + MXC_CCM_CGR0, 14);
|
|
clk[cspi3_gate] = imx_clk_gate2("cspi3_gate", "ipg", base + MXC_CCM_CGR0, 16);
|
|
clk[rng_gate] = imx_clk_gate2("rng_gate", "ipg", base + MXC_CCM_CGR0, 18);
|
|
clk[uart1_gate] = imx_clk_gate2("uart1_gate", "per", base + MXC_CCM_CGR0, 20);
|
|
clk[uart2_gate] = imx_clk_gate2("uart2_gate", "per", base + MXC_CCM_CGR0, 22);
|
|
clk[ssi1_gate] = imx_clk_gate2("ssi1_gate", "spll", base + MXC_CCM_CGR0, 24);
|
|
clk[i2c1_gate] = imx_clk_gate2("i2c1_gate", "per", base + MXC_CCM_CGR0, 26);
|
|
clk[i2c2_gate] = imx_clk_gate2("i2c2_gate", "per", base + MXC_CCM_CGR0, 28);
|
|
clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per", base + MXC_CCM_CGR0, 30);
|
|
clk[hantro_gate] = imx_clk_gate2("hantro_gate", "per", base + MXC_CCM_CGR1, 0);
|
|
clk[mstick1_gate] = imx_clk_gate2("mstick1_gate", "per", base + MXC_CCM_CGR1, 2);
|
|
clk[mstick2_gate] = imx_clk_gate2("mstick2_gate", "per", base + MXC_CCM_CGR1, 4);
|
|
clk[csi_gate] = imx_clk_gate2("csi_gate", "csi_div", base + MXC_CCM_CGR1, 6);
|
|
clk[rtc_gate] = imx_clk_gate2("rtc_gate", "ipg", base + MXC_CCM_CGR1, 8);
|
|
clk[wdog_gate] = imx_clk_gate2("wdog_gate", "ipg", base + MXC_CCM_CGR1, 10);
|
|
clk[pwm_gate] = imx_clk_gate2("pwm_gate", "per", base + MXC_CCM_CGR1, 12);
|
|
clk[sim_gate] = imx_clk_gate2("sim_gate", "per", base + MXC_CCM_CGR1, 14);
|
|
clk[ect_gate] = imx_clk_gate2("ect_gate", "per", base + MXC_CCM_CGR1, 16);
|
|
clk[usb_gate] = imx_clk_gate2("usb_gate", "ahb", base + MXC_CCM_CGR1, 18);
|
|
clk[kpp_gate] = imx_clk_gate2("kpp_gate", "ipg", base + MXC_CCM_CGR1, 20);
|
|
clk[ipu_gate] = imx_clk_gate2("ipu_gate", "hsp", base + MXC_CCM_CGR1, 22);
|
|
clk[uart3_gate] = imx_clk_gate2("uart3_gate", "per", base + MXC_CCM_CGR1, 24);
|
|
clk[uart4_gate] = imx_clk_gate2("uart4_gate", "per", base + MXC_CCM_CGR1, 26);
|
|
clk[uart5_gate] = imx_clk_gate2("uart5_gate", "per", base + MXC_CCM_CGR1, 28);
|
|
clk[owire_gate] = imx_clk_gate2("owire_gate", "per", base + MXC_CCM_CGR1, 30);
|
|
clk[ssi2_gate] = imx_clk_gate2("ssi2_gate", "spll", base + MXC_CCM_CGR2, 0);
|
|
clk[cspi1_gate] = imx_clk_gate2("cspi1_gate", "ipg", base + MXC_CCM_CGR2, 2);
|
|
clk[cspi2_gate] = imx_clk_gate2("cspi2_gate", "ipg", base + MXC_CCM_CGR2, 4);
|
|
clk[gacc_gate] = imx_clk_gate2("gacc_gate", "per", base + MXC_CCM_CGR2, 6);
|
|
clk[emi_gate] = imx_clk_gate2("emi_gate", "ahb", base + MXC_CCM_CGR2, 8);
|
|
clk[rtic_gate] = imx_clk_gate2("rtic_gate", "ahb", base + MXC_CCM_CGR2, 10);
|
|
clk[firi_gate] = imx_clk_gate2("firi_gate", "upll", base+MXC_CCM_CGR2, 12);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(clk); i++)
|
|
if (IS_ERR(clk[i]))
|
|
pr_err("imx31 clk %d: register failed with %ld\n",
|
|
i, PTR_ERR(clk[i]));
|
|
|
|
clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
|
|
clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
|
|
clk_register_clkdev(clk[cspi1_gate], NULL, "imx31-cspi.0");
|
|
clk_register_clkdev(clk[cspi2_gate], NULL, "imx31-cspi.1");
|
|
clk_register_clkdev(clk[cspi3_gate], NULL, "imx31-cspi.2");
|
|
clk_register_clkdev(clk[pwm_gate], "pwm", NULL);
|
|
clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
|
|
clk_register_clkdev(clk[rtc_gate], NULL, "mxc_rtc");
|
|
clk_register_clkdev(clk[epit1_gate], "epit", NULL);
|
|
clk_register_clkdev(clk[epit2_gate], "epit", NULL);
|
|
clk_register_clkdev(clk[nfc], NULL, "mxc_nand.0");
|
|
clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core");
|
|
clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb");
|
|
clk_register_clkdev(clk[kpp_gate], "kpp", NULL);
|
|
clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.0");
|
|
clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.0");
|
|
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.0");
|
|
clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.1");
|
|
clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.1");
|
|
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.1");
|
|
clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.2");
|
|
clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.2");
|
|
clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
|
|
clk_register_clkdev(clk[usb_div_post], "per", "fsl-usb2-udc");
|
|
clk_register_clkdev(clk[usb_gate], "ahb", "fsl-usb2-udc");
|
|
clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
|
|
clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
|
|
/* i.mx31 has the i.mx21 type uart */
|
|
clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0");
|
|
clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.0");
|
|
clk_register_clkdev(clk[uart2_gate], "per", "imx21-uart.1");
|
|
clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.1");
|
|
clk_register_clkdev(clk[uart3_gate], "per", "imx21-uart.2");
|
|
clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.2");
|
|
clk_register_clkdev(clk[uart4_gate], "per", "imx21-uart.3");
|
|
clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.3");
|
|
clk_register_clkdev(clk[uart5_gate], "per", "imx21-uart.4");
|
|
clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.4");
|
|
clk_register_clkdev(clk[i2c1_gate], NULL, "imx-i2c.0");
|
|
clk_register_clkdev(clk[i2c2_gate], NULL, "imx-i2c.1");
|
|
clk_register_clkdev(clk[i2c3_gate], NULL, "imx-i2c.2");
|
|
clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1.0");
|
|
clk_register_clkdev(clk[sdhc1_gate], NULL, "mxc-mmc.0");
|
|
clk_register_clkdev(clk[sdhc2_gate], NULL, "mxc-mmc.1");
|
|
clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0");
|
|
clk_register_clkdev(clk[ssi2_gate], NULL, "imx-ssi.1");
|
|
clk_register_clkdev(clk[firi_gate], "firi", NULL);
|
|
clk_register_clkdev(clk[ata_gate], NULL, "pata_imx");
|
|
clk_register_clkdev(clk[rtic_gate], "rtic", NULL);
|
|
clk_register_clkdev(clk[rng_gate], NULL, "mxc_rnga");
|
|
clk_register_clkdev(clk[sdma_gate], NULL, "imx31-sdma");
|
|
clk_register_clkdev(clk[iim_gate], "iim", NULL);
|
|
|
|
clk_set_parent(clk[csi], clk[upll]);
|
|
clk_prepare_enable(clk[emi_gate]);
|
|
clk_prepare_enable(clk[iim_gate]);
|
|
mx31_revision();
|
|
clk_disable_unprepare(clk[iim_gate]);
|
|
|
|
mxc_timer_init(MX31_IO_ADDRESS(MX31_GPT1_BASE_ADDR), MX31_INT_GPT);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_OF
|
|
int __init mx31_clocks_init_dt(void)
|
|
{
|
|
struct device_node *np;
|
|
u32 fref = 26000000; /* default */
|
|
|
|
for_each_compatible_node(np, NULL, "fixed-clock") {
|
|
if (!of_device_is_compatible(np, "fsl,imx-osc26m"))
|
|
continue;
|
|
|
|
if (!of_property_read_u32(np, "clock-frequency", &fref))
|
|
break;
|
|
}
|
|
|
|
return mx31_clocks_init(fref);
|
|
}
|
|
#endif
|