diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-11 17:56:37 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-11 17:56:37 -0800 |
commit | c0222ac086669a631814bbf857f8c8023452a4d7 (patch) | |
tree | bb1d9908031fcf69016eeefa7b35a4f68f414333 /drivers/clk | |
parent | 140cd7fb04a4a2bc09a30980bc8104cc89e09330 (diff) | |
parent | e2965cd0003f222bd49f67907c2bc6ed691c6d20 (diff) |
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle:
"This is an unusually large pull request for MIPS - in parts because
lots of patches missed the 3.18 deadline but primarily because some
folks opened the flood gates.
- Retire the MIPS-specific phys_t with the generic phys_addr_t.
- Improvments for the backtrace code used by oprofile.
- Better backtraces on SMP systems.
- Cleanups for the Octeon platform code.
- Cleanups and fixes for the Loongson platform code.
- Cleanups and fixes to the firmware library.
- Switch ATH79 platform to use the firmware library.
- Grand overhault to the SEAD3 and Malta interrupt code.
- Move the GIC interrupt code to drivers/irqchip
- Lots of GIC cleanups and updates to the GIC code to use modern IRQ
infrastructures and features of the kernel.
- OF documentation updates for the GIC bindings
- Move GIC clocksource driver to drivers/clocksource
- Merge GIC clocksource driver with clockevent driver.
- Further updates to bring the GIC clocksource driver up to date.
- R3000 TLB code cleanups
- Improvments to the Loongson 3 platform code.
- Convert pr_warning to pr_warn.
- Merge a bunch of small lantiq and ralink fixes that have been
staged/lingering inside the openwrt tree for a while.
- Update archhelp for IP22/IP32
- Fix a number of issues for Loongson 1B.
- New clocksource and clockevent driver for Loongson 1B.
- Further work on clk handling for Loongson 1B.
- Platform work for Broadcom BMIPS.
- Error handling cleanups for TurboChannel.
- Fixes and optimization to the microMIPS support.
- Option to disable the FTLB.
- Dump more relevant information on machine check exception
- Change binfmt to allow arch to examine PT_*PROC headers
- Support for new style FPU register model in O32
- VDSO randomization.
- BCM47xx cleanups
- BCM47xx reimplement the way the kernel accesses NVRAM information.
- Random cleanups
- Add support for ATH25 platforms
- Remove pointless locking code in some PCI platforms.
- Some improvments to EVA support
- Minor Alchemy cleanup"
* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (185 commits)
MIPS: Add MFHC0 and MTHC0 instructions to uasm.
MIPS: Cosmetic cleanups of page table headers.
MIPS: Add CP0 macros for extended EntryLo registers
MIPS: Remove now unused definition of phys_t.
MIPS: Replace use of phys_t with phys_addr_t.
MIPS: Replace MIPS-specific 64BIT_PHYS_ADDR with generic PHYS_ADDR_T_64BIT
PCMCIA: Alchemy Don't select 64BIT_PHYS_ADDR in Kconfig.
MIPS: lib: memset: Clean up some MIPS{EL,EB} ifdefery
MIPS: iomap: Use __mem_{read,write}{b,w,l} for MMIO
MIPS: <asm/types.h> fix indentation.
MAINTAINERS: Add entry for BMIPS multiplatform kernel
MIPS: Enable VDSO randomization
MIPS: Remove a temporary hack for debugging cache flushes in SMTC configuration
MIPS: Remove declaration of obsolete arch_init_clk_ops()
MIPS: atomic.h: Reformat to fit in 79 columns
MIPS: Apply `.insn' to fixup labels throughout
MIPS: Fix microMIPS LL/SC immediate offsets
MIPS: Kconfig: Only allow 32-bit microMIPS builds
MIPS: signal.c: Fix an invalid cast in ISA mode bit handling
MIPS: mm: Only build one microassembler that is suitable
...
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/clk-ls1x.c | 109 |
1 files changed, 80 insertions, 29 deletions
diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/clk-ls1x.c index f20b750235f..ca80103ac18 100644 --- a/drivers/clk/clk-ls1x.c +++ b/drivers/clk/clk-ls1x.c @@ -15,7 +15,8 @@ #include <loongson1.h> -#define OSC 33 +#define OSC (33 * 1000000) +#define DIV_APB 2 static DEFINE_SPINLOCK(_lock); @@ -29,13 +30,12 @@ static void ls1x_pll_clk_disable(struct clk_hw *hw) } static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) + unsigned long parent_rate) { u32 pll, rate; pll = __raw_readl(LS1X_CLK_PLL_FREQ); - rate = ((12 + (pll & 0x3f)) * 1000000) + - ((((pll >> 8) & 0x3ff) * 1000000) >> 10); + rate = 12 + (pll & 0x3f) + (((pll >> 8) & 0x3ff) >> 10); rate *= OSC; rate >>= 1; @@ -48,8 +48,10 @@ static const struct clk_ops ls1x_pll_clk_ops = { .recalc_rate = ls1x_pll_recalc_rate, }; -static struct clk * __init clk_register_pll(struct device *dev, - const char *name, const char *parent_name, unsigned long flags) +static struct clk *__init clk_register_pll(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags) { struct clk_hw *hw; struct clk *clk; @@ -78,34 +80,83 @@ static struct clk * __init clk_register_pll(struct device *dev, return clk; } +static const char const *cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", }; +static const char const *ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", }; +static const char const *dc_parents[] = { "dc_clk_div", "osc_33m_clk", }; + void __init ls1x_clk_init(void) { struct clk *clk; - clk = clk_register_pll(NULL, "pll_clk", NULL, CLK_IS_ROOT); - clk_prepare_enable(clk); - - clk = clk_register_divider(NULL, "cpu_clk", "pll_clk", - CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_CPU_SHIFT, - DIV_CPU_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock); - clk_prepare_enable(clk); - clk_register_clkdev(clk, "cpu", NULL); - - clk = clk_register_divider(NULL, "dc_clk", "pll_clk", - CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT, - DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock); - clk_prepare_enable(clk); - clk_register_clkdev(clk, "dc", NULL); - - clk = clk_register_divider(NULL, "ahb_clk", "pll_clk", - CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT, - DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock); - clk_prepare_enable(clk); - clk_register_clkdev(clk, "ahb", NULL); + clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, CLK_IS_ROOT, + OSC); + clk_register_clkdev(clk, "osc_33m_clk", NULL); + + /* clock derived from 33 MHz OSC clk */ + clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", 0); + clk_register_clkdev(clk, "pll_clk", NULL); + + /* clock derived from PLL clk */ + /* _____ + * _______________________| | + * OSC ___/ | MUX |___ CPU CLK + * \___ PLL ___ CPU DIV ___| | + * |_____| + */ + clk = clk_register_divider(NULL, "cpu_clk_div", "pll_clk", + CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV, + DIV_CPU_SHIFT, DIV_CPU_WIDTH, + CLK_DIVIDER_ONE_BASED | + CLK_DIVIDER_ROUND_CLOSEST, &_lock); + clk_register_clkdev(clk, "cpu_clk_div", NULL); + clk = clk_register_mux(NULL, "cpu_clk", cpu_parents, + ARRAY_SIZE(cpu_parents), + CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV, + BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock); + clk_register_clkdev(clk, "cpu_clk", NULL); + + /* _____ + * _______________________| | + * OSC ___/ | MUX |___ DC CLK + * \___ PLL ___ DC DIV ___| | + * |_____| + */ + clk = clk_register_divider(NULL, "dc_clk_div", "pll_clk", + 0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT, + DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock); + clk_register_clkdev(clk, "dc_clk_div", NULL); + clk = clk_register_mux(NULL, "dc_clk", dc_parents, + ARRAY_SIZE(dc_parents), + CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV, + BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock); + clk_register_clkdev(clk, "dc_clk", NULL); + + /* _____ + * _______________________| | + * OSC ___/ | MUX |___ DDR CLK + * \___ PLL ___ DDR DIV ___| | + * |_____| + */ + clk = clk_register_divider(NULL, "ahb_clk_div", "pll_clk", + 0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT, + DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED, + &_lock); + clk_register_clkdev(clk, "ahb_clk_div", NULL); + clk = clk_register_mux(NULL, "ahb_clk", ahb_parents, + ARRAY_SIZE(ahb_parents), + CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV, + BYPASS_DDR_SHIFT, BYPASS_DDR_WIDTH, 0, &_lock); + clk_register_clkdev(clk, "ahb_clk", NULL); clk_register_clkdev(clk, "stmmaceth", NULL); - clk = clk_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, 2); - clk_prepare_enable(clk); - clk_register_clkdev(clk, "apb", NULL); + /* clock derived from AHB clk */ + /* APB clk is always half of the AHB clk */ + clk = clk_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, + DIV_APB); + clk_register_clkdev(clk, "apb_clk", NULL); + clk_register_clkdev(clk, "ls1x_i2c", NULL); + clk_register_clkdev(clk, "ls1x_pwmtimer", NULL); + clk_register_clkdev(clk, "ls1x_spi", NULL); + clk_register_clkdev(clk, "ls1x_wdt", NULL); clk_register_clkdev(clk, "serial8250", NULL); } |