clk: mediatek: Add MT2701 clock support
Add MT2701 clock support, include topckgen, apmixedsys, infracfg, pericfg and subsystem clocks. Signed-off-by: Shunli Wang <shunli.wang@mediatek.com> Signed-off-by: James Liao <jamesjj.liao@mediatek.com> Signed-off-by: Erin Lo <erin.lo@mediatek.com> Tested-by: John Crispin <blogic@openwrt.org> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
This commit is contained in:
parent
e0a3862c14
commit
e986211827
|
@ -6,6 +6,49 @@ config COMMON_CLK_MEDIATEK
|
|||
---help---
|
||||
Mediatek SoCs' clock support.
|
||||
|
||||
config COMMON_CLK_MT2701
|
||||
bool "Clock driver for Mediatek MT2701"
|
||||
select COMMON_CLK_MEDIATEK
|
||||
default ARCH_MEDIATEK
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 basic clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_MMSYS
|
||||
bool "Clock driver for Mediatek MT2701 mmsys"
|
||||
select COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 mmsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_IMGSYS
|
||||
bool "Clock driver for Mediatek MT2701 imgsys"
|
||||
select COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 imgsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_VDECSYS
|
||||
bool "Clock driver for Mediatek MT2701 vdecsys"
|
||||
select COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 vdecsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_HIFSYS
|
||||
bool "Clock driver for Mediatek MT2701 hifsys"
|
||||
select COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 hifsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_ETHSYS
|
||||
bool "Clock driver for Mediatek MT2701 ethsys"
|
||||
select COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 ethsys clocks.
|
||||
|
||||
config COMMON_CLK_MT2701_BDPSYS
|
||||
bool "Clock driver for Mediatek MT2701 bdpsys"
|
||||
select COMMON_CLK_MT2701
|
||||
---help---
|
||||
This driver supports Mediatek MT2701 bdpsys clocks.
|
||||
|
||||
config COMMON_CLK_MT8135
|
||||
bool "Clock driver for Mediatek MT8135"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
|
||||
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
|
||||
obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
|
||||
|
|
|
@ -61,6 +61,22 @@ static void mtk_cg_clr_bit(struct clk_hw *hw)
|
|||
regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
|
||||
}
|
||||
|
||||
static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
|
||||
u32 cgbit = BIT(cg->bit);
|
||||
|
||||
regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, cgbit);
|
||||
}
|
||||
|
||||
static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw)
|
||||
{
|
||||
struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
|
||||
u32 cgbit = BIT(cg->bit);
|
||||
|
||||
regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, 0);
|
||||
}
|
||||
|
||||
static int mtk_cg_enable(struct clk_hw *hw)
|
||||
{
|
||||
mtk_cg_clr_bit(hw);
|
||||
|
@ -85,6 +101,30 @@ static void mtk_cg_disable_inv(struct clk_hw *hw)
|
|||
mtk_cg_clr_bit(hw);
|
||||
}
|
||||
|
||||
static int mtk_cg_enable_no_setclr(struct clk_hw *hw)
|
||||
{
|
||||
mtk_cg_clr_bit_no_setclr(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_cg_disable_no_setclr(struct clk_hw *hw)
|
||||
{
|
||||
mtk_cg_set_bit_no_setclr(hw);
|
||||
}
|
||||
|
||||
static int mtk_cg_enable_inv_no_setclr(struct clk_hw *hw)
|
||||
{
|
||||
mtk_cg_set_bit_no_setclr(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw)
|
||||
{
|
||||
mtk_cg_clr_bit_no_setclr(hw);
|
||||
}
|
||||
|
||||
const struct clk_ops mtk_clk_gate_ops_setclr = {
|
||||
.is_enabled = mtk_cg_bit_is_cleared,
|
||||
.enable = mtk_cg_enable,
|
||||
|
@ -97,6 +137,18 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
|
|||
.disable = mtk_cg_disable_inv,
|
||||
};
|
||||
|
||||
const struct clk_ops mtk_clk_gate_ops_no_setclr = {
|
||||
.is_enabled = mtk_cg_bit_is_cleared,
|
||||
.enable = mtk_cg_enable_no_setclr,
|
||||
.disable = mtk_cg_disable_no_setclr,
|
||||
};
|
||||
|
||||
const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = {
|
||||
.is_enabled = mtk_cg_bit_is_set,
|
||||
.enable = mtk_cg_enable_inv_no_setclr,
|
||||
.disable = mtk_cg_disable_inv_no_setclr,
|
||||
};
|
||||
|
||||
struct clk *mtk_clk_register_gate(
|
||||
const char *name,
|
||||
const char *parent_name,
|
||||
|
|
|
@ -36,6 +36,8 @@ static inline struct mtk_clk_gate *to_mtk_clk_gate(struct clk_hw *hw)
|
|||
|
||||
extern const struct clk_ops mtk_clk_gate_ops_setclr;
|
||||
extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
|
||||
extern const struct clk_ops mtk_clk_gate_ops_no_setclr;
|
||||
extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv;
|
||||
|
||||
struct clk *mtk_clk_register_gate(
|
||||
const char *name,
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: Shunli Wang <shunli.wang@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/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2701-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs bdp0_cg_regs = {
|
||||
.set_ofs = 0x0104,
|
||||
.clr_ofs = 0x0108,
|
||||
.sta_ofs = 0x0100,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs bdp1_cg_regs = {
|
||||
.set_ofs = 0x0114,
|
||||
.clr_ofs = 0x0118,
|
||||
.sta_ofs = 0x0110,
|
||||
};
|
||||
|
||||
#define GATE_BDP0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &bdp0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||
}
|
||||
|
||||
#define GATE_BDP1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &bdp1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate bdp_clks[] = {
|
||||
GATE_BDP0(CLK_BDP_BRG_BA, "brg_baclk", "mm_sel", 0),
|
||||
GATE_BDP0(CLK_BDP_BRG_DRAM, "brg_dram", "mm_sel", 1),
|
||||
GATE_BDP0(CLK_BDP_LARB_DRAM, "larb_dram", "mm_sel", 2),
|
||||
GATE_BDP0(CLK_BDP_WR_VDI_PXL, "wr_vdi_pxl", "hdmi_0_deep340m", 3),
|
||||
GATE_BDP0(CLK_BDP_WR_VDI_DRAM, "wr_vdi_dram", "mm_sel", 4),
|
||||
GATE_BDP0(CLK_BDP_WR_B, "wr_bclk", "mm_sel", 5),
|
||||
GATE_BDP0(CLK_BDP_DGI_IN, "dgi_in", "dpi1_sel", 6),
|
||||
GATE_BDP0(CLK_BDP_DGI_OUT, "dgi_out", "dpi1_sel", 7),
|
||||
GATE_BDP0(CLK_BDP_FMT_MAST_27, "fmt_mast_27", "dpi1_sel", 8),
|
||||
GATE_BDP0(CLK_BDP_FMT_B, "fmt_bclk", "mm_sel", 9),
|
||||
GATE_BDP0(CLK_BDP_OSD_B, "osd_bclk", "mm_sel", 10),
|
||||
GATE_BDP0(CLK_BDP_OSD_DRAM, "osd_dram", "mm_sel", 11),
|
||||
GATE_BDP0(CLK_BDP_OSD_AGENT, "osd_agent", "osd_sel", 12),
|
||||
GATE_BDP0(CLK_BDP_OSD_PXL, "osd_pxl", "dpi1_sel", 13),
|
||||
GATE_BDP0(CLK_BDP_RLE_B, "rle_bclk", "mm_sel", 14),
|
||||
GATE_BDP0(CLK_BDP_RLE_AGENT, "rle_agent", "mm_sel", 15),
|
||||
GATE_BDP0(CLK_BDP_RLE_DRAM, "rle_dram", "mm_sel", 16),
|
||||
GATE_BDP0(CLK_BDP_F27M, "f27m", "di_sel", 17),
|
||||
GATE_BDP0(CLK_BDP_F27M_VDOUT, "f27m_vdout", "di_sel", 18),
|
||||
GATE_BDP0(CLK_BDP_F27_74_74, "f27_74_74", "di_sel", 19),
|
||||
GATE_BDP0(CLK_BDP_F2FS, "f2fs", "di_sel", 20),
|
||||
GATE_BDP0(CLK_BDP_F2FS74_148, "f2fs74_148", "di_sel", 21),
|
||||
GATE_BDP0(CLK_BDP_FB, "fbclk", "mm_sel", 22),
|
||||
GATE_BDP0(CLK_BDP_VDO_DRAM, "vdo_dram", "mm_sel", 23),
|
||||
GATE_BDP0(CLK_BDP_VDO_2FS, "vdo_2fs", "di_sel", 24),
|
||||
GATE_BDP0(CLK_BDP_VDO_B, "vdo_bclk", "mm_sel", 25),
|
||||
GATE_BDP0(CLK_BDP_WR_DI_PXL, "wr_di_pxl", "di_sel", 26),
|
||||
GATE_BDP0(CLK_BDP_WR_DI_DRAM, "wr_di_dram", "mm_sel", 27),
|
||||
GATE_BDP0(CLK_BDP_WR_DI_B, "wr_di_bclk", "mm_sel", 28),
|
||||
GATE_BDP0(CLK_BDP_NR_PXL, "nr_pxl", "nr_sel", 29),
|
||||
GATE_BDP0(CLK_BDP_NR_DRAM, "nr_dram", "mm_sel", 30),
|
||||
GATE_BDP0(CLK_BDP_NR_B, "nr_bclk", "mm_sel", 31),
|
||||
GATE_BDP1(CLK_BDP_RX_F, "rx_fclk", "hadds2_fbclk", 0),
|
||||
GATE_BDP1(CLK_BDP_RX_X, "rx_xclk", "clk26m", 1),
|
||||
GATE_BDP1(CLK_BDP_RXPDT, "rxpdtclk", "hdmi_0_pix340m", 2),
|
||||
GATE_BDP1(CLK_BDP_RX_CSCL_N, "rx_cscl_n", "clk26m", 3),
|
||||
GATE_BDP1(CLK_BDP_RX_CSCL, "rx_cscl", "clk26m", 4),
|
||||
GATE_BDP1(CLK_BDP_RX_DDCSCL_N, "rx_ddcscl_n", "hdmi_scl_rx", 5),
|
||||
GATE_BDP1(CLK_BDP_RX_DDCSCL, "rx_ddcscl", "hdmi_scl_rx", 6),
|
||||
GATE_BDP1(CLK_BDP_RX_VCO, "rx_vcoclk", "hadds2pll_294m", 7),
|
||||
GATE_BDP1(CLK_BDP_RX_DP, "rx_dpclk", "hdmi_0_pll340m", 8),
|
||||
GATE_BDP1(CLK_BDP_RX_P, "rx_pclk", "hdmi_0_pll340m", 9),
|
||||
GATE_BDP1(CLK_BDP_RX_M, "rx_mclk", "hadds2pll_294m", 10),
|
||||
GATE_BDP1(CLK_BDP_RX_PLL, "rx_pllclk", "hdmi_0_pix340m", 11),
|
||||
GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12),
|
||||
GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13),
|
||||
GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14),
|
||||
GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15),
|
||||
GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2701_bdp[] = {
|
||||
{ .compatible = "mediatek,mt2701-bdpsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt2701_bdp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_BDP_NR);
|
||||
|
||||
mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt2701_bdp_drv = {
|
||||
.probe = clk_mt2701_bdp_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2701-bdp",
|
||||
.of_match_table = of_match_clk_mt2701_bdp,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2701_bdp_drv);
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: Shunli Wang <shunli.wang@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/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2701-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs eth_cg_regs = {
|
||||
.sta_ofs = 0x0030,
|
||||
};
|
||||
|
||||
#define GATE_ETH(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = ð_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate eth_clks[] = {
|
||||
GATE_ETH(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5),
|
||||
GATE_ETH(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6),
|
||||
GATE_ETH(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7),
|
||||
GATE_ETH(CLK_ETHSYS_GP1, "gp1_clk", "ethpll_500m_ck", 8),
|
||||
GATE_ETH(CLK_ETHSYS_PCM, "pcm_clk", "ethif_sel", 11),
|
||||
GATE_ETH(CLK_ETHSYS_GDMA, "gdma_clk", "ethif_sel", 14),
|
||||
GATE_ETH(CLK_ETHSYS_I2S, "i2s_clk", "ethif_sel", 17),
|
||||
GATE_ETH(CLK_ETHSYS_CRYPTO, "crypto_clk", "ethif_sel", 29),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2701_eth[] = {
|
||||
{ .compatible = "mediatek,mt2701-ethsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt2701_eth_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR);
|
||||
|
||||
mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt2701_eth_drv = {
|
||||
.probe = clk_mt2701_eth_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2701-eth",
|
||||
.of_match_table = of_match_clk_mt2701_eth,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2701_eth_drv);
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: Shunli Wang <shunli.wang@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/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2701-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs hif_cg_regs = {
|
||||
.sta_ofs = 0x0030,
|
||||
};
|
||||
|
||||
#define GATE_HIF(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &hif_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate hif_clks[] = {
|
||||
GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21),
|
||||
GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22),
|
||||
GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24),
|
||||
GATE_HIF(CLK_HIFSYS_PCIE1, "pcie1_clk", "ethpll_500m_ck", 25),
|
||||
GATE_HIF(CLK_HIFSYS_PCIE2, "pcie2_clk", "ethpll_500m_ck", 26),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2701_hif[] = {
|
||||
{ .compatible = "mediatek,mt2701-hifsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt2701_hif_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR);
|
||||
|
||||
mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt2701_hif_drv = {
|
||||
.probe = clk_mt2701_hif_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2701-hif",
|
||||
.of_match_table = of_match_clk_mt2701_hif,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2701_hif_drv);
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: Shunli Wang <shunli.wang@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/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2701-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs img_cg_regs = {
|
||||
.set_ofs = 0x0004,
|
||||
.clr_ofs = 0x0008,
|
||||
.sta_ofs = 0x0000,
|
||||
};
|
||||
|
||||
#define GATE_IMG(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &img_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate img_clks[] = {
|
||||
GATE_IMG(CLK_IMG_SMI_COMM, "img_smi_comm", "mm_sel", 0),
|
||||
GATE_IMG(CLK_IMG_RESZ, "img_resz", "mm_sel", 1),
|
||||
GATE_IMG(CLK_IMG_JPGDEC_SMI, "img_jpgdec_smi", "mm_sel", 5),
|
||||
GATE_IMG(CLK_IMG_JPGDEC, "img_jpgdec", "mm_sel", 6),
|
||||
GATE_IMG(CLK_IMG_VENC_LT, "img_venc_lt", "mm_sel", 8),
|
||||
GATE_IMG(CLK_IMG_VENC, "img_venc", "mm_sel", 9),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2701_img[] = {
|
||||
{ .compatible = "mediatek,mt2701-imgsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt2701_img_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
|
||||
|
||||
mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt2701_img_drv = {
|
||||
.probe = clk_mt2701_img_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2701-img",
|
||||
.of_match_table = of_match_clk_mt2701_img,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2701_img_drv);
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: Shunli Wang <shunli.wang@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/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2701-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs disp0_cg_regs = {
|
||||
.set_ofs = 0x0104,
|
||||
.clr_ofs = 0x0108,
|
||||
.sta_ofs = 0x0100,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs disp1_cg_regs = {
|
||||
.set_ofs = 0x0114,
|
||||
.clr_ofs = 0x0118,
|
||||
.sta_ofs = 0x0110,
|
||||
};
|
||||
|
||||
#define GATE_DISP0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &disp0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
#define GATE_DISP1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &disp1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate mm_clks[] = {
|
||||
GATE_DISP0(CLK_MM_SMI_COMMON, "mm_smi_comm", "mm_sel", 0),
|
||||
GATE_DISP0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
|
||||
GATE_DISP0(CLK_MM_CMDQ, "mm_cmdq", "mm_sel", 2),
|
||||
GATE_DISP0(CLK_MM_MUTEX, "mm_mutex", "mm_sel", 3),
|
||||
GATE_DISP0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 4),
|
||||
GATE_DISP0(CLK_MM_DISP_BLS, "mm_disp_bls", "mm_sel", 5),
|
||||
GATE_DISP0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "mm_sel", 6),
|
||||
GATE_DISP0(CLK_MM_DISP_RDMA, "mm_disp_rdma", "mm_sel", 7),
|
||||
GATE_DISP0(CLK_MM_DISP_OVL, "mm_disp_ovl", "mm_sel", 8),
|
||||
GATE_DISP0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9),
|
||||
GATE_DISP0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "mm_sel", 10),
|
||||
GATE_DISP0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
|
||||
GATE_DISP0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 12),
|
||||
GATE_DISP0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 13),
|
||||
GATE_DISP0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "mm_sel", 14),
|
||||
GATE_DISP0(CLK_MM_MDP_BLS_26M, "mm_mdp_bls_26m", "pwm_sel", 15),
|
||||
GATE_DISP0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 16),
|
||||
GATE_DISP0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 17),
|
||||
GATE_DISP0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 18),
|
||||
GATE_DISP0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
|
||||
GATE_DISP0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 20),
|
||||
GATE_DISP1(CLK_MM_DSI_ENGINE, "mm_dsi_eng", "mm_sel", 0),
|
||||
GATE_DISP1(CLK_MM_DSI_DIG, "mm_dsi_dig", "dsi0_lntc_dsi", 1),
|
||||
GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2),
|
||||
GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3),
|
||||
GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4),
|
||||
GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5),
|
||||
GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6),
|
||||
GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7),
|
||||
GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8),
|
||||
GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9),
|
||||
GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10),
|
||||
GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11),
|
||||
GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2701_mm[] = {
|
||||
{ .compatible = "mediatek,mt2701-mmsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt2701_mm_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_MM_NR);
|
||||
|
||||
mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt2701_mm_drv = {
|
||||
.probe = clk_mt2701_mm_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2701-mm",
|
||||
.of_match_table = of_match_clk_mt2701_mm,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2701_mm_drv);
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 2014 MediaTek Inc.
|
||||
* Author: Shunli Wang <shunli.wang@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/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "clk-mtk.h"
|
||||
#include "clk-gate.h"
|
||||
|
||||
#include <dt-bindings/clock/mt2701-clk.h>
|
||||
|
||||
static const struct mtk_gate_regs vdec0_cg_regs = {
|
||||
.set_ofs = 0x0000,
|
||||
.clr_ofs = 0x0004,
|
||||
.sta_ofs = 0x0000,
|
||||
};
|
||||
|
||||
static const struct mtk_gate_regs vdec1_cg_regs = {
|
||||
.set_ofs = 0x0008,
|
||||
.clr_ofs = 0x000c,
|
||||
.sta_ofs = 0x0008,
|
||||
};
|
||||
|
||||
#define GATE_VDEC0(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &vdec0_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||
}
|
||||
|
||||
#define GATE_VDEC1(_id, _name, _parent, _shift) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.regs = &vdec1_cg_regs, \
|
||||
.shift = _shift, \
|
||||
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||
}
|
||||
|
||||
static const struct mtk_gate vdec_clks[] = {
|
||||
GATE_VDEC0(CLK_VDEC_CKGEN, "vdec_cken", "vdec_sel", 0),
|
||||
GATE_VDEC1(CLK_VDEC_LARB, "vdec_larb_cken", "mm_sel", 0),
|
||||
};
|
||||
|
||||
static const struct of_device_id of_match_clk_mt2701_vdec[] = {
|
||||
{ .compatible = "mediatek,mt2701-vdecsys", },
|
||||
{}
|
||||
};
|
||||
|
||||
static int clk_mt2701_vdec_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
int r;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
|
||||
clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
|
||||
|
||||
mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
|
||||
clk_data);
|
||||
|
||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
if (r)
|
||||
dev_err(&pdev->dev,
|
||||
"could not register clock provider: %s: %d\n",
|
||||
pdev->name, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct platform_driver clk_mt2701_vdec_drv = {
|
||||
.probe = clk_mt2701_vdec_probe,
|
||||
.driver = {
|
||||
.name = "clk-mt2701-vdec",
|
||||
.of_match_table = of_match_clk_mt2701_vdec,
|
||||
},
|
||||
};
|
||||
|
||||
builtin_platform_driver(clk_mt2701_vdec_drv);
|
File diff suppressed because it is too large
Load Diff
|
@ -58,6 +58,9 @@ void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
|
|||
for (i = 0; i < num; i++) {
|
||||
const struct mtk_fixed_clk *rc = &clks[i];
|
||||
|
||||
if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[rc->id]))
|
||||
continue;
|
||||
|
||||
clk = clk_register_fixed_rate(NULL, rc->name, rc->parent, 0,
|
||||
rc->rate);
|
||||
|
||||
|
@ -81,6 +84,9 @@ void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
|
|||
for (i = 0; i < num; i++) {
|
||||
const struct mtk_fixed_factor *ff = &clks[i];
|
||||
|
||||
if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[ff->id]))
|
||||
continue;
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
|
||||
CLK_SET_RATE_PARENT, ff->mult, ff->div);
|
||||
|
||||
|
@ -116,6 +122,9 @@ int mtk_clk_register_gates(struct device_node *node,
|
|||
for (i = 0; i < num; i++) {
|
||||
const struct mtk_gate *gate = &clks[i];
|
||||
|
||||
if (!IS_ERR_OR_NULL(clk_data->clks[gate->id]))
|
||||
continue;
|
||||
|
||||
clk = mtk_clk_register_gate(gate->name, gate->parent_name,
|
||||
regmap,
|
||||
gate->regs->set_ofs,
|
||||
|
@ -232,6 +241,9 @@ void mtk_clk_register_composites(const struct mtk_composite *mcs,
|
|||
for (i = 0; i < num; i++) {
|
||||
const struct mtk_composite *mc = &mcs[i];
|
||||
|
||||
if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mc->id]))
|
||||
continue;
|
||||
|
||||
clk = mtk_clk_register_composite(mc, base, lock);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
|
@ -244,3 +256,31 @@ void mtk_clk_register_composites(const struct mtk_composite *mcs,
|
|||
clk_data->clks[mc->id] = clk;
|
||||
}
|
||||
}
|
||||
|
||||
void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
|
||||
int num, void __iomem *base, spinlock_t *lock,
|
||||
struct clk_onecell_data *clk_data)
|
||||
{
|
||||
struct clk *clk;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
const struct mtk_clk_divider *mcd = &mcds[i];
|
||||
|
||||
if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mcd->id]))
|
||||
continue;
|
||||
|
||||
clk = clk_register_divider(NULL, mcd->name, mcd->parent_name,
|
||||
mcd->flags, base + mcd->div_reg, mcd->div_shift,
|
||||
mcd->div_width, mcd->clk_divider_flags, lock);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("Failed to register clk %s: %ld\n",
|
||||
mcd->name, PTR_ERR(clk));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (clk_data)
|
||||
clk_data->clks[mcd->id] = clk;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,8 @@ struct mtk_composite {
|
|||
* In case the rate change propagation to parent clocks is undesirable,
|
||||
* this macro allows to specify the clock flags manually.
|
||||
*/
|
||||
#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, _flags) { \
|
||||
#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \
|
||||
_gate, _flags) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.mux_reg = _reg, \
|
||||
|
@ -106,7 +107,8 @@ struct mtk_composite {
|
|||
* parent clock by default.
|
||||
*/
|
||||
#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) \
|
||||
MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, CLK_SET_RATE_PARENT)
|
||||
MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \
|
||||
_gate, CLK_SET_RATE_PARENT)
|
||||
|
||||
#define MUX(_id, _name, _parents, _reg, _shift, _width) { \
|
||||
.id = _id, \
|
||||
|
@ -121,7 +123,8 @@ struct mtk_composite {
|
|||
.flags = CLK_SET_RATE_PARENT, \
|
||||
}
|
||||
|
||||
#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) { \
|
||||
#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \
|
||||
_div_width, _div_shift) { \
|
||||
.id = _id, \
|
||||
.parent = _parent, \
|
||||
.name = _name, \
|
||||
|
@ -156,12 +159,40 @@ struct mtk_gate {
|
|||
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);
|
||||
int mtk_clk_register_gates(struct device_node *node,
|
||||
const struct mtk_gate *clks, int num,
|
||||
struct clk_onecell_data *clk_data);
|
||||
|
||||
struct mtk_clk_divider {
|
||||
int id;
|
||||
const char *name;
|
||||
const char *parent_name;
|
||||
unsigned long flags;
|
||||
|
||||
u32 div_reg;
|
||||
unsigned char div_shift;
|
||||
unsigned char div_width;
|
||||
unsigned char clk_divider_flags;
|
||||
const struct clk_div_table *clk_div_table;
|
||||
};
|
||||
|
||||
#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \
|
||||
.id = _id, \
|
||||
.name = _name, \
|
||||
.parent_name = _parent, \
|
||||
.div_reg = _reg, \
|
||||
.div_shift = _shift, \
|
||||
.div_width = _width, \
|
||||
}
|
||||
|
||||
void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
|
||||
int num, void __iomem *base, spinlock_t *lock,
|
||||
struct clk_onecell_data *clk_data);
|
||||
|
||||
struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
|
||||
|
||||
#define HAVE_RST_BAR BIT(0)
|
||||
#define PLL_AO BIT(1)
|
||||
|
||||
struct mtk_pll_div_table {
|
||||
u32 div;
|
||||
|
|
|
@ -301,6 +301,7 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
|
|||
pll->data = data;
|
||||
|
||||
init.name = data->name;
|
||||
init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
|
||||
init.ops = &mtk_pll_ops;
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
|
Loading…
Reference in New Issue