summaryrefslogtreecommitdiff
path: root/target/linux/xburst/patches-3.2/0011-MIPS-JZ4740-Added-setting-of-PLL-rate-and-main-divid.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/xburst/patches-3.2/0011-MIPS-JZ4740-Added-setting-of-PLL-rate-and-main-divid.patch')
-rw-r--r--target/linux/xburst/patches-3.2/0011-MIPS-JZ4740-Added-setting-of-PLL-rate-and-main-divid.patch351
1 files changed, 0 insertions, 351 deletions
diff --git a/target/linux/xburst/patches-3.2/0011-MIPS-JZ4740-Added-setting-of-PLL-rate-and-main-divid.patch b/target/linux/xburst/patches-3.2/0011-MIPS-JZ4740-Added-setting-of-PLL-rate-and-main-divid.patch
deleted file mode 100644
index 01c211ba77..0000000000
--- a/target/linux/xburst/patches-3.2/0011-MIPS-JZ4740-Added-setting-of-PLL-rate-and-main-divid.patch
+++ /dev/null
@@ -1,351 +0,0 @@
-From 27ff621cd9a5347efda4be502abbef13a99146ce Mon Sep 17 00:00:00 2001
-From: Maarten ter Huurne <maarten@treewalker.org>
-Date: Sun, 29 Aug 2010 08:11:00 +0200
-Subject: [PATCH 11/21] MIPS: JZ4740: Added setting of PLL rate and main
- dividers.
-
-This functionality makes a cpufreq driver possible.
-Squashed version of the development done in the jz-2.6.39 branch.
----
- arch/mips/jz4740/clock.c | 230 ++++++++++++++++++++++++++++++++++++++++++++--
- arch/mips/jz4740/clock.h | 4 +
- 2 files changed, 224 insertions(+), 10 deletions(-)
-
---- a/arch/mips/jz4740/clock.c
-+++ b/arch/mips/jz4740/clock.c
-@@ -1,5 +1,8 @@
- /*
-+ * Copyright (c) 2006-2007, Ingenic Semiconductor Inc.
- * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
-+ * Copyright (c) 2010, Ulrich Hecht <ulrich.hecht@gmail.com>
-+ * Copyright (c) 2010, Maarten ter Huurne <maarten@treewalker.org>
- * JZ4740 SoC clock support
- *
- * This program is free software; you can redistribute it and/or modify it
-@@ -41,16 +44,20 @@
- #define JZ_CLOCK_CTRL_I2S_SRC_PLL BIT(31)
- #define JZ_CLOCK_CTRL_KO_ENABLE BIT(30)
- #define JZ_CLOCK_CTRL_UDC_SRC_PLL BIT(29)
--#define JZ_CLOCK_CTRL_UDIV_MASK 0x1f800000
- #define JZ_CLOCK_CTRL_CHANGE_ENABLE BIT(22)
- #define JZ_CLOCK_CTRL_PLL_HALF BIT(21)
--#define JZ_CLOCK_CTRL_LDIV_MASK 0x001f0000
- #define JZ_CLOCK_CTRL_UDIV_OFFSET 23
- #define JZ_CLOCK_CTRL_LDIV_OFFSET 16
- #define JZ_CLOCK_CTRL_MDIV_OFFSET 12
- #define JZ_CLOCK_CTRL_PDIV_OFFSET 8
- #define JZ_CLOCK_CTRL_HDIV_OFFSET 4
- #define JZ_CLOCK_CTRL_CDIV_OFFSET 0
-+#define JZ_CLOCK_CTRL_UDIV_MASK (0x3f << JZ_CLOCK_CTRL_UDIV_OFFSET)
-+#define JZ_CLOCK_CTRL_LDIV_MASK (0x1f << JZ_CLOCK_CTRL_LDIV_OFFSET)
-+#define JZ_CLOCK_CTRL_MDIV_MASK (0x0f << JZ_CLOCK_CTRL_MDIV_OFFSET)
-+#define JZ_CLOCK_CTRL_PDIV_MASK (0x0f << JZ_CLOCK_CTRL_PDIV_OFFSET)
-+#define JZ_CLOCK_CTRL_HDIV_MASK (0x0f << JZ_CLOCK_CTRL_HDIV_OFFSET)
-+#define JZ_CLOCK_CTRL_CDIV_MASK (0x0f << JZ_CLOCK_CTRL_CDIV_OFFSET)
-
- #define JZ_CLOCK_GATE_UART0 BIT(0)
- #define JZ_CLOCK_GATE_TCU BIT(1)
-@@ -90,6 +97,7 @@
- #define JZ_CLOCK_PLL_M_OFFSET 23
- #define JZ_CLOCK_PLL_N_OFFSET 18
- #define JZ_CLOCK_PLL_OD_OFFSET 16
-+#define JZ_CLOCK_PLL_STABILIZE_OFFSET 0
-
- #define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
- #define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
-@@ -97,10 +105,15 @@
- #define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7)
- #define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6)
-
-+#define JZ_REG_EMC_RTCNT 0x88
-+#define JZ_REG_EMC_RTCOR 0x8C
-+
- static void __iomem *jz_clock_base;
- static spinlock_t jz_clock_lock;
- static LIST_HEAD(jz_clocks);
-
-+static void __iomem *jz_emc_base;
-+
- struct main_clk {
- struct clk clk;
- uint32_t div_offset;
-@@ -204,25 +217,88 @@ static int jz_clk_ko_is_enabled(struct c
- return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE);
- }
-
-+static struct static_clk jz_clk_ext;
-+
-+static unsigned long jz_clk_pll_calc_rate(
-+ unsigned int in_div, unsigned int feedback, unsigned int out_div)
-+{
-+ return ((jz_clk_ext.rate / in_div) * feedback) / out_div;
-+}
-+
-+static void jz_clk_pll_calc_dividers(unsigned long rate,
-+ unsigned int *in_div, unsigned int *feedback, unsigned int *out_div)
-+{
-+ unsigned int target;
-+
-+ /* The frequency after the input divider must be between 1 and 15 MHz.
-+ The highest divider yields the best resolution. */
-+ *in_div = jz_clk_ext.rate / 1000000;
-+ if (*in_div >= 34)
-+ *in_div = 33;
-+
-+ /* The frequency before the output divider must be between 100 and
-+ 500 MHz. The lowest target rate is more energy efficient. */
-+ if (rate < 25000000) {
-+ *out_div = 4;
-+ target = 25000000 * 4;
-+ } else if (rate <= 50000000) {
-+ *out_div = 4;
-+ target = rate * 4;
-+ } else if (rate <= 100000000) {
-+ *out_div = 2;
-+ target = rate * 2;
-+ } else if (rate <= 500000000) {
-+ *out_div = 1;
-+ target = rate;
-+ } else {
-+ *out_div = 1;
-+ target = 500000000;
-+ }
-+
-+ /* Compute the feedback divider.
-+ Since the divided input is at least 1 MHz and the target frequency
-+ at most 500 MHz, the feedback will be at most 500 and will therefore
-+ always fit in the 9-bit register.
-+ Similarly, the divided input is at most 15 MHz and the target
-+ frequency at least 100 MHz, so the feedback will be at least 6
-+ where the minimum supported value is 2. */
-+ *feedback = ((target / 1000) * *in_div) / (jz_clk_ext.rate / 1000);
-+}
-+
-+static unsigned long jz_clk_pll_round_rate(struct clk *clk, unsigned long rate)
-+{
-+ unsigned int in_div, feedback, out_div;
-+ /* The PLL frequency must be a multiple of 24 MHz, since the LCD pixel
-+ * clock must be exactly 12 MHz for the TV-out to work.
-+ * TODO: A multiple of 12 MHz for the PLL would work if the PLL would
-+ * not be divided by 2 before being passed to the set of derived
-+ * clocks that includes the LCD pixel clock.
-+ * TODO: Systemwide decisions like this should be made by the board
-+ * support code, so add some kind of hook for that.
-+ */
-+ unsigned long rate24 = (rate / 24000000) * 24000000;
-+
-+ jz_clk_pll_calc_dividers(rate24, &in_div, &feedback, &out_div);
-+ return jz_clk_pll_calc_rate(in_div, feedback, out_div);
-+}
-+
- static const int pllno[] = {1, 2, 2, 4};
-
- static unsigned long jz_clk_pll_get_rate(struct clk *clk)
- {
- uint32_t val;
-- int m;
-- int n;
-- int od;
-+ unsigned int in_div, feedback, out_div;
-
- val = jz_clk_reg_read(JZ_REG_CLOCK_PLL);
-
- if (val & JZ_CLOCK_PLL_BYPASS)
- return clk_get_rate(clk->parent);
-
-- m = ((val >> 23) & 0x1ff) + 2;
-- n = ((val >> 18) & 0x1f) + 2;
-- od = (val >> 16) & 0x3;
-+ feedback = ((val >> 23) & 0x1ff) + 2;
-+ in_div = ((val >> 18) & 0x1f) + 2;
-+ out_div = pllno[(val >> 16) & 0x3];
-
-- return ((clk_get_rate(clk->parent) / n) * m) / pllno[od];
-+ return jz_clk_pll_calc_rate(in_div, feedback, out_div);
- }
-
- static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
-@@ -235,7 +311,77 @@ static unsigned long jz_clk_pll_half_get
- return jz_clk_pll_get_rate(clk->parent) >> 1;
- }
-
--static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
-+#define SDRAM_TREF 15625 /* Refresh period: 4096 refresh cycles/64ms */
-+
-+static void sdram_set_pll(unsigned int pllin)
-+{
-+ unsigned int ns, sdramclock;
-+
-+ ns = 1000000000 / pllin;
-+ sdramclock = (SDRAM_TREF / ns) / 64 + 1;
-+ if (sdramclock > 0xff) sdramclock = 0xff;
-+ /* Set refresh registers */
-+ writew(sdramclock, jz_emc_base + JZ_REG_EMC_RTCOR);
-+ writew(sdramclock, jz_emc_base + JZ_REG_EMC_RTCNT);
-+}
-+
-+static int jz_clk_pll_set_rate(struct clk *clk, unsigned long rate)
-+{
-+ unsigned int ctrl, plcr1;
-+ unsigned int feedback, in_div, out_div, pllout, pllout2;
-+
-+ jz_clk_pll_calc_dividers(rate, &in_div, &feedback, &out_div);
-+
-+ ctrl = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
-+ pllout = jz_clk_pll_calc_rate(in_div, feedback, out_div);
-+ pllout2 = (ctrl & JZ_CLOCK_CTRL_PLL_HALF) ? pllout : (pllout / 2);
-+
-+ /* Init UHC clock */
-+ writel(pllout2 / 48000000 - 1, jz_clock_base + JZ_REG_CLOCK_UHC);
-+
-+ plcr1 = ((feedback - 2) << JZ_CLOCK_PLL_M_OFFSET) |
-+ ((in_div - 2) << JZ_CLOCK_PLL_N_OFFSET) |
-+ ((out_div - 1) << JZ_CLOCK_PLL_OD_OFFSET) |
-+ (0x20 << JZ_CLOCK_PLL_STABILIZE_OFFSET) |
-+ JZ_CLOCK_PLL_ENABLED;
-+
-+ sdram_set_pll(pllout);
-+
-+ /* LCD pixclock */
-+ writel(pllout2 / 12000000 - 1, jz_clock_base + JZ_REG_CLOCK_LCD);
-+
-+ /* configure PLL */
-+ __asm__ __volatile__(
-+ ".set noreorder\n\t"
-+ ".align 5\n"
-+ "sw %1,0(%0)\n\t"
-+ "nop\n\t"
-+ "nop\n\t"
-+ "nop\n\t"
-+ "nop\n\t"
-+ "nop\n\t"
-+ "nop\n\t"
-+ "nop\n\t"
-+ ".set reorder\n\t"
-+ :
-+ : "r" (jz_clock_base + JZ_REG_CLOCK_PLL), "r" (plcr1));
-+
-+ /* MtH: For some reason the MSC will have problems if this flag is not
-+ restored, even though the MSC is supposedly the only divider
-+ that is not affected by this flag. */
-+ jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_CHANGE_ENABLE);
-+
-+ return 0;
-+}
-+
-+static const unsigned int jz_clk_main_divs[] = {
-+ 1, 2, 3, 4, 6, 8, 12, 16, 24, 32
-+};
-+static const unsigned int jz_clk_main_divs_inv[] = {
-+ -1, 0, 1, 2, 3, -1, 4, -1, 5, -1, -1, -1, 6, -1, -1, -1,
-+ 7, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1,
-+ 9
-+};
-
- static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
- {
-@@ -290,6 +436,64 @@ static int jz_clk_main_set_rate(struct c
- return 0;
- }
-
-+static struct main_clk jz_clk_cpu;
-+
-+int clk_main_set_dividers(bool immediate, unsigned int cdiv, unsigned int hdiv,
-+ unsigned int mdiv, unsigned int pdiv)
-+{
-+ unsigned int cdiv_enc, hdiv_enc, mdiv_enc, pdiv_enc;
-+ unsigned int ctrl;
-+ unsigned int tmp, wait;
-+
-+ if (cdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) ||
-+ hdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) ||
-+ mdiv >= ARRAY_SIZE(jz_clk_main_divs_inv) ||
-+ pdiv >= ARRAY_SIZE(jz_clk_main_divs_inv))
-+ return -EINVAL;
-+ cdiv_enc = jz_clk_main_divs_inv[cdiv];
-+ hdiv_enc = jz_clk_main_divs_inv[hdiv];
-+ mdiv_enc = jz_clk_main_divs_inv[mdiv];
-+ pdiv_enc = jz_clk_main_divs_inv[pdiv];
-+ if (cdiv_enc == (unsigned int)-1 ||
-+ hdiv_enc == (unsigned int)-1 ||
-+ mdiv_enc == (unsigned int)-1 ||
-+ pdiv_enc == (unsigned int)-1)
-+ return -EINVAL;
-+
-+ ctrl = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
-+ ctrl &= ~(JZ_CLOCK_CTRL_CHANGE_ENABLE |
-+ JZ_CLOCK_CTRL_CDIV_MASK | JZ_CLOCK_CTRL_HDIV_MASK |
-+ JZ_CLOCK_CTRL_MDIV_MASK | JZ_CLOCK_CTRL_PDIV_MASK);
-+ if (immediate) ctrl |= JZ_CLOCK_CTRL_CHANGE_ENABLE;
-+ ctrl |= (cdiv_enc << JZ_CLOCK_CTRL_CDIV_OFFSET) |
-+ (hdiv_enc << JZ_CLOCK_CTRL_HDIV_OFFSET) |
-+ (mdiv_enc << JZ_CLOCK_CTRL_MDIV_OFFSET) |
-+ (pdiv_enc << JZ_CLOCK_CTRL_PDIV_OFFSET);
-+
-+ /* set dividers */
-+ /* delay loops lifted from the old Ingenic cpufreq driver */
-+ wait = ((clk_get_rate(&jz_clk_cpu.clk) / 1000000) * 500) / 1000;
-+ __asm__ __volatile__(
-+ ".set noreorder\n\t"
-+ ".align 5\n"
-+ "sw %2,0(%1)\n\t"
-+ "li %0,0\n\t"
-+ "1:\n\t"
-+ "bne %0,%3,1b\n\t"
-+ "addi %0, 1\n\t"
-+ "nop\n\t"
-+ "nop\n\t"
-+ "nop\n\t"
-+ "nop\n\t"
-+ ".set reorder\n\t"
-+ : "=r" (tmp)
-+ : "r" (jz_clock_base + JZ_REG_CLOCK_CTRL), "r" (ctrl),
-+ "r" (wait));
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(clk_main_set_dividers);
-+
- static struct clk_ops jz_clk_static_ops = {
- .get_rate = jz_clk_static_get_rate,
- .enable = jz_clk_enable_gating,
-@@ -307,6 +511,8 @@ static struct static_clk jz_clk_ext = {
-
- static struct clk_ops jz_clk_pll_ops = {
- .get_rate = jz_clk_pll_get_rate,
-+ .set_rate = jz_clk_pll_set_rate,
-+ .round_rate = jz_clk_pll_round_rate,
- };
-
- static struct clk jz_clk_pll = {
-@@ -897,6 +1103,10 @@ static int jz4740_clock_init(void)
- if (!jz_clock_base)
- return -EBUSY;
-
-+ jz_emc_base = ioremap(JZ4740_EMC_BASE_ADDR, 0x100);
-+ if (!jz_emc_base)
-+ return -EBUSY;
-+
- spin_lock_init(&jz_clock_lock);
-
- jz_clk_ext.rate = jz4740_clock_bdata.ext_rate;
---- a/arch/mips/jz4740/clock.h
-+++ b/arch/mips/jz4740/clock.h
-@@ -17,6 +17,7 @@
- #define __MIPS_JZ4740_CLOCK_H__
-
- #include <linux/list.h>
-+#include <linux/types.h>
-
- struct jz4740_clock_board_data {
- unsigned long ext_rate;
-@@ -63,6 +64,9 @@ struct clk {
-
- int clk_is_enabled(struct clk *clk);
-
-+int clk_main_set_dividers(bool immediate, unsigned int cdiv, unsigned int hdiv,
-+ unsigned int mdiv, unsigned int pdiv);
-+
- #ifdef CONFIG_DEBUG_FS
- void jz4740_clock_debugfs_init(void);
- void jz4740_clock_debugfs_add_clk(struct clk *clk);