* [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 @ 2015-02-22 11:49 Sascha Hauer 2015-02-22 11:49 ` [PATCH 1/5] clk: mediatek: Add initial common clock support for Mediatek SoCs Sascha Hauer ` (5 more replies) 0 siblings, 6 replies; 14+ messages in thread From: Sascha Hauer @ 2015-02-22 11:49 UTC (permalink / raw) To: linux-arm-kernel This patchset contains the initial common clock support for Mediatek SoCs. Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes and clock gates. Sascha Changes in v2: - Re-ordered patchset. Fold include/dt-bindings and DT document in 1st patch. Changes in v3: - Rebase to 3.19-rc1. - Refine code. Remove unneed functions, debug logs and comments, and fine tune error logs. Changes in v4: - Support MT8173 platform. - Re-ordered patchset. driver/clk/Makefile in 2nd patch. - Extract the common part definition(mtk_gate/mtk_pll/mtk_mux) from clk-mt8135.c/clk-mt8173.c to clk-mtk.c. - Refine code. Rmove unnessacary debug information and unsed defines, add prefix "mtk_" for static functions. - Remove flag CLK_IGNORE_UNUSED and set flag CLK_SET_RATE_PARENT on gate/mux/fixed-factor. - Use spin_lock_irqsave(&clk_ops_lock, flags) instead of mtk_clk_lock. - Example above include a node for the clock controller itself, followed by the i2c controller example above. Changes in v5: - Add reset controller support for pericfg/infracfg - Use regmap for the gates - remove now unnecessary spinlock for the gates - Add PMIC wrapper support as of v3 Changes in v6: - rework PLL support, only a fraction of original size now - Move binding docs to Documentation/devicetree/bindings/arm/mediatek since the units are not really clock specific (they contain reset controllers) ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/5] clk: mediatek: Add initial common clock support for Mediatek SoCs. 2015-02-22 11:49 [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 Sascha Hauer @ 2015-02-22 11:49 ` Sascha Hauer 2015-03-13 16:46 ` Matthias Brugger 2015-02-22 11:49 ` [PATCH 2/5] clk: mediatek: Add reset controller support Sascha Hauer ` (4 subsequent siblings) 5 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2015-02-22 11:49 UTC (permalink / raw) To: linux-arm-kernel From: James Liao <jamesjj.liao@mediatek.com> This patch adds common clock support for Mediatek SoCs, including plls, muxes and clock gates. Signed-off-by: James Liao <jamesjj.liao@mediatek.com> Signed-off-by: Henry Chen <henryc.chen@mediatek.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/clk/Makefile | 1 + drivers/clk/mediatek/Makefile | 1 + drivers/clk/mediatek/clk-gate.c | 137 +++++++++++++++++ drivers/clk/mediatek/clk-gate.h | 49 ++++++ drivers/clk/mediatek/clk-mtk.c | 195 ++++++++++++++++++++++++ drivers/clk/mediatek/clk-mtk.h | 164 ++++++++++++++++++++ drivers/clk/mediatek/clk-pll.c | 330 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 877 insertions(+) create mode 100644 drivers/clk/mediatek/Makefile create mode 100644 drivers/clk/mediatek/clk-gate.c create mode 100644 drivers/clk/mediatek/clk-gate.h create mode 100644 drivers/clk/mediatek/clk-mtk.c create mode 100644 drivers/clk/mediatek/clk-mtk.h create mode 100644 drivers/clk/mediatek/clk-pll.c diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index d5fba5b..ce6c250 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ obj-$(CONFIG_ARCH_HIP04) += hisilicon/ obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/ obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ +obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_ARCH_MMP) += mmp/ endif diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile new file mode 100644 index 0000000..c384e97 --- /dev/null +++ b/drivers/clk/mediatek/Makefile @@ -0,0 +1 @@ +obj-y += clk-mtk.o clk-pll.o clk-gate.o diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c new file mode 100644 index 0000000..9d77ee3 --- /dev/null +++ b/drivers/clk/mediatek/clk-gate.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/of.h> +#include <linux/of_address.h> + +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/clkdev.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +static int mtk_cg_bit_is_cleared(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_clk_gate(hw); + u32 val; + + regmap_read(cg->regmap, cg->sta_ofs, &val); + + val &= BIT(cg->bit); + + return val == 0; +} + +static int mtk_cg_bit_is_set(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_clk_gate(hw); + u32 val; + + regmap_read(cg->regmap, cg->sta_ofs, &val); + + val &= BIT(cg->bit); + + return val != 0; +} + +static void mtk_cg_set_bit(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_clk_gate(hw); + + regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit)); +} + +static void mtk_cg_clr_bit(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_clk_gate(hw); + + regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit)); +} + +static int mtk_cg_enable(struct clk_hw *hw) +{ + mtk_cg_clr_bit(hw); + + return 0; +} + +static void mtk_cg_disable(struct clk_hw *hw) +{ + mtk_cg_set_bit(hw); +} + +static int mtk_cg_enable_inv(struct clk_hw *hw) +{ + mtk_cg_set_bit(hw); + + return 0; +} + +static void mtk_cg_disable_inv(struct clk_hw *hw) +{ + mtk_cg_clr_bit(hw); +} + +const struct clk_ops mtk_clk_gate_ops_setclr = { + .is_enabled = mtk_cg_bit_is_cleared, + .enable = mtk_cg_enable, + .disable = mtk_cg_disable, +}; + +const struct clk_ops mtk_clk_gate_ops_setclr_inv = { + .is_enabled = mtk_cg_bit_is_set, + .enable = mtk_cg_enable_inv, + .disable = mtk_cg_disable_inv, +}; + +struct clk *mtk_clk_register_gate( + const char *name, + const char *parent_name, + struct regmap *regmap, + int set_ofs, + int clr_ofs, + int sta_ofs, + u8 bit, + const struct clk_ops *ops) +{ + struct mtk_clk_gate *cg; + struct clk *clk; + struct clk_init_data init; + + cg = kzalloc(sizeof(*cg), GFP_KERNEL); + if (!cg) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.ops = ops; + + cg->regmap = regmap; + cg->set_ofs = set_ofs; + cg->clr_ofs = clr_ofs; + cg->sta_ofs = sta_ofs; + cg->bit = bit; + + cg->hw.init = &init; + + clk = clk_register(NULL, &cg->hw); + if (IS_ERR(clk)) + kfree(cg); + + return clk; +} diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h new file mode 100644 index 0000000..6b6780b --- /dev/null +++ b/drivers/clk/mediatek/clk-gate.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __DRV_CLK_GATE_H +#define __DRV_CLK_GATE_H + +#include <linux/regmap.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> + +struct mtk_clk_gate { + struct clk_hw hw; + struct regmap *regmap; + int set_ofs; + int clr_ofs; + int sta_ofs; + u8 bit; +}; + +static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw) +{ + return container_of(hw, struct mtk_clk_gate, hw); +} + +extern const struct clk_ops mtk_clk_gate_ops_setclr; +extern const struct clk_ops mtk_clk_gate_ops_setclr_inv; + +struct clk *mtk_clk_register_gate( + const char *name, + const char *parent_name, + struct regmap *regmap, + int set_ofs, + int clr_ofs, + int sta_ofs, + u8 bit, + const struct clk_ops *ops); + +#endif /* __DRV_CLK_GATE_H */ diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c new file mode 100644 index 0000000..aeb2cc0 --- /dev/null +++ b/drivers/clk/mediatek/clk-mtk.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/clkdev.h> +#include <linux/mfd/syscon.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num) +{ + int i; + struct clk_onecell_data *clk_data; + + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return NULL; + + clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL); + if (!clk_data->clks) + goto err_out; + + clk_data->clk_num = clk_num; + + for (i = 0; i < clk_num; ++i) + clk_data->clks[i] = ERR_PTR(-ENOENT); + + return clk_data; +err_out: + kfree(clk_data); + + return NULL; +} + +void mtk_clk_register_factors(struct mtk_fixed_factor *clks, int num, + struct clk_onecell_data *clk_data) +{ + int i; + struct clk *clk; + + for (i = 0; i < num; i++) { + struct mtk_fixed_factor *ff = &clks[i]; + + clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name, + CLK_SET_RATE_PARENT, ff->mult, ff->div); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + ff->name, PTR_ERR(clk)); + continue; + } + + if (clk_data) + clk_data->clks[ff->id] = clk; + } +} + +int mtk_clk_register_gates(struct device_node *node, struct mtk_gate *clks, int num, + struct clk_onecell_data *clk_data) +{ + int i; + struct clk *clk; + struct regmap *regmap; + + if (!clk_data) + return -ENOMEM; + + regmap = syscon_node_to_regmap(node); + if (IS_ERR(regmap)) { + pr_err("Cannot find regmap for %s: %ld\n", node->full_name, + PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + for (i = 0; i < num; i++) { + struct mtk_gate *gate = &clks[i]; + + clk = mtk_clk_register_gate(gate->name, gate->parent_name, + regmap, + gate->regs->set_ofs, + gate->regs->clr_ofs, + gate->regs->sta_ofs, + gate->shift, gate->ops); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + gate->name, PTR_ERR(clk)); + continue; + } + + clk_data->clks[gate->id] = clk; + } + + return 0; +} + +struct clk *mtk_clk_register_composite(struct mtk_composite *mc, void __iomem *base, + spinlock_t *lock) +{ + struct clk *clk; + struct clk_mux *mux = NULL; + struct clk_gate *gate = NULL; + struct clk_divider *div = NULL; + struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL; + const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL; + const char **parent_names; + int num_parents; + int ret; + + if (mc->mux_shift >= 0) { + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + return ERR_PTR(-ENOMEM); + + mux->reg = base + mc->mux_reg; + mux->mask = BIT(mc->mux_width) - 1; + mux->shift = mc->mux_shift; + mux->lock = lock; + + mux_hw = &mux->hw; + mux_ops = &clk_mux_ops; + + parent_names = mc->parent_names; + num_parents = mc->num_parents; + } else { + parent_names = &mc->parent; + num_parents = 1; + } + + if (mc->gate_shift >= 0) { + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) { + ret = -ENOMEM; + goto err_out; + } + + gate->reg = base + mc->gate_reg; + gate->bit_idx = mc->gate_shift; + gate->flags = CLK_GATE_SET_TO_DISABLE; + gate->lock = lock; + + gate_hw = &gate->hw; + gate_ops = &clk_gate_ops; + } + + if (mc->divider_shift >= 0) { + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) { + ret = -ENOMEM; + goto err_out; + } + + div->reg = base + mc->divider_reg; + div->shift = mc->divider_shift; + div->width = mc->divider_width; + div->lock = lock; + + div_hw = &div->hw; + div_ops = &clk_divider_ops; + } + + clk = clk_register_composite(NULL, mc->name, parent_names, num_parents, + mux_hw, mux_ops, + div_hw, div_ops, + gate_hw, gate_ops, + mc->flags); + + if (IS_ERR(clk)) { + kfree(gate); + kfree(mux); + } + + return clk; +err_out: + kfree(mux); + + return ERR_PTR(ret); +} diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h new file mode 100644 index 0000000..c7c0d35 --- /dev/null +++ b/drivers/clk/mediatek/clk-mtk.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __DRV_CLK_MTK_H +#define __DRV_CLK_MTK_H + +#include <linux/regmap.h> +#include <linux/bitops.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> + +#define MAX_MUX_GATE_BIT 31 +#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1) + +#define MHZ (1000 * 1000) + +struct mtk_fixed_factor { + int id; + const char *name; + const char *parent_name; + int mult; + int div; +}; + +#define FACTOR(_id, _name, _parent, _mult, _div) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .mult = _mult, \ + .div = _div, \ + } + +extern void mtk_clk_register_factors(struct mtk_fixed_factor *clks, int num, + struct clk_onecell_data *clk_data); + +struct mtk_composite { + int id; + const char *name; + const char **parent_names; + const char *parent; + unsigned flags; + + uint32_t mux_reg; + uint32_t divider_reg; + uint32_t gate_reg; + + signed char mux_shift; + signed char mux_width; + signed char gate_shift; + + signed char divider_shift; + signed char divider_width; + + signed char num_parents; +}; + +#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) { \ + .id = _id, \ + .name = _name, \ + .mux_reg = _reg, \ + .mux_shift = _shift, \ + .mux_width = _width, \ + .gate_reg = _reg, \ + .gate_shift = _gate, \ + .divider_shift = -1, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .flags = CLK_SET_RATE_PARENT, \ + } + +#define MUX(_id, _name, _parents, _reg, _shift, _width) { \ + .id = _id, \ + .name = _name, \ + .mux_reg = _reg, \ + .mux_shift = _shift, \ + .mux_width = _width, \ + .gate_shift = -1, \ + .divider_shift = -1, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .flags = CLK_SET_RATE_PARENT, \ + } + +#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) { \ + .id = _id, \ + .parent = _parent, \ + .name = _name, \ + .divider_reg = _div_reg, \ + .divider_shift = _div_shift, \ + .divider_width = _div_width, \ + .gate_reg = _gate_reg, \ + .gate_shift = _gate_shift, \ + .mux_shift = -1, \ + .flags = 0, \ + } + +struct clk *mtk_clk_register_composite(struct mtk_composite *mc, void __iomem *base, + spinlock_t *lock); + +struct mtk_gate_regs { + u32 sta_ofs; + u32 clr_ofs; + u32 set_ofs; +}; + +struct mtk_gate { + int id; + const char *name; + const char *parent_name; + struct mtk_gate_regs *regs; + int shift; + const struct clk_ops *ops; +}; + +int mtk_clk_register_gates(struct device_node *node, struct mtk_gate *clks, int num, + struct clk_onecell_data *clk_data); + +struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); + +#define HAVE_RST_BAR BIT(0) + +struct mtk_pll_data { + int id; + const char *name; + uint32_t reg; + uint32_t pwr_reg; + uint32_t en_mask; + uint32_t pd_reg; + uint32_t tuner_reg; + int pd_shift; + unsigned int flags; + const struct clk_ops *ops; + u32 rst_bar_mask; + unsigned long fmax; + int pcwbits; + uint32_t pcw_reg; + int pcw_shift; +}; + +void __init mtk_clk_register_plls(struct device_node *node, + const struct mtk_pll_data *plls, int num_plls); + +#ifdef CONFIG_RESET_CONTROLLER +void mtk_register_reset_controller(struct device_node *np, + unsigned int num_regs, int regofs); +#else +static inline void mtk_register_reset_controller(struct device_node *np, + unsigned int num_regs, int regofs) +{ +} +#endif + +#endif /* __DRV_CLK_MTK_H */ diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c new file mode 100644 index 0000000..06cd8c7 --- /dev/null +++ b/drivers/clk/mediatek/clk-pll.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/clkdev.h> +#include <linux/delay.h> + +#include "clk-mtk.h" + +#define CON0_BASE_EN BIT(0) +#define CON0_PWR_ON BIT(0) +#define CON0_ISO_EN BIT(1) +#define CON0_PCW_CHG BIT(31) + +#define AUDPLL_TUNER_EN BIT(31) + +/* + * MediaTek PLLs are configured through their pcw value. The pcw value describes + * a divider in the PLL feedback loop which consists of 7 bits for the integer + * part and the remaining bits (if present) for the fractional part. Also they + * have a 3 bit power-of-two post divider. + */ + +struct mtk_clk_pll { + struct clk_hw hw; + void __iomem *base_addr; + void __iomem *pd_addr; + void __iomem *pwr_addr; + void __iomem *tuner_addr; + void __iomem *pcw_addr; + const struct mtk_pll_data *data; +}; + +static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw) +{ + return container_of(hw, struct mtk_clk_pll, hw); +} + +static int mtk_pll_is_prepared(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + + return (readl(pll->base_addr) & CON0_BASE_EN) != 0; +} + +static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin, + u32 pcw, int postdiv) +{ + int pcwbits = pll->data->pcwbits; + int pcwfbits; + u64 vco; + u8 c = 0; + + /* The fractional part of the PLL divider. */ + pcwfbits = pcwbits > 7 ? pcwbits - 7 : 0; + + vco = (u64)fin * pcw; + + if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0))) + c = 1; + + vco >>= pcwfbits; + + if (c) + ++vco; + + return ((unsigned long)vco + postdiv - 1) / postdiv; +} + +static void mtk_pll_set_rate_regs(struct clk_hw *hw, u32 pcw, + int postdiv) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 con1, pd, val; + int pll_en; + + /* set postdiv */ + pd = readl(pll->pd_addr); + pd &= ~(0x7 << pll->data->pd_shift); + pd |= (ffs(postdiv) - 1) << pll->data->pd_shift; + writel(pd, pll->pd_addr); + + pll_en = readl(pll->base_addr) & CON0_BASE_EN; + + /* set pcw */ + val = readl(pll->pcw_addr); + + val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1, + pll->data->pcw_shift); + val |= pcw << pll->data->pcw_shift; + writel(val, pll->pcw_addr); + + con1 = readl(pll->base_addr + 4); + + if (pll_en) + con1 |= CON0_PCW_CHG; + + writel(con1, pll->base_addr + 4); + if (pll->tuner_addr) + writel(con1 + 1, pll->tuner_addr); + + if (pll_en) + usleep_range(20, 1000); +} + +/* + * mtk_pll_calc_values - calculate good values for a given input frequency. + * @pll: The pll + * @pcw: The pcw value (output) + * @postdiv: The post divider (output) + * @freq: The desired target frequency + * @fin: The input frequency + * + */ +static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv, + u32 freq, u32 fin) +{ + unsigned long fmin = 1000 * MHZ; + u64 _pcw; + u32 val; + + if (freq > pll->data->fmax) + freq = pll->data->fmax; + + for (val = 0; val < 4; val++) { + *postdiv = 1 << val; + if (freq * *postdiv >= fmin) + break; + } + + /* _pcw = freq * postdiv / fin * 2^pcwfbits */ + _pcw = ((u64)freq << val) << (pll->data->pcwbits - 7); + do_div(_pcw, fin); + + *pcw = (u32)_pcw; +} + +static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 pcw = 0; + u32 postdiv; + + mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate); + mtk_pll_set_rate_regs(hw, pcw, postdiv); + + return 0; +} + +static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 postdiv; + u32 pcw; + + postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & 0x7; + postdiv = 1 << postdiv; + + pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift; + pcw &= GENMASK(pll->data->pcwbits - 1, 0); + + return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv); +} + +static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 pcw = 0; + int postdiv; + + mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate); + + return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv); +} + +static int mtk_pll_prepare(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + + r = readl(pll->pwr_addr) | CON0_PWR_ON; + writel(r, pll->pwr_addr); + usleep_range(1, 100); + + r = readl(pll->pwr_addr) & ~CON0_ISO_EN; + writel(r, pll->pwr_addr); + usleep_range(1, 100); + + r = readl(pll->base_addr) | pll->data->en_mask; + writel(r, pll->base_addr); + + if (pll->tuner_addr) { + r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN; + writel(r, pll->tuner_addr); + } + + usleep_range(20, 1000); + + if (pll->data->flags & HAVE_RST_BAR) { + r = readl(pll->base_addr) | pll->data->rst_bar_mask; + writel(r, pll->base_addr); + } + + return 0; +} + +static void mtk_pll_unprepare(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + + if (pll->data->flags & HAVE_RST_BAR) { + r = readl(pll->base_addr) & ~pll->data->rst_bar_mask; + writel(r, pll->base_addr); + } + + if (pll->tuner_addr) { + r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN; + writel(r, pll->tuner_addr); + } + + r = readl(pll->base_addr) & ~CON0_BASE_EN; + writel(r, pll->base_addr); + + r = readl(pll->pwr_addr) | CON0_ISO_EN; + writel(r, pll->pwr_addr); + + r = readl(pll->pwr_addr) & ~CON0_PWR_ON; + writel(r, pll->pwr_addr); +} + +static const struct clk_ops mtk_pll_ops = { + .is_prepared = mtk_pll_is_prepared, + .prepare = mtk_pll_prepare, + .unprepare = mtk_pll_unprepare, + .recalc_rate = mtk_pll_recalc_rate, + .round_rate = mtk_pll_round_rate, + .set_rate = mtk_pll_set_rate, +}; + +static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, + void __iomem *base) +{ + struct mtk_clk_pll *pll; + struct clk_init_data init; + struct clk *clk; + const char *parent_name = "clk26m"; + + pr_debug("%s(): name: %s\n", __func__, data->name); + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + pll->base_addr = base + data->reg; + pll->pwr_addr = base + data->pwr_reg; + pll->pd_addr = base + data->pd_reg; + pll->pcw_addr = base + data->pcw_reg; + if (data->tuner_reg) + pll->tuner_addr = base + data->tuner_reg; + pll->hw.init = &init; + pll->data = data; + + init.name = data->name; + init.ops = &mtk_pll_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + + clk = clk_register(NULL, &pll->hw); + + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} + +void __init mtk_clk_register_plls(struct device_node *node, + const struct mtk_pll_data *plls, int num_plls) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r, i; + struct clk *clk; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(num_plls); + if (!clk_data) + return; + + for (i = 0; i < num_plls; i++) { + const struct mtk_pll_data *pll = &plls[i]; + + clk = mtk_clk_register_pll(pll, base); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + pll->name, PTR_ERR(clk)); + continue; + } + + clk_data->clks[pll->id] = clk; + } + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} -- 2.1.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 1/5] clk: mediatek: Add initial common clock support for Mediatek SoCs. 2015-02-22 11:49 ` [PATCH 1/5] clk: mediatek: Add initial common clock support for Mediatek SoCs Sascha Hauer @ 2015-03-13 16:46 ` Matthias Brugger 2015-03-16 5:34 ` Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Matthias Brugger @ 2015-03-13 16:46 UTC (permalink / raw) To: linux-arm-kernel On 22/02/15 12:49, Sascha Hauer wrote: > From: James Liao <jamesjj.liao@mediatek.com> > diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h > new file mode 100644 > index 0000000..c7c0d35 > --- /dev/null > +++ b/drivers/clk/mediatek/clk-mtk.h [...] > +void __init mtk_clk_register_plls(struct device_node *node, > + const struct mtk_pll_data *plls, int num_plls); > + > +#ifdef CONFIG_RESET_CONTROLLER > +void mtk_register_reset_controller(struct device_node *np, > + unsigned int num_regs, int regofs); > +#else > +static inline void mtk_register_reset_controller(struct device_node *np, > + unsigned int num_regs, int regofs) > +{ > +} > +#endif This lines should only be added once in [2/5], compiling ends with: In file included from drivers/clk/mediatek/clk-mtk.c:24:0: drivers/clk/mediatek/clk-mtk.h:168:20: error: redefinition of ?mtk_register_reset_controller? drivers/clk/mediatek/clk-mtk.h:158:20: note: previous definition of ?mtk_register_reset_controller? was here Cheers, Matthias ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/5] clk: mediatek: Add initial common clock support for Mediatek SoCs. 2015-03-13 16:46 ` Matthias Brugger @ 2015-03-16 5:34 ` Sascha Hauer 0 siblings, 0 replies; 14+ messages in thread From: Sascha Hauer @ 2015-03-16 5:34 UTC (permalink / raw) To: linux-arm-kernel On Fri, Mar 13, 2015 at 05:46:32PM +0100, Matthias Brugger wrote: > > > On 22/02/15 12:49, Sascha Hauer wrote: > > From: James Liao <jamesjj.liao@mediatek.com> > > > diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h > > new file mode 100644 > > index 0000000..c7c0d35 > > --- /dev/null > > +++ b/drivers/clk/mediatek/clk-mtk.h > > [...] > > > +void __init mtk_clk_register_plls(struct device_node *node, > > + const struct mtk_pll_data *plls, int num_plls); > > + > > +#ifdef CONFIG_RESET_CONTROLLER > > +void mtk_register_reset_controller(struct device_node *np, > > + unsigned int num_regs, int regofs); > > +#else > > +static inline void mtk_register_reset_controller(struct device_node *np, > > + unsigned int num_regs, int regofs) > > +{ > > +} > > +#endif > > This lines should only be added once in [2/5], compiling ends with: > > In file included from drivers/clk/mediatek/clk-mtk.c:24:0: > drivers/clk/mediatek/clk-mtk.h:168:20: error: redefinition of ?mtk_register_reset_controller? > drivers/clk/mediatek/clk-mtk.h:158:20: note: previous definition of ?mtk_register_reset_controller? was here Hm, seems to be a rebase accident. Fixed, thanks Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/5] clk: mediatek: Add reset controller support 2015-02-22 11:49 [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 Sascha Hauer 2015-02-22 11:49 ` [PATCH 1/5] clk: mediatek: Add initial common clock support for Mediatek SoCs Sascha Hauer @ 2015-02-22 11:49 ` Sascha Hauer 2015-02-22 11:49 ` [PATCH 3/5] clk: mediatek: Add basic clocks for Mediatek MT8135 Sascha Hauer ` (3 subsequent siblings) 5 siblings, 0 replies; 14+ messages in thread From: Sascha Hauer @ 2015-02-22 11:49 UTC (permalink / raw) To: linux-arm-kernel The pericfg and infracfg units also provide reset lines to several other SoC internal units. Add support for the reset controller. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/clk/mediatek/Makefile | 1 + drivers/clk/mediatek/clk-mtk.h | 10 +++++ drivers/clk/mediatek/reset.c | 99 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 drivers/clk/mediatek/reset.c diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index c384e97..0b6f1c3 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -1 +1,2 @@ obj-y += clk-mtk.o clk-pll.o clk-gate.o +obj-$(CONFIG_RESET_CONTROLLER) += reset.o diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index c7c0d35..fb61040 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -161,4 +161,14 @@ static inline void mtk_register_reset_controller(struct device_node *np, } #endif +#ifdef CONFIG_RESET_CONTROLLER +void mtk_register_reset_controller(struct device_node *np, + unsigned int num_regs, int regofs); +#else +static inline void mtk_register_reset_controller(struct device_node *np, + unsigned int num_regs, int regofs) +{ +} +#endif + #endif /* __DRV_CLK_MTK_H */ diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c new file mode 100644 index 0000000..3a85a53 --- /dev/null +++ b/drivers/clk/mediatek/reset.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/reset-controller.h> +#include <linux/slab.h> + +#include "clk-mtk.h" + +struct mtk_reset { + struct regmap *regmap; + int regofs; + struct reset_controller_dev rcdev; +}; + +static int mtk_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev); + + return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2), + BIT(id % 32), ~0); +} + +static int mtk_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev); + + return regmap_update_bits(data->regmap, data->regofs + ((id / 32) << 2), + BIT(id % 32), 0); +} + +static int mtk_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + int ret; + + ret = mtk_reset_assert(rcdev, id); + if (ret) + return ret; + + return mtk_reset_deassert(rcdev, id); +} + +static struct reset_control_ops mtk_reset_ops = { + .assert = mtk_reset_assert, + .deassert = mtk_reset_deassert, + .reset = mtk_reset, +}; + +void mtk_register_reset_controller(struct device_node *np, + unsigned int num_regs, int regofs) +{ + struct mtk_reset *data; + int ret; + struct regmap *regmap; + + regmap = syscon_node_to_regmap(np); + if (IS_ERR(regmap)) { + pr_err("Cannot find regmap for %s: %ld\n", np->full_name, + PTR_ERR(regmap)); + return; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return; + + data->regmap = regmap; + data->regofs = regofs; + data->rcdev.owner = THIS_MODULE; + data->rcdev.nr_resets = num_regs * 32; + data->rcdev.ops = &mtk_reset_ops; + data->rcdev.of_node = np; + + ret = reset_controller_register(&data->rcdev); + if (ret) { + pr_err("could not register reset controller: %d\n", ret); + kfree(data); + return; + } +} -- 2.1.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/5] clk: mediatek: Add basic clocks for Mediatek MT8135. 2015-02-22 11:49 [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 Sascha Hauer 2015-02-22 11:49 ` [PATCH 1/5] clk: mediatek: Add initial common clock support for Mediatek SoCs Sascha Hauer 2015-02-22 11:49 ` [PATCH 2/5] clk: mediatek: Add reset controller support Sascha Hauer @ 2015-02-22 11:49 ` Sascha Hauer 2015-03-13 7:44 ` Henry Chen 2015-03-15 16:27 ` Daniel Kurtz 2015-02-22 11:49 ` [PATCH 4/5] clk: mediatek: Add basic clocks for Mediatek MT8173 Sascha Hauer ` (2 subsequent siblings) 5 siblings, 2 replies; 14+ messages in thread From: Sascha Hauer @ 2015-02-22 11:49 UTC (permalink / raw) To: linux-arm-kernel From: James Liao <jamesjj.liao@mediatek.com> This patch adds basic clocks for MT8135, including TOPCKGEN, PLLs, INFRA and PERI clocks. Signed-off-by: James Liao <jamesjj.liao@mediatek.com> Signed-off-by: Henry Chen <henryc.chen@mediatek.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/clk/mediatek/Makefile | 1 + drivers/clk/mediatek/clk-mt8135.c | 634 +++++++++++++++++++++ include/dt-bindings/clock/mt8135-clk.h | 190 ++++++ .../dt-bindings/reset-controller/mt8135-resets.h | 64 +++ 4 files changed, 889 insertions(+) create mode 100644 drivers/clk/mediatek/clk-mt8135.c create mode 100644 include/dt-bindings/clock/mt8135-clk.h create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index 0b6f1c3..12ce576 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -1,2 +1,3 @@ obj-y += clk-mtk.o clk-pll.o clk-gate.o obj-$(CONFIG_RESET_CONTROLLER) += reset.o +obj-y += clk-mt8135.o diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c new file mode 100644 index 0000000..6157447 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8135.c @@ -0,0 +1,634 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/slab.h> +#include <linux/mfd/syscon.h> +#include <dt-bindings/clock/mt8135-clk.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +static DEFINE_SPINLOCK(lock); + +static struct mtk_fixed_factor root_clk_alias[] __initdata = { + FACTOR(TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1), + FACTOR(TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1), + FACTOR(TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1), + FACTOR(TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1), +}; + +static struct mtk_fixed_factor top_divs[] __initdata = { + FACTOR(TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2), + FACTOR(TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3), + FACTOR(TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5), + FACTOR(TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7), + + FACTOR(TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2), + FACTOR(TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3), + FACTOR(TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5), + FACTOR(TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7), + FACTOR(TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26), + + FACTOR(TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + FACTOR(TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3), + FACTOR(TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5), + FACTOR(TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7), + FACTOR(TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2), + FACTOR(TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2), + + FACTOR(TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1), + FACTOR(TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2), + FACTOR(TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3), + FACTOR(TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4), + FACTOR(TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5), + FACTOR(TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6), + FACTOR(TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8), + FACTOR(TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12), + + FACTOR(TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1), + + FACTOR(TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1), + FACTOR(TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1), + + FACTOR(TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1), + + FACTOR(TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2), + FACTOR(TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4), + FACTOR(TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6), + FACTOR(TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8), + FACTOR(TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10), + + FACTOR(TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2), + FACTOR(TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4), + FACTOR(TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6), + FACTOR(TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8), + + FACTOR(TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1), + FACTOR(TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1), + FACTOR(TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1), + FACTOR(TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 5), + FACTOR(TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1), + + FACTOR(TOP_APLL_CK, "apll_ck", "audpll", 1, 1), + FACTOR(TOP_APLL_D4, "apll_d4", "audpll", 1, 4), + FACTOR(TOP_APLL_D8, "apll_d8", "audpll", 1, 8), + FACTOR(TOP_APLL_D16, "apll_d16", "audpll", 1, 16), + FACTOR(TOP_APLL_D24, "apll_d24", "audpll", 1, 24), + + FACTOR(TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2), + FACTOR(TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4), + FACTOR(TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8), + + FACTOR(TOP_LVDSTX_CLKDIG_CT, "lvdstx_clkdig_cts", "lvdspll", 1, 1), + FACTOR(TOP_VPLL_DPIX_CK, "vpll_dpix_ck", "lvdspll", 1, 1), + + FACTOR(TOP_TVHDMI_H_CK, "tvhdmi_h_ck", "tvdpll", 1, 1), + + FACTOR(TOP_HDMITX_CLKDIG_D2, "hdmitx_clkdig_d2", "hdmitx_clkdig_cts", 1, 2), + FACTOR(TOP_HDMITX_CLKDIG_D3, "hdmitx_clkdig_d3", "hdmitx_clkdig_cts", 1, 3), + + FACTOR(TOP_TVHDMI_D2, "tvhdmi_d2", "tvhdmi_h_ck", 1, 2), + FACTOR(TOP_TVHDMI_D4, "tvhdmi_d4", "tvhdmi_h_ck", 1, 4), + + FACTOR(TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4), +}; + +static const char *axi_parents[] __initconst = { + "clk26m", + "syspll_d3", + "syspll_d4", + "syspll_d6", + "univpll_d5", + "univpll2_d2", + "syspll_d3p5" +}; + +static const char *smi_parents[] __initconst = { + "clk26m", + "clkph_mck", + "syspll_d2p5", + "syspll_d3", + "syspll_d8", + "univpll_d5", + "univpll1_d2", + "univpll1_d6", + "mmpll_d3", + "mmpll_d4", + "mmpll_d5", + "mmpll_d6", + "mmpll_d7", + "vdecpll", + "lvdspll" +}; + +static const char *mfg_parents[] __initconst = { + "clk26m", + "univpll1_d4", + "syspll_d2", + "syspll_d2p5", + "syspll_d3", + "univpll_d5", + "univpll1_d2", + "mmpll_d2", + "mmpll_d3", + "mmpll_d4", + "mmpll_d5", + "mmpll_d6", + "mmpll_d7" +}; + +static const char *irda_parents[] __initconst = { + "clk26m", + "univpll2_d8", + "univpll1_d6" +}; + +static const char *cam_parents[] __initconst = { + "clk26m", + "syspll_d3", + "syspll_d3p5", + "syspll_d4", + "univpll_d5", + "univpll2_d2", + "univpll_d7", + "univpll1_d4" +}; + +static const char *aud_intbus_parents[] __initconst = { + "clk26m", + "syspll_d6", + "univpll_d10" +}; + +static const char *jpg_parents[] __initconst = { + "clk26m", + "syspll_d5", + "syspll_d4", + "syspll_d3", + "univpll_d7", + "univpll2_d2", + "univpll_d5" +}; + +static const char *disp_parents[] __initconst = { + "clk26m", + "syspll_d3p5", + "syspll_d3", + "univpll2_d2", + "univpll_d5", + "univpll1_d2", + "lvdspll", + "vdecpll" +}; + +static const char *msdc30_parents[] __initconst = { + "clk26m", + "syspll_d6", + "syspll_d5", + "univpll1_d4", + "univpll2_d4", + "msdcpll" +}; + +static const char *usb20_parents[] __initconst = { + "clk26m", + "univpll2_d6", + "univpll1_d10" +}; + +static const char *venc_parents[] __initconst = { + "clk26m", + "syspll_d3", + "syspll_d8", + "univpll_d5", + "univpll1_d6", + "mmpll_d4", + "mmpll_d5", + "mmpll_d6" +}; + +static const char *spi_parents[] __initconst = { + "clk26m", + "syspll_d6", + "syspll_d8", + "syspll_d10", + "univpll1_d6", + "univpll1_d8" +}; + +static const char *uart_parents[] __initconst = { + "clk26m", + "univpll2_d8" +}; + +static const char *mem_parents[] __initconst = { + "clk26m", + "clkph_mck" +}; + +static const char *camtg_parents[] __initconst = { + "clk26m", + "univpll_d26", + "univpll1_d6", + "syspll_d16", + "syspll_d8" +}; + +static const char *audio_parents[] __initconst = { + "clk26m", + "syspll_d24" +}; + +static const char *fix_parents[] __initconst = { + "rtc32k", + "clk26m", + "univpll_d5", + "univpll_d7", + "univpll1_d2", + "univpll1_d4", + "univpll1_d6", + "univpll1_d8" +}; + +static const char *vdec_parents[] __initconst = { + "clk26m", + "vdecpll", + "clkph_mck", + "syspll_d2p5", + "syspll_d3", + "syspll_d3p5", + "syspll_d4", + "syspll_d5", + "syspll_d6", + "syspll_d8", + "univpll1_d2", + "univpll2_d2", + "univpll_d7", + "univpll_d10", + "univpll2_d4", + "lvdspll" +}; + +static const char *ddrphycfg_parents[] __initconst = { + "clk26m", + "axi_sel", + "syspll_d12" +}; + +static const char *dpilvds_parents[] __initconst = { + "clk26m", + "lvdspll", + "lvdspll_d2", + "lvdspll_d4", + "lvdspll_d8" +}; + +static const char *pmicspi_parents[] __initconst = { + "clk26m", + "univpll2_d6", + "syspll_d8", + "syspll_d10", + "univpll1_d10", + "mempll_mck_d4", + "univpll_d26", + "syspll_d24" +}; + +static const char *smi_mfg_as_parents[] __initconst = { + "clk26m", + "smi_sel", + "mfg_sel", + "mem_sel" +}; + +static const char *gcpu_parents[] __initconst = { + "clk26m", + "syspll_d4", + "univpll_d7", + "syspll_d5", + "syspll_d6" +}; + +static const char *dpi1_parents[] __initconst = { + "clk26m", + "tvhdmi_h_ck", + "tvhdmi_d2", + "tvhdmi_d4" +}; + +static const char *cci_parents[] __initconst = { + "clk26m", + "mainpll_537p3m", + "univpll_d3", + "syspll_d2p5", + "syspll_d3", + "syspll_d5" +}; + +static const char *apll_parents[] __initconst = { + "clk26m", + "apll_ck", + "apll_d4", + "apll_d8", + "apll_d16", + "apll_d24" +}; + +static const char *hdmipll_parents[] __initconst = { + "clk26m", + "hdmitx_clkdig_cts", + "hdmitx_clkdig_d2", + "hdmitx_clkdig_d3" +}; + +static struct mtk_composite top_muxes[] __initdata = { + /* CLK_CFG_0 */ + MUX_GATE(TOP_AXI_SEL, "axi_sel", axi_parents, + 0x0140, 0, 3, INVALID_MUX_GATE_BIT), + MUX_GATE(TOP_SMI_SEL, "smi_sel", smi_parents, 0x0140, 8, 4, 15), + MUX_GATE(TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0140, 16, 4, 23), + MUX_GATE(TOP_IRDA_SEL, "irda_sel", irda_parents, 0x0140, 24, 2, 31), + /* CLK_CFG_1 */ + MUX_GATE(TOP_CAM_SEL, "cam_sel", cam_parents, 0x0144, 0, 3, 7), + MUX_GATE(TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, + 0x0144, 8, 2, 15), + MUX_GATE(TOP_JPG_SEL, "jpg_sel", jpg_parents, 0x0144, 16, 3, 23), + MUX_GATE(TOP_DISP_SEL, "disp_sel", disp_parents, 0x0144, 24, 3, 31), + /* CLK_CFG_2 */ + MUX_GATE(TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0148, 0, 3, 7), + MUX_GATE(TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0148, 8, 3, 15), + MUX_GATE(TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x0148, 16, 3, 23), + MUX_GATE(TOP_MSDC30_4_SEL, "msdc30_4_sel", msdc30_parents, 0x0148, 24, 3, 31), + /* CLK_CFG_3 */ + MUX_GATE(TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x014c, 0, 2, 7), + /* CLK_CFG_4 */ + MUX_GATE(TOP_VENC_SEL, "venc_sel", venc_parents, 0x0150, 8, 3, 15), + MUX_GATE(TOP_SPI_SEL, "spi_sel", spi_parents, 0x0150, 16, 3, 23), + MUX_GATE(TOP_UART_SEL, "uart_sel", uart_parents, 0x0150, 24, 2, 31), + /* CLK_CFG_6 */ + MUX_GATE(TOP_MEM_SEL, "mem_sel", mem_parents, 0x0158, 0, 2, 7), + MUX_GATE(TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0158, 8, 3, 15), + MUX_GATE(TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0158, 24, 2, 31), + /* CLK_CFG_7 */ + MUX_GATE(TOP_FIX_SEL, "fix_sel", fix_parents, 0x015c, 0, 3, 7), + MUX_GATE(TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x015c, 8, 4, 15), + MUX_GATE(TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, + 0x015c, 16, 2, 23), + MUX_GATE(TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x015c, 24, 3, 31), + /* CLK_CFG_8 */ + MUX_GATE(TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0164, 0, 3, 7), + MUX_GATE(TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0164, 8, 3, 15), + MUX_GATE(TOP_SMI_MFG_AS_SEL, "smi_mfg_as_sel", smi_mfg_as_parents, + 0x0164, 16, 2, 23), + MUX_GATE(TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0164, 24, 3, 31), + /* CLK_CFG_9 */ + MUX_GATE(TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0168, 0, 2, 7), + MUX_GATE(TOP_CCI_SEL, "cci_sel", cci_parents, 0x0168, 8, 3, 15), + MUX_GATE(TOP_APLL_SEL, "apll_sel", apll_parents, 0x0168, 16, 3, 23), + MUX_GATE(TOP_HDMIPLL_SEL, "hdmipll_sel", hdmipll_parents, 0x0168, 24, 2, 31), +}; + +static void __init mtk_init_clk_topckgen(void __iomem *top_base, + struct clk_onecell_data *clk_data) +{ + int i; + struct clk *clk; + + for (i = 0; i < ARRAY_SIZE(top_muxes); i++) { + struct mtk_composite *mux = &top_muxes[i]; + + clk = mtk_clk_register_composite(mux, top_base, &lock); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + mux->name, PTR_ERR(clk)); + continue; + } + + if (clk_data) + clk_data->clks[mux->id] = clk; + } +} + +static struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x0040, + .clr_ofs = 0x0044, + .sta_ofs = 0x0048, +}; + +#define GATE_ICG(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &infra_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static struct mtk_gate infra_clks[] __initdata = { + GATE_ICG(INFRA_PMIC_WRAP_CK, "pmic_wrap_ck", "axi_sel", 23), + GATE_ICG(INFRA_PMICSPI_CK, "pmicspi_ck", "pmicspi_sel", 22), + GATE_ICG(INFRA_CCIF1_AP_CTRL, "ccif1_ap_ctrl", "axi_sel", 21), + GATE_ICG(INFRA_CCIF0_AP_CTRL, "ccif0_ap_ctrl", "axi_sel", 20), + GATE_ICG(INFRA_KP_CK, "kp_ck", "axi_sel", 16), + GATE_ICG(INFRA_CPUM_CK, "cpum_ck", "cpum_tck_in", 15), + GATE_ICG(INFRA_M4U_CK, "m4u_ck", "mem_sel", 8), + GATE_ICG(INFRA_MFGAXI_CK, "mfgaxi_ck", "axi_sel", 7), + GATE_ICG(INFRA_DEVAPC_CK, "devapc_ck", "axi_sel", 6), + GATE_ICG(INFRA_AUDIO_CK, "audio_ck", "aud_intbus_sel", 5), + GATE_ICG(INFRA_MFG_BUS_CK, "mfg_bus_ck", "axi_sel", 2), + GATE_ICG(INFRA_SMI_CK, "smi_ck", "smi_sel", 1), + GATE_ICG(INFRA_DBGCLK_CK, "dbgclk_ck", "axi_sel", 0), +}; + +static struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x0008, + .clr_ofs = 0x0010, + .sta_ofs = 0x0018, +}; + +static struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = 0x000c, + .clr_ofs = 0x0014, + .sta_ofs = 0x001c, +}; + +#define GATE_PERI0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_PERI1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static struct mtk_gate peri_clks[] __initdata = { + /* PERI0 */ + GATE_PERI0(PERI_I2C5_CK, "i2c5_ck", "axi_sel", 31), + GATE_PERI0(PERI_I2C4_CK, "i2c4_ck", "axi_sel", 30), + GATE_PERI0(PERI_I2C3_CK, "i2c3_ck", "axi_sel", 29), + GATE_PERI0(PERI_I2C2_CK, "i2c2_ck", "axi_sel", 28), + GATE_PERI0(PERI_I2C1_CK, "i2c1_ck", "axi_sel", 27), + GATE_PERI0(PERI_I2C0_CK, "i2c0_ck", "axi_sel", 26), + GATE_PERI0(PERI_UART3_CK, "uart3_ck", "axi_sel", 25), + GATE_PERI0(PERI_UART2_CK, "uart2_ck", "axi_sel", 24), + GATE_PERI0(PERI_UART1_CK, "uart1_ck", "axi_sel", 23), + GATE_PERI0(PERI_UART0_CK, "uart0_ck", "axi_sel", 22), + GATE_PERI0(PERI_IRDA_CK, "irda_ck", "irda_sel", 21), + GATE_PERI0(PERI_NLI_CK, "nli_ck", "axi_sel", 20), + GATE_PERI0(PERI_MD_HIF_CK, "md_hif_ck", "axi_sel", 19), + GATE_PERI0(PERI_AP_HIF_CK, "ap_hif_ck", "axi_sel", 18), + GATE_PERI0(PERI_MSDC30_3_CK, "msdc30_3_ck", "msdc30_4_sel", 17), + GATE_PERI0(PERI_MSDC30_2_CK, "msdc30_2_ck", "msdc30_3_sel", 16), + GATE_PERI0(PERI_MSDC30_1_CK, "msdc30_1_ck", "msdc30_2_sel", 15), + GATE_PERI0(PERI_MSDC20_2_CK, "msdc20_2_ck", "msdc30_1_sel", 14), + GATE_PERI0(PERI_MSDC20_1_CK, "msdc20_1_ck", "msdc30_0_sel", 13), + GATE_PERI0(PERI_AP_DMA_CK, "ap_dma_ck", "axi_sel", 12), + GATE_PERI0(PERI_USB1_CK, "usb1_ck", "usb20_sel", 11), + GATE_PERI0(PERI_USB0_CK, "usb0_ck", "usb20_sel", 10), + GATE_PERI0(PERI_PWM_CK, "pwm_ck", "axi_sel", 9), + GATE_PERI0(PERI_PWM7_CK, "pwm7_ck", "axi_sel", 8), + GATE_PERI0(PERI_PWM6_CK, "pwm6_ck", "axi_sel", 7), + GATE_PERI0(PERI_PWM5_CK, "pwm5_ck", "axi_sel", 6), + GATE_PERI0(PERI_PWM4_CK, "pwm4_ck", "axi_sel", 5), + GATE_PERI0(PERI_PWM3_CK, "pwm3_ck", "axi_sel", 4), + GATE_PERI0(PERI_PWM2_CK, "pwm2_ck", "axi_sel", 3), + GATE_PERI0(PERI_PWM1_CK, "pwm1_ck", "axi_sel", 2), + GATE_PERI0(PERI_THERM_CK, "therm_ck", "axi_sel", 1), + GATE_PERI0(PERI_NFI_CK, "nfi_ck", "axi_sel", 0), + /* PERI1 */ + GATE_PERI1(PERI_USBSLV_CK, "usbslv_ck", "axi_sel", 8), + GATE_PERI1(PERI_USB1_MCU_CK, "usb1_mcu_ck", "axi_sel", 7), + GATE_PERI1(PERI_USB0_MCU_CK, "usb0_mcu_ck", "axi_sel", 6), + GATE_PERI1(PERI_GCPU_CK, "gcpu_ck", "gcpu_sel", 5), + GATE_PERI1(PERI_FHCTL_CK, "fhctl_ck", "clk26m", 4), + GATE_PERI1(PERI_SPI1_CK, "spi1_ck", "spi_sel", 3), + GATE_PERI1(PERI_AUXADC_CK, "auxadc_ck", "clk26m", 2), + GATE_PERI1(PERI_PERI_PWRAP_CK, "peri_pwrap_ck", "axi_sel", 1), + GATE_PERI1(PERI_I2C6_CK, "i2c6_ck", "axi_sel", 0), +}; + +static void __init mtk_topckgen_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(TOP_NR_CLK); + + mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_init_clk_topckgen(base, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init); + +static void __init mtk_infrasys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, 2, 0x30); +} +CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init); + +static void __init mtk_pericfg_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(PERI_NR_CLK); + + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, 2, 0); +} +CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init); + +#define MT8135_PLL_FMAX (2000 * MHZ) +#define CON0_MT8135_RST_BAR BIT(27) + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT8135_RST_BAR, \ + .fmax = MT8135_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + } + +static struct mtk_pll_data plls[] = { + PLL(APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0), + PLL(APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0), + PLL(APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0), + PLL(APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9), + PLL(APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0), + PLL(APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0), + PLL(APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x296, 6, 0x0, 0x298, 0), + PLL(APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0), + PLL(APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0), + PLL(APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0), +}; + +static void __init mtk_apmixedsys_init(struct device_node *node) +{ + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls)); +} +CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys", + mtk_apmixedsys_init); diff --git a/include/dt-bindings/clock/mt8135-clk.h b/include/dt-bindings/clock/mt8135-clk.h new file mode 100644 index 0000000..8aea762 --- /dev/null +++ b/include/dt-bindings/clock/mt8135-clk.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_CLK_MT8135_H +#define _DT_BINDINGS_CLK_MT8135_H + +/* TOPCKGEN */ + +#define TOP_DSI0_LNTC_DSICLK 1 +#define TOP_HDMITX_CLKDIG_CTS 2 +#define TOP_CLKPH_MCK 3 +#define TOP_CPUM_TCK_IN 4 +#define TOP_MAINPLL_806M 5 +#define TOP_MAINPLL_537P3M 6 +#define TOP_MAINPLL_322P4M 7 +#define TOP_MAINPLL_230P3M 8 +#define TOP_UNIVPLL_624M 9 +#define TOP_UNIVPLL_416M 10 +#define TOP_UNIVPLL_249P6M 11 +#define TOP_UNIVPLL_178P3M 12 +#define TOP_UNIVPLL_48M 13 +#define TOP_MMPLL_D2 14 +#define TOP_MMPLL_D3 15 +#define TOP_MMPLL_D5 16 +#define TOP_MMPLL_D7 17 +#define TOP_MMPLL_D4 18 +#define TOP_MMPLL_D6 19 +#define TOP_SYSPLL_D2 20 +#define TOP_SYSPLL_D4 21 +#define TOP_SYSPLL_D6 22 +#define TOP_SYSPLL_D8 23 +#define TOP_SYSPLL_D10 24 +#define TOP_SYSPLL_D12 25 +#define TOP_SYSPLL_D16 26 +#define TOP_SYSPLL_D24 27 +#define TOP_SYSPLL_D3 28 +#define TOP_SYSPLL_D2P5 29 +#define TOP_SYSPLL_D5 30 +#define TOP_SYSPLL_D3P5 31 +#define TOP_UNIVPLL1_D2 32 +#define TOP_UNIVPLL1_D4 33 +#define TOP_UNIVPLL1_D6 34 +#define TOP_UNIVPLL1_D8 35 +#define TOP_UNIVPLL1_D10 36 +#define TOP_UNIVPLL2_D2 37 +#define TOP_UNIVPLL2_D4 38 +#define TOP_UNIVPLL2_D6 39 +#define TOP_UNIVPLL2_D8 40 +#define TOP_UNIVPLL_D3 41 +#define TOP_UNIVPLL_D5 42 +#define TOP_UNIVPLL_D7 43 +#define TOP_UNIVPLL_D10 44 +#define TOP_UNIVPLL_D26 45 +#define TOP_APLL_CK 46 +#define TOP_APLL_D4 47 +#define TOP_APLL_D8 48 +#define TOP_APLL_D16 49 +#define TOP_APLL_D24 50 +#define TOP_LVDSPLL_D2 51 +#define TOP_LVDSPLL_D4 52 +#define TOP_LVDSPLL_D8 53 +#define TOP_LVDSTX_CLKDIG_CT 54 +#define TOP_VPLL_DPIX_CK 55 +#define TOP_TVHDMI_H_CK 56 +#define TOP_HDMITX_CLKDIG_D2 57 +#define TOP_HDMITX_CLKDIG_D3 58 +#define TOP_TVHDMI_D2 59 +#define TOP_TVHDMI_D4 60 +#define TOP_MEMPLL_MCK_D4 61 +#define TOP_AXI_SEL 62 +#define TOP_SMI_SEL 63 +#define TOP_MFG_SEL 64 +#define TOP_IRDA_SEL 65 +#define TOP_CAM_SEL 66 +#define TOP_AUD_INTBUS_SEL 67 +#define TOP_JPG_SEL 68 +#define TOP_DISP_SEL 69 +#define TOP_MSDC30_1_SEL 70 +#define TOP_MSDC30_2_SEL 71 +#define TOP_MSDC30_3_SEL 72 +#define TOP_MSDC30_4_SEL 73 +#define TOP_USB20_SEL 74 +#define TOP_VENC_SEL 75 +#define TOP_SPI_SEL 76 +#define TOP_UART_SEL 77 +#define TOP_MEM_SEL 78 +#define TOP_CAMTG_SEL 79 +#define TOP_AUDIO_SEL 80 +#define TOP_FIX_SEL 81 +#define TOP_VDEC_SEL 82 +#define TOP_DDRPHYCFG_SEL 83 +#define TOP_DPILVDS_SEL 84 +#define TOP_PMICSPI_SEL 85 +#define TOP_MSDC30_0_SEL 86 +#define TOP_SMI_MFG_AS_SEL 87 +#define TOP_GCPU_SEL 88 +#define TOP_DPI1_SEL 89 +#define TOP_CCI_SEL 90 +#define TOP_APLL_SEL 91 +#define TOP_HDMIPLL_SEL 92 +#define TOP_NR_CLK 93 + +/* APMIXED_SYS */ + +#define APMIXED_ARMPLL1 1 +#define APMIXED_ARMPLL2 2 +#define APMIXED_MAINPLL 3 +#define APMIXED_UNIVPLL 4 +#define APMIXED_MMPLL 5 +#define APMIXED_MSDCPLL 6 +#define APMIXED_TVDPLL 7 +#define APMIXED_LVDSPLL 8 +#define APMIXED_AUDPLL 9 +#define APMIXED_VDECPLL 10 +#define APMIXED_NR_CLK 11 + +/* INFRA_SYS */ + +#define INFRA_PMIC_WRAP_CK 1 +#define INFRA_PMICSPI_CK 2 +#define INFRA_CCIF1_AP_CTRL 3 +#define INFRA_CCIF0_AP_CTRL 4 +#define INFRA_KP_CK 5 +#define INFRA_CPUM_CK 6 +#define INFRA_M4U_CK 7 +#define INFRA_MFGAXI_CK 8 +#define INFRA_DEVAPC_CK 9 +#define INFRA_AUDIO_CK 10 +#define INFRA_MFG_BUS_CK 11 +#define INFRA_SMI_CK 12 +#define INFRA_DBGCLK_CK 13 +#define INFRA_NR_CLK 14 + +/* PERI_SYS */ + +#define PERI_I2C5_CK 1 +#define PERI_I2C4_CK 2 +#define PERI_I2C3_CK 3 +#define PERI_I2C2_CK 4 +#define PERI_I2C1_CK 5 +#define PERI_I2C0_CK 6 +#define PERI_UART3_CK 7 +#define PERI_UART2_CK 8 +#define PERI_UART1_CK 9 +#define PERI_UART0_CK 10 +#define PERI_IRDA_CK 11 +#define PERI_NLI_CK 12 +#define PERI_MD_HIF_CK 13 +#define PERI_AP_HIF_CK 14 +#define PERI_MSDC30_3_CK 15 +#define PERI_MSDC30_2_CK 16 +#define PERI_MSDC30_1_CK 17 +#define PERI_MSDC20_2_CK 18 +#define PERI_MSDC20_1_CK 19 +#define PERI_AP_DMA_CK 20 +#define PERI_USB1_CK 21 +#define PERI_USB0_CK 22 +#define PERI_PWM_CK 23 +#define PERI_PWM7_CK 24 +#define PERI_PWM6_CK 25 +#define PERI_PWM5_CK 26 +#define PERI_PWM4_CK 27 +#define PERI_PWM3_CK 28 +#define PERI_PWM2_CK 29 +#define PERI_PWM1_CK 30 +#define PERI_THERM_CK 31 +#define PERI_NFI_CK 32 +#define PERI_USBSLV_CK 33 +#define PERI_USB1_MCU_CK 34 +#define PERI_USB0_MCU_CK 35 +#define PERI_GCPU_CK 36 +#define PERI_FHCTL_CK 37 +#define PERI_SPI1_CK 38 +#define PERI_AUXADC_CK 39 +#define PERI_PERI_PWRAP_CK 40 +#define PERI_I2C6_CK 41 +#define PERI_NR_CLK 42 + +#endif /* _DT_BINDINGS_CLK_MT8135_H */ diff --git a/include/dt-bindings/reset-controller/mt8135-resets.h b/include/dt-bindings/reset-controller/mt8135-resets.h new file mode 100644 index 0000000..1fb6295 --- /dev/null +++ b/include/dt-bindings/reset-controller/mt8135-resets.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Flora Fu, MediaTek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8135 +#define _DT_BINDINGS_RESET_CONTROLLER_MT8135 + +/* INFRACFG resets */ +#define MT8135_INFRA_EMI_REG_RST 0 +#define MT8135_INFRA_DRAMC0_A0_RST 1 +#define MT8135_INFRA_CCIF0_RST 2 +#define MT8135_INFRA_APCIRQ_EINT_RST 3 +#define MT8135_INFRA_APXGPT_RST 4 +#define MT8135_INFRA_SCPSYS_RST 5 +#define MT8135_INFRA_CCIF1_RST 6 +#define MT8135_INFRA_PMIC_WRAP_RST 7 +#define MT8135_INFRA_KP_RST 8 +#define MT8135_INFRA_EMI_RST 32 +#define MT8135_INFRA_DRAMC0_RST 34 +#define MT8135_INFRA_SMI_RST 35 +#define MT8135_INFRA_M4U_RST 36 + +/* PERICFG resets */ +#define MT8135_PERI_UART0_SW_RST 0 +#define MT8135_PERI_UART1_SW_RST 1 +#define MT8135_PERI_UART2_SW_RST 2 +#define MT8135_PERI_UART3_SW_RST 3 +#define MT8135_PERI_IRDA_SW_RST 4 +#define MT8135_PERI_PTP_SW_RST 5 +#define MT8135_PERI_AP_HIF_SW_RST 6 +#define MT8135_PERI_GPCU_SW_RST 7 +#define MT8135_PERI_MD_HIF_SW_RST 8 +#define MT8135_PERI_NLI_SW_RST 9 +#define MT8135_PERI_AUXADC_SW_RST 10 +#define MT8135_PERI_DMA_SW_RST 11 +#define MT8135_PERI_NFI_SW_RST 14 +#define MT8135_PERI_PWM_SW_RST 15 +#define MT8135_PERI_THERM_SW_RST 16 +#define MT8135_PERI_MSDC0_SW_RST 17 +#define MT8135_PERI_MSDC1_SW_RST 18 +#define MT8135_PERI_MSDC2_SW_RST 19 +#define MT8135_PERI_MSDC3_SW_RST 20 +#define MT8135_PERI_I2C0_SW_RST 22 +#define MT8135_PERI_I2C1_SW_RST 23 +#define MT8135_PERI_I2C2_SW_RST 24 +#define MT8135_PERI_I2C3_SW_RST 25 +#define MT8135_PERI_I2C4_SW_RST 26 +#define MT8135_PERI_I2C5_SW_RST 27 +#define MT8135_PERI_I2C6_SW_RST 28 +#define MT8135_PERI_USB_SW_RST 29 +#define MT8135_PERI_SPI1_SW_RST 33 +#define MT8135_PERI_PWRAP_BRIDGE_SW_RST 34 + +#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8135 */ -- 2.1.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/5] clk: mediatek: Add basic clocks for Mediatek MT8135. 2015-02-22 11:49 ` [PATCH 3/5] clk: mediatek: Add basic clocks for Mediatek MT8135 Sascha Hauer @ 2015-03-13 7:44 ` Henry Chen 2015-03-16 5:33 ` Sascha Hauer 2015-03-15 16:27 ` Daniel Kurtz 1 sibling, 1 reply; 14+ messages in thread From: Henry Chen @ 2015-03-13 7:44 UTC (permalink / raw) To: linux-arm-kernel On Sun, 2015-02-22 at 12:49 +0100, Sascha Hauer wrote: > +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \ > + .id = _id, \ > + .name = _name, \ > + .reg = _reg, \ > + .pwr_reg = _pwr_reg, \ > + .en_mask = _en_mask, \ > + .flags = _flags, \ > + .rst_bar_mask = CON0_MT8135_RST_BAR, \ > + .fmax = MT8135_PLL_FMAX, \ > + .pcwbits = _pcwbits, \ > + .pd_reg = _pd_reg, \ > + .pd_shift = _pd_shift, \ > + .tuner_reg = _tuner_reg, \ > + .pcw_reg = _pcw_reg, \ > + .pcw_shift = _pcw_shift, \ > + } > + > +static struct mtk_pll_data plls[] = { > + PLL(APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0), > + PLL(APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0), > + PLL(APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0), > + PLL(APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9), > + PLL(APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0), > + PLL(APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0), > + PLL(APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x296, 6, 0x0, 0x298, 0), Hi Sasha, The pd_reg of tvdpll should be 0x294. Henry > + PLL(APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0), > + PLL(APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0), > + PLL(APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0), > +}; > 15 > +#define TOP_MMPLL_D5 16 > +#define TOP_MMPLL_D7 17 > +#define TOP_MMPLL_D4 18 > +#define TOP_MMPLL_D6 19 > +#define TOP_SYSPLL_D2 20 > +#define TOP_SYSPLL_D4 21 > +#define TOP_SYSPLL_D6 22 > +#define TOP_SYSPLL_D8 23 > +#define TOP_SYSPLL_D10 24 > +#define TOP_SYSPLL_D12 25 > +#define TOP_SYSPLL_D16 26 > +#define TOP_SYSPLL_D24 27 > +#define TOP_SYSPLL_D3 28 > +#define TOP_SYSPLL_D2P5 29 > +#define TOP_SYSPLL_D5 30 > +#define TOP_SYSPLL_D3P5 31 > +#define TOP_UNIVPLL1_D2 32 > +#define TOP_UNIVPLL1_D4 33 > +#define TOP_UNIVPLL1_D6 34 > +#define TOP_UNIVPLL1_D8 35 > +#define TOP_UNIVPLL1_D10 36 > +#define TOP_UNIVPLL2_D2 37 > +#define TOP_UNIVPLL2_D4 38 > +#define TOP_UNIVPLL2_D6 39 > +#define TOP_UNIVPLL2_D8 40 > +#define TOP_UNIVPLL_D3 41 > +#define TOP_UNIVPLL_D5 42 > +#define TOP_UNIVPLL_D7 43 > +#define TOP_UNIVPLL_D10 44 > +#define TOP_UNIVPLL_D26 45 > +#define TOP_APLL_CK 46 > +#define TOP_APLL_D4 47 > +#define TOP_APLL_D8 48 > +#define TOP_APLL_D16 49 > +#define TOP_APLL_D24 50 > +#define TOP_LVDSPLL_D2 51 > +#define TOP_LVDSPLL_D4 52 > +#define TOP_LVDSPLL_D8 53 > +#define TOP_LVDSTX_CLKDIG_CT 54 > +#define TOP_VPLL_DPIX_CK 55 > +#define TOP_TVHDMI_H_CK 56 > +#define TOP_HDMITX_CLKDIG_D2 57 > +#define TOP_HDMITX_CLKDIG_D3 58 > +#define TOP_TVHDMI_D2 59 > +#define TOP_TVHDMI_D4 60 > +#define TOP_MEMPLL_MCK_D4 61 > +#define TOP_AXI_SEL 62 > +#define TOP_SMI_SEL 63 > +#define TOP_MFG_SEL 64 > +#define TOP_IRDA_SEL 65 > +#define TOP_CAM_SEL 66 > +#define TOP_AUD_INTBUS_SEL 67 > +#define TOP_JPG_SEL 68 > +#define TOP_DISP_SEL 69 > +#define TOP_MSDC30_1_SEL 70 > +#define TOP_MSDC30_2_SEL 71 > +#define TOP_MSDC30_3_SEL 72 > +#define TOP_MSDC30_4_SEL 73 > +#define TOP_USB20_SEL 74 > +#define TOP_VENC_SEL 75 > +#define TOP_SPI_SEL 76 > +#define TOP_UART_SEL 77 > +#define TOP_MEM_SEL 78 > +#define TOP_CAMTG_SEL 79 > +#define TOP_AUDIO_SEL 80 > +#define TOP_FIX_SEL 81 > +#define TOP_VDEC_SEL 82 > +#define TOP_DDRPHYCFG_SEL 83 > +#define TOP_DPILVDS_SEL 84 > +#define TOP_PMICSPI_SEL 85 > +#define TOP_MSDC30_0_SEL 86 > +#define TOP_SMI_MFG_AS_SEL 87 > +#define TOP_GCPU_SEL 88 > +#define TOP_DPI1_SEL 89 > +#define TOP_CCI_SEL 90 > +#define TOP_APLL_SEL 91 > +#define TOP_HDMIPLL_SEL 92 > +#define TOP_NR_CLK 93 > + > +/* APMIXED_SYS */ > + > +#define APMIXED_ARMPLL1 1 > +#define APMIXED_ARMPLL2 2 > +#define APMIXED_MAINPLL 3 > +#define APMIXED_UNIVPLL 4 > +#define APMIXED_MMPLL 5 > +#define APMIXED_MSDCPLL 6 > +#define APMIXED_TVDPLL 7 > +#define APMIXED_LVDSPLL 8 > +#define APMIXED_AUDPLL 9 > +#define APMIXED_VDECPLL 10 > +#define APMIXED_NR_CLK 11 > + > +/* INFRA_SYS */ > + > +#define INFRA_PMIC_WRAP_CK 1 > +#define INFRA_PMICSPI_CK 2 > +#define INFRA_CCIF1_AP_CTRL 3 > +#define INFRA_CCIF0_AP_CTRL 4 > +#define INFRA_KP_CK 5 > +#define INFRA_CPUM_CK 6 > +#define INFRA_M4U_CK 7 > +#define INFRA_MFGAXI_CK 8 > +#define INFRA_DEVAPC_CK 9 > +#define INFRA_AUDIO_CK 10 > +#define INFRA_MFG_BUS_CK 11 > +#define INFRA_SMI_CK 12 > +#define INFRA_DBGCLK_CK 13 > +#define INFRA_NR_CLK 14 > + > +/* PERI_SYS */ > + > +#define PERI_I2C5_CK 1 > +#define PERI_I2C4_CK 2 > +#define PERI_I2C3_CK 3 > +#define PERI_I2C2_CK 4 > +#define PERI_I2C1_CK 5 > +#define PERI_I2C0_CK 6 > +#define PERI_UART3_CK 7 > +#define PERI_UART2_CK 8 > +#define PERI_UART1_CK 9 > +#define PERI_UART0_CK 10 > +#define PERI_IRDA_CK 11 > +#define PERI_NLI_CK 12 > +#define PERI_MD_HIF_CK 13 > +#define PERI_AP_HIF_CK 14 > +#define PERI_MSDC30_3_CK 15 > +#define PERI_MSDC30_2_CK 16 > +#define PERI_MSDC30_1_CK 17 > +#define PERI_MSDC20_2_CK 18 > +#define PERI_MSDC20_1_CK 19 > +#define PERI_AP_DMA_CK 20 > +#define PERI_USB1_CK 21 > +#define PERI_USB0_CK 22 > +#define PERI_PWM_CK 23 > +#define PERI_PWM7_CK 24 > +#define PERI_PWM6_CK 25 > +#define PERI_PWM5_CK 26 > +#define PERI_PWM4_CK 27 > +#define PERI_PWM3_CK 28 > +#define PERI_PWM2_CK 29 > +#define PERI_PWM1_CK 30 > +#define PERI_THERM_CK 31 > +#define PERI_NFI_CK 32 > +#define PERI_USBSLV_CK 33 > +#define PERI_USB1_MCU_CK 34 > +#define PERI_USB0_MCU_CK 35 > +#define PERI_GCPU_CK 36 > +#define PERI_FHCTL_CK 37 > +#define PERI_SPI1_CK 38 > +#define PERI_AUXADC_CK 39 > +#define PERI_PERI_PWRAP_CK 40 > +#define PERI_I2C6_CK 41 > +#define PERI_NR_CLK 42 > + > +#endif /* _DT_BINDINGS_CLK_MT8135_H */ > diff --git a/include/dt-bindings/reset-controller/mt8135-resets.h b/include/dt-bindings/reset-controller/mt8135-resets.h > new file mode 100644 > index 0000000..1fb6295 > --- /dev/null > +++ b/include/dt-bindings/reset-controller/mt8135-resets.h > @@ -0,0 +1,64 @@ > +/* > + * Copyright (c) 2014 MediaTek Inc. > + * Author: Flora Fu, MediaTek > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8135 > +#define _DT_BINDINGS_RESET_CONTROLLER_MT8135 > + > +/* INFRACFG resets */ > +#define MT8135_INFRA_EMI_REG_RST 0 > +#define MT8135_INFRA_DRAMC0_A0_RST 1 > +#define MT8135_INFRA_CCIF0_RST 2 > +#define MT8135_INFRA_APCIRQ_EINT_RST 3 > +#define MT8135_INFRA_APXGPT_RST 4 > +#define MT8135_INFRA_SCPSYS_RST 5 > +#define MT8135_INFRA_CCIF1_RST 6 > +#define MT8135_INFRA_PMIC_WRAP_RST 7 > +#define MT8135_INFRA_KP_RST 8 > +#define MT8135_INFRA_EMI_RST 32 > +#define MT8135_INFRA_DRAMC0_RST 34 > +#define MT8135_INFRA_SMI_RST 35 > +#define MT8135_INFRA_M4U_RST 36 > + > +/* PERICFG resets */ > +#define MT8135_PERI_UART0_SW_RST 0 > +#define MT8135_PERI_UART1_SW_RST 1 > +#define MT8135_PERI_UART2_SW_RST 2 > +#define MT8135_PERI_UART3_SW_RST 3 > +#define MT8135_PERI_IRDA_SW_RST 4 > +#define MT8135_PERI_PTP_SW_RST 5 > +#define MT8135_PERI_AP_HIF_SW_RST 6 > +#define MT8135_PERI_GPCU_SW_RST 7 > +#define MT8135_PERI_MD_HIF_SW_RST 8 > +#define MT8135_PERI_NLI_SW_RST 9 > +#define MT8135_PERI_AUXADC_SW_RST 10 > +#define MT8135_PERI_DMA_SW_RST 11 > +#define MT8135_PERI_NFI_SW_RST 14 > +#define MT8135_PERI_PWM_SW_RST 15 > +#define MT8135_PERI_THERM_SW_RST 16 > +#define MT8135_PERI_MSDC0_SW_RST 17 > +#define MT8135_PERI_MSDC1_SW_RST 18 > +#define MT8135_PERI_MSDC2_SW_RST 19 > +#define MT8135_PERI_MSDC3_SW_RST 20 > +#define MT8135_PERI_I2C0_SW_RST 22 > +#define MT8135_PERI_I2C1_SW_RST 23 > +#define MT8135_PERI_I2C2_SW_RST 24 > +#define MT8135_PERI_I2C3_SW_RST 25 > +#define MT8135_PERI_I2C4_SW_RST 26 > +#define MT8135_PERI_I2C5_SW_RST 27 > +#define MT8135_PERI_I2C6_SW_RST 28 > +#define MT8135_PERI_USB_SW_RST 29 > +#define MT8135_PERI_SPI1_SW_RST 33 > +#define MT8135_PERI_PWRAP_BRIDGE_SW_RST 34 > + > +#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8135 */ ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 3/5] clk: mediatek: Add basic clocks for Mediatek MT8135. 2015-03-13 7:44 ` Henry Chen @ 2015-03-16 5:33 ` Sascha Hauer 0 siblings, 0 replies; 14+ messages in thread From: Sascha Hauer @ 2015-03-16 5:33 UTC (permalink / raw) To: linux-arm-kernel On Fri, Mar 13, 2015 at 03:44:30PM +0800, Henry Chen wrote: > On Sun, 2015-02-22 at 12:49 +0100, Sascha Hauer wrote: > > +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \ > > + .id = _id, \ > > + .name = _name, \ > > + .reg = _reg, \ > > + .pwr_reg = _pwr_reg, \ > > + .en_mask = _en_mask, \ > > + .flags = _flags, \ > > + .rst_bar_mask = CON0_MT8135_RST_BAR, \ > > + .fmax = MT8135_PLL_FMAX, \ > > + .pcwbits = _pcwbits, \ > > + .pd_reg = _pd_reg, \ > > + .pd_shift = _pd_shift, \ > > + .tuner_reg = _tuner_reg, \ > > + .pcw_reg = _pcw_reg, \ > > + .pcw_shift = _pcw_shift, \ > > + } > > + > > +static struct mtk_pll_data plls[] = { > > + PLL(APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0), > > + PLL(APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0), > > + PLL(APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0), > > + PLL(APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9), > > + PLL(APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0), > > + PLL(APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0), > > + PLL(APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x296, 6, 0x0, 0x298, 0), > > Hi Sasha, > > The pd_reg of tvdpll should be 0x294. Fixed, thanks Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 3/5] clk: mediatek: Add basic clocks for Mediatek MT8135. 2015-02-22 11:49 ` [PATCH 3/5] clk: mediatek: Add basic clocks for Mediatek MT8135 Sascha Hauer 2015-03-13 7:44 ` Henry Chen @ 2015-03-15 16:27 ` Daniel Kurtz 2015-03-16 5:33 ` Sascha Hauer 1 sibling, 1 reply; 14+ messages in thread From: Daniel Kurtz @ 2015-03-15 16:27 UTC (permalink / raw) To: linux-arm-kernel Hi Sascha, Drive-by review... On Sun, Feb 22, 2015 at 7:49 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote: > From: James Liao <jamesjj.liao@mediatek.com> > > This patch adds basic clocks for MT8135, including TOPCKGEN, PLLs, > INFRA and PERI clocks. > > Signed-off-by: James Liao <jamesjj.liao@mediatek.com> > Signed-off-by: Henry Chen <henryc.chen@mediatek.com> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > drivers/clk/mediatek/Makefile | 1 + > drivers/clk/mediatek/clk-mt8135.c | 634 +++++++++++++++++++++ > include/dt-bindings/clock/mt8135-clk.h | 190 ++++++ > .../dt-bindings/reset-controller/mt8135-resets.h | 64 +++ > 4 files changed, 889 insertions(+) > create mode 100644 drivers/clk/mediatek/clk-mt8135.c > create mode 100644 include/dt-bindings/clock/mt8135-clk.h > create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h > > diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile > index 0b6f1c3..12ce576 100644 > --- a/drivers/clk/mediatek/Makefile > +++ b/drivers/clk/mediatek/Makefile > @@ -1,2 +1,3 @@ > obj-y += clk-mtk.o clk-pll.o clk-gate.o > obj-$(CONFIG_RESET_CONTROLLER) += reset.o > +obj-y += clk-mt8135.o > diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c > new file mode 100644 > index 0000000..6157447 > --- /dev/null > +++ b/drivers/clk/mediatek/clk-mt8135.c > @@ -0,0 +1,634 @@ > +/* > + * Copyright (c) 2014 MediaTek Inc. > + * Author: James Liao <jamesjj.liao@mediatek.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#include <linux/of.h> > +#include <linux/of_address.h> > +#include <linux/slab.h> > +#include <linux/mfd/syscon.h> > +#include <dt-bindings/clock/mt8135-clk.h> > + > +#include "clk-mtk.h" > +#include "clk-gate.h" > + > +static DEFINE_SPINLOCK(lock); > + > +static struct mtk_fixed_factor root_clk_alias[] __initdata = { Any reason you can't use "static const" here, and on all of the other static constant structures/arrays throughout this patch. Thanks, -Dan > + FACTOR(TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1), > + FACTOR(TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1), > + FACTOR(TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1), > + FACTOR(TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1), > +}; > + > +static struct mtk_fixed_factor top_divs[] __initdata = { > + FACTOR(TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2), > + FACTOR(TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3), > + FACTOR(TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5), > + FACTOR(TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7), > + > + FACTOR(TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2), > + FACTOR(TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3), > + FACTOR(TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5), > + FACTOR(TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7), > + FACTOR(TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26), > + > + FACTOR(TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), > + FACTOR(TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3), > + FACTOR(TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5), > + FACTOR(TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7), > + FACTOR(TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2), > + FACTOR(TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2), > + > + FACTOR(TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1), > + FACTOR(TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2), > + FACTOR(TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3), > + FACTOR(TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4), > + FACTOR(TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5), > + FACTOR(TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6), > + FACTOR(TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8), > + FACTOR(TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12), > + > + FACTOR(TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1), > + > + FACTOR(TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1), > + FACTOR(TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1), > + > + FACTOR(TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1), > + > + FACTOR(TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2), > + FACTOR(TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4), > + FACTOR(TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6), > + FACTOR(TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8), > + FACTOR(TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10), > + > + FACTOR(TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2), > + FACTOR(TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4), > + FACTOR(TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6), > + FACTOR(TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8), > + > + FACTOR(TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1), > + FACTOR(TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1), > + FACTOR(TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1), > + FACTOR(TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 5), > + FACTOR(TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1), > + > + FACTOR(TOP_APLL_CK, "apll_ck", "audpll", 1, 1), > + FACTOR(TOP_APLL_D4, "apll_d4", "audpll", 1, 4), > + FACTOR(TOP_APLL_D8, "apll_d8", "audpll", 1, 8), > + FACTOR(TOP_APLL_D16, "apll_d16", "audpll", 1, 16), > + FACTOR(TOP_APLL_D24, "apll_d24", "audpll", 1, 24), > + > + FACTOR(TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2), > + FACTOR(TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4), > + FACTOR(TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8), > + > + FACTOR(TOP_LVDSTX_CLKDIG_CT, "lvdstx_clkdig_cts", "lvdspll", 1, 1), > + FACTOR(TOP_VPLL_DPIX_CK, "vpll_dpix_ck", "lvdspll", 1, 1), > + > + FACTOR(TOP_TVHDMI_H_CK, "tvhdmi_h_ck", "tvdpll", 1, 1), > + > + FACTOR(TOP_HDMITX_CLKDIG_D2, "hdmitx_clkdig_d2", "hdmitx_clkdig_cts", 1, 2), > + FACTOR(TOP_HDMITX_CLKDIG_D3, "hdmitx_clkdig_d3", "hdmitx_clkdig_cts", 1, 3), > + > + FACTOR(TOP_TVHDMI_D2, "tvhdmi_d2", "tvhdmi_h_ck", 1, 2), > + FACTOR(TOP_TVHDMI_D4, "tvhdmi_d4", "tvhdmi_h_ck", 1, 4), > + > + FACTOR(TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4), > +}; > + > +static const char *axi_parents[] __initconst = { > + "clk26m", > + "syspll_d3", > + "syspll_d4", > + "syspll_d6", > + "univpll_d5", > + "univpll2_d2", > + "syspll_d3p5" > +}; > + > +static const char *smi_parents[] __initconst = { > + "clk26m", > + "clkph_mck", > + "syspll_d2p5", > + "syspll_d3", > + "syspll_d8", > + "univpll_d5", > + "univpll1_d2", > + "univpll1_d6", > + "mmpll_d3", > + "mmpll_d4", > + "mmpll_d5", > + "mmpll_d6", > + "mmpll_d7", > + "vdecpll", > + "lvdspll" > +}; > + > +static const char *mfg_parents[] __initconst = { > + "clk26m", > + "univpll1_d4", > + "syspll_d2", > + "syspll_d2p5", > + "syspll_d3", > + "univpll_d5", > + "univpll1_d2", > + "mmpll_d2", > + "mmpll_d3", > + "mmpll_d4", > + "mmpll_d5", > + "mmpll_d6", > + "mmpll_d7" > +}; > + > +static const char *irda_parents[] __initconst = { > + "clk26m", > + "univpll2_d8", > + "univpll1_d6" > +}; > + > +static const char *cam_parents[] __initconst = { > + "clk26m", > + "syspll_d3", > + "syspll_d3p5", > + "syspll_d4", > + "univpll_d5", > + "univpll2_d2", > + "univpll_d7", > + "univpll1_d4" > +}; > + > +static const char *aud_intbus_parents[] __initconst = { > + "clk26m", > + "syspll_d6", > + "univpll_d10" > +}; > + > +static const char *jpg_parents[] __initconst = { > + "clk26m", > + "syspll_d5", > + "syspll_d4", > + "syspll_d3", > + "univpll_d7", > + "univpll2_d2", > + "univpll_d5" > +}; > + > +static const char *disp_parents[] __initconst = { > + "clk26m", > + "syspll_d3p5", > + "syspll_d3", > + "univpll2_d2", > + "univpll_d5", > + "univpll1_d2", > + "lvdspll", > + "vdecpll" > +}; > + > +static const char *msdc30_parents[] __initconst = { > + "clk26m", > + "syspll_d6", > + "syspll_d5", > + "univpll1_d4", > + "univpll2_d4", > + "msdcpll" > +}; > + > +static const char *usb20_parents[] __initconst = { > + "clk26m", > + "univpll2_d6", > + "univpll1_d10" > +}; > + > +static const char *venc_parents[] __initconst = { > + "clk26m", > + "syspll_d3", > + "syspll_d8", > + "univpll_d5", > + "univpll1_d6", > + "mmpll_d4", > + "mmpll_d5", > + "mmpll_d6" > +}; > + > +static const char *spi_parents[] __initconst = { > + "clk26m", > + "syspll_d6", > + "syspll_d8", > + "syspll_d10", > + "univpll1_d6", > + "univpll1_d8" > +}; > + > +static const char *uart_parents[] __initconst = { > + "clk26m", > + "univpll2_d8" > +}; > + > +static const char *mem_parents[] __initconst = { > + "clk26m", > + "clkph_mck" > +}; > + > +static const char *camtg_parents[] __initconst = { > + "clk26m", > + "univpll_d26", > + "univpll1_d6", > + "syspll_d16", > + "syspll_d8" > +}; > + > +static const char *audio_parents[] __initconst = { > + "clk26m", > + "syspll_d24" > +}; > + > +static const char *fix_parents[] __initconst = { > + "rtc32k", > + "clk26m", > + "univpll_d5", > + "univpll_d7", > + "univpll1_d2", > + "univpll1_d4", > + "univpll1_d6", > + "univpll1_d8" > +}; > + > +static const char *vdec_parents[] __initconst = { > + "clk26m", > + "vdecpll", > + "clkph_mck", > + "syspll_d2p5", > + "syspll_d3", > + "syspll_d3p5", > + "syspll_d4", > + "syspll_d5", > + "syspll_d6", > + "syspll_d8", > + "univpll1_d2", > + "univpll2_d2", > + "univpll_d7", > + "univpll_d10", > + "univpll2_d4", > + "lvdspll" > +}; > + > +static const char *ddrphycfg_parents[] __initconst = { > + "clk26m", > + "axi_sel", > + "syspll_d12" > +}; > + > +static const char *dpilvds_parents[] __initconst = { > + "clk26m", > + "lvdspll", > + "lvdspll_d2", > + "lvdspll_d4", > + "lvdspll_d8" > +}; > + > +static const char *pmicspi_parents[] __initconst = { > + "clk26m", > + "univpll2_d6", > + "syspll_d8", > + "syspll_d10", > + "univpll1_d10", > + "mempll_mck_d4", > + "univpll_d26", > + "syspll_d24" > +}; > + > +static const char *smi_mfg_as_parents[] __initconst = { > + "clk26m", > + "smi_sel", > + "mfg_sel", > + "mem_sel" > +}; > + > +static const char *gcpu_parents[] __initconst = { > + "clk26m", > + "syspll_d4", > + "univpll_d7", > + "syspll_d5", > + "syspll_d6" > +}; > + > +static const char *dpi1_parents[] __initconst = { > + "clk26m", > + "tvhdmi_h_ck", > + "tvhdmi_d2", > + "tvhdmi_d4" > +}; > + > +static const char *cci_parents[] __initconst = { > + "clk26m", > + "mainpll_537p3m", > + "univpll_d3", > + "syspll_d2p5", > + "syspll_d3", > + "syspll_d5" > +}; > + > +static const char *apll_parents[] __initconst = { > + "clk26m", > + "apll_ck", > + "apll_d4", > + "apll_d8", > + "apll_d16", > + "apll_d24" > +}; > + > +static const char *hdmipll_parents[] __initconst = { > + "clk26m", > + "hdmitx_clkdig_cts", > + "hdmitx_clkdig_d2", > + "hdmitx_clkdig_d3" > +}; > + > +static struct mtk_composite top_muxes[] __initdata = { > + /* CLK_CFG_0 */ > + MUX_GATE(TOP_AXI_SEL, "axi_sel", axi_parents, > + 0x0140, 0, 3, INVALID_MUX_GATE_BIT), > + MUX_GATE(TOP_SMI_SEL, "smi_sel", smi_parents, 0x0140, 8, 4, 15), > + MUX_GATE(TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0140, 16, 4, 23), > + MUX_GATE(TOP_IRDA_SEL, "irda_sel", irda_parents, 0x0140, 24, 2, 31), > + /* CLK_CFG_1 */ > + MUX_GATE(TOP_CAM_SEL, "cam_sel", cam_parents, 0x0144, 0, 3, 7), > + MUX_GATE(TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, > + 0x0144, 8, 2, 15), > + MUX_GATE(TOP_JPG_SEL, "jpg_sel", jpg_parents, 0x0144, 16, 3, 23), > + MUX_GATE(TOP_DISP_SEL, "disp_sel", disp_parents, 0x0144, 24, 3, 31), > + /* CLK_CFG_2 */ > + MUX_GATE(TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0148, 0, 3, 7), > + MUX_GATE(TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0148, 8, 3, 15), > + MUX_GATE(TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x0148, 16, 3, 23), > + MUX_GATE(TOP_MSDC30_4_SEL, "msdc30_4_sel", msdc30_parents, 0x0148, 24, 3, 31), > + /* CLK_CFG_3 */ > + MUX_GATE(TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x014c, 0, 2, 7), > + /* CLK_CFG_4 */ > + MUX_GATE(TOP_VENC_SEL, "venc_sel", venc_parents, 0x0150, 8, 3, 15), > + MUX_GATE(TOP_SPI_SEL, "spi_sel", spi_parents, 0x0150, 16, 3, 23), > + MUX_GATE(TOP_UART_SEL, "uart_sel", uart_parents, 0x0150, 24, 2, 31), > + /* CLK_CFG_6 */ > + MUX_GATE(TOP_MEM_SEL, "mem_sel", mem_parents, 0x0158, 0, 2, 7), > + MUX_GATE(TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0158, 8, 3, 15), > + MUX_GATE(TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0158, 24, 2, 31), > + /* CLK_CFG_7 */ > + MUX_GATE(TOP_FIX_SEL, "fix_sel", fix_parents, 0x015c, 0, 3, 7), > + MUX_GATE(TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x015c, 8, 4, 15), > + MUX_GATE(TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, > + 0x015c, 16, 2, 23), > + MUX_GATE(TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x015c, 24, 3, 31), > + /* CLK_CFG_8 */ > + MUX_GATE(TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0164, 0, 3, 7), > + MUX_GATE(TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0164, 8, 3, 15), > + MUX_GATE(TOP_SMI_MFG_AS_SEL, "smi_mfg_as_sel", smi_mfg_as_parents, > + 0x0164, 16, 2, 23), > + MUX_GATE(TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0164, 24, 3, 31), > + /* CLK_CFG_9 */ > + MUX_GATE(TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0168, 0, 2, 7), > + MUX_GATE(TOP_CCI_SEL, "cci_sel", cci_parents, 0x0168, 8, 3, 15), > + MUX_GATE(TOP_APLL_SEL, "apll_sel", apll_parents, 0x0168, 16, 3, 23), > + MUX_GATE(TOP_HDMIPLL_SEL, "hdmipll_sel", hdmipll_parents, 0x0168, 24, 2, 31), > +}; > + > +static void __init mtk_init_clk_topckgen(void __iomem *top_base, > + struct clk_onecell_data *clk_data) > +{ > + int i; > + struct clk *clk; > + > + for (i = 0; i < ARRAY_SIZE(top_muxes); i++) { > + struct mtk_composite *mux = &top_muxes[i]; > + > + clk = mtk_clk_register_composite(mux, top_base, &lock); > + > + if (IS_ERR(clk)) { > + pr_err("Failed to register clk %s: %ld\n", > + mux->name, PTR_ERR(clk)); > + continue; > + } > + > + if (clk_data) > + clk_data->clks[mux->id] = clk; > + } > +} > + > +static struct mtk_gate_regs infra_cg_regs = { > + .set_ofs = 0x0040, > + .clr_ofs = 0x0044, > + .sta_ofs = 0x0048, > +}; > + > +#define GATE_ICG(_id, _name, _parent, _shift) { \ > + .id = _id, \ > + .name = _name, \ > + .parent_name = _parent, \ > + .regs = &infra_cg_regs, \ > + .shift = _shift, \ > + .ops = &mtk_clk_gate_ops_setclr, \ > + } > + > +static struct mtk_gate infra_clks[] __initdata = { > + GATE_ICG(INFRA_PMIC_WRAP_CK, "pmic_wrap_ck", "axi_sel", 23), > + GATE_ICG(INFRA_PMICSPI_CK, "pmicspi_ck", "pmicspi_sel", 22), > + GATE_ICG(INFRA_CCIF1_AP_CTRL, "ccif1_ap_ctrl", "axi_sel", 21), > + GATE_ICG(INFRA_CCIF0_AP_CTRL, "ccif0_ap_ctrl", "axi_sel", 20), > + GATE_ICG(INFRA_KP_CK, "kp_ck", "axi_sel", 16), > + GATE_ICG(INFRA_CPUM_CK, "cpum_ck", "cpum_tck_in", 15), > + GATE_ICG(INFRA_M4U_CK, "m4u_ck", "mem_sel", 8), > + GATE_ICG(INFRA_MFGAXI_CK, "mfgaxi_ck", "axi_sel", 7), > + GATE_ICG(INFRA_DEVAPC_CK, "devapc_ck", "axi_sel", 6), > + GATE_ICG(INFRA_AUDIO_CK, "audio_ck", "aud_intbus_sel", 5), > + GATE_ICG(INFRA_MFG_BUS_CK, "mfg_bus_ck", "axi_sel", 2), > + GATE_ICG(INFRA_SMI_CK, "smi_ck", "smi_sel", 1), > + GATE_ICG(INFRA_DBGCLK_CK, "dbgclk_ck", "axi_sel", 0), > +}; > + > +static struct mtk_gate_regs peri0_cg_regs = { > + .set_ofs = 0x0008, > + .clr_ofs = 0x0010, > + .sta_ofs = 0x0018, > +}; > + > +static struct mtk_gate_regs peri1_cg_regs = { > + .set_ofs = 0x000c, > + .clr_ofs = 0x0014, > + .sta_ofs = 0x001c, > +}; > + > +#define GATE_PERI0(_id, _name, _parent, _shift) { \ > + .id = _id, \ > + .name = _name, \ > + .parent_name = _parent, \ > + .regs = &peri0_cg_regs, \ > + .shift = _shift, \ > + .ops = &mtk_clk_gate_ops_setclr, \ > + } > + > +#define GATE_PERI1(_id, _name, _parent, _shift) { \ > + .id = _id, \ > + .name = _name, \ > + .parent_name = _parent, \ > + .regs = &peri1_cg_regs, \ > + .shift = _shift, \ > + .ops = &mtk_clk_gate_ops_setclr, \ > + } > + > +static struct mtk_gate peri_clks[] __initdata = { > + /* PERI0 */ > + GATE_PERI0(PERI_I2C5_CK, "i2c5_ck", "axi_sel", 31), > + GATE_PERI0(PERI_I2C4_CK, "i2c4_ck", "axi_sel", 30), > + GATE_PERI0(PERI_I2C3_CK, "i2c3_ck", "axi_sel", 29), > + GATE_PERI0(PERI_I2C2_CK, "i2c2_ck", "axi_sel", 28), > + GATE_PERI0(PERI_I2C1_CK, "i2c1_ck", "axi_sel", 27), > + GATE_PERI0(PERI_I2C0_CK, "i2c0_ck", "axi_sel", 26), > + GATE_PERI0(PERI_UART3_CK, "uart3_ck", "axi_sel", 25), > + GATE_PERI0(PERI_UART2_CK, "uart2_ck", "axi_sel", 24), > + GATE_PERI0(PERI_UART1_CK, "uart1_ck", "axi_sel", 23), > + GATE_PERI0(PERI_UART0_CK, "uart0_ck", "axi_sel", 22), > + GATE_PERI0(PERI_IRDA_CK, "irda_ck", "irda_sel", 21), > + GATE_PERI0(PERI_NLI_CK, "nli_ck", "axi_sel", 20), > + GATE_PERI0(PERI_MD_HIF_CK, "md_hif_ck", "axi_sel", 19), > + GATE_PERI0(PERI_AP_HIF_CK, "ap_hif_ck", "axi_sel", 18), > + GATE_PERI0(PERI_MSDC30_3_CK, "msdc30_3_ck", "msdc30_4_sel", 17), > + GATE_PERI0(PERI_MSDC30_2_CK, "msdc30_2_ck", "msdc30_3_sel", 16), > + GATE_PERI0(PERI_MSDC30_1_CK, "msdc30_1_ck", "msdc30_2_sel", 15), > + GATE_PERI0(PERI_MSDC20_2_CK, "msdc20_2_ck", "msdc30_1_sel", 14), > + GATE_PERI0(PERI_MSDC20_1_CK, "msdc20_1_ck", "msdc30_0_sel", 13), > + GATE_PERI0(PERI_AP_DMA_CK, "ap_dma_ck", "axi_sel", 12), > + GATE_PERI0(PERI_USB1_CK, "usb1_ck", "usb20_sel", 11), > + GATE_PERI0(PERI_USB0_CK, "usb0_ck", "usb20_sel", 10), > + GATE_PERI0(PERI_PWM_CK, "pwm_ck", "axi_sel", 9), > + GATE_PERI0(PERI_PWM7_CK, "pwm7_ck", "axi_sel", 8), > + GATE_PERI0(PERI_PWM6_CK, "pwm6_ck", "axi_sel", 7), > + GATE_PERI0(PERI_PWM5_CK, "pwm5_ck", "axi_sel", 6), > + GATE_PERI0(PERI_PWM4_CK, "pwm4_ck", "axi_sel", 5), > + GATE_PERI0(PERI_PWM3_CK, "pwm3_ck", "axi_sel", 4), > + GATE_PERI0(PERI_PWM2_CK, "pwm2_ck", "axi_sel", 3), > + GATE_PERI0(PERI_PWM1_CK, "pwm1_ck", "axi_sel", 2), > + GATE_PERI0(PERI_THERM_CK, "therm_ck", "axi_sel", 1), > + GATE_PERI0(PERI_NFI_CK, "nfi_ck", "axi_sel", 0), > + /* PERI1 */ > + GATE_PERI1(PERI_USBSLV_CK, "usbslv_ck", "axi_sel", 8), > + GATE_PERI1(PERI_USB1_MCU_CK, "usb1_mcu_ck", "axi_sel", 7), > + GATE_PERI1(PERI_USB0_MCU_CK, "usb0_mcu_ck", "axi_sel", 6), > + GATE_PERI1(PERI_GCPU_CK, "gcpu_ck", "gcpu_sel", 5), > + GATE_PERI1(PERI_FHCTL_CK, "fhctl_ck", "clk26m", 4), > + GATE_PERI1(PERI_SPI1_CK, "spi1_ck", "spi_sel", 3), > + GATE_PERI1(PERI_AUXADC_CK, "auxadc_ck", "clk26m", 2), > + GATE_PERI1(PERI_PERI_PWRAP_CK, "peri_pwrap_ck", "axi_sel", 1), > + GATE_PERI1(PERI_I2C6_CK, "i2c6_ck", "axi_sel", 0), > +}; > + > +static void __init mtk_topckgen_init(struct device_node *node) > +{ > + struct clk_onecell_data *clk_data; > + void __iomem *base; > + int r; > + > + base = of_iomap(node, 0); > + if (!base) { > + pr_err("%s(): ioremap failed\n", __func__); > + return; > + } > + > + clk_data = mtk_alloc_clk_data(TOP_NR_CLK); > + > + mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data); > + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); > + mtk_init_clk_topckgen(base, clk_data); > + > + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); > + if (r) > + pr_err("%s(): could not register clock provider: %d\n", > + __func__, r); > +} > +CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init); > + > +static void __init mtk_infrasys_init(struct device_node *node) > +{ > + struct clk_onecell_data *clk_data; > + int r; > + > + clk_data = mtk_alloc_clk_data(INFRA_NR_CLK); > + > + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), > + clk_data); > + > + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); > + if (r) > + pr_err("%s(): could not register clock provider: %d\n", > + __func__, r); > + > + mtk_register_reset_controller(node, 2, 0x30); > +} > +CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init); > + > +static void __init mtk_pericfg_init(struct device_node *node) > +{ > + struct clk_onecell_data *clk_data; > + int r; > + > + clk_data = mtk_alloc_clk_data(PERI_NR_CLK); > + > + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), > + clk_data); > + > + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); > + if (r) > + pr_err("%s(): could not register clock provider: %d\n", > + __func__, r); > + > + mtk_register_reset_controller(node, 2, 0); > +} > +CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init); > + > +#define MT8135_PLL_FMAX (2000 * MHZ) > +#define CON0_MT8135_RST_BAR BIT(27) > + > +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \ > + .id = _id, \ > + .name = _name, \ > + .reg = _reg, \ > + .pwr_reg = _pwr_reg, \ > + .en_mask = _en_mask, \ > + .flags = _flags, \ > + .rst_bar_mask = CON0_MT8135_RST_BAR, \ > + .fmax = MT8135_PLL_FMAX, \ > + .pcwbits = _pcwbits, \ > + .pd_reg = _pd_reg, \ > + .pd_shift = _pd_shift, \ > + .tuner_reg = _tuner_reg, \ > + .pcw_reg = _pcw_reg, \ > + .pcw_shift = _pcw_shift, \ > + } > + > +static struct mtk_pll_data plls[] = { > + PLL(APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000001, 0, 21, 0x204, 24, 0x0, 0x204, 0), > + PLL(APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000001, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0), > + PLL(APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000001, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0), > + PLL(APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000001, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9), > + PLL(APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000001, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0), > + PLL(APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000001, 0, 21, 0x278, 6, 0x0, 0x27c, 0), > + PLL(APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000001, 0, 31, 0x296, 6, 0x0, 0x298, 0), > + PLL(APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0), > + PLL(APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000001, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0), > + PLL(APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c, 0x80000001, 0, 21, 0x2b0, 6, 0x0, 0x308, 0), > +}; > + > +static void __init mtk_apmixedsys_init(struct device_node *node) > +{ > + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls)); > +} > +CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys", > + mtk_apmixedsys_init); > diff --git a/include/dt-bindings/clock/mt8135-clk.h b/include/dt-bindings/clock/mt8135-clk.h > new file mode 100644 > index 0000000..8aea762 > --- /dev/null > +++ b/include/dt-bindings/clock/mt8135-clk.h > @@ -0,0 +1,190 @@ > +/* > + * Copyright (c) 2014 MediaTek Inc. > + * Author: James Liao <jamesjj.liao@mediatek.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#ifndef _DT_BINDINGS_CLK_MT8135_H > +#define _DT_BINDINGS_CLK_MT8135_H > + > +/* TOPCKGEN */ > + > +#define TOP_DSI0_LNTC_DSICLK 1 > +#define TOP_HDMITX_CLKDIG_CTS 2 > +#define TOP_CLKPH_MCK 3 > +#define TOP_CPUM_TCK_IN 4 > +#define TOP_MAINPLL_806M 5 > +#define TOP_MAINPLL_537P3M 6 > +#define TOP_MAINPLL_322P4M 7 > +#define TOP_MAINPLL_230P3M 8 > +#define TOP_UNIVPLL_624M 9 > +#define TOP_UNIVPLL_416M 10 > +#define TOP_UNIVPLL_249P6M 11 > +#define TOP_UNIVPLL_178P3M 12 > +#define TOP_UNIVPLL_48M 13 > +#define TOP_MMPLL_D2 14 > +#define TOP_MMPLL_D3 15 > +#define TOP_MMPLL_D5 16 > +#define TOP_MMPLL_D7 17 > +#define TOP_MMPLL_D4 18 > +#define TOP_MMPLL_D6 19 > +#define TOP_SYSPLL_D2 20 > +#define TOP_SYSPLL_D4 21 > +#define TOP_SYSPLL_D6 22 > +#define TOP_SYSPLL_D8 23 > +#define TOP_SYSPLL_D10 24 > +#define TOP_SYSPLL_D12 25 > +#define TOP_SYSPLL_D16 26 > +#define TOP_SYSPLL_D24 27 > +#define TOP_SYSPLL_D3 28 > +#define TOP_SYSPLL_D2P5 29 > +#define TOP_SYSPLL_D5 30 > +#define TOP_SYSPLL_D3P5 31 > +#define TOP_UNIVPLL1_D2 32 > +#define TOP_UNIVPLL1_D4 33 > +#define TOP_UNIVPLL1_D6 34 > +#define TOP_UNIVPLL1_D8 35 > +#define TOP_UNIVPLL1_D10 36 > +#define TOP_UNIVPLL2_D2 37 > +#define TOP_UNIVPLL2_D4 38 > +#define TOP_UNIVPLL2_D6 39 > +#define TOP_UNIVPLL2_D8 40 > +#define TOP_UNIVPLL_D3 41 > +#define TOP_UNIVPLL_D5 42 > +#define TOP_UNIVPLL_D7 43 > +#define TOP_UNIVPLL_D10 44 > +#define TOP_UNIVPLL_D26 45 > +#define TOP_APLL_CK 46 > +#define TOP_APLL_D4 47 > +#define TOP_APLL_D8 48 > +#define TOP_APLL_D16 49 > +#define TOP_APLL_D24 50 > +#define TOP_LVDSPLL_D2 51 > +#define TOP_LVDSPLL_D4 52 > +#define TOP_LVDSPLL_D8 53 > +#define TOP_LVDSTX_CLKDIG_CT 54 > +#define TOP_VPLL_DPIX_CK 55 > +#define TOP_TVHDMI_H_CK 56 > +#define TOP_HDMITX_CLKDIG_D2 57 > +#define TOP_HDMITX_CLKDIG_D3 58 > +#define TOP_TVHDMI_D2 59 > +#define TOP_TVHDMI_D4 60 > +#define TOP_MEMPLL_MCK_D4 61 > +#define TOP_AXI_SEL 62 > +#define TOP_SMI_SEL 63 > +#define TOP_MFG_SEL 64 > +#define TOP_IRDA_SEL 65 > +#define TOP_CAM_SEL 66 > +#define TOP_AUD_INTBUS_SEL 67 > +#define TOP_JPG_SEL 68 > +#define TOP_DISP_SEL 69 > +#define TOP_MSDC30_1_SEL 70 > +#define TOP_MSDC30_2_SEL 71 > +#define TOP_MSDC30_3_SEL 72 > +#define TOP_MSDC30_4_SEL 73 > +#define TOP_USB20_SEL 74 > +#define TOP_VENC_SEL 75 > +#define TOP_SPI_SEL 76 > +#define TOP_UART_SEL 77 > +#define TOP_MEM_SEL 78 > +#define TOP_CAMTG_SEL 79 > +#define TOP_AUDIO_SEL 80 > +#define TOP_FIX_SEL 81 > +#define TOP_VDEC_SEL 82 > +#define TOP_DDRPHYCFG_SEL 83 > +#define TOP_DPILVDS_SEL 84 > +#define TOP_PMICSPI_SEL 85 > +#define TOP_MSDC30_0_SEL 86 > +#define TOP_SMI_MFG_AS_SEL 87 > +#define TOP_GCPU_SEL 88 > +#define TOP_DPI1_SEL 89 > +#define TOP_CCI_SEL 90 > +#define TOP_APLL_SEL 91 > +#define TOP_HDMIPLL_SEL 92 > +#define TOP_NR_CLK 93 > + > +/* APMIXED_SYS */ > + > +#define APMIXED_ARMPLL1 1 > +#define APMIXED_ARMPLL2 2 > +#define APMIXED_MAINPLL 3 > +#define APMIXED_UNIVPLL 4 > +#define APMIXED_MMPLL 5 > +#define APMIXED_MSDCPLL 6 > +#define APMIXED_TVDPLL 7 > +#define APMIXED_LVDSPLL 8 > +#define APMIXED_AUDPLL 9 > +#define APMIXED_VDECPLL 10 > +#define APMIXED_NR_CLK 11 > + > +/* INFRA_SYS */ > + > +#define INFRA_PMIC_WRAP_CK 1 > +#define INFRA_PMICSPI_CK 2 > +#define INFRA_CCIF1_AP_CTRL 3 > +#define INFRA_CCIF0_AP_CTRL 4 > +#define INFRA_KP_CK 5 > +#define INFRA_CPUM_CK 6 > +#define INFRA_M4U_CK 7 > +#define INFRA_MFGAXI_CK 8 > +#define INFRA_DEVAPC_CK 9 > +#define INFRA_AUDIO_CK 10 > +#define INFRA_MFG_BUS_CK 11 > +#define INFRA_SMI_CK 12 > +#define INFRA_DBGCLK_CK 13 > +#define INFRA_NR_CLK 14 > + > +/* PERI_SYS */ > + > +#define PERI_I2C5_CK 1 > +#define PERI_I2C4_CK 2 > +#define PERI_I2C3_CK 3 > +#define PERI_I2C2_CK 4 > +#define PERI_I2C1_CK 5 > +#define PERI_I2C0_CK 6 > +#define PERI_UART3_CK 7 > +#define PERI_UART2_CK 8 > +#define PERI_UART1_CK 9 > +#define PERI_UART0_CK 10 > +#define PERI_IRDA_CK 11 > +#define PERI_NLI_CK 12 > +#define PERI_MD_HIF_CK 13 > +#define PERI_AP_HIF_CK 14 > +#define PERI_MSDC30_3_CK 15 > +#define PERI_MSDC30_2_CK 16 > +#define PERI_MSDC30_1_CK 17 > +#define PERI_MSDC20_2_CK 18 > +#define PERI_MSDC20_1_CK 19 > +#define PERI_AP_DMA_CK 20 > +#define PERI_USB1_CK 21 > +#define PERI_USB0_CK 22 > +#define PERI_PWM_CK 23 > +#define PERI_PWM7_CK 24 > +#define PERI_PWM6_CK 25 > +#define PERI_PWM5_CK 26 > +#define PERI_PWM4_CK 27 > +#define PERI_PWM3_CK 28 > +#define PERI_PWM2_CK 29 > +#define PERI_PWM1_CK 30 > +#define PERI_THERM_CK 31 > +#define PERI_NFI_CK 32 > +#define PERI_USBSLV_CK 33 > +#define PERI_USB1_MCU_CK 34 > +#define PERI_USB0_MCU_CK 35 > +#define PERI_GCPU_CK 36 > +#define PERI_FHCTL_CK 37 > +#define PERI_SPI1_CK 38 > +#define PERI_AUXADC_CK 39 > +#define PERI_PERI_PWRAP_CK 40 > +#define PERI_I2C6_CK 41 > +#define PERI_NR_CLK 42 > + > +#endif /* _DT_BINDINGS_CLK_MT8135_H */ > diff --git a/include/dt-bindings/reset-controller/mt8135-resets.h b/include/dt-bindings/reset-controller/mt8135-resets.h > new file mode 100644 > index 0000000..1fb6295 > --- /dev/null > +++ b/include/dt-bindings/reset-controller/mt8135-resets.h > @@ -0,0 +1,64 @@ > +/* > + * Copyright (c) 2014 MediaTek Inc. > + * Author: Flora Fu, MediaTek > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + */ > + > +#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8135 > +#define _DT_BINDINGS_RESET_CONTROLLER_MT8135 > + > +/* INFRACFG resets */ > +#define MT8135_INFRA_EMI_REG_RST 0 > +#define MT8135_INFRA_DRAMC0_A0_RST 1 > +#define MT8135_INFRA_CCIF0_RST 2 > +#define MT8135_INFRA_APCIRQ_EINT_RST 3 > +#define MT8135_INFRA_APXGPT_RST 4 > +#define MT8135_INFRA_SCPSYS_RST 5 > +#define MT8135_INFRA_CCIF1_RST 6 > +#define MT8135_INFRA_PMIC_WRAP_RST 7 > +#define MT8135_INFRA_KP_RST 8 > +#define MT8135_INFRA_EMI_RST 32 > +#define MT8135_INFRA_DRAMC0_RST 34 > +#define MT8135_INFRA_SMI_RST 35 > +#define MT8135_INFRA_M4U_RST 36 > + > +/* PERICFG resets */ > +#define MT8135_PERI_UART0_SW_RST 0 > +#define MT8135_PERI_UART1_SW_RST 1 > +#define MT8135_PERI_UART2_SW_RST 2 > +#define MT8135_PERI_UART3_SW_RST 3 > +#define MT8135_PERI_IRDA_SW_RST 4 > +#define MT8135_PERI_PTP_SW_RST 5 > +#define MT8135_PERI_AP_HIF_SW_RST 6 > +#define MT8135_PERI_GPCU_SW_RST 7 > +#define MT8135_PERI_MD_HIF_SW_RST 8 > +#define MT8135_PERI_NLI_SW_RST 9 > +#define MT8135_PERI_AUXADC_SW_RST 10 > +#define MT8135_PERI_DMA_SW_RST 11 > +#define MT8135_PERI_NFI_SW_RST 14 > +#define MT8135_PERI_PWM_SW_RST 15 > +#define MT8135_PERI_THERM_SW_RST 16 > +#define MT8135_PERI_MSDC0_SW_RST 17 > +#define MT8135_PERI_MSDC1_SW_RST 18 > +#define MT8135_PERI_MSDC2_SW_RST 19 > +#define MT8135_PERI_MSDC3_SW_RST 20 > +#define MT8135_PERI_I2C0_SW_RST 22 > +#define MT8135_PERI_I2C1_SW_RST 23 > +#define MT8135_PERI_I2C2_SW_RST 24 > +#define MT8135_PERI_I2C3_SW_RST 25 > +#define MT8135_PERI_I2C4_SW_RST 26 > +#define MT8135_PERI_I2C5_SW_RST 27 > +#define MT8135_PERI_I2C6_SW_RST 28 > +#define MT8135_PERI_USB_SW_RST 29 > +#define MT8135_PERI_SPI1_SW_RST 33 > +#define MT8135_PERI_PWRAP_BRIDGE_SW_RST 34 > + > +#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8135 */ > -- > 2.1.4 > > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel at lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 3/5] clk: mediatek: Add basic clocks for Mediatek MT8135. 2015-03-15 16:27 ` Daniel Kurtz @ 2015-03-16 5:33 ` Sascha Hauer 0 siblings, 0 replies; 14+ messages in thread From: Sascha Hauer @ 2015-03-16 5:33 UTC (permalink / raw) To: linux-arm-kernel On Mon, Mar 16, 2015 at 12:27:20AM +0800, Daniel Kurtz wrote: > Hi Sascha, > > Drive-by review... > > On Sun, Feb 22, 2015 at 7:49 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote: > > From: James Liao <jamesjj.liao@mediatek.com> > > > > This patch adds basic clocks for MT8135, including TOPCKGEN, PLLs, > > INFRA and PERI clocks. > > > > Signed-off-by: James Liao <jamesjj.liao@mediatek.com> > > Signed-off-by: Henry Chen <henryc.chen@mediatek.com> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > > --- > > drivers/clk/mediatek/Makefile | 1 + > > drivers/clk/mediatek/clk-mt8135.c | 634 +++++++++++++++++++++ > > include/dt-bindings/clock/mt8135-clk.h | 190 ++++++ > > .../dt-bindings/reset-controller/mt8135-resets.h | 64 +++ > > 4 files changed, 889 insertions(+) > > create mode 100644 drivers/clk/mediatek/clk-mt8135.c > > create mode 100644 include/dt-bindings/clock/mt8135-clk.h > > create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h > > > > diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile > > index 0b6f1c3..12ce576 100644 > > --- a/drivers/clk/mediatek/Makefile > > +++ b/drivers/clk/mediatek/Makefile > > @@ -1,2 +1,3 @@ > > obj-y += clk-mtk.o clk-pll.o clk-gate.o > > obj-$(CONFIG_RESET_CONTROLLER) += reset.o > > +obj-y += clk-mt8135.o > > diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c > > new file mode 100644 > > index 0000000..6157447 > > --- /dev/null > > +++ b/drivers/clk/mediatek/clk-mt8135.c > > @@ -0,0 +1,634 @@ > > +/* > > + * Copyright (c) 2014 MediaTek Inc. > > + * Author: James Liao <jamesjj.liao@mediatek.com> > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#include <linux/of.h> > > +#include <linux/of_address.h> > > +#include <linux/slab.h> > > +#include <linux/mfd/syscon.h> > > +#include <dt-bindings/clock/mt8135-clk.h> > > + > > +#include "clk-mtk.h" > > +#include "clk-gate.h" > > + > > +static DEFINE_SPINLOCK(lock); > > + > > > +static struct mtk_fixed_factor root_clk_alias[] __initdata = { > > Any reason you can't use "static const" here, and on all of the other > static constant structures/arrays throughout this patch. No, there is no reason. Changed it. Thanks Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 4/5] clk: mediatek: Add basic clocks for Mediatek MT8173. 2015-02-22 11:49 [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 Sascha Hauer ` (2 preceding siblings ...) 2015-02-22 11:49 ` [PATCH 3/5] clk: mediatek: Add basic clocks for Mediatek MT8135 Sascha Hauer @ 2015-02-22 11:49 ` Sascha Hauer 2015-02-22 11:49 ` [PATCH 5/5] dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers Sascha Hauer 2015-03-09 6:15 ` [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 Sascha Hauer 5 siblings, 0 replies; 14+ messages in thread From: Sascha Hauer @ 2015-02-22 11:49 UTC (permalink / raw) To: linux-arm-kernel From: James Liao <jamesjj.liao@mediatek.com> This patch adds basic clocks for MT8173, including TOPCKGEN, PLLs, INFRA and PERI clocks. Signed-off-by: James Liao <jamesjj.liao@mediatek.com> Signed-off-by: Henry Chen <henryc.chen@mediatek.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/clk/mediatek/Makefile | 1 + drivers/clk/mediatek/clk-mt8173.c | 820 +++++++++++++++++++++ include/dt-bindings/clock/mt8173-clk.h | 231 ++++++ .../dt-bindings/reset-controller/mt8173-resets.h | 63 ++ 4 files changed, 1115 insertions(+) create mode 100644 drivers/clk/mediatek/clk-mt8173.c create mode 100644 include/dt-bindings/clock/mt8173-clk.h create mode 100644 include/dt-bindings/reset-controller/mt8173-resets.h diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index 12ce576..8e4b2a4 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -1,3 +1,4 @@ obj-y += clk-mtk.o clk-pll.o clk-gate.o obj-$(CONFIG_RESET_CONTROLLER) += reset.o obj-y += clk-mt8135.o +obj-y += clk-mt8173.o diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c new file mode 100644 index 0000000..014e552 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8173.c @@ -0,0 +1,820 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/slab.h> +#include <linux/mfd/syscon.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8173-clk.h> + +static DEFINE_SPINLOCK(lock); + +static struct mtk_fixed_factor root_clk_alias[] __initdata = { + FACTOR(TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1), + FACTOR(TOP_DPI_CK, "dpi_ck", "clk_null", 1, 1), + FACTOR(TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1), + FACTOR(TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1), +}; + +static struct mtk_fixed_factor top_divs[] __initdata = { + FACTOR(TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2), + FACTOR(TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3), + + FACTOR(TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2), + FACTOR(TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3), + FACTOR(TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5), + FACTOR(TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7), + + FACTOR(TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4), + FACTOR(TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3), + + FACTOR(TOP_UNIV_624M, "univ_624m", "univpll", 1, 2), + FACTOR(TOP_UNIV_416M, "univ_416m", "univpll", 1, 3), + FACTOR(TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5), + FACTOR(TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7), + FACTOR(TOP_UNIV_48M, "univ_48m", "univpll", 1, 26), + + FACTOR(TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1), + FACTOR(TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793), + FACTOR(TOP_FPC_CK, "fpc_ck", "clk26m", 1, 1), + + FACTOR(TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2), + FACTOR(TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3), + + FACTOR(TOP_ARMCA7PLL_D2, "armca7pll_d2", "armca7pll_754m", 1, 1), + FACTOR(TOP_ARMCA7PLL_D3, "armca7pll_d3", "armca7pll_502m", 1, 1), + + FACTOR(TOP_APLL1_CK, "apll1_ck", "apll1", 1, 1), + FACTOR(TOP_APLL2_CK, "apll2_ck", "apll2", 1, 1), + + FACTOR(TOP_DMPLL_CK, "dmpll_ck", "clkph_mck_o", 1, 1), + FACTOR(TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2), + FACTOR(TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4), + FACTOR(TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8), + FACTOR(TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16), + + FACTOR(TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2), + FACTOR(TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4), + FACTOR(TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8), + + FACTOR(TOP_MMPLL_CK, "mmpll_ck", "mmpll", 1, 1), + FACTOR(TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + + FACTOR(TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1, 1), + FACTOR(TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), + FACTOR(TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4), + FACTOR(TOP_MSDCPLL2_CK, "msdcpll2_ck", "msdcpll2", 1, 1), + FACTOR(TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2), + FACTOR(TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4), + + FACTOR(TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1), + FACTOR(TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2), + FACTOR(TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4), + FACTOR(TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8), + FACTOR(TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16), + FACTOR(TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1), + FACTOR(TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2), + FACTOR(TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4), + FACTOR(TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1), + FACTOR(TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2), + FACTOR(TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4), + FACTOR(TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1), + FACTOR(TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2), + FACTOR(TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4), + + FACTOR(TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll_594m", 1, 1), + FACTOR(TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2), + FACTOR(TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4), + FACTOR(TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8), + FACTOR(TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16), + + FACTOR(TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1), + FACTOR(TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2), + FACTOR(TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4), + FACTOR(TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8), + FACTOR(TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1), + FACTOR(TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2), + FACTOR(TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4), + FACTOR(TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8), + FACTOR(TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1), + FACTOR(TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2), + FACTOR(TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4), + FACTOR(TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8), + FACTOR(TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1), + FACTOR(TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1), + FACTOR(TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2), + + FACTOR(TOP_VCODECPLL_CK, "vcodecpll_ck", "vcodecpll", 1, 3), + FACTOR(TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4), + + FACTOR(TOP_VENCPLL_CK, "vencpll_ck", "vencpll", 1, 1), + FACTOR(TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2), + FACTOR(TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4), +}; + +static const char *axi_parents[] __initconst = { + "clk26m", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "dmpll_d2", + "dmpll_d4" +}; + +static const char *mem_parents[] __initconst = { + "clk26m", + "dmpll_ck" +}; + +static const char *ddrphycfg_parents[] __initconst = { + "clk26m", + "syspll1_d8" +}; + +static const char *mm_parents[] __initconst = { + "clk26m", + "vencpll_d2", + "main_h364m", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll1_d2", + "univpll2_d2", + "dmpll_d2" +}; + +static const char *pwm_parents[] __initconst = { + "clk26m", + "univpll2_d4", + "univpll3_d2", + "univpll1_d4" +}; + +static const char *vdec_parents[] __initconst = { + "clk26m", + "vcodecpll_ck", + "tvdpll_445p5m", + "univpll_d3", + "vencpll_d2", + "syspll_d3", + "univpll1_d2", + "mmpll_d2", + "dmpll_d2", + "dmpll_d4" +}; + +static const char *venc_parents[] __initconst = { + "clk26m", + "vcodecpll_ck", + "tvdpll_445p5m", + "univpll_d3", + "vencpll_d2", + "syspll_d3", + "univpll1_d2", + "univpll2_d2", + "dmpll_d2", + "dmpll_d4" +}; + +static const char *mfg_parents[] __initconst = { + "clk26m", + "mmpll_ck", + "dmpll_ck", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "syspll_d3", + "syspll1_d2", + "syspll_d5", + "univpll_d3", + "univpll1_d2", + "univpll_d5", + "univpll2_d2" +}; + +static const char *camtg_parents[] __initconst = { + "clk26m", + "univpll_d26", + "univpll2_d2", + "syspll3_d2", + "syspll3_d4", + "univpll1_d4" +}; + +static const char *uart_parents[] __initconst = { + "clk26m", + "univpll2_d8" +}; + +static const char *spi_parents[] __initconst = { + "clk26m", + "syspll3_d2", + "syspll1_d4", + "syspll4_d2", + "univpll3_d2", + "univpll2_d4", + "univpll1_d8" +}; + +static const char *usb20_parents[] __initconst = { + "clk26m", + "univpll1_d8", + "univpll3_d4" +}; + +static const char *usb30_parents[] __initconst = { + "clk26m", + "univpll3_d2", + "usb_syspll_125m", + "univpll2_d4" +}; + +static const char *msdc50_0_h_parents[] __initconst = { + "clk26m", + "syspll1_d2", + "syspll2_d2", + "syspll4_d2", + "univpll_d5", + "univpll1_d4" +}; + +static const char *msdc50_0_parents[] __initconst = { + "clk26m", + "msdcpll_ck", + "msdcpll_d2", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "msdcpll_d4", + "vencpll_d4", + "tvdpll_ck", + "univpll_d2", + "univpll1_d2", + "mmpll_ck", + "msdcpll2_ck", + "msdcpll2_d2", + "msdcpll2_d4" +}; + +static const char *msdc30_1_parents[] __initconst = { + "clk26m", + "univpll2_d2", + "msdcpll_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d4" +}; + +static const char *msdc30_2_parents[] __initconst = { + "clk26m", + "univpll2_d2", + "msdcpll_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d2" +}; + +static const char *msdc30_3_parents[] __initconst = { + "clk26m", + "msdcpll2_ck", + "msdcpll2_d2", + "univpll2_d2", + "msdcpll2_d4", + "msdcpll_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d4", + "msdcpll_ck", + "msdcpll_d2", + "msdcpll_d4" +}; + +static const char *audio_parents[] __initconst = { + "clk26m", + "syspll3_d4", + "syspll4_d4", + "syspll1_d16" +}; + +static const char *aud_intbus_parents[] __initconst = { + "clk26m", + "syspll1_d4", + "syspll4_d2", + "univpll3_d2", + "univpll2_d8", + "dmpll_d4", + "dmpll_d8" +}; + +static const char *pmicspi_parents[] __initconst = { + "clk26m", + "syspll1_d8", + "syspll3_d4", + "syspll1_d16", + "univpll3_d4", + "univpll_d26", + "dmpll_d8", + "dmpll_d16" +}; + +static const char *scp_parents[] __initconst = { + "clk26m", + "syspll1_d2", + "univpll_d5", + "syspll_d5", + "dmpll_d2", + "dmpll_d4" +}; + +static const char *atb_parents[] __initconst = { + "clk26m", + "syspll1_d2", + "univpll_d5", + "dmpll_d2" +}; + +static const char *venc_lt_parents[] __initconst = { + "clk26m", + "univpll_d3", + "vcodecpll_ck", + "tvdpll_445p5m", + "vencpll_d2", + "syspll_d3", + "univpll1_d2", + "univpll2_d2", + "syspll1_d2", + "univpll_d5", + "vcodecpll_370p5", + "dmpll_ck" +}; + +static const char *dpi0_parents[] __initconst = { + "clk26m", + "tvdpll_d2", + "tvdpll_d4", + "clk26m", + "clk26m", + "tvdpll_d8", + "tvdpll_d16" +}; + +static const char *irda_parents[] __initconst = { + "clk26m", + "univpll2_d4", + "syspll2_d4" +}; + +static const char *cci400_parents[] __initconst = { + "clk26m", + "vencpll_ck", + "armca7pll_754m", + "armca7pll_502m", + "univpll_d2", + "syspll_d2", + "msdcpll_ck", + "dmpll_ck" +}; + +static const char *aud_1_parents[] __initconst = { + "clk26m", + "apll1_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char *aud_2_parents[] __initconst = { + "clk26m", + "apll2_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char *mem_mfg_in_parents[] __initconst = { + "clk26m", + "mmpll_ck", + "dmpll_ck", + "clk26m" +}; + +static const char *axi_mfg_in_parents[] __initconst = { + "clk26m", + "axi_sel", + "dmpll_d2" +}; + +static const char *scam_parents[] __initconst = { + "clk26m", + "syspll3_d2", + "univpll2_d4", + "dmpll_d4" +}; + +static const char *spinfi_ifr_parents[] __initconst = { + "clk26m", + "univpll2_d8", + "univpll3_d4", + "syspll4_d2", + "univpll2_d4", + "univpll3_d2", + "syspll1_d4", + "univpll1_d4" +}; + +static const char *hdmi_parents[] __initconst = { + "clk26m", + "hdmitx_dig_cts", + "hdmitxpll_d2", + "hdmitxpll_d3" +}; + +static const char *dpilvds_parents[] __initconst = { + "clk26m", + "lvdspll", + "lvdspll_d2", + "lvdspll_d4", + "lvdspll_d8", + "fpc_ck" +}; + +static const char *msdc50_2_h_parents[] __initconst = { + "clk26m", + "syspll1_d2", + "syspll2_d2", + "syspll4_d2", + "univpll_d5", + "univpll1_d4" +}; + +static const char *hdcp_parents[] __initconst = { + "clk26m", + "syspll4_d2", + "syspll3_d4", + "univpll2_d4" +}; + +static const char *hdcp_24m_parents[] __initconst = { + "clk26m", + "univpll_d26", + "univpll_d52", + "univpll2_d8" +}; + +static const char *rtc_parents[] __initconst = { + "clkrtc_int", + "clkrtc_ext", + "clk26m", + "univpll3_d8" +}; + +static const char *i2s0_m_ck_parents[] __initconst = { + "apll1_div1", + "apll2_div1" +}; + +static const char *i2s1_m_ck_parents[] __initconst = { + "apll1_div2", + "apll2_div2" +}; + +static const char *i2s2_m_ck_parents[] __initconst = { + "apll1_div3", + "apll2_div3" +}; + +static const char *i2s3_m_ck_parents[] __initconst = { + "apll1_div4", + "apll2_div4" +}; + +static const char *i2s3_b_ck_parents[] __initconst = { + "apll1_div5", + "apll2_div5" +}; + +static struct mtk_composite top_muxes[] __initdata = { + /* CLK_CFG_0 */ + MUX(TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3), + MUX(TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1), + MUX_GATE(TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23), + MUX_GATE(TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 4, 31), + /* CLK_CFG_1 */ + MUX_GATE(TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7), + MUX_GATE(TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15), + MUX_GATE(TOP_VENC_SEL, "venc_sel", venc_parents, 0x0050, 16, 4, 23), + MUX_GATE(TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 24, 4, 31), + /* CLK_CFG_2 */ + MUX_GATE(TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0060, 0, 3, 7), + MUX_GATE(TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 8, 1, 15), + MUX_GATE(TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 16, 3, 23), + MUX_GATE(TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31), + /* CLK_CFG_3 */ + MUX_GATE(TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7), + MUX_GATE(TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, 0x0070, 8, 3, 15), + MUX_GATE(TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x0070, 16, 4, 23), + MUX_GATE(TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x0070, 24, 3, 31), + /* CLK_CFG_4 */ + MUX_GATE(TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x0080, 0, 3, 7), + MUX_GATE(TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x0080, 8, 4, 15), + MUX_GATE(TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23), + MUX_GATE(TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0080, 24, 3, 31), + /* CLK_CFG_5 */ + MUX_GATE(TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0090, 0, 3, 7 /* 7:5 */), + MUX_GATE(TOP_SCP_SEL, "scp_sel", scp_parents, 0x0090, 8, 3, 15), + MUX_GATE(TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23), + MUX_GATE(TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31), + /* CLK_CFG_6 */ + MUX_GATE(TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7), + MUX_GATE(TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15), + MUX_GATE(TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23), + MUX_GATE(TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31), + /* CLK_CFG_7 */ + MUX_GATE(TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0x00b0, 0, 2, 7), + MUX_GATE(TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, 0x00b0, 8, 2, 15), + MUX_GATE(TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, 0x00b0, 16, 2, 23), + MUX_GATE(TOP_SCAM_SEL, "scam_sel", scam_parents, 0x00b0, 24, 2, 31), + /* CLK_CFG_12 */ + MUX_GATE(TOP_SPINFI_IFR_SEL, "spinfi_ifr_sel", spinfi_ifr_parents, 0x00c0, 0, 3, 7), + MUX_GATE(TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x00c0, 8, 2, 15), + MUX_GATE(TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31), + /* CLK_CFG_13 */ + MUX_GATE(TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, 0x00d0, 0, 3, 7), + MUX_GATE(TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15), + MUX_GATE(TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23), + MUX(TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00d0, 24, 2), + + DIV_GATE(TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24), + DIV_GATE(TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0), + DIV_GATE(TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8), + DIV_GATE(TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16), + DIV_GATE(TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24), + DIV_GATE(TOP_APLL1_DIV5, "apll1_div5", "aud_1_sel", 0x12c, 13, 0x12c, 4, 0), + + DIV_GATE(TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28), + DIV_GATE(TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0), + DIV_GATE(TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8), + DIV_GATE(TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16), + DIV_GATE(TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24), + DIV_GATE(TOP_APLL2_DIV5, "apll2_div5", "aud_2_sel", 0x12c, 21, 0x12c, 4, 4), + + MUX(TOP_I2S0_M_CK_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1), + MUX(TOP_I2S1_M_CK_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1), + MUX(TOP_I2S2_M_CK_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1), + MUX(TOP_I2S3_M_CK_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1), + MUX(TOP_I2S3_B_CK_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1), +}; + +static void __init mtk_init_clk_topckgen(void __iomem *top_base, + struct clk_onecell_data *clk_data) +{ + int i; + struct clk *clk; + + for (i = 0; i < ARRAY_SIZE(top_muxes); i++) { + struct mtk_composite *mux = &top_muxes[i]; + + clk = mtk_clk_register_composite(mux, top_base, &lock); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + mux->name, PTR_ERR(clk)); + continue; + } + + if (clk_data) + clk_data->clks[mux->id] = clk; + } +} + +static struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x0040, + .clr_ofs = 0x0044, + .sta_ofs = 0x0048, +}; + +#define GATE_ICG(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &infra_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static struct mtk_gate infra_clks[] __initdata = { + GATE_ICG(INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0), + GATE_ICG(INFRA_SMI, "infra_smi", "mm_sel", 1), + GATE_ICG(INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5), + GATE_ICG(INFRA_GCE, "infra_gce", "axi_sel", 6), + GATE_ICG(INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7), + GATE_ICG(INFRA_M4U, "infra_m4u", "mem_sel", 8), + GATE_ICG(INFRA_CPUM, "infra_cpum", "clk_null", 15), + GATE_ICG(INFRA_KP, "infra_kp", "axi_sel", 16), + GATE_ICG(INFRA_CEC, "infra_cec", "clk26m", 18), + GATE_ICG(INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22), + GATE_ICG(INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23), +}; + +static struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x0008, + .clr_ofs = 0x0010, + .sta_ofs = 0x0018, +}; + +static struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = 0x000c, + .clr_ofs = 0x0014, + .sta_ofs = 0x001c, +}; + +#define GATE_PERI0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_PERI1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static struct mtk_gate peri_clks[] __initdata = { + /* PERI0 */ + GATE_PERI0(PERI_NFI, "peri_nfi", "axi_sel", 0), + GATE_PERI0(PERI_THERM, "peri_therm", "axi_sel", 1), + GATE_PERI0(PERI_PWM1, "peri_pwm1", "axi_sel", 2), + GATE_PERI0(PERI_PWM2, "peri_pwm2", "axi_sel", 3), + GATE_PERI0(PERI_PWM3, "peri_pwm3", "axi_sel", 4), + GATE_PERI0(PERI_PWM4, "peri_pwm4", "axi_sel", 5), + GATE_PERI0(PERI_PWM5, "peri_pwm5", "axi_sel", 6), + GATE_PERI0(PERI_PWM6, "peri_pwm6", "axi_sel", 7), + GATE_PERI0(PERI_PWM7, "peri_pwm7", "axi_sel", 8), + GATE_PERI0(PERI_PWM, "peri_pwm", "axi_sel", 9), + GATE_PERI0(PERI_USB0, "peri_usb0", "usb20_sel", 10), + GATE_PERI0(PERI_USB1, "peri_usb1", "usb20_sel", 11), + GATE_PERI0(PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12), + GATE_PERI0(PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13), + GATE_PERI0(PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14), + GATE_PERI0(PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15), + GATE_PERI0(PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16), + GATE_PERI0(PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17), + GATE_PERI0(PERI_IRDA, "peri_irda", "irda_sel", 18), + GATE_PERI0(PERI_UART0, "peri_uart0", "uart_sel", 19), + GATE_PERI0(PERI_UART1, "peri_uart1", "uart_sel", 20), + GATE_PERI0(PERI_UART2, "peri_uart2", "uart_sel", 21), + GATE_PERI0(PERI_UART3, "peri_uart3", "uart_sel", 22), + GATE_PERI0(PERI_I2C0, "peri_i2c0", "axi_sel", 23), + GATE_PERI0(PERI_I2C1, "peri_i2c1", "axi_sel", 24), + GATE_PERI0(PERI_I2C2, "peri_i2c2", "axi_sel", 25), + GATE_PERI0(PERI_I2C3, "peri_i2c3", "axi_sel", 26), + GATE_PERI0(PERI_I2C4, "peri_i2c4", "axi_sel", 27), + GATE_PERI0(PERI_AUXADC, "peri_auxadc", "clk26m", 28), + GATE_PERI0(PERI_SPI0, "peri_spi0", "spi_sel", 29), + GATE_PERI0(PERI_I2C5, "peri_i2c5", "axi_sel", 30), + GATE_PERI0(PERI_NFIECC, "peri_nfiecc", "axi_sel", 31), + /* PERI1 */ + GATE_PERI1(PERI_SPI, "peri_spi", "spi_sel", 0), + GATE_PERI1(PERI_IRRX, "peri_irrx", "spi_sel", 1), + GATE_PERI1(PERI_I2C6, "peri_i2c6", "axi_sel", 2), +}; + +static void __init mtk_topckgen_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(TOP_NR_CLK); + + mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_init_clk_topckgen(base, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init); + +static void __init mtk_infrasys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, 2, 0x30); +} +CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init); + +static void __init mtk_pericfg_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(PERI_NR_CLK); + + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, 2, 0); +} +CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init); + +#define MT8173_PLL_FMAX (3000UL * MHZ) + +#define CON0_MT8173_RST_BAR BIT(24) + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, \ + _tuner_reg, _pcw_reg, _pcw_shift) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT8173_RST_BAR, \ + .fmax = MT8173_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + } + +static const struct mtk_pll_data plls[] = { + PLL(APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0x00000001, 0, 21, 0x204, 24, 0x0, 0x204, 0), + PLL(APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0x00000001, 0, 21, 0x214, 24, 0x0, 0x214, 0), + PLL(APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0), + PLL(APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000001, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14), + PLL(APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0x00000001, 0, 21, 0x244, 24, 0x0, 0x244, 0), + PLL(APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0x00000001, 0, 21, 0x250, 4, 0x0, 0x254, 0), + PLL(APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0x00000001, 0, 21, 0x260, 4, 0x0, 0x264, 0), + PLL(APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0x00000001, 0, 21, 0x270, 4, 0x0, 0x274, 0), + PLL(APMIXED_MPLL, "mpll", 0x280, 0x28c, 0x00000001, 0, 21, 0x280, 4, 0x0, 0x284, 0), + PLL(APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0x00000001, 0, 21, 0x290, 4, 0x0, 0x294, 0), + PLL(APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0x00000001, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0), + PLL(APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0x00000001, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0), + PLL(APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0x00000001, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0), + PLL(APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0x00000001, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0), +}; + +static void __init mtk_apmixedsys_init(struct device_node *node) +{ + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls)); +} +CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys", + mtk_apmixedsys_init); diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h new file mode 100644 index 0000000..e648b28 --- /dev/null +++ b/include/dt-bindings/clock/mt8173-clk.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_CLK_MT8173_H +#define _DT_BINDINGS_CLK_MT8173_H + +/* TOPCKGEN */ + +#define TOP_CLKPH_MCK_O 1 +#define TOP_DPI_CK 2 +#define TOP_USB_SYSPLL_125M 3 +#define TOP_HDMITX_DIG_CTS 4 +#define TOP_ARMCA7PLL_754M 5 +#define TOP_ARMCA7PLL_502M 6 +#define TOP_MAIN_H546M 7 +#define TOP_MAIN_H364M 8 +#define TOP_MAIN_H218P4M 9 +#define TOP_MAIN_H156M 10 +#define TOP_TVDPLL_445P5M 11 +#define TOP_TVDPLL_594M 12 +#define TOP_UNIV_624M 13 +#define TOP_UNIV_416M 14 +#define TOP_UNIV_249P6M 15 +#define TOP_UNIV_178P3M 16 +#define TOP_UNIV_48M 17 +#define TOP_CLKRTC_EXT 18 +#define TOP_CLKRTC_INT 19 +#define TOP_FPC_CK 20 +#define TOP_HDMITXPLL_D2 21 +#define TOP_HDMITXPLL_D3 22 +#define TOP_ARMCA7PLL_D2 23 +#define TOP_ARMCA7PLL_D3 24 +#define TOP_APLL1_CK 25 +#define TOP_APLL2_CK 26 +#define TOP_DMPLL_CK 27 +#define TOP_DMPLL_D2 28 +#define TOP_DMPLL_D4 29 +#define TOP_DMPLL_D8 30 +#define TOP_DMPLL_D16 31 +#define TOP_LVDSPLL_D2 32 +#define TOP_LVDSPLL_D4 33 +#define TOP_LVDSPLL_D8 34 +#define TOP_MMPLL_CK 35 +#define TOP_MMPLL_D2 36 +#define TOP_MSDCPLL_CK 37 +#define TOP_MSDCPLL_D2 38 +#define TOP_MSDCPLL_D4 39 +#define TOP_MSDCPLL2_CK 40 +#define TOP_MSDCPLL2_D2 41 +#define TOP_MSDCPLL2_D4 42 +#define TOP_SYSPLL_D2 43 +#define TOP_SYSPLL1_D2 44 +#define TOP_SYSPLL1_D4 45 +#define TOP_SYSPLL1_D8 46 +#define TOP_SYSPLL1_D16 47 +#define TOP_SYSPLL_D3 48 +#define TOP_SYSPLL2_D2 49 +#define TOP_SYSPLL2_D4 50 +#define TOP_SYSPLL_D5 51 +#define TOP_SYSPLL3_D2 52 +#define TOP_SYSPLL3_D4 53 +#define TOP_SYSPLL_D7 54 +#define TOP_SYSPLL4_D2 55 +#define TOP_SYSPLL4_D4 56 +#define TOP_TVDPLL_CK 57 +#define TOP_TVDPLL_D2 58 +#define TOP_TVDPLL_D4 59 +#define TOP_TVDPLL_D8 60 +#define TOP_TVDPLL_D16 61 +#define TOP_UNIVPLL_D2 62 +#define TOP_UNIVPLL1_D2 63 +#define TOP_UNIVPLL1_D4 64 +#define TOP_UNIVPLL1_D8 65 +#define TOP_UNIVPLL_D3 66 +#define TOP_UNIVPLL2_D2 67 +#define TOP_UNIVPLL2_D4 68 +#define TOP_UNIVPLL2_D8 69 +#define TOP_UNIVPLL_D5 70 +#define TOP_UNIVPLL3_D2 71 +#define TOP_UNIVPLL3_D4 72 +#define TOP_UNIVPLL3_D8 73 +#define TOP_UNIVPLL_D7 74 +#define TOP_UNIVPLL_D26 75 +#define TOP_UNIVPLL_D52 76 +#define TOP_VCODECPLL_CK 77 +#define TOP_VCODECPLL_370P5 78 +#define TOP_VENCPLL_CK 79 +#define TOP_VENCPLL_D2 80 +#define TOP_VENCPLL_D4 81 +#define TOP_AXI_SEL 82 +#define TOP_MEM_SEL 83 +#define TOP_DDRPHYCFG_SEL 84 +#define TOP_MM_SEL 85 +#define TOP_PWM_SEL 86 +#define TOP_VDEC_SEL 87 +#define TOP_VENC_SEL 88 +#define TOP_MFG_SEL 89 +#define TOP_CAMTG_SEL 90 +#define TOP_UART_SEL 91 +#define TOP_SPI_SEL 92 +#define TOP_USB20_SEL 93 +#define TOP_USB30_SEL 94 +#define TOP_MSDC50_0_H_SEL 95 +#define TOP_MSDC50_0_SEL 96 +#define TOP_MSDC30_1_SEL 97 +#define TOP_MSDC30_2_SEL 98 +#define TOP_MSDC30_3_SEL 99 +#define TOP_AUDIO_SEL 100 +#define TOP_AUD_INTBUS_SEL 101 +#define TOP_PMICSPI_SEL 102 +#define TOP_SCP_SEL 103 +#define TOP_ATB_SEL 104 +#define TOP_VENC_LT_SEL 105 +#define TOP_DPI0_SEL 106 +#define TOP_IRDA_SEL 107 +#define TOP_CCI400_SEL 108 +#define TOP_AUD_1_SEL 109 +#define TOP_AUD_2_SEL 110 +#define TOP_MEM_MFG_IN_SEL 111 +#define TOP_AXI_MFG_IN_SEL 112 +#define TOP_SCAM_SEL 113 +#define TOP_SPINFI_IFR_SEL 114 +#define TOP_HDMI_SEL 115 +#define TOP_DPILVDS_SEL 116 +#define TOP_MSDC50_2_H_SEL 117 +#define TOP_HDCP_SEL 118 +#define TOP_HDCP_24M_SEL 119 +#define TOP_RTC_SEL 120 +#define TOP_APLL1_DIV0 121 +#define TOP_APLL1_DIV1 122 +#define TOP_APLL1_DIV2 123 +#define TOP_APLL1_DIV3 124 +#define TOP_APLL1_DIV4 125 +#define TOP_APLL1_DIV5 126 +#define TOP_APLL2_DIV0 127 +#define TOP_APLL2_DIV1 128 +#define TOP_APLL2_DIV2 129 +#define TOP_APLL2_DIV3 130 +#define TOP_APLL2_DIV4 131 +#define TOP_APLL2_DIV5 132 +#define TOP_I2S0_M_CK_SEL 133 +#define TOP_I2S1_M_CK_SEL 134 +#define TOP_I2S2_M_CK_SEL 135 +#define TOP_I2S3_M_CK_SEL 136 +#define TOP_I2S3_B_CK_SEL 137 +#define TOP_NR_CLK 138 + +/* APMIXED_SYS */ + +#define APMIXED_ARMCA15PLL 1 +#define APMIXED_ARMCA7PLL 2 +#define APMIXED_MAINPLL 3 +#define APMIXED_UNIVPLL 4 +#define APMIXED_MMPLL 5 +#define APMIXED_MSDCPLL 6 +#define APMIXED_VENCPLL 7 +#define APMIXED_TVDPLL 8 +#define APMIXED_MPLL 9 +#define APMIXED_VCODECPLL 10 +#define APMIXED_APLL1 11 +#define APMIXED_APLL2 12 +#define APMIXED_LVDSPLL 13 +#define APMIXED_MSDCPLL2 14 +#define APMIXED_NR_CLK 15 + +/* INFRA_SYS */ + +#define INFRA_DBGCLK 1 +#define INFRA_SMI 2 +#define INFRA_AUDIO 3 +#define INFRA_GCE 4 +#define INFRA_L2C_SRAM 5 +#define INFRA_M4U 6 +#define INFRA_CPUM 7 +#define INFRA_KP 8 +#define INFRA_CEC 9 +#define INFRA_PMICSPI 10 +#define INFRA_PMICWRAP 11 +#define INFRA_NR_CLK 12 + +/* PERI_SYS */ + +#define PERI_NFI 1 +#define PERI_THERM 2 +#define PERI_PWM1 3 +#define PERI_PWM2 4 +#define PERI_PWM3 5 +#define PERI_PWM4 6 +#define PERI_PWM5 7 +#define PERI_PWM6 8 +#define PERI_PWM7 9 +#define PERI_PWM 10 +#define PERI_USB0 11 +#define PERI_USB1 12 +#define PERI_AP_DMA 13 +#define PERI_MSDC30_0 14 +#define PERI_MSDC30_1 15 +#define PERI_MSDC30_2 16 +#define PERI_MSDC30_3 17 +#define PERI_NLI_ARB 18 +#define PERI_IRDA 19 +#define PERI_UART0 20 +#define PERI_UART1 21 +#define PERI_UART2 22 +#define PERI_UART3 23 +#define PERI_I2C0 24 +#define PERI_I2C1 25 +#define PERI_I2C2 26 +#define PERI_I2C3 27 +#define PERI_I2C4 28 +#define PERI_AUXADC 29 +#define PERI_SPI0 30 +#define PERI_I2C5 31 +#define PERI_NFIECC 32 +#define PERI_SPI 33 +#define PERI_IRRX 34 +#define PERI_I2C6 35 +#define PERI_NR_CLK 36 + +#endif /* _DT_BINDINGS_CLK_MT8173_H */ diff --git a/include/dt-bindings/reset-controller/mt8173-resets.h b/include/dt-bindings/reset-controller/mt8173-resets.h new file mode 100644 index 0000000..9464b37 --- /dev/null +++ b/include/dt-bindings/reset-controller/mt8173-resets.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Flora Fu, MediaTek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8173 +#define _DT_BINDINGS_RESET_CONTROLLER_MT8173 + +/* INFRACFG resets */ +#define MT8173_INFRA_EMI_REG_RST 0 +#define MT8173_INFRA_DRAMC0_A0_RST 1 +#define MT8173_INFRA_APCIRQ_EINT_RST 3 +#define MT8173_INFRA_APXGPT_RST 4 +#define MT8173_INFRA_SCPSYS_RST 5 +#define MT8173_INFRA_KP_RST 6 +#define MT8173_INFRA_PMIC_WRAP_RST 7 +#define MT8173_INFRA_MPIP_RST 8 +#define MT8173_INFRA_CEC_RST 9 +#define MT8173_INFRA_EMI_RST 32 +#define MT8173_INFRA_DRAMC0_RST 34 +#define MT8173_INFRA_APMIXEDSYS_RST 35 +#define MT8173_INFRA_MIPI_DSI_RST 36 +#define MT8173_INFRA_TRNG_RST 37 +#define MT8173_INFRA_SYSIRQ_RST 38 +#define MT8173_INFRA_MIPI_CSI_RST 39 +#define MT8173_INFRA_GCE_FAXI_RST 40 +#define MT8173_INFRA_MMIOMMURST 47 + + +/* PERICFG resets */ +#define MT8173_PERI_UART0_SW_RST 0 +#define MT8173_PERI_UART1_SW_RST 1 +#define MT8173_PERI_UART2_SW_RST 2 +#define MT8173_PERI_UART3_SW_RST 3 +#define MT8173_PERI_IRRX_SW_RST 4 +#define MT8173_PERI_PWM_SW_RST 8 +#define MT8173_PERI_AUXADC_SW_RST 10 +#define MT8173_PERI_DMA_SW_RST 11 +#define MT8173_PERI_I2C6_SW_RST 13 +#define MT8173_PERI_NFI_SW_RST 14 +#define MT8173_PERI_THERM_SW_RST 16 +#define MT8173_PERI_MSDC2_SW_RST 17 +#define MT8173_PERI_MSDC3_SW_RST 18 +#define MT8173_PERI_MSDC0_SW_RST 19 +#define MT8173_PERI_MSDC1_SW_RST 20 +#define MT8173_PERI_I2C0_SW_RST 22 +#define MT8173_PERI_I2C1_SW_RST 23 +#define MT8173_PERI_I2C2_SW_RST 24 +#define MT8173_PERI_I2C3_SW_RST 25 +#define MT8173_PERI_I2C4_SW_RST 26 +#define MT8173_PERI_HDMI_SW_RST 29 +#define MT8173_PERI_SPI0_SW_RST 33 + +#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8173 */ -- 2.1.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 5/5] dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers 2015-02-22 11:49 [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 Sascha Hauer ` (3 preceding siblings ...) 2015-02-22 11:49 ` [PATCH 4/5] clk: mediatek: Add basic clocks for Mediatek MT8173 Sascha Hauer @ 2015-02-22 11:49 ` Sascha Hauer 2015-03-09 6:15 ` [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 Sascha Hauer 5 siblings, 0 replies; 14+ messages in thread From: Sascha Hauer @ 2015-02-22 11:49 UTC (permalink / raw) To: linux-arm-kernel Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- .../bindings/arm/mediatek/mediatek,apmixedsys.txt | 23 +++++++++++++++++ .../bindings/arm/mediatek/mediatek,infracfg.txt | 30 ++++++++++++++++++++++ .../bindings/arm/mediatek/mediatek,pericfg.txt | 30 ++++++++++++++++++++++ .../bindings/arm/mediatek/mediatek,topckgen.txt | 23 +++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt new file mode 100644 index 0000000..5af6d73 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt @@ -0,0 +1,23 @@ +Mediatek apmixedsys controller +============================== + +The Mediatek apmixedsys controller provides the PLLs to the system. + +Required Properties: + +- compatible: Should be: + - "mediatek,mt8135-apmixedsys" + - "mediatek,mt8173-apmixedsys" +- #clock-cells: Must be 1 + +The apmixedsys controller uses the common clk binding from +Documentation/devicetree/bindings/clock/clock-bindings.txt +The available clocks are defined in dt-bindings/clock/mt*-clk.h. + +Example: + +apmixedsys: apmixedsys at 10209000 { + compatible = "mediatek,mt8173-apmixedsys"; + reg = <0 0x10209000 0 0x1000>; + #clock-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt new file mode 100644 index 0000000..684da473 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt @@ -0,0 +1,30 @@ +Mediatek infracfg controller +============================ + +The Mediatek infracfg controller provides various clocks and reset +outputs to the system. + +Required Properties: + +- compatible: Should be: + - "mediatek,mt8135-infracfg", "syscon" + - "mediatek,mt8173-infracfg", "syscon" +- #clock-cells: Must be 1 +- #reset-cells: Must be 1 + +The infracfg controller uses the common clk binding from +Documentation/devicetree/bindings/clock/clock-bindings.txt +The available clocks are defined in dt-bindings/clock/mt*-clk.h. +Also it uses the common reset controller binding from +Documentation/devicetree/bindings/reset/reset.txt. +The available reset outputs are defined in +dt-bindings/reset-controller/mt*-resets.h + +Example: + +infracfg: infracfg at 10001000 { + compatible = "mediatek,mt8173-infracfg", "syscon"; + reg = <0 0x10001000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt new file mode 100644 index 0000000..fdb45c6 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt @@ -0,0 +1,30 @@ +Mediatek pericfg controller +=========================== + +The Mediatek pericfg controller provides various clocks and reset +outputs to the system. + +Required Properties: + +- compatible: Should be: + - "mediatek,mt8135-pericfg", "syscon" + - "mediatek,mt8173-pericfg", "syscon" +- #clock-cells: Must be 1 +- #reset-cells: Must be 1 + +The pericfg controller uses the common clk binding from +Documentation/devicetree/bindings/clock/clock-bindings.txt +The available clocks are defined in dt-bindings/clock/mt*-clk.h. +Also it uses the common reset controller binding from +Documentation/devicetree/bindings/reset/reset.txt. +The available reset outputs are defined in +dt-bindings/reset-controller/mt*-resets.h + +Example: + +pericfg: pericfg at 10003000 { + compatible = "mediatek,mt8173-pericfg", "syscon"; + reg = <0 0x10003000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; +}; diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt new file mode 100644 index 0000000..a425248 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt @@ -0,0 +1,23 @@ +Mediatek topckgen controller +============================ + +The Mediatek topckgen controller provides various clocks to the system. + +Required Properties: + +- compatible: Should be: + - "mediatek,mt8135-topckgen" + - "mediatek,mt8173-topckgen" +- #clock-cells: Must be 1 + +The topckgen controller uses the common clk binding from +Documentation/devicetree/bindings/clock/clock-bindings.txt +The available clocks are defined in dt-bindings/clock/mt*-clk.h. + +Example: + +topckgen: topckgen at 10000000 { + compatible = "mediatek,mt8173-topckgen"; + reg = <0 0x10000000 0 0x1000>; + #clock-cells = <1>; +}; -- 2.1.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 2015-02-22 11:49 [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 Sascha Hauer ` (4 preceding siblings ...) 2015-02-22 11:49 ` [PATCH 5/5] dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers Sascha Hauer @ 2015-03-09 6:15 ` Sascha Hauer 5 siblings, 0 replies; 14+ messages in thread From: Sascha Hauer @ 2015-03-09 6:15 UTC (permalink / raw) To: linux-arm-kernel Hi Mike, On Sun, Feb 22, 2015 at 12:49:20PM +0100, Sascha Hauer wrote: > This patchset contains the initial common clock support for Mediatek SoCs. > Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes > and clock gates. Are these patches ok now? If yes, please pull: The following changes since commit c517d838eb7d07bbe9507871fab3931deccff539: Linux 4.0-rc1 (2015-02-22 18:21:14 -0800) are available in the git repository at: git://git.pengutronix.de/git/imx/linux-2.6.git tags/mtk-clk-v6 for you to fetch changes up to edfdf5ab89af79d2f9a21fefdcfa5e89e8598d53: dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-03-09 06:41:24 +0100) ---------------------------------------------------------------- MTK clock support v6 ---------------------------------------------------------------- James Liao (3): clk: mediatek: Add initial common clock support for Mediatek SoCs. clk: mediatek: Add basic clocks for Mediatek MT8135. clk: mediatek: Add basic clocks for Mediatek MT8173. Sascha Hauer (2): clk: mediatek: Add reset controller support dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers .../bindings/arm/mediatek/mediatek,apmixedsys.txt | 23 + .../bindings/arm/mediatek/mediatek,infracfg.txt | 30 + .../bindings/arm/mediatek/mediatek,pericfg.txt | 30 + .../bindings/arm/mediatek/mediatek,topckgen.txt | 23 + drivers/clk/Makefile | 1 + drivers/clk/mediatek/Makefile | 4 + drivers/clk/mediatek/clk-gate.c | 137 ++++ drivers/clk/mediatek/clk-gate.h | 49 ++ drivers/clk/mediatek/clk-mt8135.c | 634 ++++++++++++++++ drivers/clk/mediatek/clk-mt8173.c | 820 +++++++++++++++++++++ drivers/clk/mediatek/clk-mtk.c | 195 +++++ drivers/clk/mediatek/clk-mtk.h | 174 +++++ drivers/clk/mediatek/clk-pll.c | 330 +++++++++ drivers/clk/mediatek/reset.c | 99 +++ include/dt-bindings/clock/mt8135-clk.h | 190 +++++ include/dt-bindings/clock/mt8173-clk.h | 231 ++++++ .../dt-bindings/reset-controller/mt8135-resets.h | 64 ++ .../dt-bindings/reset-controller/mt8173-resets.h | 63 ++ 18 files changed, 3097 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt create mode 100644 drivers/clk/mediatek/Makefile create mode 100644 drivers/clk/mediatek/clk-gate.c create mode 100644 drivers/clk/mediatek/clk-gate.h create mode 100644 drivers/clk/mediatek/clk-mt8135.c create mode 100644 drivers/clk/mediatek/clk-mt8173.c create mode 100644 drivers/clk/mediatek/clk-mtk.c create mode 100644 drivers/clk/mediatek/clk-mtk.h create mode 100644 drivers/clk/mediatek/clk-pll.c create mode 100644 drivers/clk/mediatek/reset.c create mode 100644 include/dt-bindings/clock/mt8135-clk.h create mode 100644 include/dt-bindings/clock/mt8173-clk.h create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h create mode 100644 include/dt-bindings/reset-controller/mt8173-resets.h -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v7]: clk: Add common clock support for Mediatek MT8135 and MT8173 @ 2015-03-16 5:55 Sascha Hauer 2015-03-16 5:55 ` [PATCH 1/5] clk: mediatek: Add initial common clock support for Mediatek SoCs Sascha Hauer 0 siblings, 1 reply; 14+ messages in thread From: Sascha Hauer @ 2015-03-16 5:55 UTC (permalink / raw) To: linux-arm-kernel The following changes since commit 9eccca0843205f87c00404b663188b88eb248051: Linux 4.0-rc3 (2015-03-08 16:09:09 -0700) are available in the git repository at: git://git.pengutronix.de/git/imx/linux-2.6.git tags/v4.0-clk-mediatek-v7 for you to fetch changes up to 147dc836b1206e8118509229594d82ff8ad3b99e: dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers (2015-03-16 06:31:37 +0100) ---------------------------------------------------------------- This patchset contains the initial common clock support for Mediatek SoCs. Mediatek SoC's clock architecture comprises of various PLLs, dividers, muxes and clock gates. Sascha Changes in v7: - fix duplicate definition/declaration of mtk_register_reset_controller - fix pd_reg offset of tvdpll - make clk initialization arrays const Changes in v6: - rework PLL support, only a fraction of original size now - Move binding docs to Documentation/devicetree/bindings/arm/mediatek since the units are not really clock specific (they contain reset controllers) Changes in v5: - Add reset controller support for pericfg/infracfg - Use regmap for the gates - remove now unnecessary spinlock for the gates - Add PMIC wrapper support as of v3 Changes in v4: - Support MT8173 platform. - Re-ordered patchset. driver/clk/Makefile in 2nd patch. - Extract the common part definition(mtk_gate/mtk_pll/mtk_mux) from clk-mt8135.c/clk-mt8173.c to clk-mtk.c. - Refine code. Rmove unnessacary debug information and unsed defines, add prefix "mtk_" for static functions. - Remove flag CLK_IGNORE_UNUSED and set flag CLK_SET_RATE_PARENT on gate/mux/fixed-factor. - Use spin_lock_irqsave(&clk_ops_lock, flags) instead of mtk_clk_lock. - Example above include a node for the clock controller itself, followed by the i2c controller example above. Changes in v3: - Rebase to 3.19-rc1. - Refine code. Remove unneed functions, debug logs and comments, and fine tune error logs. Changes in v2: - Re-ordered patchset. Fold include/dt-bindings and DT document in 1st patch. ---------------------------------------------------------------- James Liao (3): clk: mediatek: Add initial common clock support for Mediatek SoCs. clk: mediatek: Add basic clocks for Mediatek MT8135. clk: mediatek: Add basic clocks for Mediatek MT8173. Sascha Hauer (2): clk: mediatek: Add reset controller support dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers .../bindings/arm/mediatek/mediatek,apmixedsys.txt | 23 + .../bindings/arm/mediatek/mediatek,infracfg.txt | 30 + .../bindings/arm/mediatek/mediatek,pericfg.txt | 30 + .../bindings/arm/mediatek/mediatek,topckgen.txt | 23 + drivers/clk/Makefile | 1 + drivers/clk/mediatek/Makefile | 4 + drivers/clk/mediatek/clk-gate.c | 137 ++++ drivers/clk/mediatek/clk-gate.h | 49 ++ drivers/clk/mediatek/clk-mt8135.c | 640 ++++++++++++++++ drivers/clk/mediatek/clk-mt8173.c | 826 +++++++++++++++++++++ drivers/clk/mediatek/clk-mtk.c | 197 +++++ drivers/clk/mediatek/clk-mtk.h | 165 ++++ drivers/clk/mediatek/clk-pll.c | 325 ++++++++ drivers/clk/mediatek/reset.c | 99 +++ include/dt-bindings/clock/mt8135-clk.h | 190 +++++ include/dt-bindings/clock/mt8173-clk.h | 231 ++++++ .../dt-bindings/reset-controller/mt8135-resets.h | 64 ++ .../dt-bindings/reset-controller/mt8173-resets.h | 63 ++ 18 files changed, 3097 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,pericfg.txt create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt create mode 100644 drivers/clk/mediatek/Makefile create mode 100644 drivers/clk/mediatek/clk-gate.c create mode 100644 drivers/clk/mediatek/clk-gate.h create mode 100644 drivers/clk/mediatek/clk-mt8135.c create mode 100644 drivers/clk/mediatek/clk-mt8173.c create mode 100644 drivers/clk/mediatek/clk-mtk.c create mode 100644 drivers/clk/mediatek/clk-mtk.h create mode 100644 drivers/clk/mediatek/clk-pll.c create mode 100644 drivers/clk/mediatek/reset.c create mode 100644 include/dt-bindings/clock/mt8135-clk.h create mode 100644 include/dt-bindings/clock/mt8173-clk.h create mode 100644 include/dt-bindings/reset-controller/mt8135-resets.h create mode 100644 include/dt-bindings/reset-controller/mt8173-resets.h ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/5] clk: mediatek: Add initial common clock support for Mediatek SoCs. 2015-03-16 5:55 [PATCH v7]: " Sascha Hauer @ 2015-03-16 5:55 ` Sascha Hauer 0 siblings, 0 replies; 14+ messages in thread From: Sascha Hauer @ 2015-03-16 5:55 UTC (permalink / raw) To: linux-arm-kernel From: James Liao <jamesjj.liao@mediatek.com> This patch adds common clock support for Mediatek SoCs, including plls, muxes and clock gates. Signed-off-by: James Liao <jamesjj.liao@mediatek.com> Signed-off-by: Henry Chen <henryc.chen@mediatek.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/clk/Makefile | 1 + drivers/clk/mediatek/Makefile | 1 + drivers/clk/mediatek/clk-gate.c | 137 +++++++++++++++++ drivers/clk/mediatek/clk-gate.h | 49 ++++++ drivers/clk/mediatek/clk-mtk.c | 197 ++++++++++++++++++++++++ drivers/clk/mediatek/clk-mtk.h | 155 +++++++++++++++++++ drivers/clk/mediatek/clk-pll.c | 325 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 865 insertions(+) create mode 100644 drivers/clk/mediatek/Makefile create mode 100644 drivers/clk/mediatek/clk-gate.c create mode 100644 drivers/clk/mediatek/clk-gate.h create mode 100644 drivers/clk/mediatek/clk-mtk.c create mode 100644 drivers/clk/mediatek/clk-mtk.h create mode 100644 drivers/clk/mediatek/clk-pll.c diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index d478ceb..6d97203 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/ obj-$(CONFIG_ARCH_HIP04) += hisilicon/ obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/ obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ +obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_ARCH_MMP) += mmp/ endif diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile new file mode 100644 index 0000000..c384e97 --- /dev/null +++ b/drivers/clk/mediatek/Makefile @@ -0,0 +1 @@ +obj-y += clk-mtk.o clk-pll.o clk-gate.o diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c new file mode 100644 index 0000000..9d77ee3 --- /dev/null +++ b/drivers/clk/mediatek/clk-gate.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/of.h> +#include <linux/of_address.h> + +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/clkdev.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +static int mtk_cg_bit_is_cleared(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_clk_gate(hw); + u32 val; + + regmap_read(cg->regmap, cg->sta_ofs, &val); + + val &= BIT(cg->bit); + + return val == 0; +} + +static int mtk_cg_bit_is_set(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_clk_gate(hw); + u32 val; + + regmap_read(cg->regmap, cg->sta_ofs, &val); + + val &= BIT(cg->bit); + + return val != 0; +} + +static void mtk_cg_set_bit(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_clk_gate(hw); + + regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit)); +} + +static void mtk_cg_clr_bit(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_clk_gate(hw); + + regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit)); +} + +static int mtk_cg_enable(struct clk_hw *hw) +{ + mtk_cg_clr_bit(hw); + + return 0; +} + +static void mtk_cg_disable(struct clk_hw *hw) +{ + mtk_cg_set_bit(hw); +} + +static int mtk_cg_enable_inv(struct clk_hw *hw) +{ + mtk_cg_set_bit(hw); + + return 0; +} + +static void mtk_cg_disable_inv(struct clk_hw *hw) +{ + mtk_cg_clr_bit(hw); +} + +const struct clk_ops mtk_clk_gate_ops_setclr = { + .is_enabled = mtk_cg_bit_is_cleared, + .enable = mtk_cg_enable, + .disable = mtk_cg_disable, +}; + +const struct clk_ops mtk_clk_gate_ops_setclr_inv = { + .is_enabled = mtk_cg_bit_is_set, + .enable = mtk_cg_enable_inv, + .disable = mtk_cg_disable_inv, +}; + +struct clk *mtk_clk_register_gate( + const char *name, + const char *parent_name, + struct regmap *regmap, + int set_ofs, + int clr_ofs, + int sta_ofs, + u8 bit, + const struct clk_ops *ops) +{ + struct mtk_clk_gate *cg; + struct clk *clk; + struct clk_init_data init; + + cg = kzalloc(sizeof(*cg), GFP_KERNEL); + if (!cg) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.ops = ops; + + cg->regmap = regmap; + cg->set_ofs = set_ofs; + cg->clr_ofs = clr_ofs; + cg->sta_ofs = sta_ofs; + cg->bit = bit; + + cg->hw.init = &init; + + clk = clk_register(NULL, &cg->hw); + if (IS_ERR(clk)) + kfree(cg); + + return clk; +} diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h new file mode 100644 index 0000000..6b6780b --- /dev/null +++ b/drivers/clk/mediatek/clk-gate.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __DRV_CLK_GATE_H +#define __DRV_CLK_GATE_H + +#include <linux/regmap.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> + +struct mtk_clk_gate { + struct clk_hw hw; + struct regmap *regmap; + int set_ofs; + int clr_ofs; + int sta_ofs; + u8 bit; +}; + +static inline struct mtk_clk_gate *to_clk_gate(struct clk_hw *hw) +{ + return container_of(hw, struct mtk_clk_gate, hw); +} + +extern const struct clk_ops mtk_clk_gate_ops_setclr; +extern const struct clk_ops mtk_clk_gate_ops_setclr_inv; + +struct clk *mtk_clk_register_gate( + const char *name, + const char *parent_name, + struct regmap *regmap, + int set_ofs, + int clr_ofs, + int sta_ofs, + u8 bit, + const struct clk_ops *ops); + +#endif /* __DRV_CLK_GATE_H */ diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c new file mode 100644 index 0000000..5d3a53b --- /dev/null +++ b/drivers/clk/mediatek/clk-mtk.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/clkdev.h> +#include <linux/mfd/syscon.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num) +{ + int i; + struct clk_onecell_data *clk_data; + + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return NULL; + + clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL); + if (!clk_data->clks) + goto err_out; + + clk_data->clk_num = clk_num; + + for (i = 0; i < clk_num; ++i) + clk_data->clks[i] = ERR_PTR(-ENOENT); + + return clk_data; +err_out: + kfree(clk_data); + + return NULL; +} + +void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, + struct clk_onecell_data *clk_data) +{ + int i; + struct clk *clk; + + for (i = 0; i < num; i++) { + const struct mtk_fixed_factor *ff = &clks[i]; + + clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name, + CLK_SET_RATE_PARENT, ff->mult, ff->div); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + ff->name, PTR_ERR(clk)); + continue; + } + + if (clk_data) + clk_data->clks[ff->id] = clk; + } +} + +int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks, + int num, struct clk_onecell_data *clk_data) +{ + int i; + struct clk *clk; + struct regmap *regmap; + + if (!clk_data) + return -ENOMEM; + + regmap = syscon_node_to_regmap(node); + if (IS_ERR(regmap)) { + pr_err("Cannot find regmap for %s: %ld\n", node->full_name, + PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + for (i = 0; i < num; i++) { + const struct mtk_gate *gate = &clks[i]; + + clk = mtk_clk_register_gate(gate->name, gate->parent_name, + regmap, + gate->regs->set_ofs, + gate->regs->clr_ofs, + gate->regs->sta_ofs, + gate->shift, gate->ops); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + gate->name, PTR_ERR(clk)); + continue; + } + + clk_data->clks[gate->id] = clk; + } + + return 0; +} + +struct clk *mtk_clk_register_composite(const struct mtk_composite *mc, + void __iomem *base, spinlock_t *lock) +{ + struct clk *clk; + struct clk_mux *mux = NULL; + struct clk_gate *gate = NULL; + struct clk_divider *div = NULL; + struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL; + const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL; + const char **parent_names; + const char *parent; + int num_parents; + int ret; + + if (mc->mux_shift >= 0) { + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + return ERR_PTR(-ENOMEM); + + mux->reg = base + mc->mux_reg; + mux->mask = BIT(mc->mux_width) - 1; + mux->shift = mc->mux_shift; + mux->lock = lock; + + mux_hw = &mux->hw; + mux_ops = &clk_mux_ops; + + parent_names = mc->parent_names; + num_parents = mc->num_parents; + } else { + parent = mc->parent; + parent_names = &parent; + num_parents = 1; + } + + if (mc->gate_shift >= 0) { + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) { + ret = -ENOMEM; + goto err_out; + } + + gate->reg = base + mc->gate_reg; + gate->bit_idx = mc->gate_shift; + gate->flags = CLK_GATE_SET_TO_DISABLE; + gate->lock = lock; + + gate_hw = &gate->hw; + gate_ops = &clk_gate_ops; + } + + if (mc->divider_shift >= 0) { + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) { + ret = -ENOMEM; + goto err_out; + } + + div->reg = base + mc->divider_reg; + div->shift = mc->divider_shift; + div->width = mc->divider_width; + div->lock = lock; + + div_hw = &div->hw; + div_ops = &clk_divider_ops; + } + + clk = clk_register_composite(NULL, mc->name, parent_names, num_parents, + mux_hw, mux_ops, + div_hw, div_ops, + gate_hw, gate_ops, + mc->flags); + + if (IS_ERR(clk)) { + kfree(gate); + kfree(mux); + } + + return clk; +err_out: + kfree(mux); + + return ERR_PTR(ret); +} diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h new file mode 100644 index 0000000..c660a9e --- /dev/null +++ b/drivers/clk/mediatek/clk-mtk.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __DRV_CLK_MTK_H +#define __DRV_CLK_MTK_H + +#include <linux/regmap.h> +#include <linux/bitops.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> + +#define MAX_MUX_GATE_BIT 31 +#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1) + +#define MHZ (1000 * 1000) + +struct mtk_fixed_factor { + int id; + const char *name; + const char *parent_name; + int mult; + int div; +}; + +#define FACTOR(_id, _name, _parent, _mult, _div) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .mult = _mult, \ + .div = _div, \ + } + +extern void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, + int num, struct clk_onecell_data *clk_data); + +struct mtk_composite { + int id; + const char *name; + const char **parent_names; + const char *parent; + unsigned flags; + + uint32_t mux_reg; + uint32_t divider_reg; + uint32_t gate_reg; + + signed char mux_shift; + signed char mux_width; + signed char gate_shift; + + signed char divider_shift; + signed char divider_width; + + signed char num_parents; +}; + +#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) { \ + .id = _id, \ + .name = _name, \ + .mux_reg = _reg, \ + .mux_shift = _shift, \ + .mux_width = _width, \ + .gate_reg = _reg, \ + .gate_shift = _gate, \ + .divider_shift = -1, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .flags = CLK_SET_RATE_PARENT, \ + } + +#define MUX(_id, _name, _parents, _reg, _shift, _width) { \ + .id = _id, \ + .name = _name, \ + .mux_reg = _reg, \ + .mux_shift = _shift, \ + .mux_width = _width, \ + .gate_shift = -1, \ + .divider_shift = -1, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .flags = CLK_SET_RATE_PARENT, \ + } + +#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) { \ + .id = _id, \ + .parent = _parent, \ + .name = _name, \ + .divider_reg = _div_reg, \ + .divider_shift = _div_shift, \ + .divider_width = _div_width, \ + .gate_reg = _gate_reg, \ + .gate_shift = _gate_shift, \ + .mux_shift = -1, \ + .flags = 0, \ + } + +struct clk *mtk_clk_register_composite(const struct mtk_composite *mc, + void __iomem *base, spinlock_t *lock); + +struct mtk_gate_regs { + u32 sta_ofs; + u32 clr_ofs; + u32 set_ofs; +}; + +struct mtk_gate { + int id; + const char *name; + const char *parent_name; + const struct mtk_gate_regs *regs; + int shift; + const struct clk_ops *ops; +}; + +int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks, + int num, struct clk_onecell_data *clk_data); + +struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); + +#define HAVE_RST_BAR BIT(0) + +struct mtk_pll_data { + int id; + const char *name; + uint32_t reg; + uint32_t pwr_reg; + uint32_t en_mask; + uint32_t pd_reg; + uint32_t tuner_reg; + int pd_shift; + unsigned int flags; + const struct clk_ops *ops; + u32 rst_bar_mask; + unsigned long fmax; + int pcwbits; + uint32_t pcw_reg; + int pcw_shift; +}; + +void __init mtk_clk_register_plls(struct device_node *node, + const struct mtk_pll_data *plls, int num_plls, + struct clk_onecell_data *clk_data); + +#endif /* __DRV_CLK_MTK_H */ diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c new file mode 100644 index 0000000..5589e45 --- /dev/null +++ b/drivers/clk/mediatek/clk-pll.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/clkdev.h> +#include <linux/delay.h> + +#include "clk-mtk.h" + +#define CON0_BASE_EN BIT(0) +#define CON0_PWR_ON BIT(0) +#define CON0_ISO_EN BIT(1) +#define CON0_PCW_CHG BIT(31) + +#define AUDPLL_TUNER_EN BIT(31) + +/* + * MediaTek PLLs are configured through their pcw value. The pcw value describes + * a divider in the PLL feedback loop which consists of 7 bits for the integer + * part and the remaining bits (if present) for the fractional part. Also they + * have a 3 bit power-of-two post divider. + */ + +struct mtk_clk_pll { + struct clk_hw hw; + void __iomem *base_addr; + void __iomem *pd_addr; + void __iomem *pwr_addr; + void __iomem *tuner_addr; + void __iomem *pcw_addr; + const struct mtk_pll_data *data; +}; + +static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw) +{ + return container_of(hw, struct mtk_clk_pll, hw); +} + +static int mtk_pll_is_prepared(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + + return (readl(pll->base_addr) & CON0_BASE_EN) != 0; +} + +static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin, + u32 pcw, int postdiv) +{ + int pcwbits = pll->data->pcwbits; + int pcwfbits; + u64 vco; + u8 c = 0; + + /* The fractional part of the PLL divider. */ + pcwfbits = pcwbits > 7 ? pcwbits - 7 : 0; + + vco = (u64)fin * pcw; + + if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0))) + c = 1; + + vco >>= pcwfbits; + + if (c) + ++vco; + + return ((unsigned long)vco + postdiv - 1) / postdiv; +} + +static void mtk_pll_set_rate_regs(struct clk_hw *hw, u32 pcw, + int postdiv) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 con1, pd, val; + int pll_en; + + /* set postdiv */ + pd = readl(pll->pd_addr); + pd &= ~(0x7 << pll->data->pd_shift); + pd |= (ffs(postdiv) - 1) << pll->data->pd_shift; + writel(pd, pll->pd_addr); + + pll_en = readl(pll->base_addr) & CON0_BASE_EN; + + /* set pcw */ + val = readl(pll->pcw_addr); + + val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1, + pll->data->pcw_shift); + val |= pcw << pll->data->pcw_shift; + writel(val, pll->pcw_addr); + + con1 = readl(pll->base_addr + 4); + + if (pll_en) + con1 |= CON0_PCW_CHG; + + writel(con1, pll->base_addr + 4); + if (pll->tuner_addr) + writel(con1 + 1, pll->tuner_addr); + + if (pll_en) + usleep_range(20, 1000); +} + +/* + * mtk_pll_calc_values - calculate good values for a given input frequency. + * @pll: The pll + * @pcw: The pcw value (output) + * @postdiv: The post divider (output) + * @freq: The desired target frequency + * @fin: The input frequency + * + */ +static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv, + u32 freq, u32 fin) +{ + unsigned long fmin = 1000 * MHZ; + u64 _pcw; + u32 val; + + if (freq > pll->data->fmax) + freq = pll->data->fmax; + + for (val = 0; val < 4; val++) { + *postdiv = 1 << val; + if (freq * *postdiv >= fmin) + break; + } + + /* _pcw = freq * postdiv / fin * 2^pcwfbits */ + _pcw = ((u64)freq << val) << (pll->data->pcwbits - 7); + do_div(_pcw, fin); + + *pcw = (u32)_pcw; +} + +static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 pcw = 0; + u32 postdiv; + + mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate); + mtk_pll_set_rate_regs(hw, pcw, postdiv); + + return 0; +} + +static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 postdiv; + u32 pcw; + + postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & 0x7; + postdiv = 1 << postdiv; + + pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift; + pcw &= GENMASK(pll->data->pcwbits - 1, 0); + + return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv); +} + +static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 pcw = 0; + int postdiv; + + mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate); + + return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv); +} + +static int mtk_pll_prepare(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + + r = readl(pll->pwr_addr) | CON0_PWR_ON; + writel(r, pll->pwr_addr); + usleep_range(1, 100); + + r = readl(pll->pwr_addr) & ~CON0_ISO_EN; + writel(r, pll->pwr_addr); + usleep_range(1, 100); + + r = readl(pll->base_addr) | pll->data->en_mask; + writel(r, pll->base_addr); + + if (pll->tuner_addr) { + r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN; + writel(r, pll->tuner_addr); + } + + usleep_range(20, 1000); + + if (pll->data->flags & HAVE_RST_BAR) { + r = readl(pll->base_addr) | pll->data->rst_bar_mask; + writel(r, pll->base_addr); + } + + return 0; +} + +static void mtk_pll_unprepare(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + + if (pll->data->flags & HAVE_RST_BAR) { + r = readl(pll->base_addr) & ~pll->data->rst_bar_mask; + writel(r, pll->base_addr); + } + + if (pll->tuner_addr) { + r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN; + writel(r, pll->tuner_addr); + } + + r = readl(pll->base_addr) & ~CON0_BASE_EN; + writel(r, pll->base_addr); + + r = readl(pll->pwr_addr) | CON0_ISO_EN; + writel(r, pll->pwr_addr); + + r = readl(pll->pwr_addr) & ~CON0_PWR_ON; + writel(r, pll->pwr_addr); +} + +static const struct clk_ops mtk_pll_ops = { + .is_prepared = mtk_pll_is_prepared, + .prepare = mtk_pll_prepare, + .unprepare = mtk_pll_unprepare, + .recalc_rate = mtk_pll_recalc_rate, + .round_rate = mtk_pll_round_rate, + .set_rate = mtk_pll_set_rate, +}; + +static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, + void __iomem *base) +{ + struct mtk_clk_pll *pll; + struct clk_init_data init; + struct clk *clk; + const char *parent_name = "clk26m"; + + pr_debug("%s(): name: %s\n", __func__, data->name); + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + pll->base_addr = base + data->reg; + pll->pwr_addr = base + data->pwr_reg; + pll->pd_addr = base + data->pd_reg; + pll->pcw_addr = base + data->pcw_reg; + if (data->tuner_reg) + pll->tuner_addr = base + data->tuner_reg; + pll->hw.init = &init; + pll->data = data; + + init.name = data->name; + init.ops = &mtk_pll_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + + clk = clk_register(NULL, &pll->hw); + + if (IS_ERR(clk)) + kfree(pll); + + return clk; +} + +void __init mtk_clk_register_plls(struct device_node *node, + const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data) +{ + void __iomem *base; + int r, i; + struct clk *clk; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + for (i = 0; i < num_plls; i++) { + const struct mtk_pll_data *pll = &plls[i]; + + clk = mtk_clk_register_pll(pll, base); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %ld\n", + pll->name, PTR_ERR(clk)); + continue; + } + + clk_data->clks[pll->id] = clk; + } + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} -- 2.1.4 ^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2015-03-16 5:55 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-02-22 11:49 [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 Sascha Hauer 2015-02-22 11:49 ` [PATCH 1/5] clk: mediatek: Add initial common clock support for Mediatek SoCs Sascha Hauer 2015-03-13 16:46 ` Matthias Brugger 2015-03-16 5:34 ` Sascha Hauer 2015-02-22 11:49 ` [PATCH 2/5] clk: mediatek: Add reset controller support Sascha Hauer 2015-02-22 11:49 ` [PATCH 3/5] clk: mediatek: Add basic clocks for Mediatek MT8135 Sascha Hauer 2015-03-13 7:44 ` Henry Chen 2015-03-16 5:33 ` Sascha Hauer 2015-03-15 16:27 ` Daniel Kurtz 2015-03-16 5:33 ` Sascha Hauer 2015-02-22 11:49 ` [PATCH 4/5] clk: mediatek: Add basic clocks for Mediatek MT8173 Sascha Hauer 2015-02-22 11:49 ` [PATCH 5/5] dt-bindings: ARM: Mediatek: Document devicetree bindings for clock/reset controllers Sascha Hauer 2015-03-09 6:15 ` [PATCH v6]: clk: Add common clock support for Mediatek MT8135 and MT8173 Sascha Hauer -- strict thread matches above, loose matches on Subject: below -- 2015-03-16 5:55 [PATCH v7]: " Sascha Hauer 2015-03-16 5:55 ` [PATCH 1/5] clk: mediatek: Add initial common clock support for Mediatek SoCs Sascha Hauer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).