Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b5ca453 authored by Shawn Guo's avatar Shawn Guo
Browse files

Merge tag 'imx-clk-4.7' into imx/dt-clkdep

The i.MX clock update for 4.7:
 - Register SAI clk as shared clocks to support SAI audio on i.MX6SX
 - Add the missing ckil clock for i.MX7
 - Update clk-gate2 and vf610 clock driver to prepare for suspend
   support on VF610
 - Fix DCU clock configurations and add TCON ipg clock to support DRM
   display on VF610
parents f55532a0 69c542e8
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ struct clk_gate2 {
	struct clk_hw hw;
	void __iomem	*reg;
	u8		bit_idx;
	u8		cgr_val;
	u8		flags;
	spinlock_t	*lock;
	unsigned int	*share_count;
@@ -50,7 +51,8 @@ static int clk_gate2_enable(struct clk_hw *hw)
		goto out;

	reg = readl(gate->reg);
	reg |= 3 << gate->bit_idx;
	reg &= ~(3 << gate->bit_idx);
	reg |= gate->cgr_val << gate->bit_idx;
	writel(reg, gate->reg);

out:
@@ -125,7 +127,7 @@ static struct clk_ops clk_gate2_ops = {

struct clk *clk_register_gate2(struct device *dev, const char *name,
		const char *parent_name, unsigned long flags,
		void __iomem *reg, u8 bit_idx,
		void __iomem *reg, u8 bit_idx, u8 cgr_val,
		u8 clk_gate2_flags, spinlock_t *lock,
		unsigned int *share_count)
{
@@ -140,6 +142,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
	/* struct clk_gate2 assignments */
	gate->reg = reg;
	gate->bit_idx = bit_idx;
	gate->cgr_val = cgr_val;
	gate->flags = clk_gate2_flags;
	gate->lock = lock;
	gate->share_count = share_count;
+6 −4
Original line number Diff line number Diff line
@@ -134,6 +134,8 @@ static u32 share_count_esai;
static u32 share_count_ssi1;
static u32 share_count_ssi2;
static u32 share_count_ssi3;
static u32 share_count_sai1;
static u32 share_count_sai2;

static struct clk ** const uart_clks[] __initconst = {
	&clks[IMX6SX_CLK_UART_IPG],
@@ -469,10 +471,10 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
	clks[IMX6SX_CLK_SSI3]         = imx_clk_gate2_shared("ssi3",          "ssi3_podf",  base + 0x7c, 22, &share_count_ssi3);
	clks[IMX6SX_CLK_UART_IPG]     = imx_clk_gate2("uart_ipg",      "ipg",               base + 0x7c, 24);
	clks[IMX6SX_CLK_UART_SERIAL]  = imx_clk_gate2("uart_serial",   "uart_podf",         base + 0x7c, 26);
	clks[IMX6SX_CLK_SAI1_IPG]     = imx_clk_gate2("sai1_ipg",      "ipg",               base + 0x7c, 28);
	clks[IMX6SX_CLK_SAI2_IPG]     = imx_clk_gate2("sai2_ipg",      "ipg",               base + 0x7c, 30);
	clks[IMX6SX_CLK_SAI1]         = imx_clk_gate2("sai1",          "ssi1_podf",         base + 0x7c, 28);
	clks[IMX6SX_CLK_SAI2]         = imx_clk_gate2("sai2",          "ssi2_podf",         base + 0x7c, 30);
	clks[IMX6SX_CLK_SAI1_IPG]     = imx_clk_gate2_shared("sai1_ipg", "ipg",             base + 0x7c, 28, &share_count_sai1);
	clks[IMX6SX_CLK_SAI2_IPG]     = imx_clk_gate2_shared("sai2_ipg", "ipg",             base + 0x7c, 30, &share_count_sai2);
	clks[IMX6SX_CLK_SAI1]         = imx_clk_gate2_shared("sai1",	"ssi1_podf",        base + 0x7c, 28, &share_count_sai1);
	clks[IMX6SX_CLK_SAI2]         = imx_clk_gate2_shared("sai2",	"ssi2_podf",        base + 0x7c, 30, &share_count_sai2);

	/* CCGR6 */
	clks[IMX6SX_CLK_USBOH3]       = imx_clk_gate2("usboh3",        "ipg",               base + 0x80, 0);
+2 −1
Original line number Diff line number Diff line
@@ -342,7 +342,7 @@ static const char *clko1_sel[] = { "osc", "pll_sys_main_clk",

static const char *clko2_sel[] = { "osc", "pll_sys_main_240m_clk",
	"pll_sys_pfd0_392m_clk", "pll_sys_pfd1_166m_clk", "pll_sys_pfd4_clk",
	"pll_audio_main_clk", "pll_video_main_clk", "osc_32k_clk", };
	"pll_audio_main_clk", "pll_video_main_clk", "ckil", };

static const char *lvds1_sel[] = { "pll_arm_main_clk",
	"pll_sys_main_clk", "pll_sys_pfd0_392m_clk", "pll_sys_pfd1_332m_clk",
@@ -382,6 +382,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)

	clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
	clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc");
	clks[IMX7D_CKIL] = of_clk_get_by_name(ccm_node, "ckil");

	np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop");
	base = of_iomap(np, 0);
+58 −2
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@

#include <linux/of_address.h>
#include <linux/clk.h>
#include <linux/syscore_ops.h>
#include <dt-bindings/clock/vf610-clock.h>

#include "clk.h"
@@ -40,6 +41,7 @@
#define CCM_CCGR9		(ccm_base + 0x64)
#define CCM_CCGR10		(ccm_base + 0x68)
#define CCM_CCGR11		(ccm_base + 0x6c)
#define CCM_CCGRx(x)		(CCM_CCGR0 + (x) * 4)
#define CCM_CMEOR0		(ccm_base + 0x70)
#define CCM_CMEOR1		(ccm_base + 0x74)
#define CCM_CMEOR2		(ccm_base + 0x78)
@@ -115,10 +117,19 @@ static struct clk_div_table pll4_audio_div_table[] = {
static struct clk *clk[VF610_CLK_END];
static struct clk_onecell_data clk_data;

static u32 cscmr1;
static u32 cscmr2;
static u32 cscdr1;
static u32 cscdr2;
static u32 cscdr3;
static u32 ccgr[12];

static unsigned int const clks_init_on[] __initconst = {
	VF610_CLK_SYS_BUS,
	VF610_CLK_DDR_SEL,
	VF610_CLK_DAP,
	VF610_CLK_DDRMC,
	VF610_CLK_WKPU,
};

static struct clk * __init vf610_get_fixed_clock(
@@ -132,6 +143,43 @@ static struct clk * __init vf610_get_fixed_clock(
	return clk;
};

static int vf610_clk_suspend(void)
{
	int i;

	cscmr1 = readl_relaxed(CCM_CSCMR1);
	cscmr2 = readl_relaxed(CCM_CSCMR2);

	cscdr1 = readl_relaxed(CCM_CSCDR1);
	cscdr2 = readl_relaxed(CCM_CSCDR2);
	cscdr3 = readl_relaxed(CCM_CSCDR3);

	for (i = 0; i < 12; i++)
		ccgr[i] = readl_relaxed(CCM_CCGRx(i));

	return 0;
}

static void vf610_clk_resume(void)
{
	int i;

	writel_relaxed(cscmr1, CCM_CSCMR1);
	writel_relaxed(cscmr2, CCM_CSCMR2);

	writel_relaxed(cscdr1, CCM_CSCDR1);
	writel_relaxed(cscdr2, CCM_CSCDR2);
	writel_relaxed(cscdr3, CCM_CSCDR3);

	for (i = 0; i < 12; i++)
		writel_relaxed(ccgr[i], CCM_CCGRx(i));
}

static struct syscore_ops vf610_clk_syscore_ops = {
	.suspend = vf610_clk_suspend,
	.resume = vf610_clk_resume,
};

static void __init vf610_clocks_init(struct device_node *ccm_node)
{
	struct device_node *np;
@@ -233,6 +281,9 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
	clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_audio_div", "pll4_audio", 0, CCM_CACRR, 6, 3, 0, pll4_audio_div_table, &imx_ccm_lock);
	clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_video_div", "pll6_video", CCM_CACRR, 21, 1);

	clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc", "ddr_sel", CCM_CCGR6, CCM_CCGRx_CGn(14), 0x2);
	clk[VF610_CLK_WKPU] = imx_clk_gate2_cgr("wkpu", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(10), 0x2);

	clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_usb_otg", PLL3_CTRL, 6);
	clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_usb_host", PLL7_CTRL, 6);

@@ -321,11 +372,14 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
	clk[VF610_CLK_DCU0_SEL] = imx_clk_mux("dcu0_sel", CCM_CSCMR1, 28, 1, dcu_sels, 2);
	clk[VF610_CLK_DCU0_EN] = imx_clk_gate("dcu0_en", "dcu0_sel", CCM_CSCDR3, 19);
	clk[VF610_CLK_DCU0_DIV] = imx_clk_divider("dcu0_div", "dcu0_en", CCM_CSCDR3, 16, 3);
	clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "dcu0_div", CCM_CCGR3, CCM_CCGRx_CGn(8));
	clk[VF610_CLK_DCU0] = imx_clk_gate2("dcu0", "ipg_bus", CCM_CCGR3, CCM_CCGRx_CGn(8));
	clk[VF610_CLK_DCU1_SEL] = imx_clk_mux("dcu1_sel", CCM_CSCMR1, 29, 1, dcu_sels, 2);
	clk[VF610_CLK_DCU1_EN] = imx_clk_gate("dcu1_en", "dcu1_sel", CCM_CSCDR3, 23);
	clk[VF610_CLK_DCU1_DIV] = imx_clk_divider("dcu1_div", "dcu1_en", CCM_CSCDR3, 20, 3);
	clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "dcu1_div", CCM_CCGR9, CCM_CCGRx_CGn(8));
	clk[VF610_CLK_DCU1] = imx_clk_gate2("dcu1", "ipg_bus", CCM_CCGR9, CCM_CCGRx_CGn(8));

	clk[VF610_CLK_TCON0] = imx_clk_gate2("tcon0", "platform_bus", CCM_CCGR1, CCM_CCGRx_CGn(13));
	clk[VF610_CLK_TCON1] = imx_clk_gate2("tcon1", "platform_bus", CCM_CCGR7, CCM_CCGRx_CGn(13));

	clk[VF610_CLK_ESAI_SEL] = imx_clk_mux("esai_sel", CCM_CSCMR1, 20, 2, esai_sels, 4);
	clk[VF610_CLK_ESAI_EN] = imx_clk_gate("esai_en", "esai_sel", CCM_CSCDR2, 30);
@@ -409,6 +463,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
		clk_prepare_enable(clk[clks_init_on[i]]);

	register_syscore_ops(&vf610_clk_syscore_ops);

	/* Add the clocks to provider list */
	clk_data.clks = clk;
	clk_data.clk_num = ARRAY_SIZE(clk);
+10 −3
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,

struct clk *clk_register_gate2(struct device *dev, const char *name,
		const char *parent_name, unsigned long flags,
		void __iomem *reg, u8 bit_idx,
		void __iomem *reg, u8 bit_idx, u8 cgr_val,
		u8 clk_gate_flags, spinlock_t *lock,
		unsigned int *share_count);

@@ -55,7 +55,7 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
		void __iomem *reg, u8 shift)
{
	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
			shift, 0, &imx_ccm_lock, NULL);
			shift, 0x3, 0, &imx_ccm_lock, NULL);
}

static inline struct clk *imx_clk_gate2_shared(const char *name,
@@ -63,7 +63,14 @@ static inline struct clk *imx_clk_gate2_shared(const char *name,
		unsigned int *share_count)
{
	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
			shift, 0, &imx_ccm_lock, share_count);
			shift, 0x3, 0, &imx_ccm_lock, share_count);
}

static inline struct clk *imx_clk_gate2_cgr(const char *name, const char *parent,
		void __iomem *reg, u8 shift, u8 cgr_val)
{
	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
			shift, cgr_val, 0, &imx_ccm_lock, NULL);
}

struct clk *imx_clk_pfd(const char *name, const char *parent_name,
Loading