Commit 5df33a62 authored by Viresh Kumar's avatar Viresh Kumar Committed by Arnd Bergmann

SPEAr: Switch to common clock framework

SPEAr SoCs used its own clock framework since now. From now on they will move to
use common clock framework.

This patch updates existing SPEAr machine support to adapt for common clock
framework.
Signed-off-by: default avatarViresh Kumar <viresh.kumar@st.com>
Reviewed-by: default avatarMike Turquette <mturquette@linaro.org>
Acked-by: default avatarArnd Bergmann <arnd@arndb.de>
parent f8abc080
......@@ -6336,9 +6336,7 @@ L: spear-devel@list.st.com
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.st.com/spear
S: Maintained
F: arch/arm/mach-spear*/clock.c
F: arch/arm/plat-spear/clock.c
F: arch/arm/plat-spear/include/plat/clock.h
F: drivers/clk/spear/
SPEAR PAD MULTIPLEXING SUPPORT
M: Viresh Kumar <viresh.kumar@st.com>
......
......@@ -980,6 +980,7 @@ config PLAT_SPEAR
select ARM_AMBA
select ARCH_REQUIRE_GPIOLIB
select CLKDEV_LOOKUP
select COMMON_CLK
select CLKSRC_MMIO
select GENERIC_CLOCKEVENTS
select HAVE_CLK
......
......@@ -3,7 +3,7 @@
#
# common files
obj-y += spear3xx.o clock.o
obj-y += spear3xx.o
# spear300 specific files
obj-$(CONFIG_MACH_SPEAR300) += spear300.o
......
/*
* arch/arm/mach-spear3xx/clock.c
*
* SPEAr3xx machines clock framework source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <asm/mach-types.h>
#include <plat/clock.h>
#include <mach/misc_regs.h>
/* root clks */
/* 32 KHz oscillator clock */
static struct clk osc_32k_clk = {
.flags = ALWAYS_ENABLED,
.rate = 32000,
};
/* 24 MHz oscillator clock */
static struct clk osc_24m_clk = {
.flags = ALWAYS_ENABLED,
.rate = 24000000,
};
/* clock derived from 32 KHz osc clk */
/* rtc clock */
static struct clk rtc_clk = {
.pclk = &osc_32k_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = RTC_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from 24 MHz osc clk */
/* pll masks structure */
static struct pll_clk_masks pll1_masks = {
.mode_mask = PLL_MODE_MASK,
.mode_shift = PLL_MODE_SHIFT,
.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
.norm_fdbk_m_shift = PLL_NORM_FDBK_M_SHIFT,
.dith_fdbk_m_mask = PLL_DITH_FDBK_M_MASK,
.dith_fdbk_m_shift = PLL_DITH_FDBK_M_SHIFT,
.div_p_mask = PLL_DIV_P_MASK,
.div_p_shift = PLL_DIV_P_SHIFT,
.div_n_mask = PLL_DIV_N_MASK,
.div_n_shift = PLL_DIV_N_SHIFT,
};
/* pll1 configuration structure */
static struct pll_clk_config pll1_config = {
.mode_reg = PLL1_CTR,
.cfg_reg = PLL1_FRQ,
.masks = &pll1_masks,
};
/* pll rate configuration table, in ascending order of rates */
struct pll_rate_tbl pll_rtbl[] = {
{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
};
/* PLL1 clock */
static struct clk pll1_clk = {
.flags = ENABLED_ON_INIT,
.pclk = &osc_24m_clk,
.en_reg = PLL1_CTR,
.en_reg_bit = PLL_ENABLE,
.calc_rate = &pll_calc_rate,
.recalc = &pll_clk_recalc,
.set_rate = &pll_clk_set_rate,
.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
.private_data = &pll1_config,
};
/* PLL3 48 MHz clock */
static struct clk pll3_48m_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &osc_24m_clk,
.rate = 48000000,
};
/* watch dog timer clock */
static struct clk wdt_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &osc_24m_clk,
.recalc = &follow_parent,
};
/* clock derived from pll1 clk */
/* cpu clock */
static struct clk cpu_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.recalc = &follow_parent,
};
/* ahb masks structure */
static struct bus_clk_masks ahb_masks = {
.mask = PLL_HCLK_RATIO_MASK,
.shift = PLL_HCLK_RATIO_SHIFT,
};
/* ahb configuration structure */
static struct bus_clk_config ahb_config = {
.reg = CORE_CLK_CFG,
.masks = &ahb_masks,
};
/* ahb rate configuration table, in ascending order of rates */
struct bus_rate_tbl bus_rtbl[] = {
{.div = 3}, /* == parent divided by 4 */
{.div = 2}, /* == parent divided by 3 */
{.div = 1}, /* == parent divided by 2 */
{.div = 0}, /* == parent divided by 1 */
};
/* ahb clock */
static struct clk ahb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
.set_rate = &bus_clk_set_rate,
.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &ahb_config,
};
/* auxiliary synthesizers masks */
static struct aux_clk_masks aux_masks = {
.eq_sel_mask = AUX_EQ_SEL_MASK,
.eq_sel_shift = AUX_EQ_SEL_SHIFT,
.eq1_mask = AUX_EQ1_SEL,
.eq2_mask = AUX_EQ2_SEL,
.xscale_sel_mask = AUX_XSCALE_MASK,
.xscale_sel_shift = AUX_XSCALE_SHIFT,
.yscale_sel_mask = AUX_YSCALE_MASK,
.yscale_sel_shift = AUX_YSCALE_SHIFT,
};
/* uart synth configurations */
static struct aux_clk_config uart_synth_config = {
.synth_reg = UART_CLK_SYNT,
.masks = &aux_masks,
};
/* aux rate configuration table, in ascending order of rates */
struct aux_rate_tbl aux_rtbl[] = {
/* For PLL1 = 332 MHz */
{.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */
{.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */
{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
};
/* uart synth clock */
static struct clk uart_synth_clk = {
.en_reg = UART_CLK_SYNT,
.en_reg_bit = AUX_SYNT_ENB,
.pclk = &pll1_clk,
.calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
.set_rate = &aux_clk_set_rate,
.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
.private_data = &uart_synth_config,
};
/* uart parents */
static struct pclk_info uart_pclk_info[] = {
{
.pclk = &uart_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* uart parent select structure */
static struct pclk_sel uart_pclk_sel = {
.pclk_info = uart_pclk_info,
.pclk_count = ARRAY_SIZE(uart_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = UART_CLK_MASK,
};
/* uart clock */
static struct clk uart_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = UART_CLK_ENB,
.pclk_sel = &uart_pclk_sel,
.pclk_sel_shift = UART_CLK_SHIFT,
.recalc = &follow_parent,
};
/* firda configurations */
static struct aux_clk_config firda_synth_config = {
.synth_reg = FIRDA_CLK_SYNT,
.masks = &aux_masks,
};
/* firda synth clock */
static struct clk firda_synth_clk = {
.en_reg = FIRDA_CLK_SYNT,
.en_reg_bit = AUX_SYNT_ENB,
.pclk = &pll1_clk,
.calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
.set_rate = &aux_clk_set_rate,
.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
.private_data = &firda_synth_config,
};
/* firda parents */
static struct pclk_info firda_pclk_info[] = {
{
.pclk = &firda_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* firda parent select structure */
static struct pclk_sel firda_pclk_sel = {
.pclk_info = firda_pclk_info,
.pclk_count = ARRAY_SIZE(firda_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = FIRDA_CLK_MASK,
};
/* firda clock */
static struct clk firda_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = FIRDA_CLK_ENB,
.pclk_sel = &firda_pclk_sel,
.pclk_sel_shift = FIRDA_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt synthesizer masks */
static struct gpt_clk_masks gpt_masks = {
.mscale_sel_mask = GPT_MSCALE_MASK,
.mscale_sel_shift = GPT_MSCALE_SHIFT,
.nscale_sel_mask = GPT_NSCALE_MASK,
.nscale_sel_shift = GPT_NSCALE_SHIFT,
};
/* gpt rate configuration table, in ascending order of rates */
struct gpt_rate_tbl gpt_rtbl[] = {
/* For pll1 = 332 MHz */
{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
{.mscale = 1, .nscale = 0}, /* 83 MHz */
};
/* gpt0 synth clk config*/
static struct gpt_clk_config gpt0_synth_config = {
.synth_reg = PRSC1_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt synth clock */
static struct clk gpt0_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt0_synth_config,
};
/* gpt parents */
static struct pclk_info gpt0_pclk_info[] = {
{
.pclk = &gpt0_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt0_pclk_sel = {
.pclk_info = gpt0_pclk_info,
.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt0 timer clock */
static struct clk gpt0_clk = {
.flags = ALWAYS_ENABLED,
.pclk_sel = &gpt0_pclk_sel,
.pclk_sel_shift = GPT0_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt1 synth clk configurations */
static struct gpt_clk_config gpt1_synth_config = {
.synth_reg = PRSC2_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt1 synth clock */
static struct clk gpt1_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt1_synth_config,
};
static struct pclk_info gpt1_pclk_info[] = {
{
.pclk = &gpt1_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt1_pclk_sel = {
.pclk_info = gpt1_pclk_info,
.pclk_count = ARRAY_SIZE(gpt1_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt1 timer clock */
static struct clk gpt1_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPT1_CLK_ENB,
.pclk_sel = &gpt1_pclk_sel,
.pclk_sel_shift = GPT1_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt2 synth clk configurations */
static struct gpt_clk_config gpt2_synth_config = {
.synth_reg = PRSC3_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt1 synth clock */
static struct clk gpt2_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt2_synth_config,
};
static struct pclk_info gpt2_pclk_info[] = {
{
.pclk = &gpt2_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt2_pclk_sel = {
.pclk_info = gpt2_pclk_info,
.pclk_count = ARRAY_SIZE(gpt2_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt2 timer clock */
static struct clk gpt2_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPT2_CLK_ENB,
.pclk_sel = &gpt2_pclk_sel,
.pclk_sel_shift = GPT2_CLK_SHIFT,
.recalc = &follow_parent,
};
/* clock derived from pll3 clk */
/* usbh clock */
static struct clk usbh_clk = {
.pclk = &pll3_48m_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = USBH_CLK_ENB,
.recalc = &follow_parent,
};
/* usbd clock */
static struct clk usbd_clk = {
.pclk = &pll3_48m_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = USBD_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from ahb clk */
/* apb masks structure */
static struct bus_clk_masks apb_masks = {
.mask = HCLK_PCLK_RATIO_MASK,
.shift = HCLK_PCLK_RATIO_SHIFT,
};
/* apb configuration structure */
static struct bus_clk_config apb_config = {
.reg = CORE_CLK_CFG,
.masks = &apb_masks,
};
/* apb clock */
static struct clk apb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
.set_rate = &bus_clk_set_rate,
.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &apb_config,
};
/* i2c clock */
static struct clk i2c_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = I2C_CLK_ENB,
.recalc = &follow_parent,
};
/* dma clock */
static struct clk dma_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = DMA_CLK_ENB,
.recalc = &follow_parent,
};
/* jpeg clock */
static struct clk jpeg_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = JPEG_CLK_ENB,
.recalc = &follow_parent,
};
/* gmac clock */
static struct clk gmac_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GMAC_CLK_ENB,
.recalc = &follow_parent,
};
/* smi clock */
static struct clk smi_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SMI_CLK_ENB,
.recalc = &follow_parent,
};
/* c3 clock */
static struct clk c3_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = C3_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from apb clk */
/* adc clock */
static struct clk adc_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = ADC_CLK_ENB,
.recalc = &follow_parent,
};
#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
/* emi clock */
static struct clk emi_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.recalc = &follow_parent,
};
#endif
/* ssp clock */
static struct clk ssp0_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SSP_CLK_ENB,
.recalc = &follow_parent,
};
/* gpio clock */
static struct clk gpio_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPIO_CLK_ENB,
.recalc = &follow_parent,
};
static struct clk dummy_apb_pclk;
#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \
defined(CONFIG_MACH_SPEAR320)
/* fsmc clock */
static struct clk fsmc_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.recalc = &follow_parent,
};
#endif
/* common clocks to spear310 and spear320 */
#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
/* uart1 clock */
static struct clk uart1_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* uart2 clock */
static struct clk uart2_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
#endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */
/* common clocks to spear300 and spear320 */
#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320)
/* clcd clock */
static struct clk clcd_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll3_48m_clk,
.recalc = &follow_parent,
};
/* sdhci clock */
static struct clk sdhci_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.recalc = &follow_parent,
};
#endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */
/* spear300 machine specific clock structures */
#ifdef CONFIG_MACH_SPEAR300
/* gpio1 clock */
static struct clk gpio1_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* keyboard clock */
static struct clk kbd_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
#endif
/* spear310 machine specific clock structures */
#ifdef CONFIG_MACH_SPEAR310
/* uart3 clock */
static struct clk uart3_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* uart4 clock */
static struct clk uart4_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* uart5 clock */
static struct clk uart5_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
#endif
/* spear320 machine specific clock structures */
#ifdef CONFIG_MACH_SPEAR320
/* can0 clock */
static struct clk can0_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* can1 clock */
static struct clk can1_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* i2c1 clock */
static struct clk i2c1_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.recalc = &follow_parent,
};
/* ssp1 clock */
static struct clk ssp1_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* ssp2 clock */
static struct clk ssp2_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* pwm clock */
static struct clk pwm_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
#endif
/* array of all spear 3xx clock lookups */
static struct clk_lookup spear_clk_lookups[] = {
{ .con_id = "apb_pclk", .clk = &dummy_apb_pclk},
/* root clks */
{ .con_id = "osc_32k_clk", .clk = &osc_32k_clk},
{ .con_id = "osc_24m_clk", .clk = &osc_24m_clk},
/* clock derived from 32 KHz osc clk */
{ .dev_id = "rtc-spear", .clk = &rtc_clk},
/* clock derived from 24 MHz osc clk */
{ .con_id = "pll1_clk", .clk = &pll1_clk},
{ .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk},
{ .dev_id = "wdt", .clk = &wdt_clk},
/* clock derived from pll1 clk */
{ .con_id = "cpu_clk", .clk = &cpu_clk},
{ .con_id = "ahb_clk", .clk = &ahb_clk},
{ .con_id = "uart_synth_clk", .clk = &uart_synth_clk},
{ .con_id = "firda_synth_clk", .clk = &firda_synth_clk},
{ .con_id = "gpt0_synth_clk", .clk = &gpt0_synth_clk},
{ .con_id = "gpt1_synth_clk", .clk = &gpt1_synth_clk},
{ .con_id = "gpt2_synth_clk", .clk = &gpt2_synth_clk},
{ .dev_id = "uart", .clk = &uart_clk},
{ .dev_id = "firda", .clk = &firda_clk},
{ .dev_id = "gpt0", .clk = &gpt0_clk},
{ .dev_id = "gpt1", .clk = &gpt1_clk},
{ .dev_id = "gpt2", .clk = &gpt2_clk},
/* clock derived from pll3 clk */
{ .dev_id = "designware_udc", .clk = &usbd_clk},
{ .con_id = "usbh_clk", .clk = &usbh_clk},
/* clock derived from ahb clk */
{ .con_id = "apb_clk", .clk = &apb_clk},
{ .dev_id = "i2c_designware.0", .clk = &i2c_clk},
{ .dev_id = "dma", .clk = &dma_clk},
{ .dev_id = "jpeg", .clk = &jpeg_clk},
{ .dev_id = "gmac", .clk = &gmac_clk},
{ .dev_id = "smi", .clk = &smi_clk},
{ .dev_id = "c3", .clk = &c3_clk},
/* clock derived from apb clk */
{ .dev_id = "adc", .clk = &adc_clk},
{ .dev_id = "ssp-pl022.0", .clk = &ssp0_clk},
{ .dev_id = "gpio", .clk = &gpio_clk},
};
/* array of all spear 300 clock lookups */
#ifdef CONFIG_MACH_SPEAR300
static struct clk_lookup spear300_clk_lookups[] = {
{ .dev_id = "clcd", .clk = &clcd_clk},
{ .con_id = "fsmc", .clk = &fsmc_clk},
{ .dev_id = "gpio1", .clk = &gpio1_clk},
{ .dev_id = "keyboard", .clk = &kbd_clk},
{ .dev_id = "sdhci", .clk = &sdhci_clk},
};
#endif
/* array of all spear 310 clock lookups */
#ifdef CONFIG_MACH_SPEAR310
static struct clk_lookup spear310_clk_lookups[] = {
{ .con_id = "fsmc", .clk = &fsmc_clk},
{ .con_id = "emi", .clk = &emi_clk},
{ .dev_id = "uart1", .clk = &uart1_clk},
{ .dev_id = "uart2", .clk = &uart2_clk},
{ .dev_id = "uart3", .clk = &uart3_clk},
{ .dev_id = "uart4", .clk = &uart4_clk},
{ .dev_id = "uart5", .clk = &uart5_clk},
};
#endif
/* array of all spear 320 clock lookups */
#ifdef CONFIG_MACH_SPEAR320
static struct clk_lookup spear320_clk_lookups[] = {
{ .dev_id = "clcd", .clk = &clcd_clk},
{ .con_id = "fsmc", .clk = &fsmc_clk},
{ .dev_id = "i2c_designware.1", .clk = &i2c1_clk},
{ .con_id = "emi", .clk = &emi_clk},
{ .dev_id = "pwm", .clk = &pwm_clk},
{ .dev_id = "sdhci", .clk = &sdhci_clk},
{ .dev_id = "c_can_platform.0", .clk = &can0_clk},
{ .dev_id = "c_can_platform.1", .clk = &can1_clk},
{ .dev_id = "ssp-pl022.1", .clk = &ssp1_clk},
{ .dev_id = "ssp-pl022.2", .clk = &ssp2_clk},
{ .dev_id = "uart1", .clk = &uart1_clk},
{ .dev_id = "uart2", .clk = &uart2_clk},
};
#endif
void __init spear3xx_clk_init(void)
{
int i, cnt;
struct clk_lookup *lookups;
if (machine_is_spear300()) {
cnt = ARRAY_SIZE(spear300_clk_lookups);
lookups = spear300_clk_lookups;
} else if (machine_is_spear310()) {
cnt = ARRAY_SIZE(spear310_clk_lookups);
lookups = spear310_clk_lookups;
} else {
cnt = ARRAY_SIZE(spear320_clk_lookups);
lookups = spear320_clk_lookups;
}
for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
clk_register(&spear_clk_lookups[i]);
for (i = 0; i < cnt; i++)
clk_register(&lookups[i]);
clk_init();
}
......@@ -36,8 +36,8 @@ extern struct amba_device spear3xx_uart_device;
extern struct sys_timer spear3xx_timer;
/* Add spear3xx family function declarations here */
void __init spear3xx_clk_init(void);
void __init spear_setup_timer(void);
void __init spear3xx_clk_init(void);
void __init spear3xx_map_io(void);
void __init spear3xx_init_irq(void);
void __init spear3xx_init(void);
......@@ -156,7 +156,6 @@ extern struct pmx_dev spear310_pmx_tdm0;
/* Add spear310 machine function declarations here */
void __init spear310_init(struct pmx_mode *pmx_mode, struct pmx_dev **pmx_devs,
u8 pmx_dev_count);
#endif /* CONFIG_MACH_SPEAR310 */
/* spear320 declarations */
......
......@@ -15,150 +15,8 @@
#define __MACH_MISC_REGS_H
#include <mach/hardware.h>
#include <mach/spear.h>
#define MISC_BASE IOMEM(VA_SPEAR3XX_ICM3_MISC_REG_BASE)
#define SOC_CFG_CTR (MISC_BASE + 0x000)
#define DIAG_CFG_CTR (MISC_BASE + 0x004)
#define PLL1_CTR (MISC_BASE + 0x008)
#define PLL1_FRQ (MISC_BASE + 0x00C)
#define PLL1_MOD (MISC_BASE + 0x010)
#define PLL2_CTR (MISC_BASE + 0x014)
/* PLL_CTR register masks */
#define PLL_ENABLE 2
#define PLL_MODE_SHIFT 4
#define PLL_MODE_MASK 0x3
#define PLL_MODE_NORMAL 0
#define PLL_MODE_FRACTION 1
#define PLL_MODE_DITH_DSB 2
#define PLL_MODE_DITH_SSB 3
#define PLL2_FRQ (MISC_BASE + 0x018)
/* PLL FRQ register masks */
#define PLL_DIV_N_SHIFT 0
#define PLL_DIV_N_MASK 0xFF
#define PLL_DIV_P_SHIFT 8
#define PLL_DIV_P_MASK 0x7
#define PLL_NORM_FDBK_M_SHIFT 24
#define PLL_NORM_FDBK_M_MASK 0xFF
#define PLL_DITH_FDBK_M_SHIFT 16
#define PLL_DITH_FDBK_M_MASK 0xFFFF
#define PLL2_MOD (MISC_BASE + 0x01C)
#define PLL_CLK_CFG (MISC_BASE + 0x020)
#define CORE_CLK_CFG (MISC_BASE + 0x024)
/* CORE CLK CFG register masks */
#define PLL_HCLK_RATIO_SHIFT 10
#define PLL_HCLK_RATIO_MASK 0x3
#define HCLK_PCLK_RATIO_SHIFT 8
#define HCLK_PCLK_RATIO_MASK 0x3
#define PERIP_CLK_CFG (MISC_BASE + 0x028)
/* PERIP_CLK_CFG register masks */
#define UART_CLK_SHIFT 4
#define UART_CLK_MASK 0x1
#define FIRDA_CLK_SHIFT 5
#define FIRDA_CLK_MASK 0x3
#define GPT0_CLK_SHIFT 8
#define GPT1_CLK_SHIFT 11
#define GPT2_CLK_SHIFT 12
#define GPT_CLK_MASK 0x1
#define AUX_CLK_PLL3_VAL 0
#define AUX_CLK_PLL1_VAL 1
#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
/* PERIP1_CLK_ENB register masks */
#define UART_CLK_ENB 3
#define SSP_CLK_ENB 5
#define I2C_CLK_ENB 7
#define JPEG_CLK_ENB 8
#define FIRDA_CLK_ENB 10
#define GPT1_CLK_ENB 11
#define GPT2_CLK_ENB 12
#define ADC_CLK_ENB 15
#define RTC_CLK_ENB 17
#define GPIO_CLK_ENB 18
#define DMA_CLK_ENB 19
#define SMI_CLK_ENB 21
#define GMAC_CLK_ENB 23
#define USBD_CLK_ENB 24
#define USBH_CLK_ENB 25
#define C3_CLK_ENB 31
#define SOC_CORE_ID (MISC_BASE + 0x030)
#define RAS_CLK_ENB (MISC_BASE + 0x034)
#define PERIP1_SOF_RST (MISC_BASE + 0x038)
/* PERIP1_SOF_RST register masks */
#define JPEG_SOF_RST 8
#define SOC_USER_ID (MISC_BASE + 0x03C)
#define RAS_SOF_RST (MISC_BASE + 0x040)
#define PRSC1_CLK_CFG (MISC_BASE + 0x044)
#define PRSC2_CLK_CFG (MISC_BASE + 0x048)
#define PRSC3_CLK_CFG (MISC_BASE + 0x04C)
/* gpt synthesizer register masks */
#define GPT_MSCALE_SHIFT 0
#define GPT_MSCALE_MASK 0xFFF
#define GPT_NSCALE_SHIFT 12
#define GPT_NSCALE_MASK 0xF
#define AMEM_CLK_CFG (MISC_BASE + 0x050)
#define EXPI_CLK_CFG (MISC_BASE + 0x054)
#define CLCD_CLK_SYNT (MISC_BASE + 0x05C)
#define FIRDA_CLK_SYNT (MISC_BASE + 0x060)
#define UART_CLK_SYNT (MISC_BASE + 0x064)
#define GMAC_CLK_SYNT (MISC_BASE + 0x068)
#define RAS1_CLK_SYNT (MISC_BASE + 0x06C)
#define RAS2_CLK_SYNT (MISC_BASE + 0x070)
#define RAS3_CLK_SYNT (MISC_BASE + 0x074)
#define RAS4_CLK_SYNT (MISC_BASE + 0x078)
/* aux clk synthesiser register masks for irda to ras4 */
#define AUX_SYNT_ENB 31
#define AUX_EQ_SEL_SHIFT 30
#define AUX_EQ_SEL_MASK 1
#define AUX_EQ1_SEL 0
#define AUX_EQ2_SEL 1
#define AUX_XSCALE_SHIFT 16
#define AUX_XSCALE_MASK 0xFFF
#define AUX_YSCALE_SHIFT 0
#define AUX_YSCALE_MASK 0xFFF
#define ICM1_ARB_CFG (MISC_BASE + 0x07C)
#define ICM2_ARB_CFG (MISC_BASE + 0x080)
#define ICM3_ARB_CFG (MISC_BASE + 0x084)
#define ICM4_ARB_CFG (MISC_BASE + 0x088)
#define ICM5_ARB_CFG (MISC_BASE + 0x08C)
#define ICM6_ARB_CFG (MISC_BASE + 0x090)
#define ICM7_ARB_CFG (MISC_BASE + 0x094)
#define ICM8_ARB_CFG (MISC_BASE + 0x098)
#define ICM9_ARB_CFG (MISC_BASE + 0x09C)
#define DMA_CHN_CFG (MISC_BASE + 0x0A0)
#define USB2_PHY_CFG (MISC_BASE + 0x0A4)
#define GMAC_CFG_CTR (MISC_BASE + 0x0A8)
#define EXPI_CFG_CTR (MISC_BASE + 0x0AC)
#define PRC1_LOCK_CTR (MISC_BASE + 0x0C0)
#define PRC2_LOCK_CTR (MISC_BASE + 0x0C4)
#define PRC3_LOCK_CTR (MISC_BASE + 0x0C8)
#define PRC4_LOCK_CTR (MISC_BASE + 0x0CC)
#define PRC1_IRQ_CTR (MISC_BASE + 0x0D0)
#define PRC2_IRQ_CTR (MISC_BASE + 0x0D4)
#define PRC3_IRQ_CTR (MISC_BASE + 0x0D8)
#define PRC4_IRQ_CTR (MISC_BASE + 0x0DC)
#define PWRDOWN_CFG_CTR (MISC_BASE + 0x0E0)
#define COMPSSTL_1V8_CFG (MISC_BASE + 0x0E4)
#define COMPSSTL_2V5_CFG (MISC_BASE + 0x0E8)
#define COMPCOR_3V3_CFG (MISC_BASE + 0x0EC)
#define SSTLPAD_CFG_CTR (MISC_BASE + 0x0F0)
#define BIST1_CFG_CTR (MISC_BASE + 0x0F4)
#define BIST2_CFG_CTR (MISC_BASE + 0x0F8)
#define BIST3_CFG_CTR (MISC_BASE + 0x0FC)
#define BIST4_CFG_CTR (MISC_BASE + 0x100)
#define BIST5_CFG_CTR (MISC_BASE + 0x104)
#define BIST1_STS_RES (MISC_BASE + 0x108)
#define BIST2_STS_RES (MISC_BASE + 0x10C)
#define BIST3_STS_RES (MISC_BASE + 0x110)
#define BIST4_STS_RES (MISC_BASE + 0x114)
#define BIST5_STS_RES (MISC_BASE + 0x118)
#define SYSERR_CFG_CTR (MISC_BASE + 0x11C)
#endif /* __MACH_MISC_REGS_H */
......@@ -78,4 +78,17 @@
#define SPEAR_SYS_CTRL_BASE SPEAR3XX_ICM3_SYS_CTRL_BASE
#define VA_SPEAR_SYS_CTRL_BASE VA_SPEAR3XX_ICM3_SYS_CTRL_BASE
/* SPEAr320 Macros */
#define SPEAR320_SOC_CONFIG_BASE UL(0xB3000000)
#define VA_SPEAR320_SOC_CONFIG_BASE UL(0xFE000000)
#define SPEAR320_CONTROL_REG IOMEM(VA_SPEAR320_SOC_CONFIG_BASE)
#define SPEAR320_EXT_CTRL_REG IOMEM(VA_SPEAR320_SOC_CONFIG_BASE + 0x0018)
#define SPEAR320_UARTX_PCLK_MASK 0x1
#define SPEAR320_UART2_PCLK_SHIFT 8
#define SPEAR320_UART3_PCLK_SHIFT 9
#define SPEAR320_UART4_PCLK_SHIFT 10
#define SPEAR320_UART5_PCLK_SHIFT 11
#define SPEAR320_UART6_PCLK_SHIFT 12
#define SPEAR320_RS485_PCLK_SHIFT 13
#endif /* __MACH_SPEAR3XX_H */
......@@ -16,6 +16,7 @@
#include <plat/shirq.h>
#include <mach/generic.h>
#include <mach/hardware.h>
#include <mach/spear.h>
/* pad multiplexing support */
/* muxing registers */
......
......@@ -511,6 +511,8 @@ static void __init spear3xx_timer_init(void)
char pclk_name[] = "pll3_48m_clk";
struct clk *gpt_clk, *pclk;
spear3xx_clk_init();
/* get the system timer clock */
gpt_clk = clk_get_sys("gpt0", NULL);
if (IS_ERR(gpt_clk)) {
......
......@@ -3,4 +3,4 @@
#
# common files
obj-y += clock.o spear6xx.o
obj-y += spear6xx.o
/*
* arch/arm/mach-spear6xx/clock.c
*
* SPEAr6xx machines clock framework source file
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <plat/clock.h>
#include <mach/misc_regs.h>
/* root clks */
/* 32 KHz oscillator clock */
static struct clk osc_32k_clk = {
.flags = ALWAYS_ENABLED,
.rate = 32000,
};
/* 30 MHz oscillator clock */
static struct clk osc_30m_clk = {
.flags = ALWAYS_ENABLED,
.rate = 30000000,
};
/* clock derived from 32 KHz osc clk */
/* rtc clock */
static struct clk rtc_clk = {
.pclk = &osc_32k_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = RTC_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from 30 MHz osc clk */
/* pll masks structure */
static struct pll_clk_masks pll1_masks = {
.mode_mask = PLL_MODE_MASK,
.mode_shift = PLL_MODE_SHIFT,
.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
.norm_fdbk_m_shift = PLL_NORM_FDBK_M_SHIFT,
.dith_fdbk_m_mask = PLL_DITH_FDBK_M_MASK,
.dith_fdbk_m_shift = PLL_DITH_FDBK_M_SHIFT,
.div_p_mask = PLL_DIV_P_MASK,
.div_p_shift = PLL_DIV_P_SHIFT,
.div_n_mask = PLL_DIV_N_MASK,
.div_n_shift = PLL_DIV_N_SHIFT,
};
/* pll1 configuration structure */
static struct pll_clk_config pll1_config = {
.mode_reg = PLL1_CTR,
.cfg_reg = PLL1_FRQ,
.masks = &pll1_masks,
};
/* pll rate configuration table, in ascending order of rates */
struct pll_rate_tbl pll_rtbl[] = {
{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
};
/* PLL1 clock */
static struct clk pll1_clk = {
.flags = ENABLED_ON_INIT,
.pclk = &osc_30m_clk,
.en_reg = PLL1_CTR,
.en_reg_bit = PLL_ENABLE,
.calc_rate = &pll_calc_rate,
.recalc = &pll_clk_recalc,
.set_rate = &pll_clk_set_rate,
.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
.private_data = &pll1_config,
};
/* PLL3 48 MHz clock */
static struct clk pll3_48m_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &osc_30m_clk,
.rate = 48000000,
};
/* watch dog timer clock */
static struct clk wdt_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &osc_30m_clk,
.recalc = &follow_parent,
};
/* clock derived from pll1 clk */
/* cpu clock */
static struct clk cpu_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.recalc = &follow_parent,
};
/* ahb masks structure */
static struct bus_clk_masks ahb_masks = {
.mask = PLL_HCLK_RATIO_MASK,
.shift = PLL_HCLK_RATIO_SHIFT,
};
/* ahb configuration structure */
static struct bus_clk_config ahb_config = {
.reg = CORE_CLK_CFG,
.masks = &ahb_masks,
};
/* ahb rate configuration table, in ascending order of rates */
struct bus_rate_tbl bus_rtbl[] = {
{.div = 3}, /* == parent divided by 4 */
{.div = 2}, /* == parent divided by 3 */
{.div = 1}, /* == parent divided by 2 */
{.div = 0}, /* == parent divided by 1 */
};
/* ahb clock */
static struct clk ahb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
.set_rate = &bus_clk_set_rate,
.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &ahb_config,
};
/* auxiliary synthesizers masks */
static struct aux_clk_masks aux_masks = {
.eq_sel_mask = AUX_EQ_SEL_MASK,
.eq_sel_shift = AUX_EQ_SEL_SHIFT,
.eq1_mask = AUX_EQ1_SEL,
.eq2_mask = AUX_EQ2_SEL,
.xscale_sel_mask = AUX_XSCALE_MASK,
.xscale_sel_shift = AUX_XSCALE_SHIFT,
.yscale_sel_mask = AUX_YSCALE_MASK,
.yscale_sel_shift = AUX_YSCALE_SHIFT,
};
/* uart configurations */
static struct aux_clk_config uart_synth_config = {
.synth_reg = UART_CLK_SYNT,
.masks = &aux_masks,
};
/* aux rate configuration table, in ascending order of rates */
struct aux_rate_tbl aux_rtbl[] = {
/* For PLL1 = 332 MHz */
{.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */
{.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */
{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
};
/* uart synth clock */
static struct clk uart_synth_clk = {
.en_reg = UART_CLK_SYNT,
.en_reg_bit = AUX_SYNT_ENB,
.pclk = &pll1_clk,
.calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
.set_rate = &aux_clk_set_rate,
.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
.private_data = &uart_synth_config,
};
/* uart parents */
static struct pclk_info uart_pclk_info[] = {
{
.pclk = &uart_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* uart parent select structure */
static struct pclk_sel uart_pclk_sel = {
.pclk_info = uart_pclk_info,
.pclk_count = ARRAY_SIZE(uart_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = UART_CLK_MASK,
};
/* uart0 clock */
static struct clk uart0_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = UART0_CLK_ENB,
.pclk_sel = &uart_pclk_sel,
.pclk_sel_shift = UART_CLK_SHIFT,
.recalc = &follow_parent,
};
/* uart1 clock */
static struct clk uart1_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = UART1_CLK_ENB,
.pclk_sel = &uart_pclk_sel,
.pclk_sel_shift = UART_CLK_SHIFT,
.recalc = &follow_parent,
};
/* firda configurations */
static struct aux_clk_config firda_synth_config = {
.synth_reg = FIRDA_CLK_SYNT,
.masks = &aux_masks,
};
/* firda synth clock */
static struct clk firda_synth_clk = {
.en_reg = FIRDA_CLK_SYNT,
.en_reg_bit = AUX_SYNT_ENB,
.pclk = &pll1_clk,
.calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
.set_rate = &aux_clk_set_rate,
.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
.private_data = &firda_synth_config,
};
/* firda parents */
static struct pclk_info firda_pclk_info[] = {
{
.pclk = &firda_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* firda parent select structure */
static struct pclk_sel firda_pclk_sel = {
.pclk_info = firda_pclk_info,
.pclk_count = ARRAY_SIZE(firda_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = FIRDA_CLK_MASK,
};
/* firda clock */
static struct clk firda_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = FIRDA_CLK_ENB,
.pclk_sel = &firda_pclk_sel,
.pclk_sel_shift = FIRDA_CLK_SHIFT,
.recalc = &follow_parent,
};
/* clcd configurations */
static struct aux_clk_config clcd_synth_config = {
.synth_reg = CLCD_CLK_SYNT,
.masks = &aux_masks,
};
/* firda synth clock */
static struct clk clcd_synth_clk = {
.en_reg = CLCD_CLK_SYNT,
.en_reg_bit = AUX_SYNT_ENB,
.pclk = &pll1_clk,
.calc_rate = &aux_calc_rate,
.recalc = &aux_clk_recalc,
.set_rate = &aux_clk_set_rate,
.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
.private_data = &clcd_synth_config,
};
/* clcd parents */
static struct pclk_info clcd_pclk_info[] = {
{
.pclk = &clcd_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* clcd parent select structure */
static struct pclk_sel clcd_pclk_sel = {
.pclk_info = clcd_pclk_info,
.pclk_count = ARRAY_SIZE(clcd_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = CLCD_CLK_MASK,
};
/* clcd clock */
static struct clk clcd_clk = {
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = CLCD_CLK_ENB,
.pclk_sel = &clcd_pclk_sel,
.pclk_sel_shift = CLCD_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt synthesizer masks */
static struct gpt_clk_masks gpt_masks = {
.mscale_sel_mask = GPT_MSCALE_MASK,
.mscale_sel_shift = GPT_MSCALE_SHIFT,
.nscale_sel_mask = GPT_NSCALE_MASK,
.nscale_sel_shift = GPT_NSCALE_SHIFT,
};
/* gpt rate configuration table, in ascending order of rates */
struct gpt_rate_tbl gpt_rtbl[] = {
/* For pll1 = 332 MHz */
{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
{.mscale = 1, .nscale = 0}, /* 83 MHz */
};
/* gpt0 synth clk config*/
static struct gpt_clk_config gpt0_synth_config = {
.synth_reg = PRSC1_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt synth clock */
static struct clk gpt0_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt0_synth_config,
};
/* gpt parents */
static struct pclk_info gpt0_pclk_info[] = {
{
.pclk = &gpt0_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt0_pclk_sel = {
.pclk_info = gpt0_pclk_info,
.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt0 ARM1 subsystem timer clock */
static struct clk gpt0_clk = {
.flags = ALWAYS_ENABLED,
.pclk_sel = &gpt0_pclk_sel,
.pclk_sel_shift = GPT0_CLK_SHIFT,
.recalc = &follow_parent,
};
/* Note: gpt0 and gpt1 share same parent clocks */
/* gpt parent select structure */
static struct pclk_sel gpt1_pclk_sel = {
.pclk_info = gpt0_pclk_info,
.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt1 timer clock */
static struct clk gpt1_clk = {
.flags = ALWAYS_ENABLED,
.pclk_sel = &gpt1_pclk_sel,
.pclk_sel_shift = GPT1_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt2 synth clk config*/
static struct gpt_clk_config gpt2_synth_config = {
.synth_reg = PRSC2_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt synth clock */
static struct clk gpt2_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt2_synth_config,
};
/* gpt parents */
static struct pclk_info gpt2_pclk_info[] = {
{
.pclk = &gpt2_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt2_pclk_sel = {
.pclk_info = gpt2_pclk_info,
.pclk_count = ARRAY_SIZE(gpt2_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt2 timer clock */
static struct clk gpt2_clk = {
.flags = ALWAYS_ENABLED,
.pclk_sel = &gpt2_pclk_sel,
.pclk_sel_shift = GPT2_CLK_SHIFT,
.recalc = &follow_parent,
};
/* gpt3 synth clk config*/
static struct gpt_clk_config gpt3_synth_config = {
.synth_reg = PRSC3_CLK_CFG,
.masks = &gpt_masks,
};
/* gpt synth clock */
static struct clk gpt3_synth_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &pll1_clk,
.calc_rate = &gpt_calc_rate,
.recalc = &gpt_clk_recalc,
.set_rate = &gpt_clk_set_rate,
.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
.private_data = &gpt3_synth_config,
};
/* gpt parents */
static struct pclk_info gpt3_pclk_info[] = {
{
.pclk = &gpt3_synth_clk,
.pclk_val = AUX_CLK_PLL1_VAL,
}, {
.pclk = &pll3_48m_clk,
.pclk_val = AUX_CLK_PLL3_VAL,
},
};
/* gpt parent select structure */
static struct pclk_sel gpt3_pclk_sel = {
.pclk_info = gpt3_pclk_info,
.pclk_count = ARRAY_SIZE(gpt3_pclk_info),
.pclk_sel_reg = PERIP_CLK_CFG,
.pclk_sel_mask = GPT_CLK_MASK,
};
/* gpt3 timer clock */
static struct clk gpt3_clk = {
.flags = ALWAYS_ENABLED,
.pclk_sel = &gpt3_pclk_sel,
.pclk_sel_shift = GPT3_CLK_SHIFT,
.recalc = &follow_parent,
};
/* clock derived from pll3 clk */
/* usbh0 clock */
static struct clk usbh0_clk = {
.pclk = &pll3_48m_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = USBH0_CLK_ENB,
.recalc = &follow_parent,
};
/* usbh1 clock */
static struct clk usbh1_clk = {
.pclk = &pll3_48m_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = USBH1_CLK_ENB,
.recalc = &follow_parent,
};
/* usbd clock */
static struct clk usbd_clk = {
.pclk = &pll3_48m_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = USBD_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from ahb clk */
/* apb masks structure */
static struct bus_clk_masks apb_masks = {
.mask = HCLK_PCLK_RATIO_MASK,
.shift = HCLK_PCLK_RATIO_SHIFT,
};
/* apb configuration structure */
static struct bus_clk_config apb_config = {
.reg = CORE_CLK_CFG,
.masks = &apb_masks,
};
/* apb clock */
static struct clk apb_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &ahb_clk,
.calc_rate = &bus_calc_rate,
.recalc = &bus_clk_recalc,
.set_rate = &bus_clk_set_rate,
.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
.private_data = &apb_config,
};
/* i2c clock */
static struct clk i2c_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = I2C_CLK_ENB,
.recalc = &follow_parent,
};
/* dma clock */
static struct clk dma_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = DMA_CLK_ENB,
.recalc = &follow_parent,
};
/* jpeg clock */
static struct clk jpeg_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = JPEG_CLK_ENB,
.recalc = &follow_parent,
};
/* gmac clock */
static struct clk gmac_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GMAC_CLK_ENB,
.recalc = &follow_parent,
};
/* smi clock */
static struct clk smi_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SMI_CLK_ENB,
.recalc = &follow_parent,
};
/* fsmc clock */
static struct clk fsmc_clk = {
.pclk = &ahb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = FSMC_CLK_ENB,
.recalc = &follow_parent,
};
/* clock derived from apb clk */
/* adc clock */
static struct clk adc_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = ADC_CLK_ENB,
.recalc = &follow_parent,
};
/* ssp0 clock */
static struct clk ssp0_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SSP0_CLK_ENB,
.recalc = &follow_parent,
};
/* ssp1 clock */
static struct clk ssp1_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SSP1_CLK_ENB,
.recalc = &follow_parent,
};
/* ssp2 clock */
static struct clk ssp2_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = SSP2_CLK_ENB,
.recalc = &follow_parent,
};
/* gpio0 ARM subsystem clock */
static struct clk gpio0_clk = {
.flags = ALWAYS_ENABLED,
.pclk = &apb_clk,
.recalc = &follow_parent,
};
/* gpio1 clock */
static struct clk gpio1_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPIO1_CLK_ENB,
.recalc = &follow_parent,
};
/* gpio2 clock */
static struct clk gpio2_clk = {
.pclk = &apb_clk,
.en_reg = PERIP1_CLK_ENB,
.en_reg_bit = GPIO2_CLK_ENB,
.recalc = &follow_parent,
};
static struct clk dummy_apb_pclk;
/* array of all spear 6xx clock lookups */
static struct clk_lookup spear_clk_lookups[] = {
{ .con_id = "apb_pclk", .clk = &dummy_apb_pclk},
/* root clks */
{ .con_id = "osc_32k_clk", .clk = &osc_32k_clk},
{ .con_id = "osc_30m_clk", .clk = &osc_30m_clk},
/* clock derived from 32 KHz os clk */
{ .dev_id = "rtc-spear", .clk = &rtc_clk},
/* clock derived from 30 MHz os clk */
{ .con_id = "pll1_clk", .clk = &pll1_clk},
{ .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk},
{ .dev_id = "wdt", .clk = &wdt_clk},
/* clock derived from pll1 clk */
{ .con_id = "cpu_clk", .clk = &cpu_clk},
{ .con_id = "ahb_clk", .clk = &ahb_clk},
{ .con_id = "uart_synth_clk", .clk = &uart_synth_clk},
{ .con_id = "firda_synth_clk", .clk = &firda_synth_clk},
{ .con_id = "clcd_synth_clk", .clk = &clcd_synth_clk},
{ .con_id = "gpt0_synth_clk", .clk = &gpt0_synth_clk},
{ .con_id = "gpt2_synth_clk", .clk = &gpt2_synth_clk},
{ .con_id = "gpt3_synth_clk", .clk = &gpt3_synth_clk},
{ .dev_id = "d0000000.serial", .clk = &uart0_clk},
{ .dev_id = "d0080000.serial", .clk = &uart1_clk},
{ .dev_id = "firda", .clk = &firda_clk},
{ .dev_id = "clcd", .clk = &clcd_clk},
{ .dev_id = "gpt0", .clk = &gpt0_clk},
{ .dev_id = "gpt1", .clk = &gpt1_clk},
{ .dev_id = "gpt2", .clk = &gpt2_clk},
{ .dev_id = "gpt3", .clk = &gpt3_clk},
/* clock derived from pll3 clk */
{ .dev_id = "designware_udc", .clk = &usbd_clk},
{ .con_id = "usbh.0_clk", .clk = &usbh0_clk},
{ .con_id = "usbh.1_clk", .clk = &usbh1_clk},
/* clock derived from ahb clk */
{ .con_id = "apb_clk", .clk = &apb_clk},
{ .dev_id = "d0200000.i2c", .clk = &i2c_clk},
{ .dev_id = "dma", .clk = &dma_clk},
{ .dev_id = "jpeg", .clk = &jpeg_clk},
{ .dev_id = "gmac", .clk = &gmac_clk},
{ .dev_id = "smi", .clk = &smi_clk},
{ .dev_id = "fsmc-nand", .clk = &fsmc_clk},
/* clock derived from apb clk */
{ .dev_id = "adc", .clk = &adc_clk},
{ .dev_id = "ssp-pl022.0", .clk = &ssp0_clk},
{ .dev_id = "ssp-pl022.1", .clk = &ssp1_clk},
{ .dev_id = "ssp-pl022.2", .clk = &ssp2_clk},
{ .dev_id = "f0100000.gpio", .clk = &gpio0_clk},
{ .dev_id = "fc980000.gpio", .clk = &gpio1_clk},
{ .dev_id = "d8100000.gpio", .clk = &gpio2_clk},
};
void __init spear6xx_clk_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++)
clk_register(&spear_clk_lookups[i]);
clk_init();
}
......@@ -15,160 +15,8 @@
#define __MACH_MISC_REGS_H
#include <mach/hardware.h>
#include <mach/spear.h>
#define MISC_BASE IOMEM(VA_SPEAR6XX_ICM3_MISC_REG_BASE)
#define SOC_CFG_CTR (MISC_BASE + 0x000)
#define DIAG_CFG_CTR (MISC_BASE + 0x004)
#define PLL1_CTR (MISC_BASE + 0x008)
#define PLL1_FRQ (MISC_BASE + 0x00C)
#define PLL1_MOD (MISC_BASE + 0x010)
#define PLL2_CTR (MISC_BASE + 0x014)
/* PLL_CTR register masks */
#define PLL_ENABLE 2
#define PLL_MODE_SHIFT 4
#define PLL_MODE_MASK 0x3
#define PLL_MODE_NORMAL 0
#define PLL_MODE_FRACTION 1
#define PLL_MODE_DITH_DSB 2
#define PLL_MODE_DITH_SSB 3
#define PLL2_FRQ (MISC_BASE + 0x018)
/* PLL FRQ register masks */
#define PLL_DIV_N_SHIFT 0
#define PLL_DIV_N_MASK 0xFF
#define PLL_DIV_P_SHIFT 8
#define PLL_DIV_P_MASK 0x7
#define PLL_NORM_FDBK_M_SHIFT 24
#define PLL_NORM_FDBK_M_MASK 0xFF
#define PLL_DITH_FDBK_M_SHIFT 16
#define PLL_DITH_FDBK_M_MASK 0xFFFF
#define PLL2_MOD (MISC_BASE + 0x01C)
#define PLL_CLK_CFG (MISC_BASE + 0x020)
#define CORE_CLK_CFG (MISC_BASE + 0x024)
/* CORE CLK CFG register masks */
#define PLL_HCLK_RATIO_SHIFT 10
#define PLL_HCLK_RATIO_MASK 0x3
#define HCLK_PCLK_RATIO_SHIFT 8
#define HCLK_PCLK_RATIO_MASK 0x3
#define PERIP_CLK_CFG (MISC_BASE + 0x028)
/* PERIP_CLK_CFG register masks */
#define CLCD_CLK_SHIFT 2
#define CLCD_CLK_MASK 0x3
#define UART_CLK_SHIFT 4
#define UART_CLK_MASK 0x1
#define FIRDA_CLK_SHIFT 5
#define FIRDA_CLK_MASK 0x3
#define GPT0_CLK_SHIFT 8
#define GPT1_CLK_SHIFT 10
#define GPT2_CLK_SHIFT 11
#define GPT3_CLK_SHIFT 12
#define GPT_CLK_MASK 0x1
#define AUX_CLK_PLL3_VAL 0
#define AUX_CLK_PLL1_VAL 1
#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
/* PERIP1_CLK_ENB register masks */
#define UART0_CLK_ENB 3
#define UART1_CLK_ENB 4
#define SSP0_CLK_ENB 5
#define SSP1_CLK_ENB 6
#define I2C_CLK_ENB 7
#define JPEG_CLK_ENB 8
#define FSMC_CLK_ENB 9
#define FIRDA_CLK_ENB 10
#define GPT2_CLK_ENB 11
#define GPT3_CLK_ENB 12
#define GPIO2_CLK_ENB 13
#define SSP2_CLK_ENB 14
#define ADC_CLK_ENB 15
#define GPT1_CLK_ENB 11
#define RTC_CLK_ENB 17
#define GPIO1_CLK_ENB 18
#define DMA_CLK_ENB 19
#define SMI_CLK_ENB 21
#define CLCD_CLK_ENB 22
#define GMAC_CLK_ENB 23
#define USBD_CLK_ENB 24
#define USBH0_CLK_ENB 25
#define USBH1_CLK_ENB 26
#define SOC_CORE_ID (MISC_BASE + 0x030)
#define RAS_CLK_ENB (MISC_BASE + 0x034)
#define PERIP1_SOF_RST (MISC_BASE + 0x038)
/* PERIP1_SOF_RST register masks */
#define JPEG_SOF_RST 8
#define SOC_USER_ID (MISC_BASE + 0x03C)
#define RAS_SOF_RST (MISC_BASE + 0x040)
#define PRSC1_CLK_CFG (MISC_BASE + 0x044)
#define PRSC2_CLK_CFG (MISC_BASE + 0x048)
#define PRSC3_CLK_CFG (MISC_BASE + 0x04C)
/* gpt synthesizer register masks */
#define GPT_MSCALE_SHIFT 0
#define GPT_MSCALE_MASK 0xFFF
#define GPT_NSCALE_SHIFT 12
#define GPT_NSCALE_MASK 0xF
#define AMEM_CLK_CFG (MISC_BASE + 0x050)
#define EXPI_CLK_CFG (MISC_BASE + 0x054)
#define CLCD_CLK_SYNT (MISC_BASE + 0x05C)
#define FIRDA_CLK_SYNT (MISC_BASE + 0x060)
#define UART_CLK_SYNT (MISC_BASE + 0x064)
#define GMAC_CLK_SYNT (MISC_BASE + 0x068)
#define RAS1_CLK_SYNT (MISC_BASE + 0x06C)
#define RAS2_CLK_SYNT (MISC_BASE + 0x070)
#define RAS3_CLK_SYNT (MISC_BASE + 0x074)
#define RAS4_CLK_SYNT (MISC_BASE + 0x078)
/* aux clk synthesiser register masks for irda to ras4 */
#define AUX_SYNT_ENB 31
#define AUX_EQ_SEL_SHIFT 30
#define AUX_EQ_SEL_MASK 1
#define AUX_EQ1_SEL 0
#define AUX_EQ2_SEL 1
#define AUX_XSCALE_SHIFT 16
#define AUX_XSCALE_MASK 0xFFF
#define AUX_YSCALE_SHIFT 0
#define AUX_YSCALE_MASK 0xFFF
#define ICM1_ARB_CFG (MISC_BASE + 0x07C)
#define ICM2_ARB_CFG (MISC_BASE + 0x080)
#define ICM3_ARB_CFG (MISC_BASE + 0x084)
#define ICM4_ARB_CFG (MISC_BASE + 0x088)
#define ICM5_ARB_CFG (MISC_BASE + 0x08C)
#define ICM6_ARB_CFG (MISC_BASE + 0x090)
#define ICM7_ARB_CFG (MISC_BASE + 0x094)
#define ICM8_ARB_CFG (MISC_BASE + 0x098)
#define ICM9_ARB_CFG (MISC_BASE + 0x09C)
#define DMA_CHN_CFG (MISC_BASE + 0x0A0)
#define USB2_PHY_CFG (MISC_BASE + 0x0A4)
#define GMAC_CFG_CTR (MISC_BASE + 0x0A8)
#define EXPI_CFG_CTR (MISC_BASE + 0x0AC)
#define PRC1_LOCK_CTR (MISC_BASE + 0x0C0)
#define PRC2_LOCK_CTR (MISC_BASE + 0x0C4)
#define PRC3_LOCK_CTR (MISC_BASE + 0x0C8)
#define PRC4_LOCK_CTR (MISC_BASE + 0x0CC)
#define PRC1_IRQ_CTR (MISC_BASE + 0x0D0)
#define PRC2_IRQ_CTR (MISC_BASE + 0x0D4)
#define PRC3_IRQ_CTR (MISC_BASE + 0x0D8)
#define PRC4_IRQ_CTR (MISC_BASE + 0x0DC)
#define PWRDOWN_CFG_CTR (MISC_BASE + 0x0E0)
#define COMPSSTL_1V8_CFG (MISC_BASE + 0x0E4)
#define COMPSSTL_2V5_CFG (MISC_BASE + 0x0E8)
#define COMPCOR_3V3_CFG (MISC_BASE + 0x0EC)
#define SSTLPAD_CFG_CTR (MISC_BASE + 0x0F0)
#define BIST1_CFG_CTR (MISC_BASE + 0x0F4)
#define BIST2_CFG_CTR (MISC_BASE + 0x0F8)
#define BIST3_CFG_CTR (MISC_BASE + 0x0FC)
#define BIST4_CFG_CTR (MISC_BASE + 0x100)
#define BIST5_CFG_CTR (MISC_BASE + 0x104)
#define BIST1_STS_RES (MISC_BASE + 0x108)
#define BIST2_STS_RES (MISC_BASE + 0x10C)
#define BIST3_STS_RES (MISC_BASE + 0x110)
#define BIST4_STS_RES (MISC_BASE + 0x114)
#define BIST5_STS_RES (MISC_BASE + 0x118)
#define SYSERR_CFG_CTR (MISC_BASE + 0x11C)
#endif /* __MACH_MISC_REGS_H */
......@@ -56,9 +56,6 @@ static struct map_desc spear6xx_io_desc[] __initdata = {
void __init spear6xx_map_io(void)
{
iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc));
/* This will initialize clock framework */
spear6xx_clk_init();
}
static void __init spear6xx_timer_init(void)
......@@ -66,6 +63,8 @@ static void __init spear6xx_timer_init(void)
char pclk_name[] = "pll3_48m_clk";
struct clk *gpt_clk, *pclk;
spear6xx_clk_init();
/* get the system timer clock */
gpt_clk = clk_get_sys("gpt0", NULL);
if (IS_ERR(gpt_clk)) {
......
......@@ -3,6 +3,6 @@
#
# Common support
obj-y := clock.o restart.o time.o
obj-y := restart.o time.o
obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o padmux.o
/*
* arch/arm/plat-spear/clock.c
*
* Clock framework for SPEAr platform
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/bug.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <plat/clock.h>
static DEFINE_SPINLOCK(clocks_lock);
static LIST_HEAD(root_clks);
#ifdef CONFIG_DEBUG_FS
static LIST_HEAD(clocks);
#endif
static void propagate_rate(struct clk *, int on_init);
#ifdef CONFIG_DEBUG_FS
static int clk_debugfs_reparent(struct clk *);
#endif
static int generic_clk_enable(struct clk *clk)
{
unsigned int val;
if (!clk->en_reg)
return -EFAULT;
val = readl(clk->en_reg);
if (unlikely(clk->flags & RESET_TO_ENABLE))
val &= ~(1 << clk->en_reg_bit);
else
val |= 1 << clk->en_reg_bit;
writel(val, clk->en_reg);
return 0;
}
static void generic_clk_disable(struct clk *clk)
{
unsigned int val;
if (!clk->en_reg)
return;
val = readl(clk->en_reg);
if (unlikely(clk->flags & RESET_TO_ENABLE))
val |= 1 << clk->en_reg_bit;
else
val &= ~(1 << clk->en_reg_bit);
writel(val, clk->en_reg);
}
/* generic clk ops */
static struct clkops generic_clkops = {
.enable = generic_clk_enable,
.disable = generic_clk_disable,
};
/* returns current programmed clocks clock info structure */
static struct pclk_info *pclk_info_get(struct clk *clk)
{
unsigned int val, i;
struct pclk_info *info = NULL;
val = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift)
& clk->pclk_sel->pclk_sel_mask;
for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
if (clk->pclk_sel->pclk_info[i].pclk_val == val)
info = &clk->pclk_sel->pclk_info[i];
}
return info;
}
/*
* Set Update pclk, and pclk_info of clk and add clock sibling node to current
* parents children list
*/
static void clk_reparent(struct clk *clk, struct pclk_info *pclk_info)
{
unsigned long flags;
spin_lock_irqsave(&clocks_lock, flags);
list_del(&clk->sibling);
list_add(&clk->sibling, &pclk_info->pclk->children);
clk->pclk = pclk_info->pclk;
spin_unlock_irqrestore(&clocks_lock, flags);
#ifdef CONFIG_DEBUG_FS
clk_debugfs_reparent(clk);
#endif
}
static void do_clk_disable(struct clk *clk)
{
if (!clk)
return;
if (!clk->usage_count) {
WARN_ON(1);
return;
}
clk->usage_count--;
if (clk->usage_count == 0) {
/*
* Surely, there are no active childrens or direct users
* of this clock
*/
if (clk->pclk)
do_clk_disable(clk->pclk);
if (clk->ops && clk->ops->disable)
clk->ops->disable(clk);
}
}
static int do_clk_enable(struct clk *clk)
{
int ret = 0;
if (!clk)
return -EFAULT;
if (clk->usage_count == 0) {
if (clk->pclk) {
ret = do_clk_enable(clk->pclk);
if (ret)
goto err;
}
if (clk->ops && clk->ops->enable) {
ret = clk->ops->enable(clk);
if (ret) {
if (clk->pclk)
do_clk_disable(clk->pclk);
goto err;
}
}
/*
* Since the clock is going to be used for the first
* time please reclac
*/
if (clk->recalc) {
ret = clk->recalc(clk);
if (ret)
goto err;
}
}
clk->usage_count++;
err:
return ret;
}
/*
* clk_enable - inform the system when the clock source should be running.
* @clk: clock source
*
* If the clock can not be enabled/disabled, this should return success.
*
* Returns success (0) or negative errno.
*/
int clk_enable(struct clk *clk)
{
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&clocks_lock, flags);
ret = do_clk_enable(clk);
spin_unlock_irqrestore(&clocks_lock, flags);
return ret;
}
EXPORT_SYMBOL(clk_enable);
/*
* clk_disable - inform the system when the clock source is no longer required.
* @clk: clock source
*
* Inform the system that a clock source is no longer required by
* a driver and may be shut down.
*
* Implementation detail: if the clock source is shared between
* multiple drivers, clk_enable() calls must be balanced by the
* same number of clk_disable() calls for the clock source to be
* disabled.
*/
void clk_disable(struct clk *clk)
{
unsigned long flags;
spin_lock_irqsave(&clocks_lock, flags);
do_clk_disable(clk);
spin_unlock_irqrestore(&clocks_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
/**
* clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
* This is only valid once the clock source has been enabled.
* @clk: clock source
*/
unsigned long clk_get_rate(struct clk *clk)
{
unsigned long flags, rate;
spin_lock_irqsave(&clocks_lock, flags);
rate = clk->rate;
spin_unlock_irqrestore(&clocks_lock, flags);
return rate;
}
EXPORT_SYMBOL(clk_get_rate);
/**
* clk_set_parent - set the parent clock source for this clock
* @clk: clock source
* @parent: parent clock source
*
* Returns success (0) or negative errno.
*/
int clk_set_parent(struct clk *clk, struct clk *parent)
{
int i, found = 0, val = 0;
unsigned long flags;
if (!clk || !parent)
return -EFAULT;
if (clk->pclk == parent)
return 0;
if (!clk->pclk_sel)
return -EPERM;
/* check if requested parent is in clk parent list */
for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
if (clk->pclk_sel->pclk_info[i].pclk == parent) {
found = 1;
break;
}
}
if (!found)
return -EINVAL;
spin_lock_irqsave(&clocks_lock, flags);
/* reflect parent change in hardware */
val = readl(clk->pclk_sel->pclk_sel_reg);
val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift);
val |= clk->pclk_sel->pclk_info[i].pclk_val << clk->pclk_sel_shift;
writel(val, clk->pclk_sel->pclk_sel_reg);
spin_unlock_irqrestore(&clocks_lock, flags);
/* reflect parent change in software */
clk_reparent(clk, &clk->pclk_sel->pclk_info[i]);
propagate_rate(clk, 0);
return 0;
}
EXPORT_SYMBOL(clk_set_parent);
/**
* clk_set_rate - set the clock rate for a clock source
* @clk: clock source
* @rate: desired clock rate in Hz
*
* Returns success (0) or negative errno.
*/
int clk_set_rate(struct clk *clk, unsigned long rate)
{
unsigned long flags;
int ret = -EINVAL;
if (!clk || !rate)
return -EFAULT;
if (clk->set_rate) {
spin_lock_irqsave(&clocks_lock, flags);
ret = clk->set_rate(clk, rate);
if (!ret)
/* if successful -> propagate */
propagate_rate(clk, 0);
spin_unlock_irqrestore(&clocks_lock, flags);
} else if (clk->pclk) {
u32 mult = clk->div_factor ? clk->div_factor : 1;
ret = clk_set_rate(clk->pclk, mult * rate);
}
return ret;
}
EXPORT_SYMBOL(clk_set_rate);
/* registers clock in platform clock framework */
void clk_register(struct clk_lookup *cl)
{
struct clk *clk;
unsigned long flags;
if (!cl || !cl->clk)
return;
clk = cl->clk;
spin_lock_irqsave(&clocks_lock, flags);
INIT_LIST_HEAD(&clk->children);
if (clk->flags & ALWAYS_ENABLED)
clk->ops = NULL;
else if (!clk->ops)
clk->ops = &generic_clkops;
/* root clock don't have any parents */
if (!clk->pclk && !clk->pclk_sel) {
list_add(&clk->sibling, &root_clks);
} else if (clk->pclk && !clk->pclk_sel) {
/* add clocks with only one parent to parent's children list */
list_add(&clk->sibling, &clk->pclk->children);
} else {
/* clocks with more than one parent */
struct pclk_info *pclk_info;
pclk_info = pclk_info_get(clk);
if (!pclk_info) {
pr_err("CLKDEV: invalid pclk info of clk with"
" %s dev_id and %s con_id\n",
cl->dev_id, cl->con_id);
} else {
clk->pclk = pclk_info->pclk;
list_add(&clk->sibling, &pclk_info->pclk->children);
}
}
spin_unlock_irqrestore(&clocks_lock, flags);
/* debugfs specific */
#ifdef CONFIG_DEBUG_FS
list_add(&clk->node, &clocks);
clk->cl = cl;
#endif
/* add clock to arm clockdev framework */
clkdev_add(cl);
}
/**
* propagate_rate - recalculate and propagate all clocks to children
* @pclk: parent clock required to be propogated
* @on_init: flag for enabling clocks which are ENABLED_ON_INIT.
*
* Recalculates all children clocks
*/
void propagate_rate(struct clk *pclk, int on_init)
{
struct clk *clk, *_temp;
int ret = 0;
list_for_each_entry_safe(clk, _temp, &pclk->children, sibling) {
if (clk->recalc) {
ret = clk->recalc(clk);
/*
* recalc will return error if clk out is not programmed
* In this case configure default rate.
*/
if (ret && clk->set_rate)
clk->set_rate(clk, 0);
}
propagate_rate(clk, on_init);
if (!on_init)
continue;
/* Enable clks enabled on init, in software view */
if (clk->flags & ENABLED_ON_INIT)
do_clk_enable(clk);
}
}
/**
* round_rate_index - return closest programmable rate index in rate_config tbl
* @clk: ptr to clock structure
* @drate: desired rate
* @rate: final rate will be returned in this variable only.
*
* Finds index in rate_config for highest clk rate which is less than
* requested rate. If there is no clk rate lesser than requested rate then
* -EINVAL is returned. This routine assumes that rate_config is written
* in incrementing order of clk rates.
* If drate passed is zero then default rate is programmed.
*/
static int
round_rate_index(struct clk *clk, unsigned long drate, unsigned long *rate)
{
unsigned long tmp = 0, prev_rate = 0;
int index;
if (!clk->calc_rate)
return -EFAULT;
if (!drate)
return -EINVAL;
/*
* This loops ends on two conditions:
* - as soon as clk is found with rate greater than requested rate.
* - if all clks in rate_config are smaller than requested rate.
*/
for (index = 0; index < clk->rate_config.count; index++) {
prev_rate = tmp;
tmp = clk->calc_rate(clk, index);
if (drate < tmp) {
index--;
break;
}
}
/* return if can't find suitable clock */
if (index < 0) {
index = -EINVAL;
*rate = 0;
} else if (index == clk->rate_config.count) {
/* program with highest clk rate possible */
index = clk->rate_config.count - 1;
*rate = tmp;
} else
*rate = prev_rate;
return index;
}
/**
* clk_round_rate - adjust a rate to the exact rate a clock can provide
* @clk: clock source
* @rate: desired clock rate in Hz
*
* Returns rounded clock rate in Hz, or negative errno.
*/
long clk_round_rate(struct clk *clk, unsigned long drate)
{
long rate = 0;
int index;
/*
* propagate call to parent who supports calc_rate. Similar approach is
* used in clk_set_rate.
*/
if (!clk->calc_rate) {
u32 mult;
if (!clk->pclk)
return clk->rate;
mult = clk->div_factor ? clk->div_factor : 1;
return clk_round_rate(clk->pclk, mult * drate) / mult;
}
index = round_rate_index(clk, drate, &rate);
if (index >= 0)
return rate;
else
return index;
}
EXPORT_SYMBOL(clk_round_rate);
/*All below functions are called with lock held */
/*
* Calculates pll clk rate for specific value of mode, m, n and p
*
* In normal mode
* rate = (2 * M[15:8] * Fin)/(N * 2^P)
*
* In Dithered mode
* rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
*/
unsigned long pll_calc_rate(struct clk *clk, int index)
{
unsigned long rate = clk->pclk->rate;
struct pll_rate_tbl *tbls = clk->rate_config.tbls;
unsigned int mode;
mode = tbls[index].mode ? 256 : 1;
return (((2 * rate / 10000) * tbls[index].m) /
(mode * tbls[index].n * (1 << tbls[index].p))) * 10000;
}
/*
* calculates current programmed rate of pll1
*
* In normal mode
* rate = (2 * M[15:8] * Fin)/(N * 2^P)
*
* In Dithered mode
* rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
*/
int pll_clk_recalc(struct clk *clk)
{
struct pll_clk_config *config = clk->private_data;
unsigned int num = 2, den = 0, val, mode = 0;
mode = (readl(config->mode_reg) >> config->masks->mode_shift) &
config->masks->mode_mask;
val = readl(config->cfg_reg);
/* calculate denominator */
den = (val >> config->masks->div_p_shift) & config->masks->div_p_mask;
den = 1 << den;
den *= (val >> config->masks->div_n_shift) & config->masks->div_n_mask;
/* calculate numerator & denominator */
if (!mode) {
/* Normal mode */
num *= (val >> config->masks->norm_fdbk_m_shift) &
config->masks->norm_fdbk_m_mask;
} else {
/* Dithered mode */
num *= (val >> config->masks->dith_fdbk_m_shift) &
config->masks->dith_fdbk_m_mask;
den *= 256;
}
if (!den)
return -EINVAL;
clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
return 0;
}
/*
* Configures new clock rate of pll
*/
int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate)
{
struct pll_rate_tbl *tbls = clk->rate_config.tbls;
struct pll_clk_config *config = clk->private_data;
unsigned long val, rate;
int i;
i = round_rate_index(clk, desired_rate, &rate);
if (i < 0)
return i;
val = readl(config->mode_reg) &
~(config->masks->mode_mask << config->masks->mode_shift);
val |= (tbls[i].mode & config->masks->mode_mask) <<
config->masks->mode_shift;
writel(val, config->mode_reg);
val = readl(config->cfg_reg) &
~(config->masks->div_p_mask << config->masks->div_p_shift);
val |= (tbls[i].p & config->masks->div_p_mask) <<
config->masks->div_p_shift;
val &= ~(config->masks->div_n_mask << config->masks->div_n_shift);
val |= (tbls[i].n & config->masks->div_n_mask) <<
config->masks->div_n_shift;
val &= ~(config->masks->dith_fdbk_m_mask <<
config->masks->dith_fdbk_m_shift);
if (tbls[i].mode)
val |= (tbls[i].m & config->masks->dith_fdbk_m_mask) <<
config->masks->dith_fdbk_m_shift;
else
val |= (tbls[i].m & config->masks->norm_fdbk_m_mask) <<
config->masks->norm_fdbk_m_shift;
writel(val, config->cfg_reg);
clk->rate = rate;
return 0;
}
/*
* Calculates ahb, apb clk rate for specific value of div
*/
unsigned long bus_calc_rate(struct clk *clk, int index)
{
unsigned long rate = clk->pclk->rate;
struct bus_rate_tbl *tbls = clk->rate_config.tbls;
return rate / (tbls[index].div + 1);
}
/* calculates current programmed rate of ahb or apb bus */
int bus_clk_recalc(struct clk *clk)
{
struct bus_clk_config *config = clk->private_data;
unsigned int div;
div = ((readl(config->reg) >> config->masks->shift) &
config->masks->mask) + 1;
if (!div)
return -EINVAL;
clk->rate = (unsigned long)clk->pclk->rate / div;
return 0;
}
/* Configures new clock rate of AHB OR APB bus */
int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate)
{
struct bus_rate_tbl *tbls = clk->rate_config.tbls;
struct bus_clk_config *config = clk->private_data;
unsigned long val, rate;
int i;
i = round_rate_index(clk, desired_rate, &rate);
if (i < 0)
return i;
val = readl(config->reg) &
~(config->masks->mask << config->masks->shift);
val |= (tbls[i].div & config->masks->mask) << config->masks->shift;
writel(val, config->reg);
clk->rate = rate;
return 0;
}
/*
* gives rate for different values of eq, x and y
*
* Fout from synthesizer can be given from two equations:
* Fout1 = (Fin * X/Y)/2 EQ1
* Fout2 = Fin * X/Y EQ2
*/
unsigned long aux_calc_rate(struct clk *clk, int index)
{
unsigned long rate = clk->pclk->rate;
struct aux_rate_tbl *tbls = clk->rate_config.tbls;
u8 eq = tbls[index].eq ? 1 : 2;
return (((rate/10000) * tbls[index].xscale) /
(tbls[index].yscale * eq)) * 10000;
}
/*
* calculates current programmed rate of auxiliary synthesizers
* used by: UART, FIRDA
*
* Fout from synthesizer can be given from two equations:
* Fout1 = (Fin * X/Y)/2
* Fout2 = Fin * X/Y
*
* Selection of eqn 1 or 2 is programmed in register
*/
int aux_clk_recalc(struct clk *clk)
{
struct aux_clk_config *config = clk->private_data;
unsigned int num = 1, den = 1, val, eqn;
val = readl(config->synth_reg);
eqn = (val >> config->masks->eq_sel_shift) &
config->masks->eq_sel_mask;
if (eqn == config->masks->eq1_mask)
den *= 2;
/* calculate numerator */
num = (val >> config->masks->xscale_sel_shift) &
config->masks->xscale_sel_mask;
/* calculate denominator */
den *= (val >> config->masks->yscale_sel_shift) &
config->masks->yscale_sel_mask;
if (!den)
return -EINVAL;
clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
return 0;
}
/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/
int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate)
{
struct aux_rate_tbl *tbls = clk->rate_config.tbls;
struct aux_clk_config *config = clk->private_data;
unsigned long val, rate;
int i;
i = round_rate_index(clk, desired_rate, &rate);
if (i < 0)
return i;
val = readl(config->synth_reg) &
~(config->masks->eq_sel_mask << config->masks->eq_sel_shift);
val |= (tbls[i].eq & config->masks->eq_sel_mask) <<
config->masks->eq_sel_shift;
val &= ~(config->masks->xscale_sel_mask <<
config->masks->xscale_sel_shift);
val |= (tbls[i].xscale & config->masks->xscale_sel_mask) <<
config->masks->xscale_sel_shift;
val &= ~(config->masks->yscale_sel_mask <<
config->masks->yscale_sel_shift);
val |= (tbls[i].yscale & config->masks->yscale_sel_mask) <<
config->masks->yscale_sel_shift;
writel(val, config->synth_reg);
clk->rate = rate;
return 0;
}
/*
* Calculates gpt clk rate for different values of mscale and nscale
*
* Fout= Fin/((2 ^ (N+1)) * (M+1))
*/
unsigned long gpt_calc_rate(struct clk *clk, int index)
{
unsigned long rate = clk->pclk->rate;
struct gpt_rate_tbl *tbls = clk->rate_config.tbls;
return rate / ((1 << (tbls[index].nscale + 1)) *
(tbls[index].mscale + 1));
}
/*
* calculates current programmed rate of gpt synthesizers
* Fout from synthesizer can be given from below equations:
* Fout= Fin/((2 ^ (N+1)) * (M+1))
*/
int gpt_clk_recalc(struct clk *clk)
{
struct gpt_clk_config *config = clk->private_data;
unsigned int div = 1, val;
val = readl(config->synth_reg);
div += (val >> config->masks->mscale_sel_shift) &
config->masks->mscale_sel_mask;
div *= 1 << (((val >> config->masks->nscale_sel_shift) &
config->masks->nscale_sel_mask) + 1);
if (!div)
return -EINVAL;
clk->rate = (unsigned long)clk->pclk->rate / div;
return 0;
}
/* Configures new clock rate of gptiliary synthesizers used by: UART, FIRDA*/
int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate)
{
struct gpt_rate_tbl *tbls = clk->rate_config.tbls;
struct gpt_clk_config *config = clk->private_data;
unsigned long val, rate;
int i;
i = round_rate_index(clk, desired_rate, &rate);
if (i < 0)
return i;
val = readl(config->synth_reg) & ~(config->masks->mscale_sel_mask <<
config->masks->mscale_sel_shift);
val |= (tbls[i].mscale & config->masks->mscale_sel_mask) <<
config->masks->mscale_sel_shift;
val &= ~(config->masks->nscale_sel_mask <<
config->masks->nscale_sel_shift);
val |= (tbls[i].nscale & config->masks->nscale_sel_mask) <<
config->masks->nscale_sel_shift;
writel(val, config->synth_reg);
clk->rate = rate;
return 0;
}
/*
* Calculates clcd clk rate for different values of div
*
* Fout from synthesizer can be given from below equation:
* Fout= Fin/2*div (division factor)
* div is 17 bits:-
* 0-13 (fractional part)
* 14-16 (integer part)
* To calculate Fout we left shift val by 14 bits and divide Fin by
* complete div (including fractional part) and then right shift the
* result by 14 places.
*/
unsigned long clcd_calc_rate(struct clk *clk, int index)
{
unsigned long rate = clk->pclk->rate;
struct clcd_rate_tbl *tbls = clk->rate_config.tbls;
rate /= 1000;
rate <<= 12;
rate /= (2 * tbls[index].div);
rate >>= 12;
rate *= 1000;
return rate;
}
/*
* calculates current programmed rate of clcd synthesizer
* Fout from synthesizer can be given from below equation:
* Fout= Fin/2*div (division factor)
* div is 17 bits:-
* 0-13 (fractional part)
* 14-16 (integer part)
* To calculate Fout we left shift val by 14 bits and divide Fin by
* complete div (including fractional part) and then right shift the
* result by 14 places.
*/
int clcd_clk_recalc(struct clk *clk)
{
struct clcd_clk_config *config = clk->private_data;
unsigned int div = 1;
unsigned long prate;
unsigned int val;
val = readl(config->synth_reg);
div = (val >> config->masks->div_factor_shift) &
config->masks->div_factor_mask;
if (!div)
return -EINVAL;
prate = clk->pclk->rate / 1000; /* first level division, make it KHz */
clk->rate = (((unsigned long)prate << 12) / (2 * div)) >> 12;
clk->rate *= 1000;
return 0;
}
/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/
int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate)
{
struct clcd_rate_tbl *tbls = clk->rate_config.tbls;
struct clcd_clk_config *config = clk->private_data;
unsigned long val, rate;
int i;
i = round_rate_index(clk, desired_rate, &rate);
if (i < 0)
return i;
val = readl(config->synth_reg) & ~(config->masks->div_factor_mask <<
config->masks->div_factor_shift);
val |= (tbls[i].div & config->masks->div_factor_mask) <<
config->masks->div_factor_shift;
writel(val, config->synth_reg);
clk->rate = rate;
return 0;
}
/*
* Used for clocks that always have value as the parent clock divided by a
* fixed divisor
*/
int follow_parent(struct clk *clk)
{
unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor;
clk->rate = clk->pclk->rate/div_factor;
return 0;
}
/**
* recalc_root_clocks - recalculate and propagate all root clocks
*
* Recalculates all root clocks (clocks with no parent), which if the
* clock's .recalc is set correctly, should also propagate their rates.
*/
void recalc_root_clocks(void)
{
struct clk *pclk;
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&clocks_lock, flags);
list_for_each_entry(pclk, &root_clks, sibling) {
if (pclk->recalc) {
ret = pclk->recalc(pclk);
/*
* recalc will return error if clk out is not programmed
* In this case configure default clock.
*/
if (ret && pclk->set_rate)
pclk->set_rate(pclk, 0);
}
propagate_rate(pclk, 1);
/* Enable clks enabled on init, in software view */
if (pclk->flags & ENABLED_ON_INIT)
do_clk_enable(pclk);
}
spin_unlock_irqrestore(&clocks_lock, flags);
}
void __init clk_init(void)
{
recalc_root_clocks();
}
#ifdef CONFIG_DEBUG_FS
/*
* debugfs support to trace clock tree hierarchy and attributes
*/
static struct dentry *clk_debugfs_root;
static int clk_debugfs_register_one(struct clk *c)
{
int err;
struct dentry *d;
struct clk *pa = c->pclk;
char s[255];
char *p = s;
if (c) {
if (c->cl->con_id)
p += sprintf(p, "%s", c->cl->con_id);
if (c->cl->dev_id)
p += sprintf(p, "%s", c->cl->dev_id);
}
d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
if (!d)
return -ENOMEM;
c->dent = d;
d = debugfs_create_u32("usage_count", S_IRUGO, c->dent,
(u32 *)&c->usage_count);
if (!d) {
err = -ENOMEM;
goto err_out;
}
d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
if (!d) {
err = -ENOMEM;
goto err_out;
}
d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
if (!d) {
err = -ENOMEM;
goto err_out;
}
return 0;
err_out:
debugfs_remove_recursive(c->dent);
return err;
}
static int clk_debugfs_register(struct clk *c)
{
int err;
struct clk *pa = c->pclk;
if (pa && !pa->dent) {
err = clk_debugfs_register(pa);
if (err)
return err;
}
if (!c->dent) {
err = clk_debugfs_register_one(c);
if (err)
return err;
}
return 0;
}
static int __init clk_debugfs_init(void)
{
struct clk *c;
struct dentry *d;
int err;
d = debugfs_create_dir("clock", NULL);
if (!d)
return -ENOMEM;
clk_debugfs_root = d;
list_for_each_entry(c, &clocks, node) {
err = clk_debugfs_register(c);
if (err)
goto err_out;
}
return 0;
err_out:
debugfs_remove_recursive(clk_debugfs_root);
return err;
}
late_initcall(clk_debugfs_init);
static int clk_debugfs_reparent(struct clk *c)
{
debugfs_remove(c->dent);
return clk_debugfs_register_one(c);
}
#endif /* CONFIG_DEBUG_FS */
/*
* arch/arm/plat-spear/include/plat/clock.h
*
* Clock framework definitions for SPEAr platform
*
* Copyright (C) 2009 ST Microelectronics
* Viresh Kumar<viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#ifndef __PLAT_CLOCK_H
#define __PLAT_CLOCK_H
#include <linux/list.h>
#include <linux/clkdev.h>
#include <linux/types.h>
/* clk structure flags */
#define ALWAYS_ENABLED (1 << 0) /* clock always enabled */
#define RESET_TO_ENABLE (1 << 1) /* reset register bit to enable clk */
#define ENABLED_ON_INIT (1 << 2) /* clocks enabled at init */
/**
* struct clkops - clock operations
* @enable: pointer to clock enable function
* @disable: pointer to clock disable function
*/
struct clkops {
int (*enable) (struct clk *);
void (*disable) (struct clk *);
};
/**
* struct pclk_info - parents info
* @pclk: pointer to parent clk
* @pclk_val: value to be written for selecting this parent
*/
struct pclk_info {
struct clk *pclk;
u8 pclk_val;
};
/**
* struct pclk_sel - parents selection configuration
* @pclk_info: pointer to array of parent clock info
* @pclk_count: number of parents
* @pclk_sel_reg: register for selecting a parent
* @pclk_sel_mask: mask for selecting parent (can be used to clear bits also)
*/
struct pclk_sel {
struct pclk_info *pclk_info;
u8 pclk_count;
void __iomem *pclk_sel_reg;
unsigned int pclk_sel_mask;
};
/**
* struct rate_config - clk rate configurations
* @tbls: array of device specific clk rate tables, in ascending order of rates
* @count: size of tbls array
* @default_index: default setting when originally disabled
*/
struct rate_config {
void *tbls;
u8 count;
u8 default_index;
};
/**
* struct clk - clock structure
* @usage_count: num of users who enabled this clock
* @flags: flags for clock properties
* @rate: programmed clock rate in Hz
* @en_reg: clk enable/disable reg
* @en_reg_bit: clk enable/disable bit
* @ops: clk enable/disable ops - generic_clkops selected if NULL
* @recalc: pointer to clock rate recalculate function
* @set_rate: pointer to clock set rate function
* @calc_rate: pointer to clock get rate function for index
* @rate_config: rate configuration information, used by set_rate
* @div_factor: division factor to parent clock.
* @pclk: current parent clk
* @pclk_sel: pointer to parent selection structure
* @pclk_sel_shift: register shift for selecting parent of this clock
* @children: list for childrens or this clock
* @sibling: node for list of clocks having same parents
* @private_data: clock specific private data
* @node: list to maintain clocks linearly
* @cl: clocklook up associated with this clock
* @dent: object for debugfs
*/
struct clk {
unsigned int usage_count;
unsigned int flags;
unsigned long rate;
void __iomem *en_reg;
u8 en_reg_bit;
const struct clkops *ops;
int (*recalc) (struct clk *);
int (*set_rate) (struct clk *, unsigned long rate);
unsigned long (*calc_rate)(struct clk *, int index);
struct rate_config rate_config;
unsigned int div_factor;
struct clk *pclk;
struct pclk_sel *pclk_sel;
unsigned int pclk_sel_shift;
struct list_head children;
struct list_head sibling;
void *private_data;
#ifdef CONFIG_DEBUG_FS
struct list_head node;
struct clk_lookup *cl;
struct dentry *dent;
#endif
};
/* pll configuration structure */
struct pll_clk_masks {
u32 mode_mask;
u32 mode_shift;
u32 norm_fdbk_m_mask;
u32 norm_fdbk_m_shift;
u32 dith_fdbk_m_mask;
u32 dith_fdbk_m_shift;
u32 div_p_mask;
u32 div_p_shift;
u32 div_n_mask;
u32 div_n_shift;
};
struct pll_clk_config {
void __iomem *mode_reg;
void __iomem *cfg_reg;
struct pll_clk_masks *masks;
};
/* pll clk rate config structure */
struct pll_rate_tbl {
u8 mode;
u16 m;
u8 n;
u8 p;
};
/* ahb and apb bus configuration structure */
struct bus_clk_masks {
u32 mask;
u32 shift;
};
struct bus_clk_config {
void __iomem *reg;
struct bus_clk_masks *masks;
};
/* ahb and apb clk bus rate config structure */
struct bus_rate_tbl {
u8 div;
};
/* Aux clk configuration structure: applicable to UART and FIRDA */
struct aux_clk_masks {
u32 eq_sel_mask;
u32 eq_sel_shift;
u32 eq1_mask;
u32 eq2_mask;
u32 xscale_sel_mask;
u32 xscale_sel_shift;
u32 yscale_sel_mask;
u32 yscale_sel_shift;
};
struct aux_clk_config {
void __iomem *synth_reg;
struct aux_clk_masks *masks;
};
/* aux clk rate config structure */
struct aux_rate_tbl {
u16 xscale;
u16 yscale;
u8 eq;
};
/* GPT clk configuration structure */
struct gpt_clk_masks {
u32 mscale_sel_mask;
u32 mscale_sel_shift;
u32 nscale_sel_mask;
u32 nscale_sel_shift;
};
struct gpt_clk_config {
void __iomem *synth_reg;
struct gpt_clk_masks *masks;
};
/* gpt clk rate config structure */
struct gpt_rate_tbl {
u16 mscale;
u16 nscale;
};
/* clcd clk configuration structure */
struct clcd_synth_masks {
u32 div_factor_mask;
u32 div_factor_shift;
};
struct clcd_clk_config {
void __iomem *synth_reg;
struct clcd_synth_masks *masks;
};
/* clcd clk rate config structure */
struct clcd_rate_tbl {
u16 div;
};
/* platform specific clock functions */
void __init clk_init(void);
void clk_register(struct clk_lookup *cl);
void recalc_root_clocks(void);
/* clock recalc & set rate functions */
int follow_parent(struct clk *clk);
unsigned long pll_calc_rate(struct clk *clk, int index);
int pll_clk_recalc(struct clk *clk);
int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate);
unsigned long bus_calc_rate(struct clk *clk, int index);
int bus_clk_recalc(struct clk *clk);
int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate);
unsigned long gpt_calc_rate(struct clk *clk, int index);
int gpt_clk_recalc(struct clk *clk);
int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate);
unsigned long aux_calc_rate(struct clk *clk, int index);
int aux_clk_recalc(struct clk *clk);
int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate);
unsigned long clcd_calc_rate(struct clk *clk, int index);
int clcd_clk_recalc(struct clk *clk);
int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate);
#endif /* __PLAT_CLOCK_H */
......@@ -3,3 +3,6 @@
#
obj-y += clk.o clk-aux-synth.o clk-frac-synth.o clk-gpt-synth.o clk-vco-pll.o
obj-$(CONFIG_ARCH_SPEAR3XX) += spear3xx_clock.o
obj-$(CONFIG_ARCH_SPEAR6XX) += spear6xx_clock.o
/*
* SPEAr3xx machines clock framework source file
*
* Copyright (C) 2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of_platform.h>
#include <linux/spinlock_types.h>
#include <mach/misc_regs.h>
#include "clk.h"
static DEFINE_SPINLOCK(_lock);
#define PLL1_CTR (MISC_BASE + 0x008)
#define PLL1_FRQ (MISC_BASE + 0x00C)
#define PLL2_CTR (MISC_BASE + 0x014)
#define PLL2_FRQ (MISC_BASE + 0x018)
#define PLL_CLK_CFG (MISC_BASE + 0x020)
/* PLL_CLK_CFG register masks */
#define MCTR_CLK_SHIFT 28
#define MCTR_CLK_MASK 3
#define CORE_CLK_CFG (MISC_BASE + 0x024)
/* CORE CLK CFG register masks */
#define GEN_SYNTH2_3_CLK_SHIFT 18
#define GEN_SYNTH2_3_CLK_MASK 1
#define HCLK_RATIO_SHIFT 10
#define HCLK_RATIO_MASK 2
#define PCLK_RATIO_SHIFT 8
#define PCLK_RATIO_MASK 2
#define PERIP_CLK_CFG (MISC_BASE + 0x028)
/* PERIP_CLK_CFG register masks */
#define UART_CLK_SHIFT 4
#define UART_CLK_MASK 1
#define FIRDA_CLK_SHIFT 5
#define FIRDA_CLK_MASK 2
#define GPT0_CLK_SHIFT 8
#define GPT1_CLK_SHIFT 11
#define GPT2_CLK_SHIFT 12
#define GPT_CLK_MASK 1
#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
/* PERIP1_CLK_ENB register masks */
#define UART_CLK_ENB 3
#define SSP_CLK_ENB 5
#define I2C_CLK_ENB 7
#define JPEG_CLK_ENB 8
#define FIRDA_CLK_ENB 10
#define GPT1_CLK_ENB 11
#define GPT2_CLK_ENB 12
#define ADC_CLK_ENB 15
#define RTC_CLK_ENB 17
#define GPIO_CLK_ENB 18
#define DMA_CLK_ENB 19
#define SMI_CLK_ENB 21
#define GMAC_CLK_ENB 23
#define USBD_CLK_ENB 24
#define USBH_CLK_ENB 25
#define C3_CLK_ENB 31
#define RAS_CLK_ENB (MISC_BASE + 0x034)
#define RAS_AHB_CLK_ENB 0
#define RAS_PLL1_CLK_ENB 1
#define RAS_APB_CLK_ENB 2
#define RAS_32K_CLK_ENB 3
#define RAS_24M_CLK_ENB 4
#define RAS_48M_CLK_ENB 5
#define RAS_PLL2_CLK_ENB 7
#define RAS_SYNT0_CLK_ENB 8
#define RAS_SYNT1_CLK_ENB 9
#define RAS_SYNT2_CLK_ENB 10
#define RAS_SYNT3_CLK_ENB 11
#define PRSC0_CLK_CFG (MISC_BASE + 0x044)
#define PRSC1_CLK_CFG (MISC_BASE + 0x048)
#define PRSC2_CLK_CFG (MISC_BASE + 0x04C)
#define AMEM_CLK_CFG (MISC_BASE + 0x050)
#define AMEM_CLK_ENB 0
#define CLCD_CLK_SYNT (MISC_BASE + 0x05C)
#define FIRDA_CLK_SYNT (MISC_BASE + 0x060)
#define UART_CLK_SYNT (MISC_BASE + 0x064)
#define GMAC_CLK_SYNT (MISC_BASE + 0x068)
#define GEN0_CLK_SYNT (MISC_BASE + 0x06C)
#define GEN1_CLK_SYNT (MISC_BASE + 0x070)
#define GEN2_CLK_SYNT (MISC_BASE + 0x074)
#define GEN3_CLK_SYNT (MISC_BASE + 0x078)
/* pll rate configuration table, in ascending order of rates */
static struct pll_rate_tbl pll_rtbl[] = {
{.mode = 0, .m = 0x53, .n = 0x0C, .p = 0x1}, /* vco 332 & pll 166 MHz */
{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* vco 532 & pll 266 MHz */
{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* vco 664 & pll 332 MHz */
};
/* aux rate configuration table, in ascending order of rates */
static struct aux_rate_tbl aux_rtbl[] = {
/* For PLL1 = 332 MHz */
{.xscale = 2, .yscale = 27, .eq = 0}, /* 12.296 MHz */
{.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */
{.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */
{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
};
/* gpt rate configuration table, in ascending order of rates */
static struct gpt_rate_tbl gpt_rtbl[] = {
/* For pll1 = 332 MHz */
{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
{.mscale = 1, .nscale = 0}, /* 83 MHz */
};
/* clock parents */
static const char *uart0_parents[] = { "pll3_48m_clk", "uart_synth_gate_clk", };
static const char *firda_parents[] = { "pll3_48m_clk", "firda_synth_gate_clk",
};
static const char *gpt0_parents[] = { "pll3_48m_clk", "gpt0_synth_clk", };
static const char *gpt1_parents[] = { "pll3_48m_clk", "gpt1_synth_clk", };
static const char *gpt2_parents[] = { "pll3_48m_clk", "gpt2_synth_clk", };
static const char *gen2_3_parents[] = { "pll1_clk", "pll2_clk", };
static const char *ddr_parents[] = { "ahb_clk", "ahbmult2_clk", "none",
"pll2_clk", };
#ifdef CONFIG_MACH_SPEAR300
static void __init spear300_clk_init(void)
{
struct clk *clk;
clk = clk_register_fixed_factor(NULL, "clcd_clk", "ras_pll3_48m_clk", 0,
1, 1);
clk_register_clkdev(clk, NULL, "60000000.clcd");
clk = clk_register_fixed_factor(NULL, "fsmc_clk", "ras_ahb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "94000000.flash");
clk = clk_register_fixed_factor(NULL, "sdhci_clk", "ras_ahb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "70000000.sdhci");
clk = clk_register_fixed_factor(NULL, "gpio1_clk", "ras_apb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "a9000000.gpio");
clk = clk_register_fixed_factor(NULL, "kbd_clk", "ras_apb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "a0000000.kbd");
}
#endif
/* array of all spear 310 clock lookups */
#ifdef CONFIG_MACH_SPEAR310
static void __init spear310_clk_init(void)
{
struct clk *clk;
clk = clk_register_fixed_factor(NULL, "emi_clk", "ras_ahb_clk", 0, 1,
1);
clk_register_clkdev(clk, "emi", NULL);
clk = clk_register_fixed_factor(NULL, "fsmc_clk", "ras_ahb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "44000000.flash");
clk = clk_register_fixed_factor(NULL, "tdm_clk", "ras_ahb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "tdm");
clk = clk_register_fixed_factor(NULL, "uart1_clk", "ras_apb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "b2000000.serial");
clk = clk_register_fixed_factor(NULL, "uart2_clk", "ras_apb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "b2080000.serial");
clk = clk_register_fixed_factor(NULL, "uart3_clk", "ras_apb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "b2100000.serial");
clk = clk_register_fixed_factor(NULL, "uart4_clk", "ras_apb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "b2180000.serial");
clk = clk_register_fixed_factor(NULL, "uart5_clk", "ras_apb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "b2200000.serial");
}
#endif
/* array of all spear 320 clock lookups */
#ifdef CONFIG_MACH_SPEAR320
#define SMII_PCLK_SHIFT 18
#define SMII_PCLK_MASK 2
#define SMII_PCLK_VAL_PAD 0x0
#define SMII_PCLK_VAL_PLL2 0x1
#define SMII_PCLK_VAL_SYNTH0 0x2
#define SDHCI_PCLK_SHIFT 15
#define SDHCI_PCLK_MASK 1
#define SDHCI_PCLK_VAL_48M 0x0
#define SDHCI_PCLK_VAL_SYNTH3 0x1
#define I2S_REF_PCLK_SHIFT 8
#define I2S_REF_PCLK_MASK 1
#define I2S_REF_PCLK_SYNTH_VAL 0x1
#define I2S_REF_PCLK_PLL2_VAL 0x0
#define UART1_PCLK_SHIFT 6
#define UART1_PCLK_MASK 1
#define SPEAR320_UARTX_PCLK_VAL_SYNTH1 0x0
#define SPEAR320_UARTX_PCLK_VAL_APB 0x1
static const char *i2s_ref_parents[] = { "ras_pll2_clk",
"ras_gen2_synth_gate_clk", };
static const char *sdhci_parents[] = { "ras_pll3_48m_clk",
"ras_gen3_synth_gate_clk",
};
static const char *smii0_parents[] = { "smii_125m_pad", "ras_pll2_clk",
"ras_gen0_synth_gate_clk", };
static const char *uartx_parents[] = { "ras_gen1_synth_gate_clk", "ras_apb_clk",
};
static void __init spear320_clk_init(void)
{
struct clk *clk;
clk = clk_register_fixed_rate(NULL, "smii_125m_pad_clk", NULL,
CLK_IS_ROOT, 125000000);
clk_register_clkdev(clk, "smii_125m_pad", NULL);
clk = clk_register_fixed_factor(NULL, "clcd_clk", "ras_pll3_48m_clk", 0,
1, 1);
clk_register_clkdev(clk, NULL, "90000000.clcd");
clk = clk_register_fixed_factor(NULL, "emi_clk", "ras_ahb_clk", 0, 1,
1);
clk_register_clkdev(clk, "emi", NULL);
clk = clk_register_fixed_factor(NULL, "fsmc_clk", "ras_ahb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "4c000000.flash");
clk = clk_register_fixed_factor(NULL, "i2c1_clk", "ras_ahb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "a7000000.i2c");
clk = clk_register_fixed_factor(NULL, "pwm_clk", "ras_ahb_clk", 0, 1,
1);
clk_register_clkdev(clk, "pwm", NULL);
clk = clk_register_fixed_factor(NULL, "ssp1_clk", "ras_ahb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "a5000000.spi");
clk = clk_register_fixed_factor(NULL, "ssp2_clk", "ras_ahb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "a6000000.spi");
clk = clk_register_fixed_factor(NULL, "can0_clk", "ras_apb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "c_can_platform.0");
clk = clk_register_fixed_factor(NULL, "can1_clk", "ras_apb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "c_can_platform.1");
clk = clk_register_fixed_factor(NULL, "i2s_clk", "ras_apb_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "i2s");
clk = clk_register_mux(NULL, "i2s_ref_clk", i2s_ref_parents,
ARRAY_SIZE(i2s_ref_parents), 0, SPEAR320_CONTROL_REG,
I2S_REF_PCLK_SHIFT, I2S_REF_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "i2s_ref_clk", NULL);
clk = clk_register_fixed_factor(NULL, "i2s_sclk", "i2s_ref_clk", 0, 1,
4);
clk_register_clkdev(clk, "i2s_sclk", NULL);
clk = clk_register_mux(NULL, "rs485_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
SPEAR320_RS485_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, NULL, "a9300000.serial");
clk = clk_register_mux(NULL, "sdhci_clk", sdhci_parents,
ARRAY_SIZE(sdhci_parents), 0, SPEAR320_CONTROL_REG,
SDHCI_PCLK_SHIFT, SDHCI_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "70000000.sdhci");
clk = clk_register_mux(NULL, "smii_pclk", smii0_parents,
ARRAY_SIZE(smii0_parents), 0, SPEAR320_CONTROL_REG,
SMII_PCLK_SHIFT, SMII_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "smii_pclk");
clk = clk_register_fixed_factor(NULL, "smii_clk", "smii_pclk", 0, 1, 1);
clk_register_clkdev(clk, NULL, "smii");
clk = clk_register_mux(NULL, "uart1_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), 0, SPEAR320_CONTROL_REG,
UART1_PCLK_SHIFT, UART1_PCLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "a3000000.serial");
clk = clk_register_mux(NULL, "uart2_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
SPEAR320_UART2_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, NULL, "a4000000.serial");
clk = clk_register_mux(NULL, "uart3_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
SPEAR320_UART3_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, NULL, "a9100000.serial");
clk = clk_register_mux(NULL, "uart4_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
SPEAR320_UART4_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, NULL, "a9200000.serial");
clk = clk_register_mux(NULL, "uart5_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
SPEAR320_UART5_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, NULL, "60000000.serial");
clk = clk_register_mux(NULL, "uart6_clk", uartx_parents,
ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
SPEAR320_UART6_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, NULL, "60100000.serial");
}
#endif
void __init spear3xx_clk_init(void)
{
struct clk *clk, *clk1;
clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
clk_register_clkdev(clk, "apb_pclk", NULL);
clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
32000);
clk_register_clkdev(clk, "osc_32k_clk", NULL);
clk = clk_register_fixed_rate(NULL, "osc_24m_clk", NULL, CLK_IS_ROOT,
24000000);
clk_register_clkdev(clk, "osc_24m_clk", NULL);
/* clock derived from 32 KHz osc clk */
clk = clk_register_gate(NULL, "rtc-spear", "osc_32k_clk", 0,
PERIP1_CLK_ENB, RTC_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "fc900000.rtc");
/* clock derived from 24 MHz osc clk */
clk = clk_register_fixed_rate(NULL, "pll3_48m_clk", "osc_24m_clk", 0,
48000000);
clk_register_clkdev(clk, "pll3_48m_clk", NULL);
clk = clk_register_fixed_factor(NULL, "wdt_clk", "osc_24m_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "fc880000.wdt");
clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL,
"osc_24m_clk", 0, PLL1_CTR, PLL1_FRQ, pll_rtbl,
ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
clk_register_clkdev(clk, "vco1_clk", NULL);
clk_register_clkdev(clk1, "pll1_clk", NULL);
clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL,
"osc_24m_clk", 0, PLL2_CTR, PLL2_FRQ, pll_rtbl,
ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
clk_register_clkdev(clk, "vco2_clk", NULL);
clk_register_clkdev(clk1, "pll2_clk", NULL);
/* clock derived from pll1 clk */
clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 1);
clk_register_clkdev(clk, "cpu_clk", NULL);
clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk",
CLK_SET_RATE_PARENT, CORE_CLK_CFG, HCLK_RATIO_SHIFT,
HCLK_RATIO_MASK, 0, &_lock);
clk_register_clkdev(clk, "ahb_clk", NULL);
clk = clk_register_aux("uart_synth_clk", "uart_synth_gate_clk",
"pll1_clk", 0, UART_CLK_SYNT, NULL, aux_rtbl,
ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
clk_register_clkdev(clk, "uart_synth_clk", NULL);
clk_register_clkdev(clk1, "uart_synth_gate_clk", NULL);
clk = clk_register_mux(NULL, "uart0_mux_clk", uart0_parents,
ARRAY_SIZE(uart0_parents), 0, PERIP_CLK_CFG,
UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart0_mux_clk", NULL);
clk = clk_register_gate(NULL, "uart0", "uart0_mux_clk", 0,
PERIP1_CLK_ENB, UART_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "d0000000.serial");
clk = clk_register_aux("firda_synth_clk", "firda_synth_gate_clk",
"pll1_clk", 0, FIRDA_CLK_SYNT, NULL, aux_rtbl,
ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
clk_register_clkdev(clk, "firda_synth_clk", NULL);
clk_register_clkdev(clk1, "firda_synth_gate_clk", NULL);
clk = clk_register_mux(NULL, "firda_mux_clk", firda_parents,
ARRAY_SIZE(firda_parents), 0, PERIP_CLK_CFG,
FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "firda_mux_clk", NULL);
clk = clk_register_gate(NULL, "firda_clk", "firda_mux_clk", 0,
PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "firda");
/* gpt clocks */
clk_register_gpt("gpt0_synth_clk", "pll1_clk", 0, PRSC0_CLK_CFG,
gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
clk = clk_register_mux(NULL, "gpt0_clk", gpt0_parents,
ARRAY_SIZE(gpt0_parents), 0, PERIP_CLK_CFG,
GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "gpt0");
clk_register_gpt("gpt1_synth_clk", "pll1_clk", 0, PRSC1_CLK_CFG,
gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
clk = clk_register_mux(NULL, "gpt1_mux_clk", gpt1_parents,
ARRAY_SIZE(gpt1_parents), 0, PERIP_CLK_CFG,
GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt1_mux_clk", NULL);
clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mux_clk", 0,
PERIP1_CLK_ENB, GPT1_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "gpt1");
clk_register_gpt("gpt2_synth_clk", "pll1_clk", 0, PRSC2_CLK_CFG,
gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
clk = clk_register_mux(NULL, "gpt2_mux_clk", gpt2_parents,
ARRAY_SIZE(gpt2_parents), 0, PERIP_CLK_CFG,
GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt2_mux_clk", NULL);
clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mux_clk", 0,
PERIP1_CLK_ENB, GPT2_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "gpt2");
/* general synths clocks */
clk = clk_register_aux("gen0_synth_clk", "gen0_synth_gate_clk",
"pll1_clk", 0, GEN0_CLK_SYNT, NULL, aux_rtbl,
ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
clk_register_clkdev(clk, "gen0_synth_clk", NULL);
clk_register_clkdev(clk1, "gen0_synth_gate_clk", NULL);
clk = clk_register_aux("gen1_synth_clk", "gen1_synth_gate_clk",
"pll1_clk", 0, GEN1_CLK_SYNT, NULL, aux_rtbl,
ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
clk_register_clkdev(clk, "gen1_synth_clk", NULL);
clk_register_clkdev(clk1, "gen1_synth_gate_clk", NULL);
clk = clk_register_mux(NULL, "gen2_3_parent_clk", gen2_3_parents,
ARRAY_SIZE(gen2_3_parents), 0, CORE_CLK_CFG,
GEN_SYNTH2_3_CLK_SHIFT, GEN_SYNTH2_3_CLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, "gen2_3_parent_clk", NULL);
clk = clk_register_aux("gen2_synth_clk", "gen2_synth_gate_clk",
"gen2_3_parent_clk", 0, GEN2_CLK_SYNT, NULL, aux_rtbl,
ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
clk_register_clkdev(clk, "gen2_synth_clk", NULL);
clk_register_clkdev(clk1, "gen2_synth_gate_clk", NULL);
clk = clk_register_aux("gen3_synth_clk", "gen3_synth_gate_clk",
"gen2_3_parent_clk", 0, GEN3_CLK_SYNT, NULL, aux_rtbl,
ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
clk_register_clkdev(clk, "gen3_synth_clk", NULL);
clk_register_clkdev(clk1, "gen3_synth_gate_clk", NULL);
/* clock derived from pll3 clk */
clk = clk_register_gate(NULL, "usbh_clk", "pll3_48m_clk", 0,
PERIP1_CLK_ENB, USBH_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "usbh_clk", NULL);
clk = clk_register_fixed_factor(NULL, "usbh.0_clk", "usbh_clk", 0, 1,
1);
clk_register_clkdev(clk, "usbh.0_clk", NULL);
clk = clk_register_fixed_factor(NULL, "usbh.1_clk", "usbh_clk", 0, 1,
1);
clk_register_clkdev(clk, "usbh.1_clk", NULL);
clk = clk_register_gate(NULL, "usbd_clk", "pll3_48m_clk", 0,
PERIP1_CLK_ENB, USBD_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "designware_udc");
/* clock derived from ahb clk */
clk = clk_register_fixed_factor(NULL, "ahbmult2_clk", "ahb_clk", 0, 2,
1);
clk_register_clkdev(clk, "ahbmult2_clk", NULL);
clk = clk_register_mux(NULL, "ddr_clk", ddr_parents,
ARRAY_SIZE(ddr_parents), 0, PLL_CLK_CFG, MCTR_CLK_SHIFT,
MCTR_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "ddr_clk", NULL);
clk = clk_register_divider(NULL, "apb_clk", "ahb_clk",
CLK_SET_RATE_PARENT, CORE_CLK_CFG, PCLK_RATIO_SHIFT,
PCLK_RATIO_MASK, 0, &_lock);
clk_register_clkdev(clk, "apb_clk", NULL);
clk = clk_register_gate(NULL, "amem_clk", "ahb_clk", 0, AMEM_CLK_CFG,
AMEM_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "amem_clk", NULL);
clk = clk_register_gate(NULL, "c3_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
C3_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "c3_clk");
clk = clk_register_gate(NULL, "dma_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
DMA_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "fc400000.dma");
clk = clk_register_gate(NULL, "gmac_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
GMAC_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "e0800000.eth");
clk = clk_register_gate(NULL, "i2c0_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
I2C_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "d0180000.i2c");
clk = clk_register_gate(NULL, "jpeg_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
JPEG_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "jpeg");
clk = clk_register_gate(NULL, "smi_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
SMI_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "fc000000.flash");
/* clock derived from apb clk */
clk = clk_register_gate(NULL, "adc_clk", "apb_clk", 0, PERIP1_CLK_ENB,
ADC_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "adc");
clk = clk_register_gate(NULL, "gpio0_clk", "apb_clk", 0, PERIP1_CLK_ENB,
GPIO_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "fc980000.gpio");
clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0, PERIP1_CLK_ENB,
SSP_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "d0100000.spi");
/* RAS clk enable */
clk = clk_register_gate(NULL, "ras_ahb_clk", "ahb_clk", 0, RAS_CLK_ENB,
RAS_AHB_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_ahb_clk", NULL);
clk = clk_register_gate(NULL, "ras_apb_clk", "apb_clk", 0, RAS_CLK_ENB,
RAS_APB_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_apb_clk", NULL);
clk = clk_register_gate(NULL, "ras_32k_clk", "osc_32k_clk", 0,
RAS_CLK_ENB, RAS_32K_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_32k_clk", NULL);
clk = clk_register_gate(NULL, "ras_24m_clk", "osc_24m_clk", 0,
RAS_CLK_ENB, RAS_24M_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_24m_clk", NULL);
clk = clk_register_gate(NULL, "ras_pll1_clk", "pll1_clk", 0,
RAS_CLK_ENB, RAS_PLL1_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_pll1_clk", NULL);
clk = clk_register_gate(NULL, "ras_pll2_clk", "pll2_clk", 0,
RAS_CLK_ENB, RAS_PLL2_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_pll2_clk", NULL);
clk = clk_register_gate(NULL, "ras_pll3_48m_clk", "pll3_48m_clk", 0,
RAS_CLK_ENB, RAS_48M_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_pll3_48m_clk", NULL);
clk = clk_register_gate(NULL, "ras_gen0_synth_gate_clk",
"gen0_synth_gate_clk", 0, RAS_CLK_ENB,
RAS_SYNT0_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_gen0_synth_gate_clk", NULL);
clk = clk_register_gate(NULL, "ras_gen1_synth_gate_clk",
"gen1_synth_gate_clk", 0, RAS_CLK_ENB,
RAS_SYNT1_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_gen1_synth_gate_clk", NULL);
clk = clk_register_gate(NULL, "ras_gen2_synth_gate_clk",
"gen2_synth_gate_clk", 0, RAS_CLK_ENB,
RAS_SYNT2_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_gen2_synth_gate_clk", NULL);
clk = clk_register_gate(NULL, "ras_gen3_synth_gate_clk",
"gen3_synth_gate_clk", 0, RAS_CLK_ENB,
RAS_SYNT3_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, "ras_gen3_synth_gate_clk", NULL);
if (of_machine_is_compatible("st,spear300"))
spear300_clk_init();
else if (of_machine_is_compatible("st,spear310"))
spear310_clk_init();
else if (of_machine_is_compatible("st,spear320"))
spear320_clk_init();
}
/*
* SPEAr6xx machines clock framework source file
*
* Copyright (C) 2012 ST Microelectronics
* Viresh Kumar <viresh.kumar@st.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/spinlock_types.h>
#include <mach/misc_regs.h>
#include "clk.h"
static DEFINE_SPINLOCK(_lock);
#define PLL1_CTR (MISC_BASE + 0x008)
#define PLL1_FRQ (MISC_BASE + 0x00C)
#define PLL2_CTR (MISC_BASE + 0x014)
#define PLL2_FRQ (MISC_BASE + 0x018)
#define PLL_CLK_CFG (MISC_BASE + 0x020)
/* PLL_CLK_CFG register masks */
#define MCTR_CLK_SHIFT 28
#define MCTR_CLK_MASK 3
#define CORE_CLK_CFG (MISC_BASE + 0x024)
/* CORE CLK CFG register masks */
#define HCLK_RATIO_SHIFT 10
#define HCLK_RATIO_MASK 2
#define PCLK_RATIO_SHIFT 8
#define PCLK_RATIO_MASK 2
#define PERIP_CLK_CFG (MISC_BASE + 0x028)
/* PERIP_CLK_CFG register masks */
#define CLCD_CLK_SHIFT 2
#define CLCD_CLK_MASK 2
#define UART_CLK_SHIFT 4
#define UART_CLK_MASK 1
#define FIRDA_CLK_SHIFT 5
#define FIRDA_CLK_MASK 2
#define GPT0_CLK_SHIFT 8
#define GPT1_CLK_SHIFT 10
#define GPT2_CLK_SHIFT 11
#define GPT3_CLK_SHIFT 12
#define GPT_CLK_MASK 1
#define PERIP1_CLK_ENB (MISC_BASE + 0x02C)
/* PERIP1_CLK_ENB register masks */
#define UART0_CLK_ENB 3
#define UART1_CLK_ENB 4
#define SSP0_CLK_ENB 5
#define SSP1_CLK_ENB 6
#define I2C_CLK_ENB 7
#define JPEG_CLK_ENB 8
#define FSMC_CLK_ENB 9
#define FIRDA_CLK_ENB 10
#define GPT2_CLK_ENB 11
#define GPT3_CLK_ENB 12
#define GPIO2_CLK_ENB 13
#define SSP2_CLK_ENB 14
#define ADC_CLK_ENB 15
#define GPT1_CLK_ENB 11
#define RTC_CLK_ENB 17
#define GPIO1_CLK_ENB 18
#define DMA_CLK_ENB 19
#define SMI_CLK_ENB 21
#define CLCD_CLK_ENB 22
#define GMAC_CLK_ENB 23
#define USBD_CLK_ENB 24
#define USBH0_CLK_ENB 25
#define USBH1_CLK_ENB 26
#define PRSC0_CLK_CFG (MISC_BASE + 0x044)
#define PRSC1_CLK_CFG (MISC_BASE + 0x048)
#define PRSC2_CLK_CFG (MISC_BASE + 0x04C)
#define CLCD_CLK_SYNT (MISC_BASE + 0x05C)
#define FIRDA_CLK_SYNT (MISC_BASE + 0x060)
#define UART_CLK_SYNT (MISC_BASE + 0x064)
/* vco rate configuration table, in ascending order of rates */
static struct pll_rate_tbl pll_rtbl[] = {
{.mode = 0, .m = 0x53, .n = 0x0F, .p = 0x1}, /* vco 332 & pll 166 MHz */
{.mode = 0, .m = 0x85, .n = 0x0F, .p = 0x1}, /* vco 532 & pll 266 MHz */
{.mode = 0, .m = 0xA6, .n = 0x0F, .p = 0x1}, /* vco 664 & pll 332 MHz */
};
/* aux rate configuration table, in ascending order of rates */
static struct aux_rate_tbl aux_rtbl[] = {
/* For PLL1 = 332 MHz */
{.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */
{.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */
{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
};
static const char *clcd_parents[] = { "pll3_48m_clk", "clcd_synth_gate_clk", };
static const char *firda_parents[] = { "pll3_48m_clk", "firda_synth_gate_clk",
};
static const char *uart_parents[] = { "pll3_48m_clk", "uart_synth_gate_clk", };
static const char *gpt0_1_parents[] = { "pll3_48m_clk", "gpt0_1_synth_clk", };
static const char *gpt2_parents[] = { "pll3_48m_clk", "gpt2_synth_clk", };
static const char *gpt3_parents[] = { "pll3_48m_clk", "gpt3_synth_clk", };
static const char *ddr_parents[] = { "ahb_clk", "ahbmult2_clk", "none",
"pll2_clk", };
/* gpt rate configuration table, in ascending order of rates */
static struct gpt_rate_tbl gpt_rtbl[] = {
/* For pll1 = 332 MHz */
{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
{.mscale = 1, .nscale = 0}, /* 83 MHz */
};
void __init spear6xx_clk_init(void)
{
struct clk *clk, *clk1;
clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
clk_register_clkdev(clk, "apb_pclk", NULL);
clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
32000);
clk_register_clkdev(clk, "osc_32k_clk", NULL);
clk = clk_register_fixed_rate(NULL, "osc_30m_clk", NULL, CLK_IS_ROOT,
30000000);
clk_register_clkdev(clk, "osc_30m_clk", NULL);
/* clock derived from 32 KHz osc clk */
clk = clk_register_gate(NULL, "rtc_spear", "osc_32k_clk", 0,
PERIP1_CLK_ENB, RTC_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "rtc-spear");
/* clock derived from 30 MHz osc clk */
clk = clk_register_fixed_rate(NULL, "pll3_48m_clk", "osc_24m_clk", 0,
48000000);
clk_register_clkdev(clk, "pll3_48m_clk", NULL);
clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "osc_30m_clk",
0, PLL1_CTR, PLL1_FRQ, pll_rtbl, ARRAY_SIZE(pll_rtbl),
&_lock, &clk1, NULL);
clk_register_clkdev(clk, "vco1_clk", NULL);
clk_register_clkdev(clk1, "pll1_clk", NULL);
clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL,
"osc_30m_clk", 0, PLL2_CTR, PLL2_FRQ, pll_rtbl,
ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
clk_register_clkdev(clk, "vco2_clk", NULL);
clk_register_clkdev(clk1, "pll2_clk", NULL);
clk = clk_register_fixed_factor(NULL, "wdt_clk", "osc_30m_clk", 0, 1,
1);
clk_register_clkdev(clk, NULL, "wdt");
/* clock derived from pll1 clk */
clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 1);
clk_register_clkdev(clk, "cpu_clk", NULL);
clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk",
CLK_SET_RATE_PARENT, CORE_CLK_CFG, HCLK_RATIO_SHIFT,
HCLK_RATIO_MASK, 0, &_lock);
clk_register_clkdev(clk, "ahb_clk", NULL);
clk = clk_register_aux("uart_synth_clk", "uart_synth_gate_clk",
"pll1_clk", 0, UART_CLK_SYNT, NULL, aux_rtbl,
ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
clk_register_clkdev(clk, "uart_synth_clk", NULL);
clk_register_clkdev(clk1, "uart_synth_gate_clk", NULL);
clk = clk_register_mux(NULL, "uart_mux_clk", uart_parents,
ARRAY_SIZE(uart_parents), 0, PERIP_CLK_CFG,
UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "uart_mux_clk", NULL);
clk = clk_register_gate(NULL, "uart0", "uart_mux_clk", 0,
PERIP1_CLK_ENB, UART0_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "d0000000.serial");
clk = clk_register_gate(NULL, "uart1", "uart_mux_clk", 0,
PERIP1_CLK_ENB, UART1_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "d0080000.serial");
clk = clk_register_aux("firda_synth_clk", "firda_synth_gate_clk",
"pll1_clk", 0, FIRDA_CLK_SYNT, NULL, aux_rtbl,
ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
clk_register_clkdev(clk, "firda_synth_clk", NULL);
clk_register_clkdev(clk1, "firda_synth_gate_clk", NULL);
clk = clk_register_mux(NULL, "firda_mux_clk", firda_parents,
ARRAY_SIZE(firda_parents), 0, PERIP_CLK_CFG,
FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "firda_mux_clk", NULL);
clk = clk_register_gate(NULL, "firda_clk", "firda_mux_clk", 0,
PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "firda");
clk = clk_register_aux("clcd_synth_clk", "clcd_synth_gate_clk",
"pll1_clk", 0, CLCD_CLK_SYNT, NULL, aux_rtbl,
ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
clk_register_clkdev(clk, "clcd_synth_clk", NULL);
clk_register_clkdev(clk1, "clcd_synth_gate_clk", NULL);
clk = clk_register_mux(NULL, "clcd_mux_clk", clcd_parents,
ARRAY_SIZE(clcd_parents), 0, PERIP_CLK_CFG,
CLCD_CLK_SHIFT, CLCD_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "clcd_mux_clk", NULL);
clk = clk_register_gate(NULL, "clcd_clk", "clcd_mux_clk", 0,
PERIP1_CLK_ENB, CLCD_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "clcd");
/* gpt clocks */
clk = clk_register_gpt("gpt0_1_synth_clk", "pll1_clk", 0, PRSC0_CLK_CFG,
gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
clk_register_clkdev(clk, "gpt0_1_synth_clk", NULL);
clk = clk_register_mux(NULL, "gpt0_mux_clk", gpt0_1_parents,
ARRAY_SIZE(gpt0_1_parents), 0, PERIP_CLK_CFG,
GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, NULL, "gpt0");
clk = clk_register_mux(NULL, "gpt1_mux_clk", gpt0_1_parents,
ARRAY_SIZE(gpt0_1_parents), 0, PERIP_CLK_CFG,
GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt1_mux_clk", NULL);
clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mux_clk", 0,
PERIP1_CLK_ENB, GPT1_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "gpt1");
clk = clk_register_gpt("gpt2_synth_clk", "pll1_clk", 0, PRSC1_CLK_CFG,
gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
clk_register_clkdev(clk, "gpt2_synth_clk", NULL);
clk = clk_register_mux(NULL, "gpt2_mux_clk", gpt2_parents,
ARRAY_SIZE(gpt2_parents), 0, PERIP_CLK_CFG,
GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt2_mux_clk", NULL);
clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mux_clk", 0,
PERIP1_CLK_ENB, GPT2_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "gpt2");
clk = clk_register_gpt("gpt3_synth_clk", "pll1_clk", 0, PRSC2_CLK_CFG,
gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
clk_register_clkdev(clk, "gpt3_synth_clk", NULL);
clk = clk_register_mux(NULL, "gpt3_mux_clk", gpt3_parents,
ARRAY_SIZE(gpt3_parents), 0, PERIP_CLK_CFG,
GPT3_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
clk_register_clkdev(clk, "gpt3_mux_clk", NULL);
clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mux_clk", 0,
PERIP1_CLK_ENB, GPT3_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "gpt3");
/* clock derived from pll3 clk */
clk = clk_register_gate(NULL, "usbh0_clk", "pll3_48m_clk", 0,
PERIP1_CLK_ENB, USBH0_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "usbh.0_clk");
clk = clk_register_gate(NULL, "usbh1_clk", "pll3_48m_clk", 0,
PERIP1_CLK_ENB, USBH1_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "usbh.1_clk");
clk = clk_register_gate(NULL, "usbd_clk", "pll3_48m_clk", 0,
PERIP1_CLK_ENB, USBD_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "designware_udc");
/* clock derived from ahb clk */
clk = clk_register_fixed_factor(NULL, "ahbmult2_clk", "ahb_clk", 0, 2,
1);
clk_register_clkdev(clk, "ahbmult2_clk", NULL);
clk = clk_register_mux(NULL, "ddr_clk", ddr_parents,
ARRAY_SIZE(ddr_parents),
0, PLL_CLK_CFG, MCTR_CLK_SHIFT, MCTR_CLK_MASK, 0,
&_lock);
clk_register_clkdev(clk, "ddr_clk", NULL);
clk = clk_register_divider(NULL, "apb_clk", "ahb_clk",
CLK_SET_RATE_PARENT, CORE_CLK_CFG, PCLK_RATIO_SHIFT,
PCLK_RATIO_MASK, 0, &_lock);
clk_register_clkdev(clk, "apb_clk", NULL);
clk = clk_register_gate(NULL, "dma_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
DMA_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "fc400000.dma");
clk = clk_register_gate(NULL, "fsmc_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
FSMC_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "d1800000.flash");
clk = clk_register_gate(NULL, "gmac_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
GMAC_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "gmac");
clk = clk_register_gate(NULL, "i2c_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
I2C_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "d0200000.i2c");
clk = clk_register_gate(NULL, "jpeg_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
JPEG_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "jpeg");
clk = clk_register_gate(NULL, "smi_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
SMI_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "fc000000.flash");
/* clock derived from apb clk */
clk = clk_register_gate(NULL, "adc_clk", "apb_clk", 0, PERIP1_CLK_ENB,
ADC_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "adc");
clk = clk_register_fixed_factor(NULL, "gpio0_clk", "apb_clk", 0, 1, 1);
clk_register_clkdev(clk, NULL, "f0100000.gpio");
clk = clk_register_gate(NULL, "gpio1_clk", "apb_clk", 0, PERIP1_CLK_ENB,
GPIO1_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "fc980000.gpio");
clk = clk_register_gate(NULL, "gpio2_clk", "apb_clk", 0, PERIP1_CLK_ENB,
GPIO2_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "d8100000.gpio");
clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0, PERIP1_CLK_ENB,
SSP0_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "ssp-pl022.0");
clk = clk_register_gate(NULL, "ssp1_clk", "apb_clk", 0, PERIP1_CLK_ENB,
SSP1_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "ssp-pl022.1");
clk = clk_register_gate(NULL, "ssp2_clk", "apb_clk", 0, PERIP1_CLK_ENB,
SSP2_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "ssp-pl022.2");
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment