* [PATCH 0/2] mmc: dw_mmc: k3 remove clk_table
@ 2014-01-13 9:14 ` Zhangfei Gao
0 siblings, 0 replies; 44+ messages in thread
From: Zhangfei Gao @ 2014-01-13 9:14 UTC (permalink / raw)
To: Chris Ball, Arnd Bergmann, Mike Turquette, Jaehoon Chung,
Seungwon Jeon, Haojian Zhuang, brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao
clk_table is used to set clock source in each mode, as well as limitation, max_rate and init rate.
It concerned many experts though, and Seungwon recommended some limitation can be hide in clk.c.
Also soc is updated as the limitation now same as max_rate, so directly using ios->clock.
Zhangfei Gao (2):
clk: hisilicon: add hi3620_mmc_clks
mmc: dw_mmc: k3: remove clk_table
.../bindings/arm/hisilicon/hisilicon.txt | 14 +
.../devicetree/bindings/clock/hi3620-clock.txt | 1 +
.../devicetree/bindings/mmc/k3-dw-mshc.txt | 14 -
drivers/clk/hisilicon/clk-hi3620.c | 267 ++++++++++++++++++++
drivers/mmc/host/dw_mmc-k3.c | 41 +--
include/dt-bindings/clock/hi3620-clock.h | 5 +
6 files changed, 289 insertions(+), 53 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 0/2] mmc: dw_mmc: k3 remove clk_table
@ 2014-01-13 9:14 ` Zhangfei Gao
0 siblings, 0 replies; 44+ messages in thread
From: Zhangfei Gao @ 2014-01-13 9:14 UTC (permalink / raw)
To: linux-arm-kernel
clk_table is used to set clock source in each mode, as well as limitation, max_rate and init rate.
It concerned many experts though, and Seungwon recommended some limitation can be hide in clk.c.
Also soc is updated as the limitation now same as max_rate, so directly using ios->clock.
Zhangfei Gao (2):
clk: hisilicon: add hi3620_mmc_clks
mmc: dw_mmc: k3: remove clk_table
.../bindings/arm/hisilicon/hisilicon.txt | 14 +
.../devicetree/bindings/clock/hi3620-clock.txt | 1 +
.../devicetree/bindings/mmc/k3-dw-mshc.txt | 14 -
drivers/clk/hisilicon/clk-hi3620.c | 267 ++++++++++++++++++++
drivers/mmc/host/dw_mmc-k3.c | 41 +--
include/dt-bindings/clock/hi3620-clock.h | 5 +
6 files changed, 289 insertions(+), 53 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-13 9:14 ` Zhangfei Gao
@ 2014-01-13 9:14 ` Zhangfei Gao
-1 siblings, 0 replies; 44+ messages in thread
From: Zhangfei Gao @ 2014-01-13 9:14 UTC (permalink / raw)
To: Chris Ball, Arnd Bergmann, Mike Turquette, Jaehoon Chung,
Seungwon Jeon, Haojian Zhuang, brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao
Suggest by Arnd: abstract mmc tuning as clock behavior,
also because different soc have different tuning method and registers.
hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
---
.../bindings/arm/hisilicon/hisilicon.txt | 14 +
.../devicetree/bindings/clock/hi3620-clock.txt | 1 +
drivers/clk/hisilicon/clk-hi3620.c | 267 ++++++++++++++++++++
include/dt-bindings/clock/hi3620-clock.h | 5 +
4 files changed, 287 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 8c7a4653508d..df0a452b8526 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -30,3 +30,17 @@ Example:
resume-offset = <0x308>;
reboot-offset = <0x4>;
};
+
+PCTRL: Peripheral misc control register
+
+Required Properties:
+- compatible: "hisilicon,pctrl"
+- reg: Address and size of pctrl.
+
+Example:
+
+ /* for Hi3620 */
+ pctrl: pctrl@fca09000 {
+ compatible = "hisilicon,pctrl";
+ reg = <0xfca09000 0x1000>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
index 4b71ab41be53..dad6269f52c5 100644
--- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
+++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
@@ -7,6 +7,7 @@ Required Properties:
- compatible: should be one of the following.
- "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
+ - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
- reg: physical base address of the controller and length of memory mapped
region.
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index f24ad6a3a797..54cc3475ec36 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -240,3 +240,270 @@ static void __init hi3620_clk_init(struct device_node *np)
base);
}
CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
+
+struct hisi_mmc_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ u32 clken_reg;
+ u32 clken_bit;
+ u32 div_reg;
+ u32 div_off;
+ u32 div_bits;
+ u32 drv_reg;
+ u32 drv_off;
+ u32 drv_bits;
+ u32 sam_reg;
+ u32 sam_off;
+ u32 sam_bits;
+};
+
+struct clk_mmc {
+ struct clk_hw hw;
+ u32 id;
+ void __iomem *clken_reg;
+ u32 clken_bit;
+ void __iomem *div_reg;
+ u32 div_off;
+ u32 div_bits;
+ void __iomem *drv_reg;
+ u32 drv_off;
+ u32 drv_bits;
+ void __iomem *sam_reg;
+ u32 sam_off;
+ u32 sam_bits;
+};
+
+#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
+
+static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
+ { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
+ { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
+ { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
+ { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
+};
+
+static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ switch (parent_rate) {
+ case 26000000:
+ return 13000000;
+ case 180000000:
+ return 25000000;
+ case 360000000:
+ return 50000000;
+ case 720000000:
+ return 100000000;
+ default:
+ return parent_rate;
+ }
+}
+
+static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *best_parent_rate,
+ struct clk **best_parent_p)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long best = 0;
+
+ if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
+ rate = 13000000;
+ best = 26000000;
+ } else if (rate <= 26000000) {
+ rate = 25000000;
+ best = 180000000;
+ } else if (rate <= 52000000) {
+ rate = 50000000;
+ best = 360000000;
+ } else if (rate <= 100000000) {
+ rate = 100000000;
+ best = 720000000;
+ } else {
+ /* max is 180M */
+ rate = 180000000;
+ best = 1440000000;
+ }
+ *best_parent_rate = best;
+ return rate;
+}
+
+static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
+{
+ u32 i;
+
+ if (para >= 0) {
+ for (i = 0; i < len; i++) {
+ if (para % 2)
+ val |= 1 << (off + i);
+ else
+ val &= ~(1 << (off + i));
+ para = para >> 1;
+ }
+ }
+ return val;
+}
+
+static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long flags;
+ u32 sam, drv, div, val;
+ static DEFINE_SPINLOCK(mmc_clk_lock);
+
+ switch (rate) {
+ case 13000000:
+ sam = 3;
+ drv = 1;
+ div = 1;
+ break;
+ case 25000000:
+ sam = 13;
+ drv = 6;
+ div = 6;
+ break;
+ case 50000000:
+ sam = 3;
+ drv = 6;
+ div = 6;
+ break;
+ case 100000000:
+ sam = 6;
+ drv = 4;
+ div = 6;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&mmc_clk_lock, flags);
+
+ val = readl_relaxed(mclk->clken_reg);
+ val &= ~(1 << mclk->clken_bit);
+ writel_relaxed(val, mclk->clken_reg);
+
+ val = readl_relaxed(mclk->sam_reg);
+ val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
+ writel_relaxed(val, mclk->sam_reg);
+
+ val = readl_relaxed(mclk->drv_reg);
+ val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
+ writel_relaxed(val, mclk->drv_reg);
+
+ val = readl_relaxed(mclk->div_reg);
+ val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
+ writel_relaxed(val, mclk->div_reg);
+
+ val = readl_relaxed(mclk->clken_reg);
+ val |= 1 << mclk->clken_bit;
+ writel_relaxed(val, mclk->clken_reg);
+
+ spin_unlock_irqrestore(&mmc_clk_lock, flags);
+
+ return 0;
+}
+
+static int mmc_clk_prepare(struct clk_hw *hw)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long rate;
+
+ if (mclk->id == HI3620_MMC_CIUCLK1)
+ rate = 13000000;
+ else
+ rate = 25000000;
+
+ return mmc_clk_set_timing(hw, rate);
+}
+
+static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ return mmc_clk_set_timing(hw, rate);
+}
+
+static struct clk_ops clk_mmc_ops = {
+ .prepare = mmc_clk_prepare,
+ .determine_rate = mmc_clk_determine_rate,
+ .set_rate = mmc_clk_set_rate,
+ .recalc_rate = mmc_clk_recalc_rate,
+};
+
+static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
+ void __iomem *base, struct device_node *np)
+{
+ struct clk_mmc *mclk;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
+ if (!mclk) {
+ pr_err("%s: fail to allocate mmc clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ init.name = mmc_clk->name;
+ init.ops = &clk_mmc_ops;
+ init.flags = mmc_clk->flags | CLK_IS_BASIC;
+ init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
+ init.num_parents = (mmc_clk->parent_name ? 1 : 0);
+ mclk->hw.init = &init;
+
+ mclk->id = mmc_clk->id;
+ mclk->clken_reg = base + mmc_clk->clken_reg;
+ mclk->clken_bit = mmc_clk->clken_bit;
+ mclk->div_reg = base + mmc_clk->div_reg;
+ mclk->div_off = mmc_clk->div_off;
+ mclk->div_bits = mmc_clk->div_bits;
+ mclk->drv_reg = base + mmc_clk->drv_reg;
+ mclk->drv_off = mmc_clk->drv_off;
+ mclk->drv_bits = mmc_clk->drv_bits;
+ mclk->sam_reg = base + mmc_clk->sam_reg;
+ mclk->sam_off = mmc_clk->sam_off;
+ mclk->sam_bits = mmc_clk->sam_bits;
+
+ clk = clk_register(NULL, &mclk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ kfree(mclk);
+ return clk;
+}
+
+static void __init hi3620_mmc_clk_init(struct device_node *node)
+{
+ void __iomem *base;
+ int i, num = ARRAY_SIZE(hi3620_mmc_clks);
+ struct clk_onecell_data *clk_data;
+
+ if (!node) {
+ pr_err("failed to find pctrl node in DTS\n");
+ return;
+ }
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("failed to map pctrl\n");
+ return;
+ }
+
+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+ if (WARN_ON(!clk_data))
+ return;
+
+ clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
+ if (!clk_data->clks) {
+ pr_err("%s: fail to allocate mmc clk\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < num; i++) {
+ struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
+ clk_data->clks[mmc_clk->id] =
+ hisi_register_clk_mmc(mmc_clk, base, node);
+ }
+
+ clk_data->clk_num = num;
+ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
index 6eaa6a45e110..21b9d0e2eb0c 100644
--- a/include/dt-bindings/clock/hi3620-clock.h
+++ b/include/dt-bindings/clock/hi3620-clock.h
@@ -147,6 +147,11 @@
#define HI3620_MMC_CLK3 217
#define HI3620_MCU_CLK 218
+#define HI3620_SD_CIUCLK 0
+#define HI3620_MMC_CIUCLK1 1
+#define HI3620_MMC_CIUCLK2 2
+#define HI3620_MMC_CIUCLK3 3
+
#define HI3620_NR_CLKS 219
#endif /* __DTS_HI3620_CLOCK_H */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-13 9:14 ` Zhangfei Gao
0 siblings, 0 replies; 44+ messages in thread
From: Zhangfei Gao @ 2014-01-13 9:14 UTC (permalink / raw)
To: linux-arm-kernel
Suggest by Arnd: abstract mmc tuning as clock behavior,
also because different soc have different tuning method and registers.
hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
---
.../bindings/arm/hisilicon/hisilicon.txt | 14 +
.../devicetree/bindings/clock/hi3620-clock.txt | 1 +
drivers/clk/hisilicon/clk-hi3620.c | 267 ++++++++++++++++++++
include/dt-bindings/clock/hi3620-clock.h | 5 +
4 files changed, 287 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 8c7a4653508d..df0a452b8526 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -30,3 +30,17 @@ Example:
resume-offset = <0x308>;
reboot-offset = <0x4>;
};
+
+PCTRL: Peripheral misc control register
+
+Required Properties:
+- compatible: "hisilicon,pctrl"
+- reg: Address and size of pctrl.
+
+Example:
+
+ /* for Hi3620 */
+ pctrl: pctrl at fca09000 {
+ compatible = "hisilicon,pctrl";
+ reg = <0xfca09000 0x1000>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
index 4b71ab41be53..dad6269f52c5 100644
--- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
+++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
@@ -7,6 +7,7 @@ Required Properties:
- compatible: should be one of the following.
- "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
+ - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
- reg: physical base address of the controller and length of memory mapped
region.
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index f24ad6a3a797..54cc3475ec36 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -240,3 +240,270 @@ static void __init hi3620_clk_init(struct device_node *np)
base);
}
CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
+
+struct hisi_mmc_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ u32 clken_reg;
+ u32 clken_bit;
+ u32 div_reg;
+ u32 div_off;
+ u32 div_bits;
+ u32 drv_reg;
+ u32 drv_off;
+ u32 drv_bits;
+ u32 sam_reg;
+ u32 sam_off;
+ u32 sam_bits;
+};
+
+struct clk_mmc {
+ struct clk_hw hw;
+ u32 id;
+ void __iomem *clken_reg;
+ u32 clken_bit;
+ void __iomem *div_reg;
+ u32 div_off;
+ u32 div_bits;
+ void __iomem *drv_reg;
+ u32 drv_off;
+ u32 drv_bits;
+ void __iomem *sam_reg;
+ u32 sam_off;
+ u32 sam_bits;
+};
+
+#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
+
+static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
+ { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
+ { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
+ { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
+ { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
+};
+
+static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ switch (parent_rate) {
+ case 26000000:
+ return 13000000;
+ case 180000000:
+ return 25000000;
+ case 360000000:
+ return 50000000;
+ case 720000000:
+ return 100000000;
+ default:
+ return parent_rate;
+ }
+}
+
+static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *best_parent_rate,
+ struct clk **best_parent_p)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long best = 0;
+
+ if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
+ rate = 13000000;
+ best = 26000000;
+ } else if (rate <= 26000000) {
+ rate = 25000000;
+ best = 180000000;
+ } else if (rate <= 52000000) {
+ rate = 50000000;
+ best = 360000000;
+ } else if (rate <= 100000000) {
+ rate = 100000000;
+ best = 720000000;
+ } else {
+ /* max is 180M */
+ rate = 180000000;
+ best = 1440000000;
+ }
+ *best_parent_rate = best;
+ return rate;
+}
+
+static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
+{
+ u32 i;
+
+ if (para >= 0) {
+ for (i = 0; i < len; i++) {
+ if (para % 2)
+ val |= 1 << (off + i);
+ else
+ val &= ~(1 << (off + i));
+ para = para >> 1;
+ }
+ }
+ return val;
+}
+
+static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long flags;
+ u32 sam, drv, div, val;
+ static DEFINE_SPINLOCK(mmc_clk_lock);
+
+ switch (rate) {
+ case 13000000:
+ sam = 3;
+ drv = 1;
+ div = 1;
+ break;
+ case 25000000:
+ sam = 13;
+ drv = 6;
+ div = 6;
+ break;
+ case 50000000:
+ sam = 3;
+ drv = 6;
+ div = 6;
+ break;
+ case 100000000:
+ sam = 6;
+ drv = 4;
+ div = 6;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&mmc_clk_lock, flags);
+
+ val = readl_relaxed(mclk->clken_reg);
+ val &= ~(1 << mclk->clken_bit);
+ writel_relaxed(val, mclk->clken_reg);
+
+ val = readl_relaxed(mclk->sam_reg);
+ val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
+ writel_relaxed(val, mclk->sam_reg);
+
+ val = readl_relaxed(mclk->drv_reg);
+ val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
+ writel_relaxed(val, mclk->drv_reg);
+
+ val = readl_relaxed(mclk->div_reg);
+ val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
+ writel_relaxed(val, mclk->div_reg);
+
+ val = readl_relaxed(mclk->clken_reg);
+ val |= 1 << mclk->clken_bit;
+ writel_relaxed(val, mclk->clken_reg);
+
+ spin_unlock_irqrestore(&mmc_clk_lock, flags);
+
+ return 0;
+}
+
+static int mmc_clk_prepare(struct clk_hw *hw)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long rate;
+
+ if (mclk->id == HI3620_MMC_CIUCLK1)
+ rate = 13000000;
+ else
+ rate = 25000000;
+
+ return mmc_clk_set_timing(hw, rate);
+}
+
+static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ return mmc_clk_set_timing(hw, rate);
+}
+
+static struct clk_ops clk_mmc_ops = {
+ .prepare = mmc_clk_prepare,
+ .determine_rate = mmc_clk_determine_rate,
+ .set_rate = mmc_clk_set_rate,
+ .recalc_rate = mmc_clk_recalc_rate,
+};
+
+static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
+ void __iomem *base, struct device_node *np)
+{
+ struct clk_mmc *mclk;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
+ if (!mclk) {
+ pr_err("%s: fail to allocate mmc clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ init.name = mmc_clk->name;
+ init.ops = &clk_mmc_ops;
+ init.flags = mmc_clk->flags | CLK_IS_BASIC;
+ init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
+ init.num_parents = (mmc_clk->parent_name ? 1 : 0);
+ mclk->hw.init = &init;
+
+ mclk->id = mmc_clk->id;
+ mclk->clken_reg = base + mmc_clk->clken_reg;
+ mclk->clken_bit = mmc_clk->clken_bit;
+ mclk->div_reg = base + mmc_clk->div_reg;
+ mclk->div_off = mmc_clk->div_off;
+ mclk->div_bits = mmc_clk->div_bits;
+ mclk->drv_reg = base + mmc_clk->drv_reg;
+ mclk->drv_off = mmc_clk->drv_off;
+ mclk->drv_bits = mmc_clk->drv_bits;
+ mclk->sam_reg = base + mmc_clk->sam_reg;
+ mclk->sam_off = mmc_clk->sam_off;
+ mclk->sam_bits = mmc_clk->sam_bits;
+
+ clk = clk_register(NULL, &mclk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ kfree(mclk);
+ return clk;
+}
+
+static void __init hi3620_mmc_clk_init(struct device_node *node)
+{
+ void __iomem *base;
+ int i, num = ARRAY_SIZE(hi3620_mmc_clks);
+ struct clk_onecell_data *clk_data;
+
+ if (!node) {
+ pr_err("failed to find pctrl node in DTS\n");
+ return;
+ }
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("failed to map pctrl\n");
+ return;
+ }
+
+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+ if (WARN_ON(!clk_data))
+ return;
+
+ clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
+ if (!clk_data->clks) {
+ pr_err("%s: fail to allocate mmc clk\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < num; i++) {
+ struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
+ clk_data->clks[mmc_clk->id] =
+ hisi_register_clk_mmc(mmc_clk, base, node);
+ }
+
+ clk_data->clk_num = num;
+ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
index 6eaa6a45e110..21b9d0e2eb0c 100644
--- a/include/dt-bindings/clock/hi3620-clock.h
+++ b/include/dt-bindings/clock/hi3620-clock.h
@@ -147,6 +147,11 @@
#define HI3620_MMC_CLK3 217
#define HI3620_MCU_CLK 218
+#define HI3620_SD_CIUCLK 0
+#define HI3620_MMC_CIUCLK1 1
+#define HI3620_MMC_CIUCLK2 2
+#define HI3620_MMC_CIUCLK3 3
+
#define HI3620_NR_CLKS 219
#endif /* __DTS_HI3620_CLOCK_H */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
2014-01-13 9:14 ` Zhangfei Gao
@ 2014-01-13 9:14 ` Zhangfei Gao
-1 siblings, 0 replies; 44+ messages in thread
From: Zhangfei Gao @ 2014-01-13 9:14 UTC (permalink / raw)
To: Chris Ball, Arnd Bergmann, Mike Turquette, Jaehoon Chung,
Seungwon Jeon, Haojian Zhuang, brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao
Remove clk_table and directly use ios->clock as clock source rate.
Abstract init clock rate and max clock limitation in clk.c
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
---
.../devicetree/bindings/mmc/k3-dw-mshc.txt | 14 -------
drivers/mmc/host/dw_mmc-k3.c | 41 +-------------------
2 files changed, 2 insertions(+), 53 deletions(-)
diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
index d7e2d7f159bb..b8653ea97957 100644
--- a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -14,18 +14,6 @@ Required Properties:
* compatible: should be one of the following.
- "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
-* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
- in each supported mode.
- 0. CIU clock rate in Hz for DS mode
- 1. CIU clock rate in Hz for MMC HS mode
- 2. CIU clock rate in Hz for SD HS mode
- 3. CIU clock rate in Hz for SDR12 mode
- 4. CIU clock rate in Hz for SDR25 mode
- 5. CIU clock rate in Hz for SDR50 mode
- 6. CIU clock rate in Hz for SDR104 mode
- 7. CIU clock rate in Hz for DDR50 mode
- 8. CIU clock rate in Hz for HS200 mode
-
Example:
/* for Hi3620 */
@@ -39,8 +27,6 @@ Example:
#size-cells = <0>;
clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
clock-names = "ciu", "biu";
- clock-freq-table =
- <25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
};
/* Board portion */
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
index 68e5e428e8f6..84e1a670f8c7 100644
--- a/drivers/mmc/host/dw_mmc-k3.c
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -18,56 +18,19 @@
#include "dw_mmc.h"
#include "dw_mmc-pltfm.h"
-#define MAX_NUMS 10
-struct dw_mci_k3_priv_data {
- u32 clk_table[MAX_NUMS];
-};
-
static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
{
- struct dw_mci_k3_priv_data *priv = host->priv;
- u32 rate = priv->clk_table[ios->timing];
int ret;
- if (!rate) {
- dev_warn(host->dev,
- "no specified rate in timing %u\n", ios->timing);
- return;
- }
-
- ret = clk_set_rate(host->ciu_clk, rate);
+ ret = clk_set_rate(host->ciu_clk, ios->clock);
if (ret)
- dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+ dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock);
host->bus_hz = clk_get_rate(host->ciu_clk);
}
-static int dw_mci_k3_parse_dt(struct dw_mci *host)
-{
- struct dw_mci_k3_priv_data *priv;
- struct device_node *node = host->dev->of_node;
- struct property *prop;
- const __be32 *cur;
- u32 val, num = 0;
-
- priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(host->dev, "mem alloc failed for private data\n");
- return -ENOMEM;
- }
- host->priv = priv;
-
- of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
- if (num >= MAX_NUMS)
- break;
- priv->clk_table[num++] = val;
- }
- return 0;
-}
-
static const struct dw_mci_drv_data k3_drv_data = {
.set_ios = dw_mci_k3_set_ios,
- .parse_dt = dw_mci_k3_parse_dt,
};
static const struct of_device_id dw_mci_k3_match[] = {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
@ 2014-01-13 9:14 ` Zhangfei Gao
0 siblings, 0 replies; 44+ messages in thread
From: Zhangfei Gao @ 2014-01-13 9:14 UTC (permalink / raw)
To: linux-arm-kernel
Remove clk_table and directly use ios->clock as clock source rate.
Abstract init clock rate and max clock limitation in clk.c
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
---
.../devicetree/bindings/mmc/k3-dw-mshc.txt | 14 -------
drivers/mmc/host/dw_mmc-k3.c | 41 +-------------------
2 files changed, 2 insertions(+), 53 deletions(-)
diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
index d7e2d7f159bb..b8653ea97957 100644
--- a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -14,18 +14,6 @@ Required Properties:
* compatible: should be one of the following.
- "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
-* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
- in each supported mode.
- 0. CIU clock rate in Hz for DS mode
- 1. CIU clock rate in Hz for MMC HS mode
- 2. CIU clock rate in Hz for SD HS mode
- 3. CIU clock rate in Hz for SDR12 mode
- 4. CIU clock rate in Hz for SDR25 mode
- 5. CIU clock rate in Hz for SDR50 mode
- 6. CIU clock rate in Hz for SDR104 mode
- 7. CIU clock rate in Hz for DDR50 mode
- 8. CIU clock rate in Hz for HS200 mode
-
Example:
/* for Hi3620 */
@@ -39,8 +27,6 @@ Example:
#size-cells = <0>;
clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
clock-names = "ciu", "biu";
- clock-freq-table =
- <25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
};
/* Board portion */
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
index 68e5e428e8f6..84e1a670f8c7 100644
--- a/drivers/mmc/host/dw_mmc-k3.c
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -18,56 +18,19 @@
#include "dw_mmc.h"
#include "dw_mmc-pltfm.h"
-#define MAX_NUMS 10
-struct dw_mci_k3_priv_data {
- u32 clk_table[MAX_NUMS];
-};
-
static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
{
- struct dw_mci_k3_priv_data *priv = host->priv;
- u32 rate = priv->clk_table[ios->timing];
int ret;
- if (!rate) {
- dev_warn(host->dev,
- "no specified rate in timing %u\n", ios->timing);
- return;
- }
-
- ret = clk_set_rate(host->ciu_clk, rate);
+ ret = clk_set_rate(host->ciu_clk, ios->clock);
if (ret)
- dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+ dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock);
host->bus_hz = clk_get_rate(host->ciu_clk);
}
-static int dw_mci_k3_parse_dt(struct dw_mci *host)
-{
- struct dw_mci_k3_priv_data *priv;
- struct device_node *node = host->dev->of_node;
- struct property *prop;
- const __be32 *cur;
- u32 val, num = 0;
-
- priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(host->dev, "mem alloc failed for private data\n");
- return -ENOMEM;
- }
- host->priv = priv;
-
- of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
- if (num >= MAX_NUMS)
- break;
- priv->clk_table[num++] = val;
- }
- return 0;
-}
-
static const struct dw_mci_drv_data k3_drv_data = {
.set_ios = dw_mci_k3_set_ios,
- .parse_dt = dw_mci_k3_parse_dt,
};
static const struct of_device_id dw_mci_k3_match[] = {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH] clk: hisilicon: add hi3620_mmc_clks
2014-01-13 9:14 ` Zhangfei Gao
@ 2014-01-13 9:37 ` Zhangfei Gao
-1 siblings, 0 replies; 44+ messages in thread
From: Zhangfei Gao @ 2014-01-13 9:37 UTC (permalink / raw)
To: Chris Ball, Arnd Bergmann, Mike Turquette, Jaehoon Chung,
Seungwon Jeon, Haojian Zhuang, brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao
Suggest by Arnd: abstract mmc tuning as clock behavior,
also because different soc have different tuning method and registers.
hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
---
.../bindings/arm/hisilicon/hisilicon.txt | 14 +
.../devicetree/bindings/clock/hi3620-clock.txt | 1 +
drivers/clk/hisilicon/clk-hi3620.c | 274 ++++++++++++++++++++
include/dt-bindings/clock/hi3620-clock.h | 5 +
4 files changed, 294 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 8c7a4653508d..df0a452b8526 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -30,3 +30,17 @@ Example:
resume-offset = <0x308>;
reboot-offset = <0x4>;
};
+
+PCTRL: Peripheral misc control register
+
+Required Properties:
+- compatible: "hisilicon,pctrl"
+- reg: Address and size of pctrl.
+
+Example:
+
+ /* for Hi3620 */
+ pctrl: pctrl@fca09000 {
+ compatible = "hisilicon,pctrl";
+ reg = <0xfca09000 0x1000>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
index 4b71ab41be53..dad6269f52c5 100644
--- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
+++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
@@ -7,6 +7,7 @@ Required Properties:
- compatible: should be one of the following.
- "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
+ - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
- reg: physical base address of the controller and length of memory mapped
region.
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index f24ad6a3a797..38faa469d288 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -240,3 +240,277 @@ static void __init hi3620_clk_init(struct device_node *np)
base);
}
CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
+
+struct hisi_mmc_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ u32 clken_reg;
+ u32 clken_bit;
+ u32 div_reg;
+ u32 div_off;
+ u32 div_bits;
+ u32 drv_reg;
+ u32 drv_off;
+ u32 drv_bits;
+ u32 sam_reg;
+ u32 sam_off;
+ u32 sam_bits;
+};
+
+struct clk_mmc {
+ struct clk_hw hw;
+ u32 id;
+ void __iomem *clken_reg;
+ u32 clken_bit;
+ void __iomem *div_reg;
+ u32 div_off;
+ u32 div_bits;
+ void __iomem *drv_reg;
+ u32 drv_off;
+ u32 drv_bits;
+ void __iomem *sam_reg;
+ u32 sam_off;
+ u32 sam_bits;
+};
+
+#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
+
+static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
+ { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
+ { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
+ { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
+ { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
+};
+
+static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ switch (parent_rate) {
+ case 26000000:
+ return 13000000;
+ case 180000000:
+ return 25000000;
+ case 360000000:
+ return 50000000;
+ case 720000000:
+ return 100000000;
+ case 1440000000:
+ return 180000000;
+ default:
+ return parent_rate;
+ }
+}
+
+static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *best_parent_rate,
+ struct clk **best_parent_p)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long best = 0;
+
+ if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
+ rate = 13000000;
+ best = 26000000;
+ } else if (rate <= 26000000) {
+ rate = 25000000;
+ best = 180000000;
+ } else if (rate <= 52000000) {
+ rate = 50000000;
+ best = 360000000;
+ } else if (rate <= 100000000) {
+ rate = 100000000;
+ best = 720000000;
+ } else {
+ /* max is 180M */
+ rate = 180000000;
+ best = 1440000000;
+ }
+ *best_parent_rate = best;
+ return rate;
+}
+
+static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
+{
+ u32 i;
+
+ if (para >= 0) {
+ for (i = 0; i < len; i++) {
+ if (para % 2)
+ val |= 1 << (off + i);
+ else
+ val &= ~(1 << (off + i));
+ para = para >> 1;
+ }
+ }
+ return val;
+}
+
+static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long flags;
+ u32 sam, drv, div, val;
+ static DEFINE_SPINLOCK(mmc_clk_lock);
+
+ switch (rate) {
+ case 13000000:
+ sam = 3;
+ drv = 1;
+ div = 1;
+ break;
+ case 25000000:
+ sam = 13;
+ drv = 6;
+ div = 6;
+ break;
+ case 50000000:
+ sam = 3;
+ drv = 6;
+ div = 6;
+ break;
+ case 100000000:
+ sam = 6;
+ drv = 4;
+ div = 6;
+ break;
+ case 180000000:
+ sam = 6;
+ drv = 4;
+ div = 7;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&mmc_clk_lock, flags);
+
+ val = readl_relaxed(mclk->clken_reg);
+ val &= ~(1 << mclk->clken_bit);
+ writel_relaxed(val, mclk->clken_reg);
+
+ val = readl_relaxed(mclk->sam_reg);
+ val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
+ writel_relaxed(val, mclk->sam_reg);
+
+ val = readl_relaxed(mclk->drv_reg);
+ val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
+ writel_relaxed(val, mclk->drv_reg);
+
+ val = readl_relaxed(mclk->div_reg);
+ val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
+ writel_relaxed(val, mclk->div_reg);
+
+ val = readl_relaxed(mclk->clken_reg);
+ val |= 1 << mclk->clken_bit;
+ writel_relaxed(val, mclk->clken_reg);
+
+ spin_unlock_irqrestore(&mmc_clk_lock, flags);
+
+ return 0;
+}
+
+static int mmc_clk_prepare(struct clk_hw *hw)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long rate;
+
+ if (mclk->id == HI3620_MMC_CIUCLK1)
+ rate = 13000000;
+ else
+ rate = 25000000;
+
+ return mmc_clk_set_timing(hw, rate);
+}
+
+static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ return mmc_clk_set_timing(hw, rate);
+}
+
+static struct clk_ops clk_mmc_ops = {
+ .prepare = mmc_clk_prepare,
+ .determine_rate = mmc_clk_determine_rate,
+ .set_rate = mmc_clk_set_rate,
+ .recalc_rate = mmc_clk_recalc_rate,
+};
+
+static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
+ void __iomem *base, struct device_node *np)
+{
+ struct clk_mmc *mclk;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
+ if (!mclk) {
+ pr_err("%s: fail to allocate mmc clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ init.name = mmc_clk->name;
+ init.ops = &clk_mmc_ops;
+ init.flags = mmc_clk->flags | CLK_IS_BASIC;
+ init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
+ init.num_parents = (mmc_clk->parent_name ? 1 : 0);
+ mclk->hw.init = &init;
+
+ mclk->id = mmc_clk->id;
+ mclk->clken_reg = base + mmc_clk->clken_reg;
+ mclk->clken_bit = mmc_clk->clken_bit;
+ mclk->div_reg = base + mmc_clk->div_reg;
+ mclk->div_off = mmc_clk->div_off;
+ mclk->div_bits = mmc_clk->div_bits;
+ mclk->drv_reg = base + mmc_clk->drv_reg;
+ mclk->drv_off = mmc_clk->drv_off;
+ mclk->drv_bits = mmc_clk->drv_bits;
+ mclk->sam_reg = base + mmc_clk->sam_reg;
+ mclk->sam_off = mmc_clk->sam_off;
+ mclk->sam_bits = mmc_clk->sam_bits;
+
+ clk = clk_register(NULL, &mclk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ kfree(mclk);
+ return clk;
+}
+
+static void __init hi3620_mmc_clk_init(struct device_node *node)
+{
+ void __iomem *base;
+ int i, num = ARRAY_SIZE(hi3620_mmc_clks);
+ struct clk_onecell_data *clk_data;
+
+ if (!node) {
+ pr_err("failed to find pctrl node in DTS\n");
+ return;
+ }
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("failed to map pctrl\n");
+ return;
+ }
+
+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+ if (WARN_ON(!clk_data))
+ return;
+
+ clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
+ if (!clk_data->clks) {
+ pr_err("%s: fail to allocate mmc clk\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < num; i++) {
+ struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
+ clk_data->clks[mmc_clk->id] =
+ hisi_register_clk_mmc(mmc_clk, base, node);
+ }
+
+ clk_data->clk_num = num;
+ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
index 6eaa6a45e110..21b9d0e2eb0c 100644
--- a/include/dt-bindings/clock/hi3620-clock.h
+++ b/include/dt-bindings/clock/hi3620-clock.h
@@ -147,6 +147,11 @@
#define HI3620_MMC_CLK3 217
#define HI3620_MCU_CLK 218
+#define HI3620_SD_CIUCLK 0
+#define HI3620_MMC_CIUCLK1 1
+#define HI3620_MMC_CIUCLK2 2
+#define HI3620_MMC_CIUCLK3 3
+
#define HI3620_NR_CLKS 219
#endif /* __DTS_HI3620_CLOCK_H */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* [PATCH] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-13 9:37 ` Zhangfei Gao
0 siblings, 0 replies; 44+ messages in thread
From: Zhangfei Gao @ 2014-01-13 9:37 UTC (permalink / raw)
To: linux-arm-kernel
Suggest by Arnd: abstract mmc tuning as clock behavior,
also because different soc have different tuning method and registers.
hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
---
.../bindings/arm/hisilicon/hisilicon.txt | 14 +
.../devicetree/bindings/clock/hi3620-clock.txt | 1 +
drivers/clk/hisilicon/clk-hi3620.c | 274 ++++++++++++++++++++
include/dt-bindings/clock/hi3620-clock.h | 5 +
4 files changed, 294 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 8c7a4653508d..df0a452b8526 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -30,3 +30,17 @@ Example:
resume-offset = <0x308>;
reboot-offset = <0x4>;
};
+
+PCTRL: Peripheral misc control register
+
+Required Properties:
+- compatible: "hisilicon,pctrl"
+- reg: Address and size of pctrl.
+
+Example:
+
+ /* for Hi3620 */
+ pctrl: pctrl at fca09000 {
+ compatible = "hisilicon,pctrl";
+ reg = <0xfca09000 0x1000>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
index 4b71ab41be53..dad6269f52c5 100644
--- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
+++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
@@ -7,6 +7,7 @@ Required Properties:
- compatible: should be one of the following.
- "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
+ - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
- reg: physical base address of the controller and length of memory mapped
region.
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index f24ad6a3a797..38faa469d288 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -240,3 +240,277 @@ static void __init hi3620_clk_init(struct device_node *np)
base);
}
CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
+
+struct hisi_mmc_clock {
+ unsigned int id;
+ const char *name;
+ const char *parent_name;
+ unsigned long flags;
+ u32 clken_reg;
+ u32 clken_bit;
+ u32 div_reg;
+ u32 div_off;
+ u32 div_bits;
+ u32 drv_reg;
+ u32 drv_off;
+ u32 drv_bits;
+ u32 sam_reg;
+ u32 sam_off;
+ u32 sam_bits;
+};
+
+struct clk_mmc {
+ struct clk_hw hw;
+ u32 id;
+ void __iomem *clken_reg;
+ u32 clken_bit;
+ void __iomem *div_reg;
+ u32 div_off;
+ u32 div_bits;
+ void __iomem *drv_reg;
+ u32 drv_off;
+ u32 drv_bits;
+ void __iomem *sam_reg;
+ u32 sam_off;
+ u32 sam_bits;
+};
+
+#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
+
+static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
+ { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
+ { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
+ { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
+ { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
+};
+
+static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ switch (parent_rate) {
+ case 26000000:
+ return 13000000;
+ case 180000000:
+ return 25000000;
+ case 360000000:
+ return 50000000;
+ case 720000000:
+ return 100000000;
+ case 1440000000:
+ return 180000000;
+ default:
+ return parent_rate;
+ }
+}
+
+static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *best_parent_rate,
+ struct clk **best_parent_p)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long best = 0;
+
+ if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
+ rate = 13000000;
+ best = 26000000;
+ } else if (rate <= 26000000) {
+ rate = 25000000;
+ best = 180000000;
+ } else if (rate <= 52000000) {
+ rate = 50000000;
+ best = 360000000;
+ } else if (rate <= 100000000) {
+ rate = 100000000;
+ best = 720000000;
+ } else {
+ /* max is 180M */
+ rate = 180000000;
+ best = 1440000000;
+ }
+ *best_parent_rate = best;
+ return rate;
+}
+
+static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
+{
+ u32 i;
+
+ if (para >= 0) {
+ for (i = 0; i < len; i++) {
+ if (para % 2)
+ val |= 1 << (off + i);
+ else
+ val &= ~(1 << (off + i));
+ para = para >> 1;
+ }
+ }
+ return val;
+}
+
+static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long flags;
+ u32 sam, drv, div, val;
+ static DEFINE_SPINLOCK(mmc_clk_lock);
+
+ switch (rate) {
+ case 13000000:
+ sam = 3;
+ drv = 1;
+ div = 1;
+ break;
+ case 25000000:
+ sam = 13;
+ drv = 6;
+ div = 6;
+ break;
+ case 50000000:
+ sam = 3;
+ drv = 6;
+ div = 6;
+ break;
+ case 100000000:
+ sam = 6;
+ drv = 4;
+ div = 6;
+ break;
+ case 180000000:
+ sam = 6;
+ drv = 4;
+ div = 7;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&mmc_clk_lock, flags);
+
+ val = readl_relaxed(mclk->clken_reg);
+ val &= ~(1 << mclk->clken_bit);
+ writel_relaxed(val, mclk->clken_reg);
+
+ val = readl_relaxed(mclk->sam_reg);
+ val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
+ writel_relaxed(val, mclk->sam_reg);
+
+ val = readl_relaxed(mclk->drv_reg);
+ val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
+ writel_relaxed(val, mclk->drv_reg);
+
+ val = readl_relaxed(mclk->div_reg);
+ val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
+ writel_relaxed(val, mclk->div_reg);
+
+ val = readl_relaxed(mclk->clken_reg);
+ val |= 1 << mclk->clken_bit;
+ writel_relaxed(val, mclk->clken_reg);
+
+ spin_unlock_irqrestore(&mmc_clk_lock, flags);
+
+ return 0;
+}
+
+static int mmc_clk_prepare(struct clk_hw *hw)
+{
+ struct clk_mmc *mclk = to_mmc(hw);
+ unsigned long rate;
+
+ if (mclk->id == HI3620_MMC_CIUCLK1)
+ rate = 13000000;
+ else
+ rate = 25000000;
+
+ return mmc_clk_set_timing(hw, rate);
+}
+
+static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ return mmc_clk_set_timing(hw, rate);
+}
+
+static struct clk_ops clk_mmc_ops = {
+ .prepare = mmc_clk_prepare,
+ .determine_rate = mmc_clk_determine_rate,
+ .set_rate = mmc_clk_set_rate,
+ .recalc_rate = mmc_clk_recalc_rate,
+};
+
+static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
+ void __iomem *base, struct device_node *np)
+{
+ struct clk_mmc *mclk;
+ struct clk *clk;
+ struct clk_init_data init;
+
+ mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
+ if (!mclk) {
+ pr_err("%s: fail to allocate mmc clk\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ init.name = mmc_clk->name;
+ init.ops = &clk_mmc_ops;
+ init.flags = mmc_clk->flags | CLK_IS_BASIC;
+ init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
+ init.num_parents = (mmc_clk->parent_name ? 1 : 0);
+ mclk->hw.init = &init;
+
+ mclk->id = mmc_clk->id;
+ mclk->clken_reg = base + mmc_clk->clken_reg;
+ mclk->clken_bit = mmc_clk->clken_bit;
+ mclk->div_reg = base + mmc_clk->div_reg;
+ mclk->div_off = mmc_clk->div_off;
+ mclk->div_bits = mmc_clk->div_bits;
+ mclk->drv_reg = base + mmc_clk->drv_reg;
+ mclk->drv_off = mmc_clk->drv_off;
+ mclk->drv_bits = mmc_clk->drv_bits;
+ mclk->sam_reg = base + mmc_clk->sam_reg;
+ mclk->sam_off = mmc_clk->sam_off;
+ mclk->sam_bits = mmc_clk->sam_bits;
+
+ clk = clk_register(NULL, &mclk->hw);
+ if (WARN_ON(IS_ERR(clk)))
+ kfree(mclk);
+ return clk;
+}
+
+static void __init hi3620_mmc_clk_init(struct device_node *node)
+{
+ void __iomem *base;
+ int i, num = ARRAY_SIZE(hi3620_mmc_clks);
+ struct clk_onecell_data *clk_data;
+
+ if (!node) {
+ pr_err("failed to find pctrl node in DTS\n");
+ return;
+ }
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("failed to map pctrl\n");
+ return;
+ }
+
+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+ if (WARN_ON(!clk_data))
+ return;
+
+ clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
+ if (!clk_data->clks) {
+ pr_err("%s: fail to allocate mmc clk\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < num; i++) {
+ struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
+ clk_data->clks[mmc_clk->id] =
+ hisi_register_clk_mmc(mmc_clk, base, node);
+ }
+
+ clk_data->clk_num = num;
+ of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
index 6eaa6a45e110..21b9d0e2eb0c 100644
--- a/include/dt-bindings/clock/hi3620-clock.h
+++ b/include/dt-bindings/clock/hi3620-clock.h
@@ -147,6 +147,11 @@
#define HI3620_MMC_CLK3 217
#define HI3620_MCU_CLK 218
+#define HI3620_SD_CIUCLK 0
+#define HI3620_MMC_CIUCLK1 1
+#define HI3620_MMC_CIUCLK2 2
+#define HI3620_MMC_CIUCLK3 3
+
#define HI3620_NR_CLKS 219
#endif /* __DTS_HI3620_CLOCK_H */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 44+ messages in thread
* RE: [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-13 9:14 ` Zhangfei Gao
@ 2014-01-14 9:47 ` Seungwon Jeon
-1 siblings, 0 replies; 44+ messages in thread
From: Seungwon Jeon @ 2014-01-14 9:47 UTC (permalink / raw)
To: 'Zhangfei Gao', 'Chris Ball',
'Arnd Bergmann', 'Mike Turquette',
'Jaehoon Chung', 'Haojian Zhuang',
brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree
On Mon, January 13, 2014, Zhangfei Gao wrote:
> Suggest by Arnd: abstract mmc tuning as clock behavior,
> also because different soc have different tuning method and registers.
> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
> ---
> .../bindings/arm/hisilicon/hisilicon.txt | 14 +
> .../devicetree/bindings/clock/hi3620-clock.txt | 1 +
> drivers/clk/hisilicon/clk-hi3620.c | 267 ++++++++++++++++++++
> include/dt-bindings/clock/hi3620-clock.h | 5 +
> 4 files changed, 287 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index 8c7a4653508d..df0a452b8526 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -30,3 +30,17 @@ Example:
> resume-offset = <0x308>;
> reboot-offset = <0x4>;
> };
> +
> +PCTRL: Peripheral misc control register
> +
> +Required Properties:
> +- compatible: "hisilicon,pctrl"
> +- reg: Address and size of pctrl.
> +
> +Example:
> +
> + /* for Hi3620 */
> + pctrl: pctrl@fca09000 {
> + compatible = "hisilicon,pctrl";
> + reg = <0xfca09000 0x1000>;
> + };
> diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> index 4b71ab41be53..dad6269f52c5 100644
> --- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> @@ -7,6 +7,7 @@ Required Properties:
>
> - compatible: should be one of the following.
> - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
> + - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
>
> - reg: physical base address of the controller and length of memory mapped
> region.
> diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
> index f24ad6a3a797..54cc3475ec36 100644
> --- a/drivers/clk/hisilicon/clk-hi3620.c
> +++ b/drivers/clk/hisilicon/clk-hi3620.c
> @@ -240,3 +240,270 @@ static void __init hi3620_clk_init(struct device_node *np)
> base);
> }
> CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
> +
> +struct hisi_mmc_clock {
> + unsigned int id;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + u32 clken_reg;
> + u32 clken_bit;
> + u32 div_reg;
> + u32 div_off;
> + u32 div_bits;
> + u32 drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + u32 sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +struct clk_mmc {
> + struct clk_hw hw;
> + u32 id;
> + void __iomem *clken_reg;
> + u32 clken_bit;
> + void __iomem *div_reg;
> + u32 div_off;
> + u32 div_bits;
> + void __iomem *drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + void __iomem *sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
> +
> +static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
> + { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4,
> 4, 0x1f8, 8, 4},
> + { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3,
> 0x1f8, 16, 4, 0x1f8, 20, 4},
> + { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3,
> 0x1f8, 28, 4, 0x1fc, 0, 4},
> + { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3,
> 0x1fc, 8, 4, 0x1fc, 12, 4},
> +};
> +
> +static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + switch (parent_rate) {
> + case 26000000:
> + return 13000000;
> + case 180000000:
> + return 25000000;
> + case 360000000:
> + return 50000000;
> + case 720000000:
> + return 100000000;
> + default:
> + return parent_rate;
> + }
> +}
> +
> +static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long *best_parent_rate,
> + struct clk **best_parent_p)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long best = 0;
> +
> + if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
No need to check HI3620_MMC_CIUCLK2 and HI3620_MMC_CIUCLK3?
> + rate = 13000000;
> + best = 26000000;
> + } else if (rate <= 26000000) {
> + rate = 25000000;
> + best = 180000000;
> + } else if (rate <= 52000000) {
> + rate = 50000000;
> + best = 360000000;
> + } else if (rate <= 100000000) {
> + rate = 100000000;
> + best = 720000000;
> + } else {
> + /* max is 180M */
> + rate = 180000000;
> + best = 1440000000;
> + }
> + *best_parent_rate = best;
> + return rate;
> +}
> +
> +static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
> +{
> + u32 i;
> +
> + if (para >= 0) {
> + for (i = 0; i < len; i++) {
> + if (para % 2)
> + val |= 1 << (off + i);
> + else
> + val &= ~(1 << (off + i));
> + para = para >> 1;
> + }
> + }
> + return val;
> +}
> +
> +static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long flags;
> + u32 sam, drv, div, val;
> + static DEFINE_SPINLOCK(mmc_clk_lock);
> +
> + switch (rate) {
> + case 13000000:
> + sam = 3;
> + drv = 1;
> + div = 1;
> + break;
> + case 25000000:
> + sam = 13;
> + drv = 6;
> + div = 6;
> + break;
> + case 50000000:
> + sam = 3;
> + drv = 6;
> + div = 6;
> + break;
> + case 100000000:
> + sam = 6;
> + drv = 4;
> + div = 6;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + spin_lock_irqsave(&mmc_clk_lock, flags);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val &= ~(1 << mclk->clken_bit);
> + writel_relaxed(val, mclk->clken_reg);
> +
> + val = readl_relaxed(mclk->sam_reg);
> + val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
> + writel_relaxed(val, mclk->sam_reg);
> +
> + val = readl_relaxed(mclk->drv_reg);
> + val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
> + writel_relaxed(val, mclk->drv_reg);
> +
> + val = readl_relaxed(mclk->div_reg);
> + val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
> + writel_relaxed(val, mclk->div_reg);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val |= 1 << mclk->clken_bit;
> + writel_relaxed(val, mclk->clken_reg);
> +
> + spin_unlock_irqrestore(&mmc_clk_lock, flags);
> +
> + return 0;
> +}
> +
> +static int mmc_clk_prepare(struct clk_hw *hw)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long rate;
> +
> + if (mclk->id == HI3620_MMC_CIUCLK1)
HI3620_SD_CIUCLK was used in previous version.
Is it fixed with HI3620_MMC_CIUCLK1?
And, please clarify in case of HI3620_MMC_CIUCLK2 and HI3620_MMC_CIUCLK3 as well.
Thanks,
Seungwon Jeon
> + rate = 13000000;
> + else
> + rate = 25000000;
> +
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static struct clk_ops clk_mmc_ops = {
> + .prepare = mmc_clk_prepare,
> + .determine_rate = mmc_clk_determine_rate,
> + .set_rate = mmc_clk_set_rate,
> + .recalc_rate = mmc_clk_recalc_rate,
> +};
> +
> +static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
> + void __iomem *base, struct device_node *np)
> +{
> + struct clk_mmc *mclk;
> + struct clk *clk;
> + struct clk_init_data init;
> +
> + mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
> + if (!mclk) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + init.name = mmc_clk->name;
> + init.ops = &clk_mmc_ops;
> + init.flags = mmc_clk->flags | CLK_IS_BASIC;
> + init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
> + init.num_parents = (mmc_clk->parent_name ? 1 : 0);
> + mclk->hw.init = &init;
> +
> + mclk->id = mmc_clk->id;
> + mclk->clken_reg = base + mmc_clk->clken_reg;
> + mclk->clken_bit = mmc_clk->clken_bit;
> + mclk->div_reg = base + mmc_clk->div_reg;
> + mclk->div_off = mmc_clk->div_off;
> + mclk->div_bits = mmc_clk->div_bits;
> + mclk->drv_reg = base + mmc_clk->drv_reg;
> + mclk->drv_off = mmc_clk->drv_off;
> + mclk->drv_bits = mmc_clk->drv_bits;
> + mclk->sam_reg = base + mmc_clk->sam_reg;
> + mclk->sam_off = mmc_clk->sam_off;
> + mclk->sam_bits = mmc_clk->sam_bits;
> +
> + clk = clk_register(NULL, &mclk->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + kfree(mclk);
> + return clk;
> +}
> +
> +static void __init hi3620_mmc_clk_init(struct device_node *node)
> +{
> + void __iomem *base;
> + int i, num = ARRAY_SIZE(hi3620_mmc_clks);
> + struct clk_onecell_data *clk_data;
> +
> + if (!node) {
> + pr_err("failed to find pctrl node in DTS\n");
> + return;
> + }
> +
> + base = of_iomap(node, 0);
> + if (!base) {
> + pr_err("failed to map pctrl\n");
> + return;
> + }
> +
> + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> + if (WARN_ON(!clk_data))
> + return;
> +
> + clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
> + if (!clk_data->clks) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return;
> + }
> +
> + for (i = 0; i < num; i++) {
> + struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
> + clk_data->clks[mmc_clk->id] =
> + hisi_register_clk_mmc(mmc_clk, base, node);
> + }
> +
> + clk_data->clk_num = num;
> + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +}
> +
> +CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
> diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
> index 6eaa6a45e110..21b9d0e2eb0c 100644
> --- a/include/dt-bindings/clock/hi3620-clock.h
> +++ b/include/dt-bindings/clock/hi3620-clock.h
> @@ -147,6 +147,11 @@
> #define HI3620_MMC_CLK3 217
> #define HI3620_MCU_CLK 218
>
> +#define HI3620_SD_CIUCLK 0
> +#define HI3620_MMC_CIUCLK1 1
> +#define HI3620_MMC_CIUCLK2 2
> +#define HI3620_MMC_CIUCLK3 3
> +
> #define HI3620_NR_CLKS 219
>
> #endif /* __DTS_HI3620_CLOCK_H */
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-14 9:47 ` Seungwon Jeon
0 siblings, 0 replies; 44+ messages in thread
From: Seungwon Jeon @ 2014-01-14 9:47 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, January 13, 2014, Zhangfei Gao wrote:
> Suggest by Arnd: abstract mmc tuning as clock behavior,
> also because different soc have different tuning method and registers.
> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
> ---
> .../bindings/arm/hisilicon/hisilicon.txt | 14 +
> .../devicetree/bindings/clock/hi3620-clock.txt | 1 +
> drivers/clk/hisilicon/clk-hi3620.c | 267 ++++++++++++++++++++
> include/dt-bindings/clock/hi3620-clock.h | 5 +
> 4 files changed, 287 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index 8c7a4653508d..df0a452b8526 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -30,3 +30,17 @@ Example:
> resume-offset = <0x308>;
> reboot-offset = <0x4>;
> };
> +
> +PCTRL: Peripheral misc control register
> +
> +Required Properties:
> +- compatible: "hisilicon,pctrl"
> +- reg: Address and size of pctrl.
> +
> +Example:
> +
> + /* for Hi3620 */
> + pctrl: pctrl at fca09000 {
> + compatible = "hisilicon,pctrl";
> + reg = <0xfca09000 0x1000>;
> + };
> diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> index 4b71ab41be53..dad6269f52c5 100644
> --- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> @@ -7,6 +7,7 @@ Required Properties:
>
> - compatible: should be one of the following.
> - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
> + - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
>
> - reg: physical base address of the controller and length of memory mapped
> region.
> diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
> index f24ad6a3a797..54cc3475ec36 100644
> --- a/drivers/clk/hisilicon/clk-hi3620.c
> +++ b/drivers/clk/hisilicon/clk-hi3620.c
> @@ -240,3 +240,270 @@ static void __init hi3620_clk_init(struct device_node *np)
> base);
> }
> CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
> +
> +struct hisi_mmc_clock {
> + unsigned int id;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + u32 clken_reg;
> + u32 clken_bit;
> + u32 div_reg;
> + u32 div_off;
> + u32 div_bits;
> + u32 drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + u32 sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +struct clk_mmc {
> + struct clk_hw hw;
> + u32 id;
> + void __iomem *clken_reg;
> + u32 clken_bit;
> + void __iomem *div_reg;
> + u32 div_off;
> + u32 div_bits;
> + void __iomem *drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + void __iomem *sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
> +
> +static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
> + { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4,
> 4, 0x1f8, 8, 4},
> + { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3,
> 0x1f8, 16, 4, 0x1f8, 20, 4},
> + { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3,
> 0x1f8, 28, 4, 0x1fc, 0, 4},
> + { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3,
> 0x1fc, 8, 4, 0x1fc, 12, 4},
> +};
> +
> +static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + switch (parent_rate) {
> + case 26000000:
> + return 13000000;
> + case 180000000:
> + return 25000000;
> + case 360000000:
> + return 50000000;
> + case 720000000:
> + return 100000000;
> + default:
> + return parent_rate;
> + }
> +}
> +
> +static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long *best_parent_rate,
> + struct clk **best_parent_p)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long best = 0;
> +
> + if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
No need to check HI3620_MMC_CIUCLK2 and HI3620_MMC_CIUCLK3?
> + rate = 13000000;
> + best = 26000000;
> + } else if (rate <= 26000000) {
> + rate = 25000000;
> + best = 180000000;
> + } else if (rate <= 52000000) {
> + rate = 50000000;
> + best = 360000000;
> + } else if (rate <= 100000000) {
> + rate = 100000000;
> + best = 720000000;
> + } else {
> + /* max is 180M */
> + rate = 180000000;
> + best = 1440000000;
> + }
> + *best_parent_rate = best;
> + return rate;
> +}
> +
> +static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
> +{
> + u32 i;
> +
> + if (para >= 0) {
> + for (i = 0; i < len; i++) {
> + if (para % 2)
> + val |= 1 << (off + i);
> + else
> + val &= ~(1 << (off + i));
> + para = para >> 1;
> + }
> + }
> + return val;
> +}
> +
> +static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long flags;
> + u32 sam, drv, div, val;
> + static DEFINE_SPINLOCK(mmc_clk_lock);
> +
> + switch (rate) {
> + case 13000000:
> + sam = 3;
> + drv = 1;
> + div = 1;
> + break;
> + case 25000000:
> + sam = 13;
> + drv = 6;
> + div = 6;
> + break;
> + case 50000000:
> + sam = 3;
> + drv = 6;
> + div = 6;
> + break;
> + case 100000000:
> + sam = 6;
> + drv = 4;
> + div = 6;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + spin_lock_irqsave(&mmc_clk_lock, flags);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val &= ~(1 << mclk->clken_bit);
> + writel_relaxed(val, mclk->clken_reg);
> +
> + val = readl_relaxed(mclk->sam_reg);
> + val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
> + writel_relaxed(val, mclk->sam_reg);
> +
> + val = readl_relaxed(mclk->drv_reg);
> + val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
> + writel_relaxed(val, mclk->drv_reg);
> +
> + val = readl_relaxed(mclk->div_reg);
> + val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
> + writel_relaxed(val, mclk->div_reg);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val |= 1 << mclk->clken_bit;
> + writel_relaxed(val, mclk->clken_reg);
> +
> + spin_unlock_irqrestore(&mmc_clk_lock, flags);
> +
> + return 0;
> +}
> +
> +static int mmc_clk_prepare(struct clk_hw *hw)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long rate;
> +
> + if (mclk->id == HI3620_MMC_CIUCLK1)
HI3620_SD_CIUCLK was used in previous version.
Is it fixed with HI3620_MMC_CIUCLK1?
And, please clarify in case of HI3620_MMC_CIUCLK2 and HI3620_MMC_CIUCLK3 as well.
Thanks,
Seungwon Jeon
> + rate = 13000000;
> + else
> + rate = 25000000;
> +
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static struct clk_ops clk_mmc_ops = {
> + .prepare = mmc_clk_prepare,
> + .determine_rate = mmc_clk_determine_rate,
> + .set_rate = mmc_clk_set_rate,
> + .recalc_rate = mmc_clk_recalc_rate,
> +};
> +
> +static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
> + void __iomem *base, struct device_node *np)
> +{
> + struct clk_mmc *mclk;
> + struct clk *clk;
> + struct clk_init_data init;
> +
> + mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
> + if (!mclk) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + init.name = mmc_clk->name;
> + init.ops = &clk_mmc_ops;
> + init.flags = mmc_clk->flags | CLK_IS_BASIC;
> + init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
> + init.num_parents = (mmc_clk->parent_name ? 1 : 0);
> + mclk->hw.init = &init;
> +
> + mclk->id = mmc_clk->id;
> + mclk->clken_reg = base + mmc_clk->clken_reg;
> + mclk->clken_bit = mmc_clk->clken_bit;
> + mclk->div_reg = base + mmc_clk->div_reg;
> + mclk->div_off = mmc_clk->div_off;
> + mclk->div_bits = mmc_clk->div_bits;
> + mclk->drv_reg = base + mmc_clk->drv_reg;
> + mclk->drv_off = mmc_clk->drv_off;
> + mclk->drv_bits = mmc_clk->drv_bits;
> + mclk->sam_reg = base + mmc_clk->sam_reg;
> + mclk->sam_off = mmc_clk->sam_off;
> + mclk->sam_bits = mmc_clk->sam_bits;
> +
> + clk = clk_register(NULL, &mclk->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + kfree(mclk);
> + return clk;
> +}
> +
> +static void __init hi3620_mmc_clk_init(struct device_node *node)
> +{
> + void __iomem *base;
> + int i, num = ARRAY_SIZE(hi3620_mmc_clks);
> + struct clk_onecell_data *clk_data;
> +
> + if (!node) {
> + pr_err("failed to find pctrl node in DTS\n");
> + return;
> + }
> +
> + base = of_iomap(node, 0);
> + if (!base) {
> + pr_err("failed to map pctrl\n");
> + return;
> + }
> +
> + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> + if (WARN_ON(!clk_data))
> + return;
> +
> + clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
> + if (!clk_data->clks) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return;
> + }
> +
> + for (i = 0; i < num; i++) {
> + struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
> + clk_data->clks[mmc_clk->id] =
> + hisi_register_clk_mmc(mmc_clk, base, node);
> + }
> +
> + clk_data->clk_num = num;
> + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +}
> +
> +CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
> diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
> index 6eaa6a45e110..21b9d0e2eb0c 100644
> --- a/include/dt-bindings/clock/hi3620-clock.h
> +++ b/include/dt-bindings/clock/hi3620-clock.h
> @@ -147,6 +147,11 @@
> #define HI3620_MMC_CLK3 217
> #define HI3620_MCU_CLK 218
>
> +#define HI3620_SD_CIUCLK 0
> +#define HI3620_MMC_CIUCLK1 1
> +#define HI3620_MMC_CIUCLK2 2
> +#define HI3620_MMC_CIUCLK3 3
> +
> #define HI3620_NR_CLKS 219
>
> #endif /* __DTS_HI3620_CLOCK_H */
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-14 9:47 ` Seungwon Jeon
@ 2014-01-14 10:04 ` Zhangfei Gao
-1 siblings, 0 replies; 44+ messages in thread
From: Zhangfei Gao @ 2014-01-14 10:04 UTC (permalink / raw)
To: Seungwon Jeon
Cc: Zhangfei Gao, Chris Ball, Arnd Bergmann, Mike Turquette,
Jaehoon Chung, Haojian Zhuang, Zhigang Wang, devicetree,
linux-mmc, linux-arm-kernel, patches
>> +static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
>> + unsigned long *best_parent_rate,
>> + struct clk **best_parent_p)
>> +{
>> + struct clk_mmc *mclk = to_mmc(hw);
>> + unsigned long best = 0;
>> +
>> + if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
> No need to check HI3620_MMC_CIUCLK2 and HI3620_MMC_CIUCLK3?
Yes, only emmc, id=HI3620_MMC_CIUCLK1, using init clk 13M, while
others use init clock 25M.
Add this to handle init mmc init clk 400K and return source clock rate
13M, from your suggestion in fact.
>
>> + rate = 13000000;
>> + best = 26000000;
>> + } else if (rate <= 26000000) {
>> + rate = 25000000;
>> + best = 180000000;
>> + } else if (rate <= 52000000) {
>> + rate = 50000000;
>> + best = 360000000;
>> + } else if (rate <= 100000000) {
>> + rate = 100000000;
>> + best = 720000000;
>> + } else {
>> + /* max is 180M */
>> + rate = 180000000;
>> + best = 1440000000;
>> + }
>> + *best_parent_rate = best;
>> + return rate;
>> +}
>> +static int mmc_clk_prepare(struct clk_hw *hw)
>> +{
>> + struct clk_mmc *mclk = to_mmc(hw);
>> + unsigned long rate;
>> +
>> + if (mclk->id == HI3620_MMC_CIUCLK1)
> HI3620_SD_CIUCLK was used in previous version.
Yes, fixed, though it can work on the dev board.
> Is it fixed with HI3620_MMC_CIUCLK1?
> And, please clarify in case of HI3620_MMC_CIUCLK2 and HI3620_MMC_CIUCLK3 as well.
Only HI3620_MMC_CIUCLK1 use 13M for init, all others use 25M on hi3620.
>
> Thanks,
> Seungwon Jeon
>
>> + rate = 13000000;
>> + else
>> + rate = 25000000;
>> +
>> + return mmc_clk_set_timing(hw, rate);
>> +}
>> +
Thanks
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-14 10:04 ` Zhangfei Gao
0 siblings, 0 replies; 44+ messages in thread
From: Zhangfei Gao @ 2014-01-14 10:04 UTC (permalink / raw)
To: linux-arm-kernel
>> +static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
>> + unsigned long *best_parent_rate,
>> + struct clk **best_parent_p)
>> +{
>> + struct clk_mmc *mclk = to_mmc(hw);
>> + unsigned long best = 0;
>> +
>> + if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
> No need to check HI3620_MMC_CIUCLK2 and HI3620_MMC_CIUCLK3?
Yes, only emmc, id=HI3620_MMC_CIUCLK1, using init clk 13M, while
others use init clock 25M.
Add this to handle init mmc init clk 400K and return source clock rate
13M, from your suggestion in fact.
>
>> + rate = 13000000;
>> + best = 26000000;
>> + } else if (rate <= 26000000) {
>> + rate = 25000000;
>> + best = 180000000;
>> + } else if (rate <= 52000000) {
>> + rate = 50000000;
>> + best = 360000000;
>> + } else if (rate <= 100000000) {
>> + rate = 100000000;
>> + best = 720000000;
>> + } else {
>> + /* max is 180M */
>> + rate = 180000000;
>> + best = 1440000000;
>> + }
>> + *best_parent_rate = best;
>> + return rate;
>> +}
>> +static int mmc_clk_prepare(struct clk_hw *hw)
>> +{
>> + struct clk_mmc *mclk = to_mmc(hw);
>> + unsigned long rate;
>> +
>> + if (mclk->id == HI3620_MMC_CIUCLK1)
> HI3620_SD_CIUCLK was used in previous version.
Yes, fixed, though it can work on the dev board.
> Is it fixed with HI3620_MMC_CIUCLK1?
> And, please clarify in case of HI3620_MMC_CIUCLK2 and HI3620_MMC_CIUCLK3 as well.
Only HI3620_MMC_CIUCLK1 use 13M for init, all others use 25M on hi3620.
>
> Thanks,
> Seungwon Jeon
>
>> + rate = 13000000;
>> + else
>> + rate = 25000000;
>> +
>> + return mmc_clk_set_timing(hw, rate);
>> +}
>> +
Thanks
^ permalink raw reply [flat|nested] 44+ messages in thread
* RE: [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-13 9:14 ` Zhangfei Gao
@ 2014-01-14 10:40 ` Seungwon Jeon
-1 siblings, 0 replies; 44+ messages in thread
From: Seungwon Jeon @ 2014-01-14 10:40 UTC (permalink / raw)
To: 'Zhangfei Gao', 'Chris Ball',
'Arnd Bergmann', 'Mike Turquette',
'Jaehoon Chung', 'Haojian Zhuang',
brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree
On Mon, January 13, 2014, Zhangfei Gao wrote:
> Suggest by Arnd: abstract mmc tuning as clock behavior,
> also because different soc have different tuning method and registers.
> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
I add my ack.
Please run 'checkpatch' and remove some warnings.
Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
Thanks,
Seungwon Jeon
> ---
> .../bindings/arm/hisilicon/hisilicon.txt | 14 +
> .../devicetree/bindings/clock/hi3620-clock.txt | 1 +
> drivers/clk/hisilicon/clk-hi3620.c | 267 ++++++++++++++++++++
> include/dt-bindings/clock/hi3620-clock.h | 5 +
> 4 files changed, 287 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index 8c7a4653508d..df0a452b8526 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -30,3 +30,17 @@ Example:
> resume-offset = <0x308>;
> reboot-offset = <0x4>;
> };
> +
> +PCTRL: Peripheral misc control register
> +
> +Required Properties:
> +- compatible: "hisilicon,pctrl"
> +- reg: Address and size of pctrl.
> +
> +Example:
> +
> + /* for Hi3620 */
> + pctrl: pctrl@fca09000 {
> + compatible = "hisilicon,pctrl";
> + reg = <0xfca09000 0x1000>;
> + };
> diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> index 4b71ab41be53..dad6269f52c5 100644
> --- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> @@ -7,6 +7,7 @@ Required Properties:
>
> - compatible: should be one of the following.
> - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
> + - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
>
> - reg: physical base address of the controller and length of memory mapped
> region.
> diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
> index f24ad6a3a797..54cc3475ec36 100644
> --- a/drivers/clk/hisilicon/clk-hi3620.c
> +++ b/drivers/clk/hisilicon/clk-hi3620.c
> @@ -240,3 +240,270 @@ static void __init hi3620_clk_init(struct device_node *np)
> base);
> }
> CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
> +
> +struct hisi_mmc_clock {
> + unsigned int id;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + u32 clken_reg;
> + u32 clken_bit;
> + u32 div_reg;
> + u32 div_off;
> + u32 div_bits;
> + u32 drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + u32 sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +struct clk_mmc {
> + struct clk_hw hw;
> + u32 id;
> + void __iomem *clken_reg;
> + u32 clken_bit;
> + void __iomem *div_reg;
> + u32 div_off;
> + u32 div_bits;
> + void __iomem *drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + void __iomem *sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
> +
> +static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
> + { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4,
> 4, 0x1f8, 8, 4},
> + { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3,
> 0x1f8, 16, 4, 0x1f8, 20, 4},
> + { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3,
> 0x1f8, 28, 4, 0x1fc, 0, 4},
> + { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3,
> 0x1fc, 8, 4, 0x1fc, 12, 4},
> +};
> +
> +static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + switch (parent_rate) {
> + case 26000000:
> + return 13000000;
> + case 180000000:
> + return 25000000;
> + case 360000000:
> + return 50000000;
> + case 720000000:
> + return 100000000;
> + default:
> + return parent_rate;
> + }
> +}
> +
> +static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long *best_parent_rate,
> + struct clk **best_parent_p)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long best = 0;
> +
> + if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
> + rate = 13000000;
> + best = 26000000;
> + } else if (rate <= 26000000) {
> + rate = 25000000;
> + best = 180000000;
> + } else if (rate <= 52000000) {
> + rate = 50000000;
> + best = 360000000;
> + } else if (rate <= 100000000) {
> + rate = 100000000;
> + best = 720000000;
> + } else {
> + /* max is 180M */
> + rate = 180000000;
> + best = 1440000000;
> + }
> + *best_parent_rate = best;
> + return rate;
> +}
> +
> +static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
> +{
> + u32 i;
> +
> + if (para >= 0) {
> + for (i = 0; i < len; i++) {
> + if (para % 2)
> + val |= 1 << (off + i);
> + else
> + val &= ~(1 << (off + i));
> + para = para >> 1;
> + }
> + }
> + return val;
> +}
> +
> +static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long flags;
> + u32 sam, drv, div, val;
> + static DEFINE_SPINLOCK(mmc_clk_lock);
> +
> + switch (rate) {
> + case 13000000:
> + sam = 3;
> + drv = 1;
> + div = 1;
> + break;
> + case 25000000:
> + sam = 13;
> + drv = 6;
> + div = 6;
> + break;
> + case 50000000:
> + sam = 3;
> + drv = 6;
> + div = 6;
> + break;
> + case 100000000:
> + sam = 6;
> + drv = 4;
> + div = 6;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + spin_lock_irqsave(&mmc_clk_lock, flags);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val &= ~(1 << mclk->clken_bit);
> + writel_relaxed(val, mclk->clken_reg);
> +
> + val = readl_relaxed(mclk->sam_reg);
> + val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
> + writel_relaxed(val, mclk->sam_reg);
> +
> + val = readl_relaxed(mclk->drv_reg);
> + val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
> + writel_relaxed(val, mclk->drv_reg);
> +
> + val = readl_relaxed(mclk->div_reg);
> + val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
> + writel_relaxed(val, mclk->div_reg);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val |= 1 << mclk->clken_bit;
> + writel_relaxed(val, mclk->clken_reg);
> +
> + spin_unlock_irqrestore(&mmc_clk_lock, flags);
> +
> + return 0;
> +}
> +
> +static int mmc_clk_prepare(struct clk_hw *hw)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long rate;
> +
> + if (mclk->id == HI3620_MMC_CIUCLK1)
> + rate = 13000000;
> + else
> + rate = 25000000;
> +
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static struct clk_ops clk_mmc_ops = {
> + .prepare = mmc_clk_prepare,
> + .determine_rate = mmc_clk_determine_rate,
> + .set_rate = mmc_clk_set_rate,
> + .recalc_rate = mmc_clk_recalc_rate,
> +};
> +
> +static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
> + void __iomem *base, struct device_node *np)
> +{
> + struct clk_mmc *mclk;
> + struct clk *clk;
> + struct clk_init_data init;
> +
> + mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
> + if (!mclk) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + init.name = mmc_clk->name;
> + init.ops = &clk_mmc_ops;
> + init.flags = mmc_clk->flags | CLK_IS_BASIC;
> + init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
> + init.num_parents = (mmc_clk->parent_name ? 1 : 0);
> + mclk->hw.init = &init;
> +
> + mclk->id = mmc_clk->id;
> + mclk->clken_reg = base + mmc_clk->clken_reg;
> + mclk->clken_bit = mmc_clk->clken_bit;
> + mclk->div_reg = base + mmc_clk->div_reg;
> + mclk->div_off = mmc_clk->div_off;
> + mclk->div_bits = mmc_clk->div_bits;
> + mclk->drv_reg = base + mmc_clk->drv_reg;
> + mclk->drv_off = mmc_clk->drv_off;
> + mclk->drv_bits = mmc_clk->drv_bits;
> + mclk->sam_reg = base + mmc_clk->sam_reg;
> + mclk->sam_off = mmc_clk->sam_off;
> + mclk->sam_bits = mmc_clk->sam_bits;
> +
> + clk = clk_register(NULL, &mclk->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + kfree(mclk);
> + return clk;
> +}
> +
> +static void __init hi3620_mmc_clk_init(struct device_node *node)
> +{
> + void __iomem *base;
> + int i, num = ARRAY_SIZE(hi3620_mmc_clks);
> + struct clk_onecell_data *clk_data;
> +
> + if (!node) {
> + pr_err("failed to find pctrl node in DTS\n");
> + return;
> + }
> +
> + base = of_iomap(node, 0);
> + if (!base) {
> + pr_err("failed to map pctrl\n");
> + return;
> + }
> +
> + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> + if (WARN_ON(!clk_data))
> + return;
> +
> + clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
> + if (!clk_data->clks) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return;
> + }
> +
> + for (i = 0; i < num; i++) {
> + struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
> + clk_data->clks[mmc_clk->id] =
> + hisi_register_clk_mmc(mmc_clk, base, node);
> + }
> +
> + clk_data->clk_num = num;
> + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +}
> +
> +CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
> diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
> index 6eaa6a45e110..21b9d0e2eb0c 100644
> --- a/include/dt-bindings/clock/hi3620-clock.h
> +++ b/include/dt-bindings/clock/hi3620-clock.h
> @@ -147,6 +147,11 @@
> #define HI3620_MMC_CLK3 217
> #define HI3620_MCU_CLK 218
>
> +#define HI3620_SD_CIUCLK 0
> +#define HI3620_MMC_CIUCLK1 1
> +#define HI3620_MMC_CIUCLK2 2
> +#define HI3620_MMC_CIUCLK3 3
> +
> #define HI3620_NR_CLKS 219
>
> #endif /* __DTS_HI3620_CLOCK_H */
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-14 10:40 ` Seungwon Jeon
0 siblings, 0 replies; 44+ messages in thread
From: Seungwon Jeon @ 2014-01-14 10:40 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, January 13, 2014, Zhangfei Gao wrote:
> Suggest by Arnd: abstract mmc tuning as clock behavior,
> also because different soc have different tuning method and registers.
> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
I add my ack.
Please run 'checkpatch' and remove some warnings.
Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
Thanks,
Seungwon Jeon
> ---
> .../bindings/arm/hisilicon/hisilicon.txt | 14 +
> .../devicetree/bindings/clock/hi3620-clock.txt | 1 +
> drivers/clk/hisilicon/clk-hi3620.c | 267 ++++++++++++++++++++
> include/dt-bindings/clock/hi3620-clock.h | 5 +
> 4 files changed, 287 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index 8c7a4653508d..df0a452b8526 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -30,3 +30,17 @@ Example:
> resume-offset = <0x308>;
> reboot-offset = <0x4>;
> };
> +
> +PCTRL: Peripheral misc control register
> +
> +Required Properties:
> +- compatible: "hisilicon,pctrl"
> +- reg: Address and size of pctrl.
> +
> +Example:
> +
> + /* for Hi3620 */
> + pctrl: pctrl at fca09000 {
> + compatible = "hisilicon,pctrl";
> + reg = <0xfca09000 0x1000>;
> + };
> diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> index 4b71ab41be53..dad6269f52c5 100644
> --- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> @@ -7,6 +7,7 @@ Required Properties:
>
> - compatible: should be one of the following.
> - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
> + - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
>
> - reg: physical base address of the controller and length of memory mapped
> region.
> diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
> index f24ad6a3a797..54cc3475ec36 100644
> --- a/drivers/clk/hisilicon/clk-hi3620.c
> +++ b/drivers/clk/hisilicon/clk-hi3620.c
> @@ -240,3 +240,270 @@ static void __init hi3620_clk_init(struct device_node *np)
> base);
> }
> CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
> +
> +struct hisi_mmc_clock {
> + unsigned int id;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + u32 clken_reg;
> + u32 clken_bit;
> + u32 div_reg;
> + u32 div_off;
> + u32 div_bits;
> + u32 drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + u32 sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +struct clk_mmc {
> + struct clk_hw hw;
> + u32 id;
> + void __iomem *clken_reg;
> + u32 clken_bit;
> + void __iomem *div_reg;
> + u32 div_off;
> + u32 div_bits;
> + void __iomem *drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + void __iomem *sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
> +
> +static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
> + { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4,
> 4, 0x1f8, 8, 4},
> + { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3,
> 0x1f8, 16, 4, 0x1f8, 20, 4},
> + { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3,
> 0x1f8, 28, 4, 0x1fc, 0, 4},
> + { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3,
> 0x1fc, 8, 4, 0x1fc, 12, 4},
> +};
> +
> +static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + switch (parent_rate) {
> + case 26000000:
> + return 13000000;
> + case 180000000:
> + return 25000000;
> + case 360000000:
> + return 50000000;
> + case 720000000:
> + return 100000000;
> + default:
> + return parent_rate;
> + }
> +}
> +
> +static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long *best_parent_rate,
> + struct clk **best_parent_p)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long best = 0;
> +
> + if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
> + rate = 13000000;
> + best = 26000000;
> + } else if (rate <= 26000000) {
> + rate = 25000000;
> + best = 180000000;
> + } else if (rate <= 52000000) {
> + rate = 50000000;
> + best = 360000000;
> + } else if (rate <= 100000000) {
> + rate = 100000000;
> + best = 720000000;
> + } else {
> + /* max is 180M */
> + rate = 180000000;
> + best = 1440000000;
> + }
> + *best_parent_rate = best;
> + return rate;
> +}
> +
> +static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
> +{
> + u32 i;
> +
> + if (para >= 0) {
> + for (i = 0; i < len; i++) {
> + if (para % 2)
> + val |= 1 << (off + i);
> + else
> + val &= ~(1 << (off + i));
> + para = para >> 1;
> + }
> + }
> + return val;
> +}
> +
> +static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long flags;
> + u32 sam, drv, div, val;
> + static DEFINE_SPINLOCK(mmc_clk_lock);
> +
> + switch (rate) {
> + case 13000000:
> + sam = 3;
> + drv = 1;
> + div = 1;
> + break;
> + case 25000000:
> + sam = 13;
> + drv = 6;
> + div = 6;
> + break;
> + case 50000000:
> + sam = 3;
> + drv = 6;
> + div = 6;
> + break;
> + case 100000000:
> + sam = 6;
> + drv = 4;
> + div = 6;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + spin_lock_irqsave(&mmc_clk_lock, flags);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val &= ~(1 << mclk->clken_bit);
> + writel_relaxed(val, mclk->clken_reg);
> +
> + val = readl_relaxed(mclk->sam_reg);
> + val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
> + writel_relaxed(val, mclk->sam_reg);
> +
> + val = readl_relaxed(mclk->drv_reg);
> + val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
> + writel_relaxed(val, mclk->drv_reg);
> +
> + val = readl_relaxed(mclk->div_reg);
> + val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
> + writel_relaxed(val, mclk->div_reg);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val |= 1 << mclk->clken_bit;
> + writel_relaxed(val, mclk->clken_reg);
> +
> + spin_unlock_irqrestore(&mmc_clk_lock, flags);
> +
> + return 0;
> +}
> +
> +static int mmc_clk_prepare(struct clk_hw *hw)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long rate;
> +
> + if (mclk->id == HI3620_MMC_CIUCLK1)
> + rate = 13000000;
> + else
> + rate = 25000000;
> +
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static struct clk_ops clk_mmc_ops = {
> + .prepare = mmc_clk_prepare,
> + .determine_rate = mmc_clk_determine_rate,
> + .set_rate = mmc_clk_set_rate,
> + .recalc_rate = mmc_clk_recalc_rate,
> +};
> +
> +static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
> + void __iomem *base, struct device_node *np)
> +{
> + struct clk_mmc *mclk;
> + struct clk *clk;
> + struct clk_init_data init;
> +
> + mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
> + if (!mclk) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + init.name = mmc_clk->name;
> + init.ops = &clk_mmc_ops;
> + init.flags = mmc_clk->flags | CLK_IS_BASIC;
> + init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
> + init.num_parents = (mmc_clk->parent_name ? 1 : 0);
> + mclk->hw.init = &init;
> +
> + mclk->id = mmc_clk->id;
> + mclk->clken_reg = base + mmc_clk->clken_reg;
> + mclk->clken_bit = mmc_clk->clken_bit;
> + mclk->div_reg = base + mmc_clk->div_reg;
> + mclk->div_off = mmc_clk->div_off;
> + mclk->div_bits = mmc_clk->div_bits;
> + mclk->drv_reg = base + mmc_clk->drv_reg;
> + mclk->drv_off = mmc_clk->drv_off;
> + mclk->drv_bits = mmc_clk->drv_bits;
> + mclk->sam_reg = base + mmc_clk->sam_reg;
> + mclk->sam_off = mmc_clk->sam_off;
> + mclk->sam_bits = mmc_clk->sam_bits;
> +
> + clk = clk_register(NULL, &mclk->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + kfree(mclk);
> + return clk;
> +}
> +
> +static void __init hi3620_mmc_clk_init(struct device_node *node)
> +{
> + void __iomem *base;
> + int i, num = ARRAY_SIZE(hi3620_mmc_clks);
> + struct clk_onecell_data *clk_data;
> +
> + if (!node) {
> + pr_err("failed to find pctrl node in DTS\n");
> + return;
> + }
> +
> + base = of_iomap(node, 0);
> + if (!base) {
> + pr_err("failed to map pctrl\n");
> + return;
> + }
> +
> + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> + if (WARN_ON(!clk_data))
> + return;
> +
> + clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
> + if (!clk_data->clks) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return;
> + }
> +
> + for (i = 0; i < num; i++) {
> + struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
> + clk_data->clks[mmc_clk->id] =
> + hisi_register_clk_mmc(mmc_clk, base, node);
> + }
> +
> + clk_data->clk_num = num;
> + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +}
> +
> +CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
> diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
> index 6eaa6a45e110..21b9d0e2eb0c 100644
> --- a/include/dt-bindings/clock/hi3620-clock.h
> +++ b/include/dt-bindings/clock/hi3620-clock.h
> @@ -147,6 +147,11 @@
> #define HI3620_MMC_CLK3 217
> #define HI3620_MCU_CLK 218
>
> +#define HI3620_SD_CIUCLK 0
> +#define HI3620_MMC_CIUCLK1 1
> +#define HI3620_MMC_CIUCLK2 2
> +#define HI3620_MMC_CIUCLK3 3
> +
> #define HI3620_NR_CLKS 219
>
> #endif /* __DTS_HI3620_CLOCK_H */
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 44+ messages in thread
* RE: [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
2014-01-13 9:14 ` Zhangfei Gao
@ 2014-01-14 10:42 ` Seungwon Jeon
-1 siblings, 0 replies; 44+ messages in thread
From: Seungwon Jeon @ 2014-01-14 10:42 UTC (permalink / raw)
To: 'Zhangfei Gao', 'Chris Ball',
'Arnd Bergmann', 'Mike Turquette',
'Jaehoon Chung', 'Haojian Zhuang',
brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree
On Monday, January 13, 2014, Zhangfei Gao wrote:
> Remove clk_table and directly use ios->clock as clock source rate.
> Abstract init clock rate and max clock limitation in clk.c
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
Thanks,
Seungwon Jeon
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
@ 2014-01-14 10:42 ` Seungwon Jeon
0 siblings, 0 replies; 44+ messages in thread
From: Seungwon Jeon @ 2014-01-14 10:42 UTC (permalink / raw)
To: linux-arm-kernel
On Monday, January 13, 2014, Zhangfei Gao wrote:
> Remove clk_table and directly use ios->clock as clock source rate.
> Abstract init clock rate and max clock limitation in clk.c
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
Thanks,
Seungwon Jeon
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-14 10:40 ` Seungwon Jeon
@ 2014-01-14 11:52 ` zhangfei
-1 siblings, 0 replies; 44+ messages in thread
From: zhangfei @ 2014-01-14 11:52 UTC (permalink / raw)
To: Seungwon Jeon, 'Chris Ball', 'Arnd Bergmann',
'Mike Turquette', 'Jaehoon Chung',
'Haojian Zhuang',
brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree
On 01/14/2014 06:40 PM, Seungwon Jeon wrote:
> On Mon, January 13, 2014, Zhangfei Gao wrote:
>> Suggest by Arnd: abstract mmc tuning as clock behavior,
>> also because different soc have different tuning method and registers.
>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>
> I add my ack.
> Please run 'checkpatch' and remove some warnings.
>
> Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
>
Thanks Seungwon.
Have checked before, and ignoring warnings of "line over 80 characters"
seems more neat.
Thanks
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-14 11:52 ` zhangfei
0 siblings, 0 replies; 44+ messages in thread
From: zhangfei @ 2014-01-14 11:52 UTC (permalink / raw)
To: linux-arm-kernel
On 01/14/2014 06:40 PM, Seungwon Jeon wrote:
> On Mon, January 13, 2014, Zhangfei Gao wrote:
>> Suggest by Arnd: abstract mmc tuning as clock behavior,
>> also because different soc have different tuning method and registers.
>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>
> I add my ack.
> Please run 'checkpatch' and remove some warnings.
>
> Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
>
Thanks Seungwon.
Have checked before, and ignoring warnings of "line over 80 characters"
seems more neat.
Thanks
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-13 9:14 ` Zhangfei Gao
@ 2014-01-14 20:17 ` Mike Turquette
-1 siblings, 0 replies; 44+ messages in thread
From: Mike Turquette @ 2014-01-14 20:17 UTC (permalink / raw)
To: Chris Ball, Arnd Bergmann, Jaehoon Chung, Seungwon Jeon,
Haojian Zhuang, brooke.wangzhigang-hv44wF8Li93QT0dZR+AlfA
Cc: linux-mmc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
patches-QSEj5FYQhm4dnm+yROfE0A,
devicetree-u79uwXL29TY76Z2rM5mHXA, Zhangfei Gao
Quoting Zhangfei Gao (2014-01-13 01:14:28)
> Suggest by Arnd: abstract mmc tuning as clock behavior,
> also because different soc have different tuning method and registers.
> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Acked-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> Acked-by: Jaehoon Chung <jh80.chung-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Patch looks good to me with one exception. I do not have
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
clk-next branch. Is there a stable branch I can pull in as a dependency?
Thanks,
Mike
> ---
> .../bindings/arm/hisilicon/hisilicon.txt | 14 +
> .../devicetree/bindings/clock/hi3620-clock.txt | 1 +
> drivers/clk/hisilicon/clk-hi3620.c | 267 ++++++++++++++++++++
> include/dt-bindings/clock/hi3620-clock.h | 5 +
> 4 files changed, 287 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index 8c7a4653508d..df0a452b8526 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -30,3 +30,17 @@ Example:
> resume-offset = <0x308>;
> reboot-offset = <0x4>;
> };
> +
> +PCTRL: Peripheral misc control register
> +
> +Required Properties:
> +- compatible: "hisilicon,pctrl"
> +- reg: Address and size of pctrl.
> +
> +Example:
> +
> + /* for Hi3620 */
> + pctrl: pctrl@fca09000 {
> + compatible = "hisilicon,pctrl";
> + reg = <0xfca09000 0x1000>;
> + };
> diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> index 4b71ab41be53..dad6269f52c5 100644
> --- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> @@ -7,6 +7,7 @@ Required Properties:
>
> - compatible: should be one of the following.
> - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
> + - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
>
> - reg: physical base address of the controller and length of memory mapped
> region.
> diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
> index f24ad6a3a797..54cc3475ec36 100644
> --- a/drivers/clk/hisilicon/clk-hi3620.c
> +++ b/drivers/clk/hisilicon/clk-hi3620.c
> @@ -240,3 +240,270 @@ static void __init hi3620_clk_init(struct device_node *np)
> base);
> }
> CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
> +
> +struct hisi_mmc_clock {
> + unsigned int id;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + u32 clken_reg;
> + u32 clken_bit;
> + u32 div_reg;
> + u32 div_off;
> + u32 div_bits;
> + u32 drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + u32 sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +struct clk_mmc {
> + struct clk_hw hw;
> + u32 id;
> + void __iomem *clken_reg;
> + u32 clken_bit;
> + void __iomem *div_reg;
> + u32 div_off;
> + u32 div_bits;
> + void __iomem *drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + void __iomem *sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
> +
> +static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
> + { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
> + { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
> + { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
> + { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
> +};
> +
> +static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + switch (parent_rate) {
> + case 26000000:
> + return 13000000;
> + case 180000000:
> + return 25000000;
> + case 360000000:
> + return 50000000;
> + case 720000000:
> + return 100000000;
> + default:
> + return parent_rate;
> + }
> +}
> +
> +static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long *best_parent_rate,
> + struct clk **best_parent_p)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long best = 0;
> +
> + if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
> + rate = 13000000;
> + best = 26000000;
> + } else if (rate <= 26000000) {
> + rate = 25000000;
> + best = 180000000;
> + } else if (rate <= 52000000) {
> + rate = 50000000;
> + best = 360000000;
> + } else if (rate <= 100000000) {
> + rate = 100000000;
> + best = 720000000;
> + } else {
> + /* max is 180M */
> + rate = 180000000;
> + best = 1440000000;
> + }
> + *best_parent_rate = best;
> + return rate;
> +}
> +
> +static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
> +{
> + u32 i;
> +
> + if (para >= 0) {
> + for (i = 0; i < len; i++) {
> + if (para % 2)
> + val |= 1 << (off + i);
> + else
> + val &= ~(1 << (off + i));
> + para = para >> 1;
> + }
> + }
> + return val;
> +}
> +
> +static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long flags;
> + u32 sam, drv, div, val;
> + static DEFINE_SPINLOCK(mmc_clk_lock);
> +
> + switch (rate) {
> + case 13000000:
> + sam = 3;
> + drv = 1;
> + div = 1;
> + break;
> + case 25000000:
> + sam = 13;
> + drv = 6;
> + div = 6;
> + break;
> + case 50000000:
> + sam = 3;
> + drv = 6;
> + div = 6;
> + break;
> + case 100000000:
> + sam = 6;
> + drv = 4;
> + div = 6;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + spin_lock_irqsave(&mmc_clk_lock, flags);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val &= ~(1 << mclk->clken_bit);
> + writel_relaxed(val, mclk->clken_reg);
> +
> + val = readl_relaxed(mclk->sam_reg);
> + val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
> + writel_relaxed(val, mclk->sam_reg);
> +
> + val = readl_relaxed(mclk->drv_reg);
> + val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
> + writel_relaxed(val, mclk->drv_reg);
> +
> + val = readl_relaxed(mclk->div_reg);
> + val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
> + writel_relaxed(val, mclk->div_reg);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val |= 1 << mclk->clken_bit;
> + writel_relaxed(val, mclk->clken_reg);
> +
> + spin_unlock_irqrestore(&mmc_clk_lock, flags);
> +
> + return 0;
> +}
> +
> +static int mmc_clk_prepare(struct clk_hw *hw)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long rate;
> +
> + if (mclk->id == HI3620_MMC_CIUCLK1)
> + rate = 13000000;
> + else
> + rate = 25000000;
> +
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static struct clk_ops clk_mmc_ops = {
> + .prepare = mmc_clk_prepare,
> + .determine_rate = mmc_clk_determine_rate,
> + .set_rate = mmc_clk_set_rate,
> + .recalc_rate = mmc_clk_recalc_rate,
> +};
> +
> +static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
> + void __iomem *base, struct device_node *np)
> +{
> + struct clk_mmc *mclk;
> + struct clk *clk;
> + struct clk_init_data init;
> +
> + mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
> + if (!mclk) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + init.name = mmc_clk->name;
> + init.ops = &clk_mmc_ops;
> + init.flags = mmc_clk->flags | CLK_IS_BASIC;
> + init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
> + init.num_parents = (mmc_clk->parent_name ? 1 : 0);
> + mclk->hw.init = &init;
> +
> + mclk->id = mmc_clk->id;
> + mclk->clken_reg = base + mmc_clk->clken_reg;
> + mclk->clken_bit = mmc_clk->clken_bit;
> + mclk->div_reg = base + mmc_clk->div_reg;
> + mclk->div_off = mmc_clk->div_off;
> + mclk->div_bits = mmc_clk->div_bits;
> + mclk->drv_reg = base + mmc_clk->drv_reg;
> + mclk->drv_off = mmc_clk->drv_off;
> + mclk->drv_bits = mmc_clk->drv_bits;
> + mclk->sam_reg = base + mmc_clk->sam_reg;
> + mclk->sam_off = mmc_clk->sam_off;
> + mclk->sam_bits = mmc_clk->sam_bits;
> +
> + clk = clk_register(NULL, &mclk->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + kfree(mclk);
> + return clk;
> +}
> +
> +static void __init hi3620_mmc_clk_init(struct device_node *node)
> +{
> + void __iomem *base;
> + int i, num = ARRAY_SIZE(hi3620_mmc_clks);
> + struct clk_onecell_data *clk_data;
> +
> + if (!node) {
> + pr_err("failed to find pctrl node in DTS\n");
> + return;
> + }
> +
> + base = of_iomap(node, 0);
> + if (!base) {
> + pr_err("failed to map pctrl\n");
> + return;
> + }
> +
> + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> + if (WARN_ON(!clk_data))
> + return;
> +
> + clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
> + if (!clk_data->clks) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return;
> + }
> +
> + for (i = 0; i < num; i++) {
> + struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
> + clk_data->clks[mmc_clk->id] =
> + hisi_register_clk_mmc(mmc_clk, base, node);
> + }
> +
> + clk_data->clk_num = num;
> + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +}
> +
> +CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
> diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
> index 6eaa6a45e110..21b9d0e2eb0c 100644
> --- a/include/dt-bindings/clock/hi3620-clock.h
> +++ b/include/dt-bindings/clock/hi3620-clock.h
> @@ -147,6 +147,11 @@
> #define HI3620_MMC_CLK3 217
> #define HI3620_MCU_CLK 218
>
> +#define HI3620_SD_CIUCLK 0
> +#define HI3620_MMC_CIUCLK1 1
> +#define HI3620_MMC_CIUCLK2 2
> +#define HI3620_MMC_CIUCLK3 3
> +
> #define HI3620_NR_CLKS 219
>
> #endif /* __DTS_HI3620_CLOCK_H */
> --
> 1.7.9.5
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-14 20:17 ` Mike Turquette
0 siblings, 0 replies; 44+ messages in thread
From: Mike Turquette @ 2014-01-14 20:17 UTC (permalink / raw)
To: linux-arm-kernel
Quoting Zhangfei Gao (2014-01-13 01:14:28)
> Suggest by Arnd: abstract mmc tuning as clock behavior,
> also because different soc have different tuning method and registers.
> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
Patch looks good to me with one exception. I do not have
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
clk-next branch. Is there a stable branch I can pull in as a dependency?
Thanks,
Mike
> ---
> .../bindings/arm/hisilicon/hisilicon.txt | 14 +
> .../devicetree/bindings/clock/hi3620-clock.txt | 1 +
> drivers/clk/hisilicon/clk-hi3620.c | 267 ++++++++++++++++++++
> include/dt-bindings/clock/hi3620-clock.h | 5 +
> 4 files changed, 287 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index 8c7a4653508d..df0a452b8526 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -30,3 +30,17 @@ Example:
> resume-offset = <0x308>;
> reboot-offset = <0x4>;
> };
> +
> +PCTRL: Peripheral misc control register
> +
> +Required Properties:
> +- compatible: "hisilicon,pctrl"
> +- reg: Address and size of pctrl.
> +
> +Example:
> +
> + /* for Hi3620 */
> + pctrl: pctrl at fca09000 {
> + compatible = "hisilicon,pctrl";
> + reg = <0xfca09000 0x1000>;
> + };
> diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> index 4b71ab41be53..dad6269f52c5 100644
> --- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> @@ -7,6 +7,7 @@ Required Properties:
>
> - compatible: should be one of the following.
> - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
> + - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
>
> - reg: physical base address of the controller and length of memory mapped
> region.
> diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
> index f24ad6a3a797..54cc3475ec36 100644
> --- a/drivers/clk/hisilicon/clk-hi3620.c
> +++ b/drivers/clk/hisilicon/clk-hi3620.c
> @@ -240,3 +240,270 @@ static void __init hi3620_clk_init(struct device_node *np)
> base);
> }
> CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
> +
> +struct hisi_mmc_clock {
> + unsigned int id;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + u32 clken_reg;
> + u32 clken_bit;
> + u32 div_reg;
> + u32 div_off;
> + u32 div_bits;
> + u32 drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + u32 sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +struct clk_mmc {
> + struct clk_hw hw;
> + u32 id;
> + void __iomem *clken_reg;
> + u32 clken_bit;
> + void __iomem *div_reg;
> + u32 div_off;
> + u32 div_bits;
> + void __iomem *drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + void __iomem *sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
> +
> +static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
> + { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
> + { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
> + { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
> + { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
> +};
> +
> +static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + switch (parent_rate) {
> + case 26000000:
> + return 13000000;
> + case 180000000:
> + return 25000000;
> + case 360000000:
> + return 50000000;
> + case 720000000:
> + return 100000000;
> + default:
> + return parent_rate;
> + }
> +}
> +
> +static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long *best_parent_rate,
> + struct clk **best_parent_p)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long best = 0;
> +
> + if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
> + rate = 13000000;
> + best = 26000000;
> + } else if (rate <= 26000000) {
> + rate = 25000000;
> + best = 180000000;
> + } else if (rate <= 52000000) {
> + rate = 50000000;
> + best = 360000000;
> + } else if (rate <= 100000000) {
> + rate = 100000000;
> + best = 720000000;
> + } else {
> + /* max is 180M */
> + rate = 180000000;
> + best = 1440000000;
> + }
> + *best_parent_rate = best;
> + return rate;
> +}
> +
> +static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
> +{
> + u32 i;
> +
> + if (para >= 0) {
> + for (i = 0; i < len; i++) {
> + if (para % 2)
> + val |= 1 << (off + i);
> + else
> + val &= ~(1 << (off + i));
> + para = para >> 1;
> + }
> + }
> + return val;
> +}
> +
> +static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long flags;
> + u32 sam, drv, div, val;
> + static DEFINE_SPINLOCK(mmc_clk_lock);
> +
> + switch (rate) {
> + case 13000000:
> + sam = 3;
> + drv = 1;
> + div = 1;
> + break;
> + case 25000000:
> + sam = 13;
> + drv = 6;
> + div = 6;
> + break;
> + case 50000000:
> + sam = 3;
> + drv = 6;
> + div = 6;
> + break;
> + case 100000000:
> + sam = 6;
> + drv = 4;
> + div = 6;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + spin_lock_irqsave(&mmc_clk_lock, flags);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val &= ~(1 << mclk->clken_bit);
> + writel_relaxed(val, mclk->clken_reg);
> +
> + val = readl_relaxed(mclk->sam_reg);
> + val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
> + writel_relaxed(val, mclk->sam_reg);
> +
> + val = readl_relaxed(mclk->drv_reg);
> + val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
> + writel_relaxed(val, mclk->drv_reg);
> +
> + val = readl_relaxed(mclk->div_reg);
> + val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
> + writel_relaxed(val, mclk->div_reg);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val |= 1 << mclk->clken_bit;
> + writel_relaxed(val, mclk->clken_reg);
> +
> + spin_unlock_irqrestore(&mmc_clk_lock, flags);
> +
> + return 0;
> +}
> +
> +static int mmc_clk_prepare(struct clk_hw *hw)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long rate;
> +
> + if (mclk->id == HI3620_MMC_CIUCLK1)
> + rate = 13000000;
> + else
> + rate = 25000000;
> +
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static struct clk_ops clk_mmc_ops = {
> + .prepare = mmc_clk_prepare,
> + .determine_rate = mmc_clk_determine_rate,
> + .set_rate = mmc_clk_set_rate,
> + .recalc_rate = mmc_clk_recalc_rate,
> +};
> +
> +static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
> + void __iomem *base, struct device_node *np)
> +{
> + struct clk_mmc *mclk;
> + struct clk *clk;
> + struct clk_init_data init;
> +
> + mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
> + if (!mclk) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + init.name = mmc_clk->name;
> + init.ops = &clk_mmc_ops;
> + init.flags = mmc_clk->flags | CLK_IS_BASIC;
> + init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
> + init.num_parents = (mmc_clk->parent_name ? 1 : 0);
> + mclk->hw.init = &init;
> +
> + mclk->id = mmc_clk->id;
> + mclk->clken_reg = base + mmc_clk->clken_reg;
> + mclk->clken_bit = mmc_clk->clken_bit;
> + mclk->div_reg = base + mmc_clk->div_reg;
> + mclk->div_off = mmc_clk->div_off;
> + mclk->div_bits = mmc_clk->div_bits;
> + mclk->drv_reg = base + mmc_clk->drv_reg;
> + mclk->drv_off = mmc_clk->drv_off;
> + mclk->drv_bits = mmc_clk->drv_bits;
> + mclk->sam_reg = base + mmc_clk->sam_reg;
> + mclk->sam_off = mmc_clk->sam_off;
> + mclk->sam_bits = mmc_clk->sam_bits;
> +
> + clk = clk_register(NULL, &mclk->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + kfree(mclk);
> + return clk;
> +}
> +
> +static void __init hi3620_mmc_clk_init(struct device_node *node)
> +{
> + void __iomem *base;
> + int i, num = ARRAY_SIZE(hi3620_mmc_clks);
> + struct clk_onecell_data *clk_data;
> +
> + if (!node) {
> + pr_err("failed to find pctrl node in DTS\n");
> + return;
> + }
> +
> + base = of_iomap(node, 0);
> + if (!base) {
> + pr_err("failed to map pctrl\n");
> + return;
> + }
> +
> + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> + if (WARN_ON(!clk_data))
> + return;
> +
> + clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
> + if (!clk_data->clks) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return;
> + }
> +
> + for (i = 0; i < num; i++) {
> + struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
> + clk_data->clks[mmc_clk->id] =
> + hisi_register_clk_mmc(mmc_clk, base, node);
> + }
> +
> + clk_data->clk_num = num;
> + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +}
> +
> +CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
> diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
> index 6eaa6a45e110..21b9d0e2eb0c 100644
> --- a/include/dt-bindings/clock/hi3620-clock.h
> +++ b/include/dt-bindings/clock/hi3620-clock.h
> @@ -147,6 +147,11 @@
> #define HI3620_MMC_CLK3 217
> #define HI3620_MCU_CLK 218
>
> +#define HI3620_SD_CIUCLK 0
> +#define HI3620_MMC_CIUCLK1 1
> +#define HI3620_MMC_CIUCLK2 2
> +#define HI3620_MMC_CIUCLK3 3
> +
> #define HI3620_NR_CLKS 219
>
> #endif /* __DTS_HI3620_CLOCK_H */
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-14 20:17 ` Mike Turquette
@ 2014-01-15 1:40 ` zhangfei
-1 siblings, 0 replies; 44+ messages in thread
From: zhangfei @ 2014-01-15 1:40 UTC (permalink / raw)
To: Mike Turquette, Chris Ball, Arnd Bergmann, Jaehoon Chung,
Seungwon Jeon, Haojian Zhuang, brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree
Dear Mike
On 01/15/2014 04:17 AM, Mike Turquette wrote:
> Quoting Zhangfei Gao (2014-01-13 01:14:28)
>> Suggest by Arnd: abstract mmc tuning as clock behavior,
>> also because different soc have different tuning method and registers.
>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>
> Patch looks good to me with one exception. I do not have
> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
> clk-next branch. Is there a stable branch I can pull in as a dependency?
Mach-hisi just have been uploaeded.
Have tried next-20140114, the patch can be applied successfully.
While v3.13-rc8 still can not.
Is this fine?
Thanks
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-15 1:40 ` zhangfei
0 siblings, 0 replies; 44+ messages in thread
From: zhangfei @ 2014-01-15 1:40 UTC (permalink / raw)
To: linux-arm-kernel
Dear Mike
On 01/15/2014 04:17 AM, Mike Turquette wrote:
> Quoting Zhangfei Gao (2014-01-13 01:14:28)
>> Suggest by Arnd: abstract mmc tuning as clock behavior,
>> also because different soc have different tuning method and registers.
>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>
> Patch looks good to me with one exception. I do not have
> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
> clk-next branch. Is there a stable branch I can pull in as a dependency?
Mach-hisi just have been uploaeded.
Have tried next-20140114, the patch can be applied successfully.
While v3.13-rc8 still can not.
Is this fine?
Thanks
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-15 1:40 ` zhangfei
@ 2014-01-15 3:53 ` Mike Turquette
-1 siblings, 0 replies; 44+ messages in thread
From: Mike Turquette @ 2014-01-15 3:53 UTC (permalink / raw)
To: zhangfei, Chris Ball, Arnd Bergmann, Jaehoon Chung,
Seungwon Jeon, Haojian Zhuang, brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree
Quoting zhangfei (2014-01-14 17:40:25)
> Dear Mike
>
> On 01/15/2014 04:17 AM, Mike Turquette wrote:
> > Quoting Zhangfei Gao (2014-01-13 01:14:28)
> >> Suggest by Arnd: abstract mmc tuning as clock behavior,
> >> also because different soc have different tuning method and registers.
> >> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
> >>
> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> >> Acked-by: Arnd Bergmann <arnd@arndb.de>
> >> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
> >
> > Patch looks good to me with one exception. I do not have
> > Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
> > clk-next branch. Is there a stable branch I can pull in as a dependency?
>
> Mach-hisi just have been uploaeded.
> Have tried next-20140114, the patch can be applied successfully.
> While v3.13-rc8 still can not.
>
> Is this fine?
Can you give me a link to the branch that introduces
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt?
I guess the patch introducing it is going through arm-soc. Is this going
in for 3.14? If so then perhaps the clk tree and the arm-soc tree can
share a stable branch that introduces it.
Regards,
Mike
>
> Thanks
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-15 3:53 ` Mike Turquette
0 siblings, 0 replies; 44+ messages in thread
From: Mike Turquette @ 2014-01-15 3:53 UTC (permalink / raw)
To: linux-arm-kernel
Quoting zhangfei (2014-01-14 17:40:25)
> Dear Mike
>
> On 01/15/2014 04:17 AM, Mike Turquette wrote:
> > Quoting Zhangfei Gao (2014-01-13 01:14:28)
> >> Suggest by Arnd: abstract mmc tuning as clock behavior,
> >> also because different soc have different tuning method and registers.
> >> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
> >>
> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> >> Acked-by: Arnd Bergmann <arnd@arndb.de>
> >> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
> >
> > Patch looks good to me with one exception. I do not have
> > Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
> > clk-next branch. Is there a stable branch I can pull in as a dependency?
>
> Mach-hisi just have been uploaeded.
> Have tried next-20140114, the patch can be applied successfully.
> While v3.13-rc8 still can not.
>
> Is this fine?
Can you give me a link to the branch that introduces
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt?
I guess the patch introducing it is going through arm-soc. Is this going
in for 3.14? If so then perhaps the clk tree and the arm-soc tree can
share a stable branch that introduces it.
Regards,
Mike
>
> Thanks
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-15 3:53 ` Mike Turquette
@ 2014-01-15 5:59 ` Haojian Zhuang
-1 siblings, 0 replies; 44+ messages in thread
From: Haojian Zhuang @ 2014-01-15 5:59 UTC (permalink / raw)
To: Mike Turquette, zhangfei, Chris Ball, Arnd Bergmann,
Jaehoon Chung, Seungwon Jeon, brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Kevin Hilman
On 01/15/2014 11:53 AM, Mike Turquette wrote:
> Quoting zhangfei (2014-01-14 17:40:25)
>> Dear Mike
>>
>> On 01/15/2014 04:17 AM, Mike Turquette wrote:
>>> Quoting Zhangfei Gao (2014-01-13 01:14:28)
>>>> Suggest by Arnd: abstract mmc tuning as clock behavior,
>>>> also because different soc have different tuning method and registers.
>>>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>>>>
>>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>>> Patch looks good to me with one exception. I do not have
>>> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
>>> clk-next branch. Is there a stable branch I can pull in as a dependency?
>> Mach-hisi just have been uploaeded.
>> Have tried next-20140114, the patch can be applied successfully.
>> While v3.13-rc8 still can not.
>>
>> Is this fine?
> Can you give me a link to the branch that introduces
> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt?
>
> I guess the patch introducing it is going through arm-soc. Is this going
> in for 3.14? If so then perhaps the clk tree and the arm-soc tree can
> share a stable branch that introduces it.
>
> Regards,
> Mike
>
Some patches are merged into arm-soc, and others are in clk tree.
If sharing a stable branch between arm-soc and clk tree, it only means
that we need to revert all commits that are in arm-soc and clk tree.
I think it's too complex.
How about split the patch? The patch on document should enter in arm-soc.
Regards
Haojian
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-15 5:59 ` Haojian Zhuang
0 siblings, 0 replies; 44+ messages in thread
From: Haojian Zhuang @ 2014-01-15 5:59 UTC (permalink / raw)
To: linux-arm-kernel
On 01/15/2014 11:53 AM, Mike Turquette wrote:
> Quoting zhangfei (2014-01-14 17:40:25)
>> Dear Mike
>>
>> On 01/15/2014 04:17 AM, Mike Turquette wrote:
>>> Quoting Zhangfei Gao (2014-01-13 01:14:28)
>>>> Suggest by Arnd: abstract mmc tuning as clock behavior,
>>>> also because different soc have different tuning method and registers.
>>>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>>>>
>>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>>> Patch looks good to me with one exception. I do not have
>>> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
>>> clk-next branch. Is there a stable branch I can pull in as a dependency?
>> Mach-hisi just have been uploaeded.
>> Have tried next-20140114, the patch can be applied successfully.
>> While v3.13-rc8 still can not.
>>
>> Is this fine?
> Can you give me a link to the branch that introduces
> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt?
>
> I guess the patch introducing it is going through arm-soc. Is this going
> in for 3.14? If so then perhaps the clk tree and the arm-soc tree can
> share a stable branch that introduces it.
>
> Regards,
> Mike
>
Some patches are merged into arm-soc, and others are in clk tree.
If sharing a stable branch between arm-soc and clk tree, it only means
that we need to revert all commits that are in arm-soc and clk tree.
I think it's too complex.
How about split the patch? The patch on document should enter in arm-soc.
Regards
Haojian
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-15 5:59 ` Haojian Zhuang
@ 2014-01-15 8:29 ` Mike Turquette
-1 siblings, 0 replies; 44+ messages in thread
From: Mike Turquette @ 2014-01-15 8:29 UTC (permalink / raw)
To: Haojian Zhuang, zhangfei, Chris Ball, Arnd Bergmann,
Jaehoon Chung, Seungwon Jeon, brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Kevin Hilman
Quoting Haojian Zhuang (2014-01-14 21:59:40)
>
> On 01/15/2014 11:53 AM, Mike Turquette wrote:
> > Quoting zhangfei (2014-01-14 17:40:25)
> >> Dear Mike
> >>
> >> On 01/15/2014 04:17 AM, Mike Turquette wrote:
> >>> Quoting Zhangfei Gao (2014-01-13 01:14:28)
> >>>> Suggest by Arnd: abstract mmc tuning as clock behavior,
> >>>> also because different soc have different tuning method and registers.
> >>>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
> >>>>
> >>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> >>>> Acked-by: Arnd Bergmann <arnd@arndb.de>
> >>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
> >>> Patch looks good to me with one exception. I do not have
> >>> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
> >>> clk-next branch. Is there a stable branch I can pull in as a dependency?
> >> Mach-hisi just have been uploaeded.
> >> Have tried next-20140114, the patch can be applied successfully.
> >> While v3.13-rc8 still can not.
> >>
> >> Is this fine?
> > Can you give me a link to the branch that introduces
> > Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt?
> >
> > I guess the patch introducing it is going through arm-soc. Is this going
> > in for 3.14? If so then perhaps the clk tree and the arm-soc tree can
> > share a stable branch that introduces it.
> >
> > Regards,
> > Mike
> >
> Some patches are merged into arm-soc, and others are in clk tree.
> If sharing a stable branch between arm-soc and clk tree, it only means
> that we need to revert all commits that are in arm-soc and clk tree.
> I think it's too complex.
I'm suggesting reverting any patches that are applied to arm-soc. I'm
only suggesting that there might be a common branch that both the clk
and arm-soc trees can depend on to fix this problem.
>
> How about split the patch? The patch on document should enter in arm-soc.
That is one approach. You might want to run it past the arm-soc folks
first to see if they will take in the binding definition for 3.14.
Regards,
Mike
>
> Regards
> Haojian
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-15 8:29 ` Mike Turquette
0 siblings, 0 replies; 44+ messages in thread
From: Mike Turquette @ 2014-01-15 8:29 UTC (permalink / raw)
To: linux-arm-kernel
Quoting Haojian Zhuang (2014-01-14 21:59:40)
>
> On 01/15/2014 11:53 AM, Mike Turquette wrote:
> > Quoting zhangfei (2014-01-14 17:40:25)
> >> Dear Mike
> >>
> >> On 01/15/2014 04:17 AM, Mike Turquette wrote:
> >>> Quoting Zhangfei Gao (2014-01-13 01:14:28)
> >>>> Suggest by Arnd: abstract mmc tuning as clock behavior,
> >>>> also because different soc have different tuning method and registers.
> >>>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
> >>>>
> >>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> >>>> Acked-by: Arnd Bergmann <arnd@arndb.de>
> >>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
> >>> Patch looks good to me with one exception. I do not have
> >>> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
> >>> clk-next branch. Is there a stable branch I can pull in as a dependency?
> >> Mach-hisi just have been uploaeded.
> >> Have tried next-20140114, the patch can be applied successfully.
> >> While v3.13-rc8 still can not.
> >>
> >> Is this fine?
> > Can you give me a link to the branch that introduces
> > Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt?
> >
> > I guess the patch introducing it is going through arm-soc. Is this going
> > in for 3.14? If so then perhaps the clk tree and the arm-soc tree can
> > share a stable branch that introduces it.
> >
> > Regards,
> > Mike
> >
> Some patches are merged into arm-soc, and others are in clk tree.
> If sharing a stable branch between arm-soc and clk tree, it only means
> that we need to revert all commits that are in arm-soc and clk tree.
> I think it's too complex.
I'm suggesting reverting any patches that are applied to arm-soc. I'm
only suggesting that there might be a common branch that both the clk
and arm-soc trees can depend on to fix this problem.
>
> How about split the patch? The patch on document should enter in arm-soc.
That is one approach. You might want to run it past the arm-soc folks
first to see if they will take in the binding definition for 3.14.
Regards,
Mike
>
> Regards
> Haojian
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-15 8:29 ` Mike Turquette
@ 2014-01-15 9:34 ` Haojian Zhuang
-1 siblings, 0 replies; 44+ messages in thread
From: Haojian Zhuang @ 2014-01-15 9:34 UTC (permalink / raw)
To: Mike Turquette, zhangfei, Chris Ball, Arnd Bergmann,
Jaehoon Chung, Seungwon Jeon, brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Kevin Hilman
On 01/15/2014 04:29 PM, Mike Turquette wrote:
> Quoting Haojian Zhuang (2014-01-14 21:59:40)
>> On 01/15/2014 11:53 AM, Mike Turquette wrote:
>>> Quoting zhangfei (2014-01-14 17:40:25)
>>>> Dear Mike
>>>>
>>>> On 01/15/2014 04:17 AM, Mike Turquette wrote:
>>>>> Quoting Zhangfei Gao (2014-01-13 01:14:28)
>>>>>> Suggest by Arnd: abstract mmc tuning as clock behavior,
>>>>>> also because different soc have different tuning method and registers.
>>>>>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>>>>>>
>>>>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>>>>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>>>>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>>>>> Patch looks good to me with one exception. I do not have
>>>>> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
>>>>> clk-next branch. Is there a stable branch I can pull in as a dependency?
>>>> Mach-hisi just have been uploaeded.
>>>> Have tried next-20140114, the patch can be applied successfully.
>>>> While v3.13-rc8 still can not.
>>>>
>>>> Is this fine?
>>> Can you give me a link to the branch that introduces
>>> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt?
>>>
>>> I guess the patch introducing it is going through arm-soc. Is this going
>>> in for 3.14? If so then perhaps the clk tree and the arm-soc tree can
>>> share a stable branch that introduces it.
>>>
>>> Regards,
>>> Mike
>>>
>> Some patches are merged into arm-soc, and others are in clk tree.
>> If sharing a stable branch between arm-soc and clk tree, it only means
>> that we need to revert all commits that are in arm-soc and clk tree.
>> I think it's too complex.
> I'm suggesting reverting any patches that are applied to arm-soc. I'm
> only suggesting that there might be a common branch that both the clk
> and arm-soc trees can depend on to fix this problem.
>
>> How about split the patch? The patch on document should enter in arm-soc.
> That is one approach. You might want to run it past the arm-soc folks
> first to see if they will take in the binding definition for 3.14.
>
> Regards,
> Mike
>
Yes, so I already made Kevin in this loop. Let's see whether he has
any comments on it.
Regards
Haojian
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-15 9:34 ` Haojian Zhuang
0 siblings, 0 replies; 44+ messages in thread
From: Haojian Zhuang @ 2014-01-15 9:34 UTC (permalink / raw)
To: linux-arm-kernel
On 01/15/2014 04:29 PM, Mike Turquette wrote:
> Quoting Haojian Zhuang (2014-01-14 21:59:40)
>> On 01/15/2014 11:53 AM, Mike Turquette wrote:
>>> Quoting zhangfei (2014-01-14 17:40:25)
>>>> Dear Mike
>>>>
>>>> On 01/15/2014 04:17 AM, Mike Turquette wrote:
>>>>> Quoting Zhangfei Gao (2014-01-13 01:14:28)
>>>>>> Suggest by Arnd: abstract mmc tuning as clock behavior,
>>>>>> also because different soc have different tuning method and registers.
>>>>>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>>>>>>
>>>>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>>>>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>>>>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>>>>> Patch looks good to me with one exception. I do not have
>>>>> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
>>>>> clk-next branch. Is there a stable branch I can pull in as a dependency?
>>>> Mach-hisi just have been uploaeded.
>>>> Have tried next-20140114, the patch can be applied successfully.
>>>> While v3.13-rc8 still can not.
>>>>
>>>> Is this fine?
>>> Can you give me a link to the branch that introduces
>>> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt?
>>>
>>> I guess the patch introducing it is going through arm-soc. Is this going
>>> in for 3.14? If so then perhaps the clk tree and the arm-soc tree can
>>> share a stable branch that introduces it.
>>>
>>> Regards,
>>> Mike
>>>
>> Some patches are merged into arm-soc, and others are in clk tree.
>> If sharing a stable branch between arm-soc and clk tree, it only means
>> that we need to revert all commits that are in arm-soc and clk tree.
>> I think it's too complex.
> I'm suggesting reverting any patches that are applied to arm-soc. I'm
> only suggesting that there might be a common branch that both the clk
> and arm-soc trees can depend on to fix this problem.
>
>> How about split the patch? The patch on document should enter in arm-soc.
> That is one approach. You might want to run it past the arm-soc folks
> first to see if they will take in the binding definition for 3.14.
>
> Regards,
> Mike
>
Yes, so I already made Kevin in this loop. Let's see whether he has
any comments on it.
Regards
Haojian
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
2014-01-15 8:29 ` Mike Turquette
@ 2014-01-15 16:14 ` Kevin Hilman
-1 siblings, 0 replies; 44+ messages in thread
From: Kevin Hilman @ 2014-01-15 16:14 UTC (permalink / raw)
To: Mike Turquette
Cc: Haojian Zhuang, zhangfei, Chris Ball, Arnd Bergmann,
Jaehoon Chung, Seungwon Jeon, brooke.wangzhigang, linux-mmc,
linux-arm-kernel, patches, devicetree
Mike Turquette <mturquette@linaro.org> writes:
> Quoting Haojian Zhuang (2014-01-14 21:59:40)
>>
>> On 01/15/2014 11:53 AM, Mike Turquette wrote:
>> > Quoting zhangfei (2014-01-14 17:40:25)
>> >> Dear Mike
>> >>
>> >> On 01/15/2014 04:17 AM, Mike Turquette wrote:
>> >>> Quoting Zhangfei Gao (2014-01-13 01:14:28)
>> >>>> Suggest by Arnd: abstract mmc tuning as clock behavior,
>> >>>> also because different soc have different tuning method and registers.
>> >>>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>> >>>>
>> >>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> >>>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>> >>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>> >>> Patch looks good to me with one exception. I do not have
>> >>> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
>> >>> clk-next branch. Is there a stable branch I can pull in as a dependency?
>> >> Mach-hisi just have been uploaeded.
>> >> Have tried next-20140114, the patch can be applied successfully.
>> >> While v3.13-rc8 still can not.
>> >>
>> >> Is this fine?
>> > Can you give me a link to the branch that introduces
>> > Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt?
>> >
>> > I guess the patch introducing it is going through arm-soc. Is this going
>> > in for 3.14? If so then perhaps the clk tree and the arm-soc tree can
>> > share a stable branch that introduces it.
>> >
>> > Regards,
>> > Mike
>> >
>> Some patches are merged into arm-soc, and others are in clk tree.
>> If sharing a stable branch between arm-soc and clk tree, it only means
>> that we need to revert all commits that are in arm-soc and clk tree.
>> I think it's too complex.
>
> I'm suggesting reverting any patches that are applied to arm-soc. I'm
> only suggesting that there might be a common branch that both the clk
> and arm-soc trees can depend on to fix this problem.
This one is stable, and is where the binding is introduced:
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git hisi/soc
>> How about split the patch? The patch on document should enter in arm-soc.
>
> That is one approach. You might want to run it past the arm-soc folks
> first to see if they will take in the binding definition for 3.14.
We're not taking anything new for 3.14.
Kevin
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-15 16:14 ` Kevin Hilman
0 siblings, 0 replies; 44+ messages in thread
From: Kevin Hilman @ 2014-01-15 16:14 UTC (permalink / raw)
To: linux-arm-kernel
Mike Turquette <mturquette@linaro.org> writes:
> Quoting Haojian Zhuang (2014-01-14 21:59:40)
>>
>> On 01/15/2014 11:53 AM, Mike Turquette wrote:
>> > Quoting zhangfei (2014-01-14 17:40:25)
>> >> Dear Mike
>> >>
>> >> On 01/15/2014 04:17 AM, Mike Turquette wrote:
>> >>> Quoting Zhangfei Gao (2014-01-13 01:14:28)
>> >>>> Suggest by Arnd: abstract mmc tuning as clock behavior,
>> >>>> also because different soc have different tuning method and registers.
>> >>>> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>> >>>>
>> >>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> >>>> Acked-by: Arnd Bergmann <arnd@arndb.de>
>> >>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>> >>> Patch looks good to me with one exception. I do not have
>> >>> Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt in the
>> >>> clk-next branch. Is there a stable branch I can pull in as a dependency?
>> >> Mach-hisi just have been uploaeded.
>> >> Have tried next-20140114, the patch can be applied successfully.
>> >> While v3.13-rc8 still can not.
>> >>
>> >> Is this fine?
>> > Can you give me a link to the branch that introduces
>> > Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt?
>> >
>> > I guess the patch introducing it is going through arm-soc. Is this going
>> > in for 3.14? If so then perhaps the clk tree and the arm-soc tree can
>> > share a stable branch that introduces it.
>> >
>> > Regards,
>> > Mike
>> >
>> Some patches are merged into arm-soc, and others are in clk tree.
>> If sharing a stable branch between arm-soc and clk tree, it only means
>> that we need to revert all commits that are in arm-soc and clk tree.
>> I think it's too complex.
>
> I'm suggesting reverting any patches that are applied to arm-soc. I'm
> only suggesting that there might be a common branch that both the clk
> and arm-soc trees can depend on to fix this problem.
This one is stable, and is where the binding is introduced:
git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git hisi/soc
>> How about split the patch? The patch on document should enter in arm-soc.
>
> That is one approach. You might want to run it past the arm-soc folks
> first to see if they will take in the binding definition for 3.14.
We're not taking anything new for 3.14.
Kevin
^ permalink raw reply [flat|nested] 44+ messages in thread
* RE: [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
2014-01-13 9:14 ` Zhangfei Gao
@ 2014-01-17 14:43 ` Seungwon Jeon
-1 siblings, 0 replies; 44+ messages in thread
From: Seungwon Jeon @ 2014-01-17 14:43 UTC (permalink / raw)
To: 'Seungwon Jeon', 'Zhangfei Gao',
'Chris Ball', 'Arnd Bergmann',
'Mike Turquette', 'Jaehoon Chung',
'Haojian Zhuang',
brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree
+ Chris Ball (New e-mail)
On Tue, January 14, 2014, Seungwon Jeon wrote:
> On Monday, January 13, 2014, Zhangfei Gao wrote:
> > Remove clk_table and directly use ios->clock as clock source rate.
> > Abstract init clock rate and max clock limitation in clk.c
> >
> > Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>
> Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
>
> Thanks,
> Seungwon Jeon
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
@ 2014-01-17 14:43 ` Seungwon Jeon
0 siblings, 0 replies; 44+ messages in thread
From: Seungwon Jeon @ 2014-01-17 14:43 UTC (permalink / raw)
To: linux-arm-kernel
+ Chris Ball (New e-mail)
On Tue, January 14, 2014, Seungwon Jeon wrote:
> On Monday, January 13, 2014, Zhangfei Gao wrote:
> > Remove clk_table and directly use ios->clock as clock source rate.
> > Abstract init clock rate and max clock limitation in clk.c
> >
> > Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>
> Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
>
> Thanks,
> Seungwon Jeon
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
2014-01-14 10:42 ` Seungwon Jeon
@ 2014-01-17 15:01 ` Chris Ball
-1 siblings, 0 replies; 44+ messages in thread
From: Chris Ball @ 2014-01-17 15:01 UTC (permalink / raw)
To: Seungwon Jeon
Cc: 'Zhangfei Gao', 'Arnd Bergmann',
'Mike Turquette', 'Jaehoon Chung',
'Haojian Zhuang',
brooke.wangzhigang-hv44wF8Li93QT0dZR+AlfA,
linux-mmc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
patches-QSEj5FYQhm4dnm+yROfE0A,
devicetree-u79uwXL29TY76Z2rM5mHXA
Hi,
On Tue, Jan 14 2014, Seungwon Jeon wrote:
> On Monday, January 13, 2014, Zhangfei Gao wrote:
>> Remove clk_table and directly use ios->clock as clock source rate.
>> Abstract init clock rate and max clock limitation in clk.c
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>
> Acked-by: Seungwon Jeon <tgih.jun-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
It looks like patch 1/2 did not make 3.14. Do you want me to take
this patch for 3.14 anyway? (Why?)
Thanks,
- Chris.
--
Chris Ball <chris-OsFVWbfNK3isTnJN9+BGXg@public.gmane.org> <http://printf.net/>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
@ 2014-01-17 15:01 ` Chris Ball
0 siblings, 0 replies; 44+ messages in thread
From: Chris Ball @ 2014-01-17 15:01 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
On Tue, Jan 14 2014, Seungwon Jeon wrote:
> On Monday, January 13, 2014, Zhangfei Gao wrote:
>> Remove clk_table and directly use ios->clock as clock source rate.
>> Abstract init clock rate and max clock limitation in clk.c
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>
> Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
It looks like patch 1/2 did not make 3.14. Do you want me to take
this patch for 3.14 anyway? (Why?)
Thanks,
- Chris.
--
Chris Ball <chris@printf.net> <http://printf.net/>
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
2014-01-17 15:01 ` Chris Ball
@ 2014-01-17 16:10 ` Seungwon Jeon
-1 siblings, 0 replies; 44+ messages in thread
From: Seungwon Jeon @ 2014-01-17 16:10 UTC (permalink / raw)
To: Chris Ball
Cc: Seungwon Jeon, Zhangfei Gao, Arnd Bergmann, Mike Turquette,
Jaehoon Chung, Haojian Zhuang, brooke.wangzhigang, linux-mmc,
linux-arm-kernel, patches, devicetree
On Sat, Jan 18, 2014 at 12:01 AM, Chris Ball <chris@printf.net> wrote:
>
> Hi,
>
> On Tue, Jan 14 2014, Seungwon Jeon wrote:
> > On Monday, January 13, 2014, Zhangfei Gao wrote:
> >> Remove clk_table and directly use ios->clock as clock source rate.
> >> Abstract init clock rate and max clock limitation in clk.c
> >>
> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> >
> > Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
>
> It looks like patch 1/2 did not make 3.14. Do you want me to take
> this patch for 3.14 anyway? (Why?)
Yes, I hope that it would be merged this time.
I think that this change should have been applied to (036f29: mmc:
dw_mmc: add dw_mmc-k3 for k3 platform) originally.
Thanks,
sw-j
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
@ 2014-01-17 16:10 ` Seungwon Jeon
0 siblings, 0 replies; 44+ messages in thread
From: Seungwon Jeon @ 2014-01-17 16:10 UTC (permalink / raw)
To: linux-arm-kernel
On Sat, Jan 18, 2014 at 12:01 AM, Chris Ball <chris@printf.net> wrote:
>
> Hi,
>
> On Tue, Jan 14 2014, Seungwon Jeon wrote:
> > On Monday, January 13, 2014, Zhangfei Gao wrote:
> >> Remove clk_table and directly use ios->clock as clock source rate.
> >> Abstract init clock rate and max clock limitation in clk.c
> >>
> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> >
> > Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
>
> It looks like patch 1/2 did not make 3.14. Do you want me to take
> this patch for 3.14 anyway? (Why?)
Yes, I hope that it would be merged this time.
I think that this change should have been applied to (036f29: mmc:
dw_mmc: add dw_mmc-k3 for k3 platform) originally.
Thanks,
sw-j
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
2014-01-17 16:10 ` Seungwon Jeon
@ 2014-01-17 22:56 ` Mike Turquette
-1 siblings, 0 replies; 44+ messages in thread
From: Mike Turquette @ 2014-01-17 22:56 UTC (permalink / raw)
To: Seungwon Jeon, Chris Ball
Cc: Seungwon Jeon, Zhangfei Gao, Arnd Bergmann, Jaehoon Chung,
Haojian Zhuang, brooke.wangzhigang, linux-mmc, linux-arm-kernel,
patches, devicetree
Quoting Seungwon Jeon (2014-01-17 08:10:23)
> On Sat, Jan 18, 2014 at 12:01 AM, Chris Ball <chris@printf.net> wrote:
> >
> > Hi,
> >
> > On Tue, Jan 14 2014, Seungwon Jeon wrote:
> > > On Monday, January 13, 2014, Zhangfei Gao wrote:
> > >> Remove clk_table and directly use ios->clock as clock source rate.
> > >> Abstract init clock rate and max clock limitation in clk.c
> > >>
> > >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> > >
> > > Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
> >
> > It looks like patch 1/2 did not make 3.14. Do you want me to take
> > this patch for 3.14 anyway? (Why?)
> Yes, I hope that it would be merged this time.
> I think that this change should have been applied to (036f29: mmc:
> dw_mmc: add dw_mmc-k3 for k3 platform) originally.
Oops, I just read this mail. I have taken in patch #1 through the clk
tree but have not yet pushed it out to my public mirror.
Chris, I'm happy to take it if you haven't yet.
Regards,
Mike
>
> Thanks,
> sw-j
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
@ 2014-01-17 22:56 ` Mike Turquette
0 siblings, 0 replies; 44+ messages in thread
From: Mike Turquette @ 2014-01-17 22:56 UTC (permalink / raw)
To: linux-arm-kernel
Quoting Seungwon Jeon (2014-01-17 08:10:23)
> On Sat, Jan 18, 2014 at 12:01 AM, Chris Ball <chris@printf.net> wrote:
> >
> > Hi,
> >
> > On Tue, Jan 14 2014, Seungwon Jeon wrote:
> > > On Monday, January 13, 2014, Zhangfei Gao wrote:
> > >> Remove clk_table and directly use ios->clock as clock source rate.
> > >> Abstract init clock rate and max clock limitation in clk.c
> > >>
> > >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> > >
> > > Acked-by: Seungwon Jeon <tgih.jun@samsung.com>
> >
> > It looks like patch 1/2 did not make 3.14. Do you want me to take
> > this patch for 3.14 anyway? (Why?)
> Yes, I hope that it would be merged this time.
> I think that this change should have been applied to (036f29: mmc:
> dw_mmc: add dw_mmc-k3 for k3 platform) originally.
Oops, I just read this mail. I have taken in patch #1 through the clk
tree but have not yet pushed it out to my public mirror.
Chris, I'm happy to take it if you haven't yet.
Regards,
Mike
>
> Thanks,
> sw-j
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
2014-01-17 22:56 ` Mike Turquette
@ 2014-01-17 23:00 ` Chris Ball
-1 siblings, 0 replies; 44+ messages in thread
From: Chris Ball @ 2014-01-17 23:00 UTC (permalink / raw)
To: Mike Turquette
Cc: Seungwon Jeon, Seungwon Jeon, Zhangfei Gao, Arnd Bergmann,
Jaehoon Chung, Haojian Zhuang, brooke.wangzhigang, linux-mmc,
linux-arm-kernel, patches, devicetree
Hi Mike,
On Fri, Jan 17 2014, Mike Turquette wrote:
> Oops, I just read this mail. I have taken in patch #1 through the clk
> tree but have not yet pushed it out to my public mirror.
>
> Chris, I'm happy to take it if you haven't yet.
That's fine. I'd like to take 2/2, just pushed it to mmc-next for 3.14.
Thanks,
- Chris.
--
Chris Ball <chris@printf.net> <http://printf.net/>
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table
@ 2014-01-17 23:00 ` Chris Ball
0 siblings, 0 replies; 44+ messages in thread
From: Chris Ball @ 2014-01-17 23:00 UTC (permalink / raw)
To: linux-arm-kernel
Hi Mike,
On Fri, Jan 17 2014, Mike Turquette wrote:
> Oops, I just read this mail. I have taken in patch #1 through the clk
> tree but have not yet pushed it out to my public mirror.
>
> Chris, I'm happy to take it if you haven't yet.
That's fine. I'd like to take 2/2, just pushed it to mmc-next for 3.14.
Thanks,
- Chris.
--
Chris Ball <chris@printf.net> <http://printf.net/>
^ permalink raw reply [flat|nested] 44+ messages in thread
* Re: [PATCH] clk: hisilicon: add hi3620_mmc_clks
2014-01-13 9:37 ` Zhangfei Gao
@ 2014-02-27 0:10 ` Mike Turquette
-1 siblings, 0 replies; 44+ messages in thread
From: Mike Turquette @ 2014-02-27 0:10 UTC (permalink / raw)
To: Chris Ball, Arnd Bergmann, Jaehoon Chung, Seungwon Jeon,
Haojian Zhuang, brooke.wangzhigang
Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao
Quoting Zhangfei Gao (2014-01-13 01:37:32)
> Suggest by Arnd: abstract mmc tuning as clock behavior,
> also because different soc have different tuning method and registers.
> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
Taken into clk-next (again! This one got lost when migrating my early
branch from 3.14-rcX to the new clk-next)
Regards,
Mike
> ---
> .../bindings/arm/hisilicon/hisilicon.txt | 14 +
> .../devicetree/bindings/clock/hi3620-clock.txt | 1 +
> drivers/clk/hisilicon/clk-hi3620.c | 274 ++++++++++++++++++++
> include/dt-bindings/clock/hi3620-clock.h | 5 +
> 4 files changed, 294 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index 8c7a4653508d..df0a452b8526 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -30,3 +30,17 @@ Example:
> resume-offset = <0x308>;
> reboot-offset = <0x4>;
> };
> +
> +PCTRL: Peripheral misc control register
> +
> +Required Properties:
> +- compatible: "hisilicon,pctrl"
> +- reg: Address and size of pctrl.
> +
> +Example:
> +
> + /* for Hi3620 */
> + pctrl: pctrl@fca09000 {
> + compatible = "hisilicon,pctrl";
> + reg = <0xfca09000 0x1000>;
> + };
> diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> index 4b71ab41be53..dad6269f52c5 100644
> --- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> @@ -7,6 +7,7 @@ Required Properties:
>
> - compatible: should be one of the following.
> - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
> + - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
>
> - reg: physical base address of the controller and length of memory mapped
> region.
> diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
> index f24ad6a3a797..38faa469d288 100644
> --- a/drivers/clk/hisilicon/clk-hi3620.c
> +++ b/drivers/clk/hisilicon/clk-hi3620.c
> @@ -240,3 +240,277 @@ static void __init hi3620_clk_init(struct device_node *np)
> base);
> }
> CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
> +
> +struct hisi_mmc_clock {
> + unsigned int id;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + u32 clken_reg;
> + u32 clken_bit;
> + u32 div_reg;
> + u32 div_off;
> + u32 div_bits;
> + u32 drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + u32 sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +struct clk_mmc {
> + struct clk_hw hw;
> + u32 id;
> + void __iomem *clken_reg;
> + u32 clken_bit;
> + void __iomem *div_reg;
> + u32 div_off;
> + u32 div_bits;
> + void __iomem *drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + void __iomem *sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
> +
> +static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
> + { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
> + { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
> + { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
> + { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
> +};
> +
> +static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + switch (parent_rate) {
> + case 26000000:
> + return 13000000;
> + case 180000000:
> + return 25000000;
> + case 360000000:
> + return 50000000;
> + case 720000000:
> + return 100000000;
> + case 1440000000:
> + return 180000000;
> + default:
> + return parent_rate;
> + }
> +}
> +
> +static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long *best_parent_rate,
> + struct clk **best_parent_p)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long best = 0;
> +
> + if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
> + rate = 13000000;
> + best = 26000000;
> + } else if (rate <= 26000000) {
> + rate = 25000000;
> + best = 180000000;
> + } else if (rate <= 52000000) {
> + rate = 50000000;
> + best = 360000000;
> + } else if (rate <= 100000000) {
> + rate = 100000000;
> + best = 720000000;
> + } else {
> + /* max is 180M */
> + rate = 180000000;
> + best = 1440000000;
> + }
> + *best_parent_rate = best;
> + return rate;
> +}
> +
> +static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
> +{
> + u32 i;
> +
> + if (para >= 0) {
> + for (i = 0; i < len; i++) {
> + if (para % 2)
> + val |= 1 << (off + i);
> + else
> + val &= ~(1 << (off + i));
> + para = para >> 1;
> + }
> + }
> + return val;
> +}
> +
> +static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long flags;
> + u32 sam, drv, div, val;
> + static DEFINE_SPINLOCK(mmc_clk_lock);
> +
> + switch (rate) {
> + case 13000000:
> + sam = 3;
> + drv = 1;
> + div = 1;
> + break;
> + case 25000000:
> + sam = 13;
> + drv = 6;
> + div = 6;
> + break;
> + case 50000000:
> + sam = 3;
> + drv = 6;
> + div = 6;
> + break;
> + case 100000000:
> + sam = 6;
> + drv = 4;
> + div = 6;
> + break;
> + case 180000000:
> + sam = 6;
> + drv = 4;
> + div = 7;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + spin_lock_irqsave(&mmc_clk_lock, flags);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val &= ~(1 << mclk->clken_bit);
> + writel_relaxed(val, mclk->clken_reg);
> +
> + val = readl_relaxed(mclk->sam_reg);
> + val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
> + writel_relaxed(val, mclk->sam_reg);
> +
> + val = readl_relaxed(mclk->drv_reg);
> + val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
> + writel_relaxed(val, mclk->drv_reg);
> +
> + val = readl_relaxed(mclk->div_reg);
> + val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
> + writel_relaxed(val, mclk->div_reg);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val |= 1 << mclk->clken_bit;
> + writel_relaxed(val, mclk->clken_reg);
> +
> + spin_unlock_irqrestore(&mmc_clk_lock, flags);
> +
> + return 0;
> +}
> +
> +static int mmc_clk_prepare(struct clk_hw *hw)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long rate;
> +
> + if (mclk->id == HI3620_MMC_CIUCLK1)
> + rate = 13000000;
> + else
> + rate = 25000000;
> +
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static struct clk_ops clk_mmc_ops = {
> + .prepare = mmc_clk_prepare,
> + .determine_rate = mmc_clk_determine_rate,
> + .set_rate = mmc_clk_set_rate,
> + .recalc_rate = mmc_clk_recalc_rate,
> +};
> +
> +static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
> + void __iomem *base, struct device_node *np)
> +{
> + struct clk_mmc *mclk;
> + struct clk *clk;
> + struct clk_init_data init;
> +
> + mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
> + if (!mclk) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + init.name = mmc_clk->name;
> + init.ops = &clk_mmc_ops;
> + init.flags = mmc_clk->flags | CLK_IS_BASIC;
> + init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
> + init.num_parents = (mmc_clk->parent_name ? 1 : 0);
> + mclk->hw.init = &init;
> +
> + mclk->id = mmc_clk->id;
> + mclk->clken_reg = base + mmc_clk->clken_reg;
> + mclk->clken_bit = mmc_clk->clken_bit;
> + mclk->div_reg = base + mmc_clk->div_reg;
> + mclk->div_off = mmc_clk->div_off;
> + mclk->div_bits = mmc_clk->div_bits;
> + mclk->drv_reg = base + mmc_clk->drv_reg;
> + mclk->drv_off = mmc_clk->drv_off;
> + mclk->drv_bits = mmc_clk->drv_bits;
> + mclk->sam_reg = base + mmc_clk->sam_reg;
> + mclk->sam_off = mmc_clk->sam_off;
> + mclk->sam_bits = mmc_clk->sam_bits;
> +
> + clk = clk_register(NULL, &mclk->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + kfree(mclk);
> + return clk;
> +}
> +
> +static void __init hi3620_mmc_clk_init(struct device_node *node)
> +{
> + void __iomem *base;
> + int i, num = ARRAY_SIZE(hi3620_mmc_clks);
> + struct clk_onecell_data *clk_data;
> +
> + if (!node) {
> + pr_err("failed to find pctrl node in DTS\n");
> + return;
> + }
> +
> + base = of_iomap(node, 0);
> + if (!base) {
> + pr_err("failed to map pctrl\n");
> + return;
> + }
> +
> + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> + if (WARN_ON(!clk_data))
> + return;
> +
> + clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
> + if (!clk_data->clks) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return;
> + }
> +
> + for (i = 0; i < num; i++) {
> + struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
> + clk_data->clks[mmc_clk->id] =
> + hisi_register_clk_mmc(mmc_clk, base, node);
> + }
> +
> + clk_data->clk_num = num;
> + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +}
> +
> +CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
> diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
> index 6eaa6a45e110..21b9d0e2eb0c 100644
> --- a/include/dt-bindings/clock/hi3620-clock.h
> +++ b/include/dt-bindings/clock/hi3620-clock.h
> @@ -147,6 +147,11 @@
> #define HI3620_MMC_CLK3 217
> #define HI3620_MCU_CLK 218
>
> +#define HI3620_SD_CIUCLK 0
> +#define HI3620_MMC_CIUCLK1 1
> +#define HI3620_MMC_CIUCLK2 2
> +#define HI3620_MMC_CIUCLK3 3
> +
> #define HI3620_NR_CLKS 219
>
> #endif /* __DTS_HI3620_CLOCK_H */
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 44+ messages in thread
* [PATCH] clk: hisilicon: add hi3620_mmc_clks
@ 2014-02-27 0:10 ` Mike Turquette
0 siblings, 0 replies; 44+ messages in thread
From: Mike Turquette @ 2014-02-27 0:10 UTC (permalink / raw)
To: linux-arm-kernel
Quoting Zhangfei Gao (2014-01-13 01:37:32)
> Suggest by Arnd: abstract mmc tuning as clock behavior,
> also because different soc have different tuning method and registers.
> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
Taken into clk-next (again! This one got lost when migrating my early
branch from 3.14-rcX to the new clk-next)
Regards,
Mike
> ---
> .../bindings/arm/hisilicon/hisilicon.txt | 14 +
> .../devicetree/bindings/clock/hi3620-clock.txt | 1 +
> drivers/clk/hisilicon/clk-hi3620.c | 274 ++++++++++++++++++++
> include/dt-bindings/clock/hi3620-clock.h | 5 +
> 4 files changed, 294 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> index 8c7a4653508d..df0a452b8526 100644
> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
> @@ -30,3 +30,17 @@ Example:
> resume-offset = <0x308>;
> reboot-offset = <0x4>;
> };
> +
> +PCTRL: Peripheral misc control register
> +
> +Required Properties:
> +- compatible: "hisilicon,pctrl"
> +- reg: Address and size of pctrl.
> +
> +Example:
> +
> + /* for Hi3620 */
> + pctrl: pctrl at fca09000 {
> + compatible = "hisilicon,pctrl";
> + reg = <0xfca09000 0x1000>;
> + };
> diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> index 4b71ab41be53..dad6269f52c5 100644
> --- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> +++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
> @@ -7,6 +7,7 @@ Required Properties:
>
> - compatible: should be one of the following.
> - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
> + - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
>
> - reg: physical base address of the controller and length of memory mapped
> region.
> diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
> index f24ad6a3a797..38faa469d288 100644
> --- a/drivers/clk/hisilicon/clk-hi3620.c
> +++ b/drivers/clk/hisilicon/clk-hi3620.c
> @@ -240,3 +240,277 @@ static void __init hi3620_clk_init(struct device_node *np)
> base);
> }
> CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
> +
> +struct hisi_mmc_clock {
> + unsigned int id;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + u32 clken_reg;
> + u32 clken_bit;
> + u32 div_reg;
> + u32 div_off;
> + u32 div_bits;
> + u32 drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + u32 sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +struct clk_mmc {
> + struct clk_hw hw;
> + u32 id;
> + void __iomem *clken_reg;
> + u32 clken_bit;
> + void __iomem *div_reg;
> + u32 div_off;
> + u32 div_bits;
> + void __iomem *drv_reg;
> + u32 drv_off;
> + u32 drv_bits;
> + void __iomem *sam_reg;
> + u32 sam_off;
> + u32 sam_bits;
> +};
> +
> +#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
> +
> +static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
> + { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
> + { HI3620_MMC_CIUCLK1, "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
> + { HI3620_MMC_CIUCLK2, "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
> + { HI3620_MMC_CIUCLK3, "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
> +};
> +
> +static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + switch (parent_rate) {
> + case 26000000:
> + return 13000000;
> + case 180000000:
> + return 25000000;
> + case 360000000:
> + return 50000000;
> + case 720000000:
> + return 100000000;
> + case 1440000000:
> + return 180000000;
> + default:
> + return parent_rate;
> + }
> +}
> +
> +static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long *best_parent_rate,
> + struct clk **best_parent_p)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long best = 0;
> +
> + if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
> + rate = 13000000;
> + best = 26000000;
> + } else if (rate <= 26000000) {
> + rate = 25000000;
> + best = 180000000;
> + } else if (rate <= 52000000) {
> + rate = 50000000;
> + best = 360000000;
> + } else if (rate <= 100000000) {
> + rate = 100000000;
> + best = 720000000;
> + } else {
> + /* max is 180M */
> + rate = 180000000;
> + best = 1440000000;
> + }
> + *best_parent_rate = best;
> + return rate;
> +}
> +
> +static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
> +{
> + u32 i;
> +
> + if (para >= 0) {
> + for (i = 0; i < len; i++) {
> + if (para % 2)
> + val |= 1 << (off + i);
> + else
> + val &= ~(1 << (off + i));
> + para = para >> 1;
> + }
> + }
> + return val;
> +}
> +
> +static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long flags;
> + u32 sam, drv, div, val;
> + static DEFINE_SPINLOCK(mmc_clk_lock);
> +
> + switch (rate) {
> + case 13000000:
> + sam = 3;
> + drv = 1;
> + div = 1;
> + break;
> + case 25000000:
> + sam = 13;
> + drv = 6;
> + div = 6;
> + break;
> + case 50000000:
> + sam = 3;
> + drv = 6;
> + div = 6;
> + break;
> + case 100000000:
> + sam = 6;
> + drv = 4;
> + div = 6;
> + break;
> + case 180000000:
> + sam = 6;
> + drv = 4;
> + div = 7;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + spin_lock_irqsave(&mmc_clk_lock, flags);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val &= ~(1 << mclk->clken_bit);
> + writel_relaxed(val, mclk->clken_reg);
> +
> + val = readl_relaxed(mclk->sam_reg);
> + val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
> + writel_relaxed(val, mclk->sam_reg);
> +
> + val = readl_relaxed(mclk->drv_reg);
> + val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
> + writel_relaxed(val, mclk->drv_reg);
> +
> + val = readl_relaxed(mclk->div_reg);
> + val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
> + writel_relaxed(val, mclk->div_reg);
> +
> + val = readl_relaxed(mclk->clken_reg);
> + val |= 1 << mclk->clken_bit;
> + writel_relaxed(val, mclk->clken_reg);
> +
> + spin_unlock_irqrestore(&mmc_clk_lock, flags);
> +
> + return 0;
> +}
> +
> +static int mmc_clk_prepare(struct clk_hw *hw)
> +{
> + struct clk_mmc *mclk = to_mmc(hw);
> + unsigned long rate;
> +
> + if (mclk->id == HI3620_MMC_CIUCLK1)
> + rate = 13000000;
> + else
> + rate = 25000000;
> +
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
> + return mmc_clk_set_timing(hw, rate);
> +}
> +
> +static struct clk_ops clk_mmc_ops = {
> + .prepare = mmc_clk_prepare,
> + .determine_rate = mmc_clk_determine_rate,
> + .set_rate = mmc_clk_set_rate,
> + .recalc_rate = mmc_clk_recalc_rate,
> +};
> +
> +static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
> + void __iomem *base, struct device_node *np)
> +{
> + struct clk_mmc *mclk;
> + struct clk *clk;
> + struct clk_init_data init;
> +
> + mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
> + if (!mclk) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + init.name = mmc_clk->name;
> + init.ops = &clk_mmc_ops;
> + init.flags = mmc_clk->flags | CLK_IS_BASIC;
> + init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
> + init.num_parents = (mmc_clk->parent_name ? 1 : 0);
> + mclk->hw.init = &init;
> +
> + mclk->id = mmc_clk->id;
> + mclk->clken_reg = base + mmc_clk->clken_reg;
> + mclk->clken_bit = mmc_clk->clken_bit;
> + mclk->div_reg = base + mmc_clk->div_reg;
> + mclk->div_off = mmc_clk->div_off;
> + mclk->div_bits = mmc_clk->div_bits;
> + mclk->drv_reg = base + mmc_clk->drv_reg;
> + mclk->drv_off = mmc_clk->drv_off;
> + mclk->drv_bits = mmc_clk->drv_bits;
> + mclk->sam_reg = base + mmc_clk->sam_reg;
> + mclk->sam_off = mmc_clk->sam_off;
> + mclk->sam_bits = mmc_clk->sam_bits;
> +
> + clk = clk_register(NULL, &mclk->hw);
> + if (WARN_ON(IS_ERR(clk)))
> + kfree(mclk);
> + return clk;
> +}
> +
> +static void __init hi3620_mmc_clk_init(struct device_node *node)
> +{
> + void __iomem *base;
> + int i, num = ARRAY_SIZE(hi3620_mmc_clks);
> + struct clk_onecell_data *clk_data;
> +
> + if (!node) {
> + pr_err("failed to find pctrl node in DTS\n");
> + return;
> + }
> +
> + base = of_iomap(node, 0);
> + if (!base) {
> + pr_err("failed to map pctrl\n");
> + return;
> + }
> +
> + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
> + if (WARN_ON(!clk_data))
> + return;
> +
> + clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
> + if (!clk_data->clks) {
> + pr_err("%s: fail to allocate mmc clk\n", __func__);
> + return;
> + }
> +
> + for (i = 0; i < num; i++) {
> + struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
> + clk_data->clks[mmc_clk->id] =
> + hisi_register_clk_mmc(mmc_clk, base, node);
> + }
> +
> + clk_data->clk_num = num;
> + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> +}
> +
> +CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
> diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
> index 6eaa6a45e110..21b9d0e2eb0c 100644
> --- a/include/dt-bindings/clock/hi3620-clock.h
> +++ b/include/dt-bindings/clock/hi3620-clock.h
> @@ -147,6 +147,11 @@
> #define HI3620_MMC_CLK3 217
> #define HI3620_MCU_CLK 218
>
> +#define HI3620_SD_CIUCLK 0
> +#define HI3620_MMC_CIUCLK1 1
> +#define HI3620_MMC_CIUCLK2 2
> +#define HI3620_MMC_CIUCLK3 3
> +
> #define HI3620_NR_CLKS 219
>
> #endif /* __DTS_HI3620_CLOCK_H */
> --
> 1.7.9.5
>
^ permalink raw reply [flat|nested] 44+ messages in thread
end of thread, other threads:[~2014-02-27 0:10 UTC | newest]
Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-13 9:14 [PATCH 0/2] mmc: dw_mmc: k3 remove clk_table Zhangfei Gao
2014-01-13 9:14 ` Zhangfei Gao
2014-01-13 9:14 ` [PATCH 1/2] clk: hisilicon: add hi3620_mmc_clks Zhangfei Gao
2014-01-13 9:14 ` Zhangfei Gao
2014-01-13 9:37 ` [PATCH] " Zhangfei Gao
2014-01-13 9:37 ` Zhangfei Gao
2014-02-27 0:10 ` Mike Turquette
2014-02-27 0:10 ` Mike Turquette
2014-01-14 9:47 ` [PATCH 1/2] " Seungwon Jeon
2014-01-14 9:47 ` Seungwon Jeon
2014-01-14 10:04 ` Zhangfei Gao
2014-01-14 10:04 ` Zhangfei Gao
2014-01-14 10:40 ` Seungwon Jeon
2014-01-14 10:40 ` Seungwon Jeon
2014-01-14 11:52 ` zhangfei
2014-01-14 11:52 ` zhangfei
[not found] ` <1389604469-8064-2-git-send-email-zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-01-14 20:17 ` Mike Turquette
2014-01-14 20:17 ` Mike Turquette
2014-01-15 1:40 ` zhangfei
2014-01-15 1:40 ` zhangfei
2014-01-15 3:53 ` Mike Turquette
2014-01-15 3:53 ` Mike Turquette
2014-01-15 5:59 ` Haojian Zhuang
2014-01-15 5:59 ` Haojian Zhuang
2014-01-15 8:29 ` Mike Turquette
2014-01-15 8:29 ` Mike Turquette
2014-01-15 9:34 ` Haojian Zhuang
2014-01-15 9:34 ` Haojian Zhuang
2014-01-15 16:14 ` Kevin Hilman
2014-01-15 16:14 ` Kevin Hilman
2014-01-13 9:14 ` [PATCH 2/2] mmc: dw_mmc: k3: remove clk_table Zhangfei Gao
2014-01-13 9:14 ` Zhangfei Gao
2014-01-14 10:42 ` Seungwon Jeon
2014-01-14 10:42 ` Seungwon Jeon
[not found] ` <002b01cf1115$4cdfe240$e69fa6c0$%jun-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2014-01-17 15:01 ` Chris Ball
2014-01-17 15:01 ` Chris Ball
2014-01-17 16:10 ` Seungwon Jeon
2014-01-17 16:10 ` Seungwon Jeon
2014-01-17 22:56 ` Mike Turquette
2014-01-17 22:56 ` Mike Turquette
2014-01-17 23:00 ` Chris Ball
2014-01-17 23:00 ` Chris Ball
2014-01-17 14:43 ` Seungwon Jeon
2014-01-17 14:43 ` Seungwon Jeon
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.