[PATCH v3 2/4] clk: mediatek: Add initial common clock support for Mediatek SoCs.
Matthias Brugger
matthias.bgg at gmail.com
Wed Jan 7 09:22:06 PST 2015
2015-01-07 4:25 GMT+01:00 James Liao <jamesjj.liao at mediatek.com>:
> This patch adds common clock support for Mediatek SoCs, including plls,
> muxes and clock gates.
>
> Change-Id: I19b5f02615610b8825fd7e028bc9b87133181bf0
> Signed-off-by: James Liao <jamesjj.liao at mediatek.com>
> ---
> drivers/clk/mediatek/clk-gate.c | 150 ++++++++++++++++++++++++++++++++++++++++
> drivers/clk/mediatek/clk-gate.h | 48 +++++++++++++
> drivers/clk/mediatek/clk-mtk.c | 89 ++++++++++++++++++++++++
> drivers/clk/mediatek/clk-mtk.h | 47 +++++++++++++
> drivers/clk/mediatek/clk-pll.c | 59 ++++++++++++++++
> drivers/clk/mediatek/clk-pll.h | 50 ++++++++++++++
> 6 files changed, 443 insertions(+)
> 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
> create mode 100644 drivers/clk/mediatek/clk-pll.h
>
> diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c
> new file mode 100644
> index 0000000..2a694b1
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-gate.c
> @@ -0,0 +1,150 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at 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 void cg_set_mask(struct mtk_clk_gate *cg, u32 mask)
Please add mtk_ prefix to all functions generic for the mediatek SoCs.
> +{
> + u32 r;
> +
> + if (cg->flags & CLK_GATE_NO_SETCLR_REG) {
Is the CLK_GATE_NO_SETCLR_REG ever used?
As far as I can see, in this patch set it is not.
> + r = readl_relaxed(cg->sta_addr) | mask;
> + writel_relaxed(r, cg->sta_addr);
> + } else
> + writel_relaxed(mask, cg->set_addr);
> +}
> +
> +static void cg_clr_mask(struct mtk_clk_gate *cg, u32 mask)
> +{
> + u32 r;
> +
> + if (cg->flags & CLK_GATE_NO_SETCLR_REG) {
> + r = readl_relaxed(cg->sta_addr) & ~mask;
> + writel_relaxed(r, cg->sta_addr);
> + } else
> + writel_relaxed(mask, cg->clr_addr);
> +}
> +
> +static int cg_enable(struct clk_hw *hw)
> +{
> + unsigned long flags = 0;
> + struct mtk_clk_gate *cg = to_clk_gate(hw);
> + u32 mask = BIT(cg->bit);
> +
> + pr_debug("%s(): %s, bit: %u\n",
> + __func__, __clk_get_name(hw->clk), cg->bit);
We really need this?
> +
> + mtk_clk_lock(flags);
> +
> + if (cg->flags & CLK_GATE_INVERSE)
> + cg_set_mask(cg, mask);
> + else
> + cg_clr_mask(cg, mask);
> +
> + mtk_clk_unlock(flags);
> +
> + return 0;
> +}
Actually we should use CLK_GATE_SET_TO_DISABLE instead of inventing a
new bit, right?
> +
> +static void cg_disable(struct clk_hw *hw)
> +{
> + unsigned long flags = 0;
> + struct mtk_clk_gate *cg = to_clk_gate(hw);
> + u32 mask = BIT(cg->bit);
> +
> + pr_debug("%s(): %s, bit: %u\n",
> + __func__, __clk_get_name(hw->clk), cg->bit);
We really need this?
> +
> + mtk_clk_lock(flags);
> +
> + if (cg->flags & CLK_GATE_INVERSE)
> + cg_clr_mask(cg, mask);
> + else
> + cg_set_mask(cg, mask);
> +
> + mtk_clk_unlock(flags);
> +}
> +
> +static int cg_is_enabled(struct clk_hw *hw)
> +{
> + struct mtk_clk_gate *cg = to_clk_gate(hw);
> + u32 mask;
> + u32 val;
> + int r;
> +
> + mask = BIT(cg->bit);
> + val = mask & readl(cg->sta_addr);
> +
> + r = (cg->flags & CLK_GATE_INVERSE) ? (val != 0) : (val == 0);
> +
> + pr_debug("%s(): %d, %s, bit[%d]\n",
> + __func__, r, __clk_get_name(hw->clk), (int)cg->bit);
Same here. Please review all debug messages.
> +
> + return r;
> +}
> +
> +static const struct clk_ops mtk_clk_gate_ops = {
> + .is_enabled = cg_is_enabled,
> + .enable = cg_enable,
> + .disable = cg_disable,
> +};
> +
> +struct clk *mtk_clk_register_gate(
> + const char *name,
> + const char *parent_name,
> + void __iomem *set_addr,
> + void __iomem *clr_addr,
> + void __iomem *sta_addr,
> + u8 bit,
> + u32 flags)
> +{
> + struct mtk_clk_gate *cg;
> + struct clk *clk;
> + struct clk_init_data init;
> +
> + pr_debug("%s(): name: %s, bit: %d\n", __func__, name, (int)bit);
> +
> + cg = kzalloc(sizeof(*cg), GFP_KERNEL);
> + if (!cg)
> + return ERR_PTR(-ENOMEM);
> +
> + init.name = name;
> + init.flags = CLK_IGNORE_UNUSED;
> + init.parent_names = parent_name ? &parent_name : NULL;
> + init.num_parents = parent_name ? 1 : 0;
> + init.ops = &mtk_clk_gate_ops;
> +
> + cg->set_addr = set_addr;
> + cg->clr_addr = clr_addr;
> + cg->sta_addr = sta_addr;
> + cg->bit = bit;
> + cg->flags = flags;
> +
> + 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..0d71aad
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-gate.h
> @@ -0,0 +1,48 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at 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
> +
> +/*
> + * This is a private header file. DO NOT include it except clk-*.c.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +
> +struct mtk_clk_gate {
> + struct clk_hw hw;
> + void __iomem *set_addr;
> + void __iomem *clr_addr;
> + void __iomem *sta_addr;
> + u8 bit;
> + u32 flags;
> +};
> +
> +#define to_clk_gate(_hw) container_of(_hw, struct mtk_clk_gate, hw)
> +
> +#define CLK_GATE_INVERSE BIT(0)
> +#define CLK_GATE_NO_SETCLR_REG BIT(1)
> +
> +struct clk *mtk_clk_register_gate(
> + const char *name,
> + const char *parent_name,
> + void __iomem *set_addr,
> + void __iomem *clr_addr,
> + void __iomem *sta_addr,
> + u8 bit,
> + u32 flags);
> +
> +#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..b137ca9
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mtk.c
> @@ -0,0 +1,89 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at 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"
> +
> +static DEFINE_SPINLOCK(clk_ops_lock);
> +
> +spinlock_t *get_mtk_clk_lock(void)
> +{
> + return &clk_ops_lock;
> +}
> +
> +struct clk *mtk_clk_register_mux(
> + const char *name,
> + const char **parent_names,
> + u8 num_parents,
> + void __iomem *base_addr,
> + u8 shift,
> + u8 width,
> + u8 gate_bit)
> +{
> + struct clk *clk;
> + struct clk_mux *mux;
> + struct clk_gate *gate = NULL;
> + struct clk_hw *gate_hw = NULL;
> + const struct clk_ops *gate_ops = NULL;
> + u32 mask = BIT(width) - 1;
> +
> + pr_debug("%s(): name: %s, num_parents: %d, gate_bit: %d\n",
> + __func__, name, (int)num_parents, (int)gate_bit);
> +
> + mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
> + if (!mux)
> + return ERR_PTR(-ENOMEM);
> +
> + mux->reg = base_addr;
> + mux->mask = mask;
> + mux->shift = shift;
> + mux->flags = 0;
> + mux->lock = &clk_ops_lock;
> +
> + if (gate_bit <= MAX_MUX_GATE_BIT) {
> + gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
> + if (!gate) {
> + kfree(mux);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + gate->reg = base_addr;
> + gate->bit_idx = gate_bit;
> + gate->flags = CLK_GATE_SET_TO_DISABLE;
> + gate->lock = &clk_ops_lock;
> +
> + gate_hw = &gate->hw;
> + gate_ops = &clk_gate_ops;
> + }
> +
> + clk = clk_register_composite(NULL, name, parent_names, num_parents,
> + &mux->hw, &clk_mux_ops,
> + NULL, NULL,
> + gate_hw, gate_ops,
> + CLK_IGNORE_UNUSED);
> +
> + if (IS_ERR(clk)) {
> + kfree(gate);
> + kfree(mux);
> + }
> +
> + return clk;
> +}
> diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
> new file mode 100644
> index 0000000..b69245d
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-mtk.h
> @@ -0,0 +1,47 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at 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
> +
> +/*
> + * This is a private header file. DO NOT include it except clk-*.c.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +
> +#define CLK_DEBUG 0
> +#define DUMMY_REG_TEST 0
This defines are not used, delete them.
> +
> +extern spinlock_t *get_mtk_clk_lock(void);
> +
> +#define mtk_clk_lock(flags) spin_lock_irqsave(get_mtk_clk_lock(), flags)
> +#define mtk_clk_unlock(flags) \
> + spin_unlock_irqrestore(get_mtk_clk_lock(), flags)
Please use the spinlock directly without this akward defines.
> +
> +#define MAX_MUX_GATE_BIT 31
> +#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1)
> +
> +struct clk *mtk_clk_register_mux(
> + const char *name,
> + const char **parent_names,
> + u8 num_parents,
> + void __iomem *base_addr,
> + u8 shift,
> + u8 width,
> + u8 gate_bit);
> +
> +#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..c48630b
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-pll.c
> @@ -0,0 +1,59 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at 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/io.h>
> +#include <linux/slab.h>
> +#include <linux/clkdev.h>
> +
> +#include "clk-mtk.h"
> +#include "clk-pll.h"
> +
> +struct clk *mtk_clk_register_pll(
> + const char *name,
> + const char *parent_name,
> + u32 *base_addr,
> + u32 *pwr_addr,
> + u32 en_mask,
> + u32 flags,
> + const struct clk_ops *ops)
> +{
> + struct mtk_clk_pll *pll;
> + struct clk_init_data init;
> + struct clk *clk;
> +
> + pr_debug("%s(): name: %s\n", __func__, name);
> +
> + pll = kzalloc(sizeof(*pll), GFP_KERNEL);
> + if (!pll)
> + return ERR_PTR(-ENOMEM);
> +
> + pll->base_addr = base_addr;
> + pll->pwr_addr = pwr_addr;
> + pll->en_mask = en_mask;
> + pll->flags = flags;
> + pll->hw.init = &init;
> +
> + init.name = name;
> + init.ops = ops;
> + init.flags = CLK_IGNORE_UNUSED;
> + init.parent_names = &parent_name;
> + init.num_parents = 1;
> +
> + clk = clk_register(NULL, &pll->hw);
> +
> + if (IS_ERR(clk))
> + kfree(pll);
> +
> + return clk;
> +}
> diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h
> new file mode 100644
> index 0000000..cb7f335
> --- /dev/null
> +++ b/drivers/clk/mediatek/clk-pll.h
> @@ -0,0 +1,50 @@
> +/*
> + * Copyright (c) 2014 MediaTek Inc.
> + * Author: James Liao <jamesjj.liao at 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_PLL_H
> +#define __DRV_CLK_PLL_H
> +
> +/*
> + * This is a private header file. DO NOT include it except clk-*.c.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +
> +struct mtk_clk_pll {
> + struct clk_hw hw;
> + void __iomem *base_addr;
> + void __iomem *pwr_addr;
> + u32 en_mask;
> + u32 flags;
> +};
> +
> +#define to_mtk_clk_pll(_hw) container_of(_hw, struct mtk_clk_pll, hw)
> +
> +#define HAVE_RST_BAR BIT(0)
> +#define HAVE_PLL_HP BIT(1)
> +#define HAVE_FIX_FRQ BIT(2)
> +#define PLL_AO BIT(3)
> +
> +struct clk *mtk_clk_register_pll(
> + const char *name,
> + const char *parent_name,
> + u32 *base_addr,
> + u32 *pwr_addr,
> + u32 en_mask,
> + u32 flags,
> + const struct clk_ops *ops);
> +
> +#endif /* __DRV_CLK_PLL_H */
> --
> 1.8.1.1.dirty
>
--
motzblog.wordpress.com
More information about the linux-arm-kernel
mailing list