forked from Minki/linux
5ce7aba976
* Updates to the ux500 cpufreq code * Moving the u300 DMA controller driver to drivers/dma * Moving versatile express drivers out of arch/arm for sharing with arch/arm64 * Device tree bindings for the OMAP General Purpose Memory Controller There is a simple conflict in drivers/cpufreq/dbx500-cpufreq.c, because the mach/id.h header and the cpu_is_u8500_family() function in it are now gone. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIVAwUAUSaEc2CrR//JCVInAQKROg//V6LrAmewM4ugCLJFOHDsRN5n27QHOnMb 7g1b56OVtwb+Zer9HLAyZyY6MX12JbDTdC53LDWf6CEU8Z3LfdaPNXyDoGwKQMsA cq2qDufcFoVnaAFMO4uxpe/Y/ZuJJTPm+24dviztMp5PIl4gRkgou5w2fRzd7iLk rETnjvDzB1lKrlrTlnEoPemroErX10AhkjGIQ1zkImqlCOUL1Fs+IMui5gUA3I8X S7q+JPMoIjCFUtuG9QV+/PWcY0SnsGJBZiYdh1XGbCiint5Oi/6hawbBtT4L067H HfSsWe+mx8c2B84V0AFOpKcV6v9VYeyxSkmr40yG3laPReGA8CWjjGQj1kIkyY07 1XujeEjbpp4zgaggtv9Jdb7BAPWWopuqMrpGdcuxBWYN7HwiPoseGzJMo3F7D5Ti KBRsBLDoK514oGLZdgh3i/QQZwhFuJRcHdaoqRU0pWNJBKMxAFdfgeKYdNWtB7HA XrtJvANrrIeKin3bbeodlhaHLxlBImarQjqdK85H0nmLs71jNphihDRVe3wNy5Qu OYbVHbf3cIboIQiLYLgiVc4NxypCXzeAB6pCdX/NWee9P2qgDCb0SEI6OcpBftPh di004nMEquomIkoyNSlAZffcxeUrHiFlqSvHWqzuLqLCGRToxaoWUC0ES3qJA321 23zzC9IYF6Y= =R0p0 -----END PGP SIGNATURE----- Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc Pull ARM SoC driver specific changes from Arnd Bergmann: - Updates to the ux500 cpufreq code - Moving the u300 DMA controller driver to drivers/dma - Moving versatile express drivers out of arch/arm for sharing with arch/arm64 - Device tree bindings for the OMAP General Purpose Memory Controller * tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (27 commits) ARM: OMAP2+: gpmc: Add device tree documentation for elm handle ARM: OMAP2+: gpmc: add DT bindings for OneNAND ARM: OMAP2+: gpmc-onenand: drop __init annotation mtd: omap-onenand: pass device_node in platform data ARM: OMAP2+: Prevent potential crash if GPMC probe fails ARM: OMAP2+: gpmc: Remove unneeded of_node_put() arm: Move sp810.h to include/linux/amba/ ARM: OMAP: gpmc: add DT bindings for GPMC timings and NAND ARM: OMAP: gpmc: enable hwecc for AM33xx SoCs ARM: OMAP: gpmc-nand: drop __init annotation mtd: omap-nand: pass device_node in platform data ARM: OMAP: gpmc: don't create devices from initcall on DT dma: coh901318: cut down on platform data abstraction dma: coh901318: merge header files dma: coh901318: push definitions into driver dma: coh901318: push header down into the DMA subsystem dma: coh901318: skip hard-coded addresses dma: coh901318: remove hardcoded target addresses dma: coh901318: push platform data into driver dma: coh901318: create a proper platform data file ...
136 lines
3.6 KiB
C
136 lines
3.6 KiB
C
/*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* 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.
|
|
*
|
|
* Copyright (C) 2012 ARM Limited
|
|
*/
|
|
|
|
#include <linux/amba/sp810.h>
|
|
#include <linux/clkdev.h>
|
|
#include <linux/clk-provider.h>
|
|
#include <linux/err.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/vexpress.h>
|
|
|
|
static struct clk *vexpress_sp810_timerclken[4];
|
|
static DEFINE_SPINLOCK(vexpress_sp810_lock);
|
|
|
|
static void __init vexpress_sp810_init(void __iomem *base)
|
|
{
|
|
int i;
|
|
|
|
if (WARN_ON(!base))
|
|
return;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) {
|
|
char name[12];
|
|
const char *parents[] = {
|
|
"v2m:refclk32khz", /* REFCLK */
|
|
"v2m:refclk1mhz" /* TIMCLK */
|
|
};
|
|
|
|
snprintf(name, ARRAY_SIZE(name), "timerclken%d", i);
|
|
|
|
vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name,
|
|
parents, 2, 0, base + SCCTRL,
|
|
SCCTRL_TIMERENnSEL_SHIFT(i), 1,
|
|
0, &vexpress_sp810_lock);
|
|
|
|
if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i])))
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
static const char * const vexpress_clk_24mhz_periphs[] __initconst = {
|
|
"mb:uart0", "mb:uart1", "mb:uart2", "mb:uart3",
|
|
"mb:mmci", "mb:kmi0", "mb:kmi1"
|
|
};
|
|
|
|
void __init vexpress_clk_init(void __iomem *sp810_base)
|
|
{
|
|
struct clk *clk;
|
|
int i;
|
|
|
|
clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
|
|
CLK_IS_ROOT, 0);
|
|
WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL));
|
|
|
|
clk = clk_register_fixed_rate(NULL, "v2m:clk_24mhz", NULL,
|
|
CLK_IS_ROOT, 24000000);
|
|
for (i = 0; i < ARRAY_SIZE(vexpress_clk_24mhz_periphs); i++)
|
|
WARN_ON(clk_register_clkdev(clk, NULL,
|
|
vexpress_clk_24mhz_periphs[i]));
|
|
|
|
clk = clk_register_fixed_rate(NULL, "v2m:refclk32khz", NULL,
|
|
CLK_IS_ROOT, 32768);
|
|
WARN_ON(clk_register_clkdev(clk, NULL, "v2m:wdt"));
|
|
|
|
clk = clk_register_fixed_rate(NULL, "v2m:refclk1mhz", NULL,
|
|
CLK_IS_ROOT, 1000000);
|
|
|
|
vexpress_sp810_init(sp810_base);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
|
|
WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i], clk));
|
|
|
|
WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
|
|
"v2m-timer0", "sp804"));
|
|
WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
|
|
"v2m-timer1", "sp804"));
|
|
}
|
|
|
|
#if defined(CONFIG_OF)
|
|
|
|
struct clk *vexpress_sp810_of_get(struct of_phandle_args *clkspec, void *data)
|
|
{
|
|
if (WARN_ON(clkspec->args_count != 1 || clkspec->args[0] >
|
|
ARRAY_SIZE(vexpress_sp810_timerclken)))
|
|
return NULL;
|
|
|
|
return vexpress_sp810_timerclken[clkspec->args[0]];
|
|
}
|
|
|
|
void __init vexpress_clk_of_init(void)
|
|
{
|
|
struct device_node *node;
|
|
struct clk *clk;
|
|
struct clk *refclk, *timclk;
|
|
|
|
of_clk_init(NULL);
|
|
|
|
node = of_find_compatible_node(NULL, NULL, "arm,sp810");
|
|
vexpress_sp810_init(of_iomap(node, 0));
|
|
of_clk_add_provider(node, vexpress_sp810_of_get, NULL);
|
|
|
|
/* Select "better" (faster) parent for SP804 timers */
|
|
refclk = of_clk_get_by_name(node, "refclk");
|
|
timclk = of_clk_get_by_name(node, "timclk");
|
|
if (!WARN_ON(IS_ERR(refclk) || IS_ERR(timclk))) {
|
|
int i = 0;
|
|
|
|
if (clk_get_rate(refclk) > clk_get_rate(timclk))
|
|
clk = refclk;
|
|
else
|
|
clk = timclk;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
|
|
WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i],
|
|
clk));
|
|
}
|
|
|
|
WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
|
|
"v2m-timer0", "sp804"));
|
|
WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
|
|
"v2m-timer1", "sp804"));
|
|
}
|
|
|
|
#endif
|