3a9b6dc313
SVN-Revision: 31336
719 lines
19 KiB
Diff
719 lines
19 KiB
Diff
From de49a17fd2d9a73b9449f04061bb08eb5d73fe98 Mon Sep 17 00:00:00 2001
|
|
From: John Crispin <blogic@openwrt.org>
|
|
Date: Thu, 8 Mar 2012 11:18:22 +0100
|
|
Subject: [PATCH 22/70] MIPS: lantiq: convert xway to clkdev api
|
|
|
|
Unify xway/ase clock code and add clkdev hooks to sysctrl.c
|
|
|
|
Signed-off-by: John Crispin <blogic@openwrt.org>
|
|
---
|
|
.../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 13 --
|
|
arch/mips/lantiq/xway/Makefile | 6 +-
|
|
arch/mips/lantiq/xway/clk-ase.c | 48 ----
|
|
arch/mips/lantiq/xway/clk-xway.c | 223 -------------------
|
|
arch/mips/lantiq/xway/clk.c | 227 ++++++++++++++++++++
|
|
arch/mips/lantiq/xway/sysctrl.c | 104 ++++++++-
|
|
6 files changed, 325 insertions(+), 296 deletions(-)
|
|
delete mode 100644 arch/mips/lantiq/xway/clk-ase.c
|
|
delete mode 100644 arch/mips/lantiq/xway/clk-xway.c
|
|
create mode 100644 arch/mips/lantiq/xway/clk.c
|
|
|
|
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
|
|
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
|
|
@@ -81,15 +81,6 @@
|
|
#define LTQ_PMU_BASE_ADDR 0x1F102000
|
|
#define LTQ_PMU_SIZE 0x1000
|
|
|
|
-#define PMU_DMA 0x0020
|
|
-#define PMU_EPHY 0x0080
|
|
-#define PMU_USB 0x8041
|
|
-#define PMU_LED 0x0800
|
|
-#define PMU_GPT 0x1000
|
|
-#define PMU_PPE 0x2000
|
|
-#define PMU_FPI 0x4000
|
|
-#define PMU_SWITCH 0x10000000
|
|
-
|
|
/* ETOP - ethernet */
|
|
#define LTQ_ETOP_BASE_ADDR 0x1E180000
|
|
#define LTQ_ETOP_SIZE 0x40000
|
|
@@ -145,10 +136,6 @@
|
|
extern __iomem void *ltq_ebu_membase;
|
|
extern __iomem void *ltq_cgu_membase;
|
|
|
|
-extern void ltq_pmu_enable(unsigned int module);
|
|
-extern void ltq_pmu_disable(unsigned int module);
|
|
-extern void ltq_cgu_enable(unsigned int clk);
|
|
-
|
|
static inline int ltq_is_ase(void)
|
|
{
|
|
return (ltq_get_soc_type() == SOC_TYPE_AMAZON_SE);
|
|
--- a/arch/mips/lantiq/xway/Makefile
|
|
+++ b/arch/mips/lantiq/xway/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
-obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
|
|
+obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o
|
|
|
|
-obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
|
|
-obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
|
|
+obj-$(CONFIG_SOC_XWAY) += prom-xway.o
|
|
+obj-$(CONFIG_SOC_AMAZON_SE) += prom-ase.o
|
|
|
|
obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
|
|
obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
|
|
--- a/arch/mips/lantiq/xway/clk-ase.c
|
|
+++ /dev/null
|
|
@@ -1,48 +0,0 @@
|
|
-/*
|
|
- * This program is free software; you can redistribute it and/or modify it
|
|
- * under the terms of the GNU General Public License version 2 as published
|
|
- * by the Free Software Foundation.
|
|
- *
|
|
- * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
|
|
- */
|
|
-
|
|
-#include <linux/io.h>
|
|
-#include <linux/export.h>
|
|
-#include <linux/init.h>
|
|
-#include <linux/clk.h>
|
|
-
|
|
-#include <asm/time.h>
|
|
-#include <asm/irq.h>
|
|
-#include <asm/div64.h>
|
|
-
|
|
-#include <lantiq_soc.h>
|
|
-
|
|
-/* cgu registers */
|
|
-#define LTQ_CGU_SYS 0x0010
|
|
-
|
|
-unsigned int ltq_get_io_region_clock(void)
|
|
-{
|
|
- return CLOCK_133M;
|
|
-}
|
|
-EXPORT_SYMBOL(ltq_get_io_region_clock);
|
|
-
|
|
-unsigned int ltq_get_fpi_bus_clock(int fpi)
|
|
-{
|
|
- return CLOCK_133M;
|
|
-}
|
|
-EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
|
|
-
|
|
-unsigned int ltq_get_cpu_hz(void)
|
|
-{
|
|
- if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
|
|
- return CLOCK_266M;
|
|
- else
|
|
- return CLOCK_133M;
|
|
-}
|
|
-EXPORT_SYMBOL(ltq_get_cpu_hz);
|
|
-
|
|
-unsigned int ltq_get_fpi_hz(void)
|
|
-{
|
|
- return CLOCK_133M;
|
|
-}
|
|
-EXPORT_SYMBOL(ltq_get_fpi_hz);
|
|
--- a/arch/mips/lantiq/xway/clk-xway.c
|
|
+++ /dev/null
|
|
@@ -1,223 +0,0 @@
|
|
-/*
|
|
- * This program is free software; you can redistribute it and/or modify it
|
|
- * under the terms of the GNU General Public License version 2 as published
|
|
- * by the Free Software Foundation.
|
|
- *
|
|
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
|
|
- */
|
|
-
|
|
-#include <linux/io.h>
|
|
-#include <linux/export.h>
|
|
-#include <linux/init.h>
|
|
-#include <linux/clk.h>
|
|
-
|
|
-#include <asm/time.h>
|
|
-#include <asm/irq.h>
|
|
-#include <asm/div64.h>
|
|
-
|
|
-#include <lantiq_soc.h>
|
|
-
|
|
-static unsigned int ltq_ram_clocks[] = {
|
|
- CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
|
|
-#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
|
|
-
|
|
-#define BASIC_FREQUENCY_1 35328000
|
|
-#define BASIC_FREQUENCY_2 36000000
|
|
-#define BASIS_REQUENCY_USB 12000000
|
|
-
|
|
-#define GET_BITS(x, msb, lsb) \
|
|
- (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
|
|
-
|
|
-#define LTQ_CGU_PLL0_CFG 0x0004
|
|
-#define LTQ_CGU_PLL1_CFG 0x0008
|
|
-#define LTQ_CGU_PLL2_CFG 0x000C
|
|
-#define LTQ_CGU_SYS 0x0010
|
|
-#define LTQ_CGU_UPDATE 0x0014
|
|
-#define LTQ_CGU_IF_CLK 0x0018
|
|
-#define LTQ_CGU_OSC_CON 0x001C
|
|
-#define LTQ_CGU_SMD 0x0020
|
|
-#define LTQ_CGU_CT1SR 0x0028
|
|
-#define LTQ_CGU_CT2SR 0x002C
|
|
-#define LTQ_CGU_PCMCR 0x0030
|
|
-#define LTQ_CGU_PCI_CR 0x0034
|
|
-#define LTQ_CGU_PD_PC 0x0038
|
|
-#define LTQ_CGU_FMR 0x003C
|
|
-
|
|
-#define CGU_PLL0_PHASE_DIVIDER_ENABLE \
|
|
- (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
|
|
-#define CGU_PLL0_BYPASS \
|
|
- (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
|
|
-#define CGU_PLL0_CFG_DSMSEL \
|
|
- (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
|
|
-#define CGU_PLL0_CFG_FRAC_EN \
|
|
- (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
|
|
-#define CGU_PLL1_SRC \
|
|
- (ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
|
|
-#define CGU_PLL2_PHASE_DIVIDER_ENABLE \
|
|
- (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
|
|
-#define CGU_SYS_FPI_SEL (1 << 6)
|
|
-#define CGU_SYS_DDR_SEL 0x3
|
|
-#define CGU_PLL0_SRC (1 << 29)
|
|
-
|
|
-#define CGU_PLL0_CFG_PLLK GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
|
|
-#define CGU_PLL0_CFG_PLLN GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
|
|
-#define CGU_PLL0_CFG_PLLM GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
|
|
-#define CGU_PLL2_SRC GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
|
|
-#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
|
|
-
|
|
-static unsigned int ltq_get_pll0_fdiv(void);
|
|
-
|
|
-static inline unsigned int get_input_clock(int pll)
|
|
-{
|
|
- switch (pll) {
|
|
- case 0:
|
|
- if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
|
|
- return BASIS_REQUENCY_USB;
|
|
- else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
|
|
- return BASIC_FREQUENCY_1;
|
|
- else
|
|
- return BASIC_FREQUENCY_2;
|
|
- case 1:
|
|
- if (CGU_PLL1_SRC)
|
|
- return BASIS_REQUENCY_USB;
|
|
- else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
|
|
- return BASIC_FREQUENCY_1;
|
|
- else
|
|
- return BASIC_FREQUENCY_2;
|
|
- case 2:
|
|
- switch (CGU_PLL2_SRC) {
|
|
- case 0:
|
|
- return ltq_get_pll0_fdiv();
|
|
- case 1:
|
|
- return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
|
|
- BASIC_FREQUENCY_1 :
|
|
- BASIC_FREQUENCY_2;
|
|
- case 2:
|
|
- return BASIS_REQUENCY_USB;
|
|
- }
|
|
- default:
|
|
- return 0;
|
|
- }
|
|
-}
|
|
-
|
|
-static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
|
|
-{
|
|
- u64 res, clock = get_input_clock(pll);
|
|
-
|
|
- res = num * clock;
|
|
- do_div(res, den);
|
|
- return res;
|
|
-}
|
|
-
|
|
-static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
|
|
- unsigned int K)
|
|
-{
|
|
- unsigned int num = ((N + 1) << 10) + K;
|
|
- unsigned int den = (M + 1) << 10;
|
|
-
|
|
- return cal_dsm(pll, num, den);
|
|
-}
|
|
-
|
|
-static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
|
|
- unsigned int K)
|
|
-{
|
|
- unsigned int num = ((N + 1) << 11) + K + 512;
|
|
- unsigned int den = (M + 1) << 11;
|
|
-
|
|
- return cal_dsm(pll, num, den);
|
|
-}
|
|
-
|
|
-static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
|
|
- unsigned int K)
|
|
-{
|
|
- unsigned int num = K >= 512 ?
|
|
- ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
|
|
- unsigned int den = (M + 1) << 12;
|
|
-
|
|
- return cal_dsm(pll, num, den);
|
|
-}
|
|
-
|
|
-static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
|
|
- unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
|
|
-{
|
|
- if (!dsmsel)
|
|
- return mash_dsm(pll, M, N, K);
|
|
- else if (!phase_div_en)
|
|
- return mash_dsm(pll, M, N, K);
|
|
- else
|
|
- return ssff_dsm_2(pll, M, N, K);
|
|
-}
|
|
-
|
|
-static inline unsigned int ltq_get_pll0_fosc(void)
|
|
-{
|
|
- if (CGU_PLL0_BYPASS)
|
|
- return get_input_clock(0);
|
|
- else
|
|
- return !CGU_PLL0_CFG_FRAC_EN
|
|
- ? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
|
|
- CGU_PLL0_CFG_DSMSEL,
|
|
- CGU_PLL0_PHASE_DIVIDER_ENABLE)
|
|
- : dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
|
|
- CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
|
|
- CGU_PLL0_PHASE_DIVIDER_ENABLE);
|
|
-}
|
|
-
|
|
-static unsigned int ltq_get_pll0_fdiv(void)
|
|
-{
|
|
- unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
|
|
-
|
|
- return (ltq_get_pll0_fosc() + (div >> 1)) / div;
|
|
-}
|
|
-
|
|
-unsigned int ltq_get_io_region_clock(void)
|
|
-{
|
|
- unsigned int ret = ltq_get_pll0_fosc();
|
|
-
|
|
- switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
|
|
- default:
|
|
- case 0:
|
|
- return (ret + 1) / 2;
|
|
- case 1:
|
|
- return (ret * 2 + 2) / 5;
|
|
- case 2:
|
|
- return (ret + 1) / 3;
|
|
- case 3:
|
|
- return (ret + 2) / 4;
|
|
- }
|
|
-}
|
|
-EXPORT_SYMBOL(ltq_get_io_region_clock);
|
|
-
|
|
-unsigned int ltq_get_fpi_bus_clock(int fpi)
|
|
-{
|
|
- unsigned int ret = ltq_get_io_region_clock();
|
|
-
|
|
- if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
|
|
- ret >>= 1;
|
|
- return ret;
|
|
-}
|
|
-EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
|
|
-
|
|
-unsigned int ltq_get_cpu_hz(void)
|
|
-{
|
|
- switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
|
|
- case 0:
|
|
- return CLOCK_333M;
|
|
- case 4:
|
|
- return DDR_HZ;
|
|
- case 8:
|
|
- return DDR_HZ << 1;
|
|
- default:
|
|
- return DDR_HZ >> 1;
|
|
- }
|
|
-}
|
|
-EXPORT_SYMBOL(ltq_get_cpu_hz);
|
|
-
|
|
-unsigned int ltq_get_fpi_hz(void)
|
|
-{
|
|
- unsigned int ddr_clock = DDR_HZ;
|
|
-
|
|
- if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
|
|
- return ddr_clock >> 1;
|
|
- return ddr_clock;
|
|
-}
|
|
-EXPORT_SYMBOL(ltq_get_fpi_hz);
|
|
--- /dev/null
|
|
+++ b/arch/mips/lantiq/xway/clk.c
|
|
@@ -0,0 +1,227 @@
|
|
+/*
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License version 2 as published
|
|
+ * by the Free Software Foundation.
|
|
+ *
|
|
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
|
|
+ */
|
|
+
|
|
+#include <linux/io.h>
|
|
+#include <linux/export.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/clk.h>
|
|
+
|
|
+#include <asm/time.h>
|
|
+#include <asm/irq.h>
|
|
+#include <asm/div64.h>
|
|
+
|
|
+#include <lantiq_soc.h>
|
|
+
|
|
+#include "../clk.h"
|
|
+
|
|
+static unsigned int ltq_ram_clocks[] = {
|
|
+ CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
|
|
+#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
|
|
+
|
|
+#define BASIC_FREQUENCY_1 35328000
|
|
+#define BASIC_FREQUENCY_2 36000000
|
|
+#define BASIS_REQUENCY_USB 12000000
|
|
+
|
|
+#define GET_BITS(x, msb, lsb) \
|
|
+ (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
|
|
+
|
|
+/* legacy xway clock */
|
|
+#define LTQ_CGU_PLL0_CFG 0x0004
|
|
+#define LTQ_CGU_PLL1_CFG 0x0008
|
|
+#define LTQ_CGU_PLL2_CFG 0x000C
|
|
+#define LTQ_CGU_SYS 0x0010
|
|
+#define LTQ_CGU_UPDATE 0x0014
|
|
+#define LTQ_CGU_IF_CLK 0x0018
|
|
+#define LTQ_CGU_OSC_CON 0x001C
|
|
+#define LTQ_CGU_SMD 0x0020
|
|
+#define LTQ_CGU_CT1SR 0x0028
|
|
+#define LTQ_CGU_CT2SR 0x002C
|
|
+#define LTQ_CGU_PCMCR 0x0030
|
|
+#define LTQ_CGU_PCI_CR 0x0034
|
|
+#define LTQ_CGU_PD_PC 0x0038
|
|
+#define LTQ_CGU_FMR 0x003C
|
|
+
|
|
+#define CGU_PLL0_PHASE_DIVIDER_ENABLE \
|
|
+ (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
|
|
+#define CGU_PLL0_BYPASS \
|
|
+ (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
|
|
+#define CGU_PLL0_CFG_DSMSEL \
|
|
+ (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
|
|
+#define CGU_PLL0_CFG_FRAC_EN \
|
|
+ (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
|
|
+#define CGU_PLL1_SRC \
|
|
+ (ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
|
|
+#define CGU_PLL2_PHASE_DIVIDER_ENABLE \
|
|
+ (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
|
|
+#define CGU_SYS_FPI_SEL (1 << 6)
|
|
+#define CGU_SYS_DDR_SEL 0x3
|
|
+#define CGU_PLL0_SRC (1 << 29)
|
|
+
|
|
+#define CGU_PLL0_CFG_PLLK GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
|
|
+#define CGU_PLL0_CFG_PLLN GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
|
|
+#define CGU_PLL0_CFG_PLLM GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
|
|
+#define CGU_PLL2_SRC GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
|
|
+#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
|
|
+
|
|
+/* vr9 clock */
|
|
+#define LTQ_CGU_SYS_VR9 0x0c
|
|
+#define LTQ_CGU_IF_CLK_VR9 0x24
|
|
+
|
|
+
|
|
+static unsigned int ltq_get_pll0_fdiv(void);
|
|
+
|
|
+static inline unsigned int get_input_clock(int pll)
|
|
+{
|
|
+ switch (pll) {
|
|
+ case 0:
|
|
+ if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
|
|
+ return BASIS_REQUENCY_USB;
|
|
+ else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
|
|
+ return BASIC_FREQUENCY_1;
|
|
+ else
|
|
+ return BASIC_FREQUENCY_2;
|
|
+ case 1:
|
|
+ if (CGU_PLL1_SRC)
|
|
+ return BASIS_REQUENCY_USB;
|
|
+ else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
|
|
+ return BASIC_FREQUENCY_1;
|
|
+ else
|
|
+ return BASIC_FREQUENCY_2;
|
|
+ case 2:
|
|
+ switch (CGU_PLL2_SRC) {
|
|
+ case 0:
|
|
+ return ltq_get_pll0_fdiv();
|
|
+ case 1:
|
|
+ return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
|
|
+ BASIC_FREQUENCY_1 :
|
|
+ BASIC_FREQUENCY_2;
|
|
+ case 2:
|
|
+ return BASIS_REQUENCY_USB;
|
|
+ }
|
|
+ default:
|
|
+ return 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
|
|
+{
|
|
+ u64 res, clock = get_input_clock(pll);
|
|
+
|
|
+ res = num * clock;
|
|
+ do_div(res, den);
|
|
+ return res;
|
|
+}
|
|
+
|
|
+static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
|
|
+ unsigned int K)
|
|
+{
|
|
+ unsigned int num = ((N + 1) << 10) + K;
|
|
+ unsigned int den = (M + 1) << 10;
|
|
+
|
|
+ return cal_dsm(pll, num, den);
|
|
+}
|
|
+
|
|
+static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
|
|
+ unsigned int K)
|
|
+{
|
|
+ unsigned int num = ((N + 1) << 11) + K + 512;
|
|
+ unsigned int den = (M + 1) << 11;
|
|
+
|
|
+ return cal_dsm(pll, num, den);
|
|
+}
|
|
+
|
|
+static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
|
|
+ unsigned int K)
|
|
+{
|
|
+ unsigned int num = K >= 512 ?
|
|
+ ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
|
|
+ unsigned int den = (M + 1) << 12;
|
|
+
|
|
+ return cal_dsm(pll, num, den);
|
|
+}
|
|
+
|
|
+static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
|
|
+ unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
|
|
+{
|
|
+ if (!dsmsel)
|
|
+ return mash_dsm(pll, M, N, K);
|
|
+ else if (!phase_div_en)
|
|
+ return mash_dsm(pll, M, N, K);
|
|
+ else
|
|
+ return ssff_dsm_2(pll, M, N, K);
|
|
+}
|
|
+
|
|
+static inline unsigned int ltq_get_pll0_fosc(void)
|
|
+{
|
|
+ if (CGU_PLL0_BYPASS)
|
|
+ return get_input_clock(0);
|
|
+ else
|
|
+ return !CGU_PLL0_CFG_FRAC_EN
|
|
+ ? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
|
|
+ CGU_PLL0_CFG_DSMSEL,
|
|
+ CGU_PLL0_PHASE_DIVIDER_ENABLE)
|
|
+ : dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
|
|
+ CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
|
|
+ CGU_PLL0_PHASE_DIVIDER_ENABLE);
|
|
+}
|
|
+
|
|
+static unsigned int ltq_get_pll0_fdiv(void)
|
|
+{
|
|
+ unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
|
|
+
|
|
+ return (ltq_get_pll0_fosc() + (div >> 1)) / div;
|
|
+}
|
|
+
|
|
+unsigned long ltq_danube_io_region_clock(void)
|
|
+{
|
|
+ unsigned int ret = ltq_get_pll0_fosc();
|
|
+
|
|
+ switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
|
|
+ default:
|
|
+ case 0:
|
|
+ return (ret + 1) / 2;
|
|
+ case 1:
|
|
+ return (ret * 2 + 2) / 5;
|
|
+ case 2:
|
|
+ return (ret + 1) / 3;
|
|
+ case 3:
|
|
+ return (ret + 2) / 4;
|
|
+ }
|
|
+}
|
|
+
|
|
+unsigned long ltq_danube_fpi_bus_clock(int fpi)
|
|
+{
|
|
+ unsigned long ret = ltq_danube_io_region_clock();
|
|
+
|
|
+ if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
|
|
+ ret >>= 1;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+unsigned long ltq_danube_cpu_hz(void)
|
|
+{
|
|
+ switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
|
|
+ case 0:
|
|
+ return CLOCK_333M;
|
|
+ case 4:
|
|
+ return DDR_HZ;
|
|
+ case 8:
|
|
+ return DDR_HZ << 1;
|
|
+ default:
|
|
+ return DDR_HZ >> 1;
|
|
+ }
|
|
+}
|
|
+
|
|
+unsigned long ltq_danube_fpi_hz(void)
|
|
+{
|
|
+ unsigned long ddr_clock = DDR_HZ;
|
|
+
|
|
+ if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
|
|
+ return ddr_clock >> 1;
|
|
+ return ddr_clock;
|
|
+}
|
|
--- a/arch/mips/lantiq/xway/sysctrl.c
|
|
+++ b/arch/mips/lantiq/xway/sysctrl.c
|
|
@@ -8,17 +8,48 @@
|
|
|
|
#include <linux/ioport.h>
|
|
#include <linux/export.h>
|
|
+#include <linux/clkdev.h>
|
|
|
|
#include <lantiq_soc.h>
|
|
|
|
+#include "../clk.h"
|
|
#include "../devices.h"
|
|
|
|
/* clock control register */
|
|
#define LTQ_CGU_IFCCR 0x0018
|
|
+/* system clock register */
|
|
+#define LTQ_CGU_SYS 0x0010
|
|
|
|
/* the enable / disable registers */
|
|
#define LTQ_PMU_PWDCR 0x1C
|
|
#define LTQ_PMU_PWDSR 0x20
|
|
+#define LTQ_PMU_PWDCR1 0x24
|
|
+#define LTQ_PMU_PWDSR1 0x28
|
|
+
|
|
+#define PWDCR(x) ((x) ? (LTQ_PMU_PWDCR1) : (LTQ_PMU_PWDCR))
|
|
+#define PWDSR(x) ((x) ? (LTQ_PMU_PWDSR1) : (LTQ_PMU_PWDSR))
|
|
+
|
|
+/* CGU - clock generation unit */
|
|
+#define CGU_EPHY 0x10
|
|
+
|
|
+/* PMU - power management unit */
|
|
+#define PMU_DMA 0x0020
|
|
+#define PMU_SPI 0x0100
|
|
+#define PMU_EPHY 0x0080
|
|
+#define PMU_USB 0x8041
|
|
+#define PMU_STP 0x0800
|
|
+#define PMU_GPT 0x1000
|
|
+#define PMU_PPE 0x2000
|
|
+#define PMU_FPI 0x4000
|
|
+#define PMU_SWITCH 0x10000000
|
|
+#define PMU_AHBS 0x2000
|
|
+#define PMU_AHBM 0x8000
|
|
+#define PMU_PCIE_CLK 0x80000000
|
|
+
|
|
+#define PMU1_PCIE_PHY 0x0001
|
|
+#define PMU1_PCIE_CTL 0x0002
|
|
+#define PMU1_PCIE_MSI 0x0020
|
|
+#define PMU1_PCIE_PDI 0x0010
|
|
|
|
#define ltq_pmu_w32(x, y) ltq_w32((x), ltq_pmu_membase + (y))
|
|
#define ltq_pmu_r32(x) ltq_r32(ltq_pmu_membase + (x))
|
|
@@ -36,28 +67,64 @@ void __iomem *ltq_cgu_membase;
|
|
void __iomem *ltq_ebu_membase;
|
|
static void __iomem *ltq_pmu_membase;
|
|
|
|
-void ltq_cgu_enable(unsigned int clk)
|
|
+static int ltq_cgu_enable(struct clk *clk)
|
|
+{
|
|
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | clk->bits, LTQ_CGU_IFCCR);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void ltq_cgu_disable(struct clk *clk)
|
|
{
|
|
- ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | clk, LTQ_CGU_IFCCR);
|
|
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~clk->bits, LTQ_CGU_IFCCR);
|
|
}
|
|
|
|
-void ltq_pmu_enable(unsigned int module)
|
|
+static int ltq_pmu_enable(struct clk *clk)
|
|
{
|
|
int err = 1000000;
|
|
|
|
- ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
|
|
- do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
|
|
+ ltq_pmu_w32(ltq_pmu_r32(PWDCR(clk->module)) & ~clk->bits,
|
|
+ PWDCR(clk->module));
|
|
+ do {} while (--err && (ltq_pmu_r32(PWDSR(clk->module)) & clk->bits));
|
|
|
|
if (!err)
|
|
panic("activating PMU module failed!\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void ltq_pmu_disable(struct clk *clk)
|
|
+{
|
|
+ ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | clk->bits, LTQ_PMU_PWDCR);
|
|
+}
|
|
+
|
|
+static inline void clkdev_add_pmu(const char *dev, const char *con,
|
|
+ unsigned int module, unsigned int bits)
|
|
+{
|
|
+ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
|
|
+
|
|
+ clk->cl.dev_id = dev;
|
|
+ clk->cl.con_id = con;
|
|
+ clk->cl.clk = clk;
|
|
+ clk->enable = ltq_pmu_enable;
|
|
+ clk->disable = ltq_pmu_disable;
|
|
+ clk->module = module;
|
|
+ clk->bits = bits;
|
|
+ clkdev_add(&clk->cl);
|
|
}
|
|
-EXPORT_SYMBOL(ltq_pmu_enable);
|
|
|
|
-void ltq_pmu_disable(unsigned int module)
|
|
+static inline void clkdev_add_cgu(const char *dev, const char *con,
|
|
+ unsigned int bits)
|
|
{
|
|
- ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
|
|
+ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
|
|
+
|
|
+ clk->cl.dev_id = dev;
|
|
+ clk->cl.con_id = con;
|
|
+ clk->cl.clk = clk;
|
|
+ clk->enable = ltq_cgu_enable;
|
|
+ clk->disable = ltq_cgu_disable;
|
|
+ clk->bits = bits;
|
|
+ clkdev_add(&clk->cl);
|
|
}
|
|
-EXPORT_SYMBOL(ltq_pmu_disable);
|
|
|
|
void __init ltq_soc_init(void)
|
|
{
|
|
@@ -75,4 +142,23 @@ void __init ltq_soc_init(void)
|
|
|
|
/* make sure to unprotect the memory region where flash is located */
|
|
ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
|
|
+
|
|
+ /* add our clocks */
|
|
+ clkdev_add_pmu("ltq_dma", NULL, 0, PMU_DMA);
|
|
+ clkdev_add_pmu("ltq_stp", NULL, 0, PMU_STP);
|
|
+ clkdev_add_pmu("ltq_spi", NULL, 0, PMU_SPI);
|
|
+ clkdev_add_pmu("ltq_etop", NULL, 0, PMU_PPE);
|
|
+ if (ltq_is_ase()) {
|
|
+ if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
|
|
+ clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M);
|
|
+ else
|
|
+ clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M);
|
|
+ clkdev_add_cgu("ltq_etop", "ephycgu", CGU_EPHY),
|
|
+ clkdev_add_pmu("ltq_etop", "ephy", 0, PMU_EPHY);
|
|
+ } else {
|
|
+ clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
|
|
+ ltq_danube_io_region_clock());
|
|
+ if (ltq_is_ar9())
|
|
+ clkdev_add_pmu("ltq_etop", "switch", 0, PMU_SWITCH);
|
|
+ }
|
|
}
|