[xburst] time.c: Timer enable registers are only 8bit width.
[openwrt.git] / target / linux / xburst / files-2.6.32 / arch / mips / jz4740 / clock.c
index 853c6d8..a780706 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
 /*
  *  Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *     JZ4740 SoC TCU support
+ *     JZ4740 SoC clock support
  *
  *  This program is free software; you can redistribute         it and/or modify it
  *  under  the terms of         the GNU General  Public License as published by the
  *
  *  This program is free software; you can redistribute         it and/or modify it
  *  under  the terms of         the GNU General  Public License as published by the
 #include <linux/list.h>
 #include <linux/err.h>
 
 #include <linux/list.h>
 #include <linux/err.h>
 
+#include <asm/mach-jz4740/clock.h>
+#include "clock.h"
+
 #define JZ_REG_CLOCK_CTRL      0x00
 #define JZ_REG_CLOCK_CTRL      0x00
+#define JZ_REG_CLOCK_LOW_POWER 0x04
 #define JZ_REG_CLOCK_PLL       0x10
 #define JZ_REG_CLOCK_GATE      0x20
 #define JZ_REG_CLOCK_PLL       0x10
 #define JZ_REG_CLOCK_GATE      0x20
+#define JZ_REG_CLOCK_SLEEP_CTRL        0x24
 #define JZ_REG_CLOCK_I2S       0x60
 #define JZ_REG_CLOCK_LCD       0x64
 #define JZ_REG_CLOCK_MMC       0x68
 #define JZ_REG_CLOCK_I2S       0x60
 #define JZ_REG_CLOCK_LCD       0x64
 #define JZ_REG_CLOCK_MMC       0x68
@@ -50,8 +55,8 @@
 #define JZ_CLOCK_GATE_RTC      BIT(2)
 #define JZ_CLOCK_GATE_I2C      BIT(3)
 #define JZ_CLOCK_GATE_SPI      BIT(4)
 #define JZ_CLOCK_GATE_RTC      BIT(2)
 #define JZ_CLOCK_GATE_I2C      BIT(3)
 #define JZ_CLOCK_GATE_SPI      BIT(4)
-#define JZ_CLOCK_GATE_AIC_PCLK BIT(5)
-#define JZ_CLOCK_GATE_AIC      BIT(6)
+#define JZ_CLOCK_GATE_AIC      BIT(5)
+#define JZ_CLOCK_GATE_I2S      BIT(6)
 #define JZ_CLOCK_GATE_MMC      BIT(7)
 #define JZ_CLOCK_GATE_ADC      BIT(8)
 #define JZ_CLOCK_GATE_CIM      BIT(9)
 #define JZ_CLOCK_GATE_MMC      BIT(7)
 #define JZ_CLOCK_GATE_ADC      BIT(8)
 #define JZ_CLOCK_GATE_CIM      BIT(9)
 #define JZ_CLOCK_PLL_N_OFFSET          18
 #define JZ_CLOCK_PLL_OD_OFFSET         16
 
 #define JZ_CLOCK_PLL_N_OFFSET          18
 #define JZ_CLOCK_PLL_OD_OFFSET         16
 
+#define JZ_CLOCK_LOW_POWER_MODE_DOZE BIT(2)
+#define JZ_CLOCK_LOW_POWER_MODE_SLEEP BIT(0)
+
+#define JZ_CLOCK_SLEEP_CTRL_SUSPEND_UHC BIT(7)
+#define JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC BIT(6)
+
 static void __iomem *jz_clock_base;
 static spinlock_t jz_clock_lock;
 static LIST_HEAD(jz_clocks);
 
 static void __iomem *jz_clock_base;
 static spinlock_t jz_clock_lock;
 static LIST_HEAD(jz_clocks);
 
-struct clk {
-       const char *name;
-       struct clk* parent;
-
-       uint32_t gate_bit;
-
-       unsigned long (*get_rate)(struct clk* clk);
-       unsigned long (*round_rate)(struct clk *clk, unsigned long rate);
-       int (*set_rate)(struct clk* clk, unsigned long rate);
-       int (*enable)(struct clk* clk);
-       int (*disable)(struct clk* clk);
-
-       int (*set_parent)(struct clk* clk, struct clk *parent);
-       struct list_head list;
-};
-
 struct main_clk {
        struct clk clk;
        uint32_t div_offset;
 struct main_clk {
        struct clk clk;
        uint32_t div_offset;
@@ -161,33 +156,51 @@ static void jz_clk_reg_clear_bits(int reg, uint32_t mask)
 
 static int jz_clk_enable_gating(struct clk *clk)
 {
 
 static int jz_clk_enable_gating(struct clk *clk)
 {
+       if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
+               return -EINVAL;
+
        jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
        return 0;
 }
 
 static int jz_clk_disable_gating(struct clk *clk)
 {
        jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
        return 0;
 }
 
 static int jz_clk_disable_gating(struct clk *clk)
 {
+       if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
+               return -EINVAL;
+
        jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
        return 0;
 }
 
        jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, clk->gate_bit);
        return 0;
 }
 
+static int jz_clk_is_enabled_gating(struct clk *clk)
+{
+       if (clk->gate_bit == JZ4740_CLK_NOT_GATED)
+               return 1;
+
+       return !(jz_clk_reg_read(JZ_REG_CLOCK_GATE) & clk->gate_bit);
+}
+
 static unsigned long jz_clk_static_get_rate(struct clk *clk)
 {
        return ((struct static_clk*)clk)->rate;
 }
 
 static unsigned long jz_clk_static_get_rate(struct clk *clk)
 {
        return ((struct static_clk*)clk)->rate;
 }
 
-static int jz_clk_ko_enable(struct clkclk)
+static int jz_clk_ko_enable(struct clk *clk)
 {
        jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
        return 0;
 }
 
 {
        jz_clk_reg_set_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
        return 0;
 }
 
-static int jz_clk_ko_disable(struct clkclk)
+static int jz_clk_ko_disable(struct clk *clk)
 {
        jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
        return 0;
 }
 
 {
        jz_clk_reg_clear_bits(JZ_REG_CLOCK_CTRL, JZ_CLOCK_CTRL_KO_ENABLE);
        return 0;
 }
 
+static int jz_clk_ko_is_enabled(struct clk *clk)
+{
+       return !!(jz_clk_reg_read(JZ_REG_CLOCK_CTRL) & JZ_CLOCK_CTRL_KO_ENABLE);
+}
 
 static const int pllno[] = {1, 2, 2, 4};
 
 
 static const int pllno[] = {1, 2, 2, 4};
 
@@ -220,8 +233,6 @@ static unsigned long jz_clk_pll_half_get_rate(struct clk *clk)
        return jz_clk_pll_get_rate(clk->parent) >> 1;
 }
 
        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};
 
 static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
 static const int jz_clk_main_divs[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
 
 static unsigned long jz_clk_main_round_rate(struct clk *clk, unsigned long rate)
@@ -276,33 +287,52 @@ static int jz_clk_main_set_rate(struct clk *clk, unsigned long rate)
        return 0;
 }
 
        return 0;
 }
 
+static struct clk_ops jz_clk_static_ops = {
+       .get_rate = jz_clk_static_get_rate,
+       .enable = jz_clk_enable_gating,
+       .disable = jz_clk_disable_gating,
+       .is_enabled = jz_clk_is_enabled_gating,
+};
 
 static struct static_clk jz_clk_ext = {
        .clk = {
                .name = "ext",
 
 static struct static_clk jz_clk_ext = {
        .clk = {
                .name = "ext",
-               .get_rate = jz_clk_static_get_rate,
+               .gate_bit = JZ4740_CLK_NOT_GATED,
+               .ops = &jz_clk_static_ops,
        },
 };
 
        },
 };
 
+static struct clk_ops jz_clk_pll_ops = {
+       .get_rate = jz_clk_static_get_rate,
+};
+
 static struct clk jz_clk_pll = {
        .name = "pll",
        .parent = &jz_clk_ext.clk,
 static struct clk jz_clk_pll = {
        .name = "pll",
        .parent = &jz_clk_ext.clk,
-       .get_rate = jz_clk_pll_get_rate,
+       .ops = &jz_clk_pll_ops,
+};
+
+static struct clk_ops jz_clk_pll_half_ops = {
+       .get_rate = jz_clk_pll_half_get_rate,
 };
 
 static struct clk jz_clk_pll_half = {
        .name = "pll half",
        .parent = &jz_clk_pll,
 };
 
 static struct clk jz_clk_pll_half = {
        .name = "pll half",
        .parent = &jz_clk_pll,
-       .get_rate = jz_clk_pll_half_get_rate,
+       .ops = &jz_clk_pll_half_ops,
+};
+
+static const struct clk_ops jz_clk_main_ops = {
+       .get_rate = jz_clk_main_get_rate,
+       .set_rate = jz_clk_main_set_rate,
+       .round_rate = jz_clk_main_round_rate,
 };
 
 static struct main_clk jz_clk_cpu = {
        .clk = {
                .name = "cclk",
                .parent = &jz_clk_pll,
 };
 
 static struct main_clk jz_clk_cpu = {
        .clk = {
                .name = "cclk",
                .parent = &jz_clk_pll,
-               .get_rate = jz_clk_main_get_rate,
-               .set_rate = jz_clk_main_set_rate,
-               .round_rate = jz_clk_main_round_rate,
+               .ops = &jz_clk_main_ops,
        },
        .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
 };
        },
        .div_offset = JZ_CLOCK_CTRL_CDIV_OFFSET,
 };
@@ -311,9 +341,7 @@ static struct main_clk jz_clk_memory = {
        .clk = {
                .name = "mclk",
                .parent = &jz_clk_pll,
        .clk = {
                .name = "mclk",
                .parent = &jz_clk_pll,
-               .get_rate = jz_clk_main_get_rate,
-               .set_rate = jz_clk_main_set_rate,
-               .round_rate = jz_clk_main_round_rate,
+               .ops = &jz_clk_main_ops,
        },
        .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
 };
        },
        .div_offset = JZ_CLOCK_CTRL_MDIV_OFFSET,
 };
@@ -322,9 +350,7 @@ static struct main_clk jz_clk_high_speed_peripheral = {
        .clk = {
                .name = "hclk",
                .parent = &jz_clk_pll,
        .clk = {
                .name = "hclk",
                .parent = &jz_clk_pll,
-               .get_rate = jz_clk_main_get_rate,
-               .set_rate = jz_clk_main_set_rate,
-               .round_rate = jz_clk_main_round_rate,
+               .ops = &jz_clk_main_ops,
        },
        .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
 };
        },
        .div_offset = JZ_CLOCK_CTRL_HDIV_OFFSET,
 };
@@ -334,17 +360,21 @@ static struct main_clk jz_clk_low_speed_peripheral = {
        .clk = {
                .name = "pclk",
                .parent = &jz_clk_pll,
        .clk = {
                .name = "pclk",
                .parent = &jz_clk_pll,
-               .get_rate = jz_clk_main_get_rate,
-               .set_rate = jz_clk_main_set_rate,
+               .ops = &jz_clk_main_ops,
        },
        .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
 };
 
        },
        .div_offset = JZ_CLOCK_CTRL_PDIV_OFFSET,
 };
 
+static const struct clk_ops jz_clk_ko_ops = {
+       .enable = jz_clk_ko_enable,
+       .disable = jz_clk_ko_disable,
+       .is_enabled = jz_clk_ko_is_enabled,
+};
+
 static struct clk jz_clk_ko = {
        .name = "cko",
        .parent = &jz_clk_memory.clk,
 static struct clk jz_clk_ko = {
        .name = "cko",
        .parent = &jz_clk_memory.clk,
-       .enable = jz_clk_ko_enable,
-       .disable = jz_clk_ko_disable,
+       .ops = &jz_clk_ko_ops,
 };
 
 static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
 };
 
 static int jz_clk_spi_set_parent(struct clk *clk, struct clk *parent)
@@ -375,6 +405,27 @@ static int jz_clk_i2s_set_parent(struct clk *clk, struct clk *parent)
        return 0;
 }
 
        return 0;
 }
 
+static int jz_clk_udc_enable(struct clk *clk)
+{
+       jz_clk_reg_set_bits(JZ_REG_CLOCK_SLEEP_CTRL,
+                       JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
+
+       return 0;
+}
+
+static int jz_clk_udc_disable(struct clk *clk)
+{
+       jz_clk_reg_clear_bits(JZ_REG_CLOCK_SLEEP_CTRL,
+                       JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
+
+       return 0;
+}
+
+static int jz_clk_udc_is_enabled(struct clk *clk)
+{
+       return !!(jz_clk_reg_read(JZ_REG_CLOCK_SLEEP_CTRL) &
+                       JZ_CLOCK_SLEEP_CTRL_ENABLE_UDC);
+}
 static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
 {
        if (parent == &jz_clk_pll_half)
 static int jz_clk_udc_set_parent(struct clk *clk, struct clk *parent)
 {
        if (parent == &jz_clk_pll_half)
@@ -501,23 +552,23 @@ static unsigned long jz_clk_ldclk_get_rate(struct clk *clk)
        return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
 }
 
        return jz_clk_pll_half_get_rate(clk->parent) / (div + 1);
 }
 
-static struct clk jz_clk_ld = {
-       .name = "lcd",
-       .parent = &jz_clk_pll_half,
+static const struct clk_ops jz_clk_ops_ld = {
        .set_rate = jz_clk_ldclk_set_rate,
        .get_rate = jz_clk_ldclk_get_rate,
        .round_rate = jz_clk_ldclk_round_rate,
        .set_rate = jz_clk_ldclk_set_rate,
        .get_rate = jz_clk_ldclk_get_rate,
        .round_rate = jz_clk_ldclk_round_rate,
+       .enable = jz_clk_enable_gating,
+       .disable = jz_clk_disable_gating,
+       .is_enabled = jz_clk_is_enabled_gating,
 };
 
 };
 
-static struct divided_clk jz_clk_lp = {
-       .clk = {
-               .name = "lcd_pclk",
-               .parent = &jz_clk_pll_half,
-       },
-       .reg = JZ_REG_CLOCK_LCD,
-       .mask = JZ_CLOCK_LCD_DIV_MASK,
+static struct clk jz_clk_ld = {
+       .name = "lcd",
+       .gate_bit = JZ_CLOCK_GATE_LCD,
+       .parent = &jz_clk_pll_half,
+       .ops = &jz_clk_ops_ld,
 };
 
 };
 
+/* TODO: ops!!! */
 static struct clk jz_clk_cim_mclk = {
        .name = "cim_mclk",
        .parent = &jz_clk_high_speed_peripheral.clk,
 static struct clk jz_clk_cim_mclk = {
        .name = "cim_mclk",
        .parent = &jz_clk_high_speed_peripheral.clk,
@@ -527,156 +578,194 @@ static struct static_clk jz_clk_cim_pclk = {
        .clk = {
                .name = "cim_pclk",
                .gate_bit = JZ_CLOCK_GATE_CIM,
        .clk = {
                .name = "cim_pclk",
                .gate_bit = JZ_CLOCK_GATE_CIM,
-               .get_rate = jz_clk_static_get_rate,
-               .enable = jz_clk_enable_gating,
-               .disable = jz_clk_disable_gating,
+               .ops = &jz_clk_static_ops,
        },
 };
 
        },
 };
 
-static struct divided_clk jz_clk_i2s = {
-       .clk = {
-               .name = "i2s",
-               .parent = &jz_clk_ext.clk,
-               .gate_bit = JZ_CLOCK_GATE_AIC,
-               .set_rate = jz_clk_divided_set_rate,
-               .get_rate = jz_clk_divided_get_rate,
-               .enable = jz_clk_enable_gating,
-               .disable = jz_clk_disable_gating,
-               .set_parent = jz_clk_i2s_set_parent,
-       },
-       .reg = JZ_REG_CLOCK_I2S,
-       .mask = JZ_CLOCK_I2S_DIV_MASK,
-};
-
-static struct  divided_clk jz_clk_mmc = {
-       .clk = {
-               .name = "mmc",
-               .parent = &jz_clk_pll_half,
-               .gate_bit = JZ_CLOCK_GATE_MMC,
-               .set_rate = jz_clk_divided_set_rate,
-               .get_rate = jz_clk_divided_get_rate,
-               .enable = jz_clk_enable_gating,
-               .disable = jz_clk_disable_gating,
-       },
-       .reg = JZ_REG_CLOCK_MMC,
-       .mask = JZ_CLOCK_MMC_DIV_MASK,
-};
-
-static struct divided_clk jz_clk_uhc = {
-       .clk = {
-               .name = "uhc",
-               .parent = &jz_clk_pll_half,
-               .gate_bit = JZ_CLOCK_GATE_UHC,
-               .set_rate = jz_clk_divided_set_rate,
-               .get_rate = jz_clk_divided_get_rate,
-               .enable = jz_clk_enable_gating,
-               .disable = jz_clk_disable_gating,
-       },
-       .reg = JZ_REG_CLOCK_UHC,
-       .mask = JZ_CLOCK_UHC_DIV_MASK,
-};
-
-static struct clk jz_clk_udc = {
-       .name = "udc",
-       .parent = &jz_clk_ext.clk,
-       .set_parent = jz_clk_udc_set_parent,
-       .set_rate = jz_clk_udc_set_rate,
-       .get_rate = jz_clk_udc_get_rate,
-};
-
-static struct divided_clk jz_clk_spi = {
-       .clk = {
-               .name = "spi",
-               .parent = &jz_clk_ext.clk,
-               .gate_bit = JZ_CLOCK_GATE_SPI,
-               .set_rate = jz_clk_divided_set_rate,
-               .get_rate = jz_clk_divided_get_rate,
-               .enable = jz_clk_enable_gating,
-               .disable = jz_clk_disable_gating,
-               .set_parent = jz_clk_spi_set_parent,
-       },
-       .reg = JZ_REG_CLOCK_SPI,
-       .mask = JZ_CLOCK_SPI_DIV_MASK,
-};
-
-static struct clk jz_clk_uart0 = {
-       .name = "uart0",
-       .parent = &jz_clk_ext.clk,
-       .gate_bit = JZ_CLOCK_GATE_UART0,
+static const struct clk_ops jz_clk_i2s_ops = 
+{
+       .set_rate = jz_clk_divided_set_rate,
+       .get_rate = jz_clk_divided_get_rate,
        .enable = jz_clk_enable_gating,
        .disable = jz_clk_disable_gating,
        .enable = jz_clk_enable_gating,
        .disable = jz_clk_disable_gating,
+       .is_enabled = jz_clk_is_enabled_gating,
+       .set_parent = jz_clk_i2s_set_parent,
 };
 
 };
 
-static struct clk jz_clk_uart1 = {
-       .name = "uart1",
-       .parent = &jz_clk_ext.clk,
-       .gate_bit = JZ_CLOCK_GATE_UART1,
+static const struct clk_ops jz_clk_spi_ops = 
+{
+       .set_rate = jz_clk_divided_set_rate,
+       .get_rate = jz_clk_divided_get_rate,
        .enable = jz_clk_enable_gating,
        .disable = jz_clk_disable_gating,
        .enable = jz_clk_enable_gating,
        .disable = jz_clk_disable_gating,
+       .is_enabled = jz_clk_is_enabled_gating,
+       .set_parent = jz_clk_spi_set_parent,
 };
 
 };
 
-static struct clk jz_clk_dma = {
-       .name = "dma",
-       .parent = &jz_clk_high_speed_peripheral.clk,
-       .gate_bit = JZ_CLOCK_GATE_UART0,
+static const struct clk_ops jz_clk_divided_ops = 
+{
+       .set_rate = jz_clk_divided_set_rate,
+       .get_rate = jz_clk_divided_get_rate,
        .enable = jz_clk_enable_gating,
        .disable = jz_clk_disable_gating,
        .enable = jz_clk_enable_gating,
        .disable = jz_clk_disable_gating,
+       .is_enabled = jz_clk_is_enabled_gating,
 };
 
 };
 
-static struct clk jz_clk_ipu = {
-       .name = "ipu",
-       .parent = &jz_clk_high_speed_peripheral.clk,
-       .gate_bit = JZ_CLOCK_GATE_IPU,
-       .enable = jz_clk_enable_gating,
-       .disable = jz_clk_disable_gating,
+static struct divided_clk jz4740_clock_divided_clks[] = {
+       {
+               .clk = {
+                       .name = "lcd_pclk",
+                       .parent = &jz_clk_pll_half,
+                       .gate_bit = JZ4740_CLK_NOT_GATED,
+                       .ops = &jz_clk_divided_ops,
+               },
+               .reg = JZ_REG_CLOCK_LCD,
+               .mask = JZ_CLOCK_LCD_DIV_MASK,
+       },
+       {
+               .clk = {
+                       .name = "i2s",
+                       .parent = &jz_clk_ext.clk,
+                       .gate_bit = JZ_CLOCK_GATE_I2S,
+                       .ops = &jz_clk_i2s_ops,
+               },
+               .reg = JZ_REG_CLOCK_I2S,
+               .mask = JZ_CLOCK_I2S_DIV_MASK,
+       },
+       {
+               .clk = {
+                       .name = "spi",
+                       .parent = &jz_clk_ext.clk,
+                       .gate_bit = JZ_CLOCK_GATE_SPI,
+                       .ops = &jz_clk_spi_ops,
+               },
+               .reg = JZ_REG_CLOCK_SPI,
+               .mask = JZ_CLOCK_SPI_DIV_MASK,
+       },
+       {
+               .clk = {
+                       .name = "mmc",
+                       .parent = &jz_clk_pll_half,
+                       .gate_bit = JZ_CLOCK_GATE_MMC,
+                       .ops = &jz_clk_divided_ops,
+               },
+               .reg = JZ_REG_CLOCK_MMC,
+               .mask = JZ_CLOCK_MMC_DIV_MASK,
+       },
+       {
+               .clk = {
+                       .name = "uhc",
+                       .parent = &jz_clk_pll_half,
+                       .gate_bit = JZ_CLOCK_GATE_UHC,
+                       .ops = &jz_clk_divided_ops,
+               },
+               .reg = JZ_REG_CLOCK_UHC,
+               .mask = JZ_CLOCK_UHC_DIV_MASK,
+       },
 };
 
 };
 
-static struct clk jz_clk_adc = {
-       .name = "adc",
-       .parent = &jz_clk_ext.clk,
-       .gate_bit = JZ_CLOCK_GATE_ADC,
-       .enable = jz_clk_enable_gating,
-       .disable = jz_clk_disable_gating,
+static const struct clk_ops jz_clk_udc_ops = {
+       .set_parent = jz_clk_udc_set_parent,
+       .set_rate = jz_clk_udc_set_rate,
+       .get_rate = jz_clk_udc_get_rate,
+       .enable = jz_clk_udc_enable,
+       .disable = jz_clk_udc_disable,
+       .is_enabled = jz_clk_udc_is_enabled,
 };
 
 };
 
-static struct clk jz_clk_i2c = {
-       .name = "i2c",
-       .parent = &jz_clk_ext.clk,
-       .gate_bit = JZ_CLOCK_GATE_I2C,
+static const struct clk_ops jz_clk_simple_ops = {
        .enable = jz_clk_enable_gating,
        .disable = jz_clk_disable_gating,
        .enable = jz_clk_enable_gating,
        .disable = jz_clk_disable_gating,
+       .is_enabled = jz_clk_is_enabled_gating,
+};
+
+static struct clk jz4740_clock_simple_clks[] = {
+       {
+               .name = "udc",
+               .parent = &jz_clk_ext.clk,
+               .ops = &jz_clk_udc_ops,
+       },
+       {
+               .name = "uart0",
+               .parent = &jz_clk_ext.clk,
+               .gate_bit = JZ_CLOCK_GATE_UART0,
+               .ops = &jz_clk_simple_ops,
+       },
+       {
+               .name = "uart1",
+               .parent = &jz_clk_ext.clk,
+               .gate_bit = JZ_CLOCK_GATE_UART1,
+               .ops = &jz_clk_simple_ops,
+       },
+       {
+               .name = "dma",
+               .parent = &jz_clk_high_speed_peripheral.clk,
+               .gate_bit = JZ_CLOCK_GATE_UART0,
+               .ops = &jz_clk_simple_ops,
+       },
+       {
+               .name = "ipu",
+               .parent = &jz_clk_high_speed_peripheral.clk,
+               .gate_bit = JZ_CLOCK_GATE_IPU,
+               .ops = &jz_clk_simple_ops,
+       },
+       {
+               .name = "adc",
+               .parent = &jz_clk_ext.clk,
+               .gate_bit = JZ_CLOCK_GATE_ADC,
+               .ops = &jz_clk_simple_ops,
+       },
+       {
+               .name = "i2c",
+               .parent = &jz_clk_ext.clk,
+               .gate_bit = JZ_CLOCK_GATE_I2C,
+               .ops = &jz_clk_simple_ops,
+       },
+       {
+               .name = "aic",
+               .parent = &jz_clk_ext.clk,
+               .gate_bit = JZ_CLOCK_GATE_AIC,
+               .ops = &jz_clk_simple_ops,
+       },
 };
 
 static struct static_clk jz_clk_rtc = {
        .clk = {
                .name = "rtc",
                .gate_bit = JZ_CLOCK_GATE_RTC,
 };
 
 static struct static_clk jz_clk_rtc = {
        .clk = {
                .name = "rtc",
                .gate_bit = JZ_CLOCK_GATE_RTC,
-               .enable = jz_clk_enable_gating,
-               .disable = jz_clk_disable_gating,
+               .ops = &jz_clk_static_ops,
        },
        .rate = 32768,
 };
 
 int clk_enable(struct clk *clk)
 {
        },
        .rate = 32768,
 };
 
 int clk_enable(struct clk *clk)
 {
-       if (!clk->enable)
+       if (!clk->ops->enable)
                return -EINVAL;
 
                return -EINVAL;
 
-       return clk->enable(clk);
+       return clk->ops->enable(clk);
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
 void clk_disable(struct clk *clk)
 {
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
 void clk_disable(struct clk *clk)
 {
-       if (clk->disable)
-               clk->disable(clk);
+       if (clk->ops->disable)
+               clk->ops->disable(clk);
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
+int clk_is_enabled(struct clk *clk)
+{
+       if (clk->ops->is_enabled)
+               return clk->ops->is_enabled(clk);
+
+       return 1;
+}
+
 unsigned long clk_get_rate(struct clk *clk)
 {
 unsigned long clk_get_rate(struct clk *clk)
 {
-       if (clk->get_rate)
-               return clk->get_rate(clk);
+       if (clk->ops->get_rate)
+               return clk->ops->get_rate(clk);
        if (clk->parent)
                return clk_get_rate(clk->parent);
 
        if (clk->parent)
                return clk_get_rate(clk->parent);
 
@@ -686,16 +775,16 @@ EXPORT_SYMBOL_GPL(clk_get_rate);
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-       if (!clk->set_rate)
+       if (!clk->ops->set_rate)
                return -EINVAL;
                return -EINVAL;
-       return clk->set_rate(clk, rate);
+       return clk->ops->set_rate(clk, rate);
 }
 EXPORT_SYMBOL_GPL(clk_set_rate);
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
 }
 EXPORT_SYMBOL_GPL(clk_set_rate);
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
-       if (clk->round_rate)
-               return clk->round_rate(clk, rate);
+       if (clk->ops->round_rate)
+               return clk->ops->round_rate(clk, rate);
 
        return -EINVAL;
 }
 
        return -EINVAL;
 }
@@ -705,18 +794,19 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 {
        int ret;
 
 {
        int ret;
 
-       if (!clk->set_parent)
+       if (!clk->ops->set_parent)
                return -EINVAL;
 
                return -EINVAL;
 
-       clk->disable(clk);
-       ret = clk->set_parent(clk, parent);
-       clk->enable(clk);
+       clk_disable(clk);
+       ret = clk->ops->set_parent(clk, parent);
+       clk_enable(clk);
+
+       jz4740_clock_debugfs_update_parent(clk);
 
        return ret;
 }
 EXPORT_SYMBOL_GPL(clk_set_parent);
 
 
        return ret;
 }
 EXPORT_SYMBOL_GPL(clk_set_parent);
 
-
 struct clk *clk_get(struct device *dev, const char *name)
 {
        struct clk *clk;
 struct clk *clk_get(struct device *dev, const char *name)
 {
        struct clk *clk;
@@ -734,62 +824,107 @@ void clk_put(struct clk *clk)
 }
 EXPORT_SYMBOL_GPL(clk_put);
 
 }
 EXPORT_SYMBOL_GPL(clk_put);
 
+
 inline static void clk_add(struct clk *clk)
 {
 inline static void clk_add(struct clk *clk)
 {
-    list_add_tail(&clk->list, &jz_clocks);
+       list_add_tail(&clk->list, &jz_clocks);
+
+       jz4740_clock_debugfs_add_clk(clk);
 }
 
 static void clk_register_clks(void)
 {
 }
 
 static void clk_register_clks(void)
 {
-    clk_add(&jz_clk_ext.clk);
-    clk_add(&jz_clk_pll);
-    clk_add(&jz_clk_pll_half);
-    clk_add(&jz_clk_cpu.clk);
-    clk_add(&jz_clk_high_speed_peripheral.clk);
-    clk_add(&jz_clk_low_speed_peripheral.clk);
-    clk_add(&jz_clk_ko);
-    clk_add(&jz_clk_ld);
-    clk_add(&jz_clk_lp.clk);
-    clk_add(&jz_clk_cim_mclk);
-    clk_add(&jz_clk_cim_pclk.clk);
-    clk_add(&jz_clk_i2s.clk);
-    clk_add(&jz_clk_mmc.clk);
-    clk_add(&jz_clk_uhc.clk);
-    clk_add(&jz_clk_udc);
-    clk_add(&jz_clk_uart0);
-    clk_add(&jz_clk_uart1);
-    clk_add(&jz_clk_dma);
-    clk_add(&jz_clk_ipu);
-    clk_add(&jz_clk_adc);
-    clk_add(&jz_clk_i2c);
-    clk_add(&jz_clk_rtc.clk);
-}
-
-int jz_init_clocks(unsigned long ext_rate)
+       size_t i;
+
+       clk_add(&jz_clk_ext.clk);
+       clk_add(&jz_clk_pll);
+       clk_add(&jz_clk_pll_half);
+       clk_add(&jz_clk_cpu.clk);
+       clk_add(&jz_clk_high_speed_peripheral.clk);
+       clk_add(&jz_clk_low_speed_peripheral.clk);
+       clk_add(&jz_clk_ko);
+       clk_add(&jz_clk_ld);
+       clk_add(&jz_clk_cim_mclk);
+       clk_add(&jz_clk_cim_pclk.clk);
+       clk_add(&jz_clk_rtc.clk);
+
+       for (i = 0; i < ARRAY_SIZE(jz4740_clock_divided_clks); ++i)
+               clk_add(&jz4740_clock_divided_clks[i].clk);
+
+       for (i = 0; i < ARRAY_SIZE(jz4740_clock_simple_clks); ++i)
+               clk_add(&jz4740_clock_simple_clks[i]);
+}
+
+void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
+{
+       switch (mode) {
+       case JZ4740_WAIT_MODE_IDLE:
+               jz_clk_reg_clear_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
+               break;
+       case JZ4740_WAIT_MODE_SLEEP:
+               jz_clk_reg_set_bits(JZ_REG_CLOCK_LOW_POWER, JZ_CLOCK_LOW_POWER_MODE_SLEEP);
+               break;
+       }
+}
+
+void jz4740_clock_udc_disable_auto_suspend(void)
+{
+       jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
+}
+EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
+
+void jz4740_clock_udc_enable_auto_suspend(void)
+{
+       jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE, JZ_CLOCK_GATE_UDC);
+}
+EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
+
+void jz4740_clock_suspend(void)
+{
+       jz_clk_reg_set_bits(JZ_REG_CLOCK_GATE,
+               JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
+
+       jz_clk_reg_clear_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
+}
+
+void jz4740_clock_resume(void)
+{
+       jz_clk_reg_set_bits(JZ_REG_CLOCK_PLL, JZ_CLOCK_PLL_ENABLED);
+       while ((jz_clk_reg_read(JZ_REG_CLOCK_PLL) & JZ_CLOCK_PLL_STABLE) == 0);
+
+       jz_clk_reg_clear_bits(JZ_REG_CLOCK_GATE,
+               JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0);
+}
+
+int jz4740_clock_init(void)
 {
        uint32_t val;
 
 {
        uint32_t val;
 
-       jz_clock_base = ioremap(0x10000000, 0x100);
+       jz_clock_base = ioremap(CPHYSADDR(CPM_BASE), 0x100);
        if (!jz_clock_base)
                return -EBUSY;
 
        if (!jz_clock_base)
                return -EBUSY;
 
-       jz_clk_ext.rate = ext_rate;
+       spin_lock_init(&jz_clock_lock);
+
+       jz_clk_ext.rate = jz4740_clock_bdata.ext_rate;
+       jz_clk_rtc.rate = jz4740_clock_bdata.rtc_rate;
 
        val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
 
        if (val & JZ_CLOCK_SPI_SRC_PLL)
 
        val = jz_clk_reg_read(JZ_REG_CLOCK_SPI);
 
        if (val & JZ_CLOCK_SPI_SRC_PLL)
-               jz_clk_spi.clk.parent = &jz_clk_pll_half;
+               jz4740_clock_divided_clks[1].clk.parent = &jz_clk_pll_half;
 
        val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
 
        if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
 
        val = jz_clk_reg_read(JZ_REG_CLOCK_CTRL);
 
        if (val & JZ_CLOCK_CTRL_I2S_SRC_PLL)
-               jz_clk_i2s.clk.parent = &jz_clk_pll_half;
+               jz4740_clock_divided_clks[0].clk.parent = &jz_clk_pll_half;
 
        if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
 
        if (val & JZ_CLOCK_CTRL_UDC_SRC_PLL)
-               jz_clk_udc.parent = &jz_clk_pll_half;
+               jz4740_clock_simple_clks[0].parent = &jz_clk_pll_half;
+
+       jz4740_clock_debugfs_init();
 
        clk_register_clks();
 
        return 0;
 }
 
        clk_register_clks();
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(jz_init_clocks);
This page took 0.050614 seconds and 4 git commands to generate.