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

Commit 88b1988e authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge branch 'mxs/clk' of git://git.linaro.org/people/shawnguo/linux-2.6 into next/soc

* 'mxs/clk' of git://git.linaro.org/people/shawnguo/linux-2.6:
  ARM: mxs: Use a proper timeout mechanism
  ARM: mx28: check for gated clocks when setting saif divider
  arm/mxs: Add support for SSP/MMC ports 2 & 3
parents afd96f83 444a7c3b
Loading
Loading
Loading
Loading
+5 −29
Original line number Original line Diff line number Diff line
@@ -223,7 +223,6 @@ static int cpu_clk_set_rate(struct clk *clk, unsigned long rate)
{
{
	u32 reg, bm_busy, div_max, d, f, div, frac;
	u32 reg, bm_busy, div_max, d, f, div, frac;
	unsigned long diff, parent_rate, calc_rate;
	unsigned long diff, parent_rate, calc_rate;
	int i;


	parent_rate = clk_get_rate(clk->parent);
	parent_rate = clk_get_rate(clk->parent);


@@ -275,14 +274,7 @@ static int cpu_clk_set_rate(struct clk *clk, unsigned long rate)
	reg |= div << BP_CLKCTRL_CPU_DIV_CPU;
	reg |= div << BP_CLKCTRL_CPU_DIV_CPU;
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU);
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU);


	for (i = 10000; i; i--)
	mxs_clkctrl_timeout(HW_CLKCTRL_CPU, bm_busy);
		if (!(__raw_readl(CLKCTRL_BASE_ADDR +
					HW_CLKCTRL_CPU) & bm_busy))
			break;
	if (!i)	{
		pr_err("%s: divider writing timeout\n", __func__);
		return -ETIMEDOUT;
	}


	return 0;
	return 0;
}
}
@@ -292,7 +284,6 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
{									\
{									\
	u32 reg, div_max, div;						\
	u32 reg, div_max, div;						\
	unsigned long parent_rate;					\
	unsigned long parent_rate;					\
	int i;								\
									\
									\
	parent_rate = clk_get_rate(clk->parent);			\
	parent_rate = clk_get_rate(clk->parent);			\
	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
@@ -310,15 +301,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
	}								\
	}								\
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
									\
									\
	for (i = 10000; i; i--)						\
	mxs_clkctrl_timeout(HW_CLKCTRL_##dr, BM_CLKCTRL_##dr##_BUSY);	\
		if (!(__raw_readl(CLKCTRL_BASE_ADDR +			\
			HW_CLKCTRL_##dr) & BM_CLKCTRL_##dr##_BUSY))	\
			break;						\
	if (!i)	{							\
		pr_err("%s: divider writing timeout\n", __func__);	\
		return -ETIMEDOUT;					\
	}								\
									\
	return 0;							\
	return 0;							\
}
}


@@ -461,7 +444,7 @@ static struct clk_lookup lookups[] = {
static int clk_misc_init(void)
static int clk_misc_init(void)
{
{
	u32 reg;
	u32 reg;
	int i;
	int ret;


	/* Fix up parent per register setting */
	/* Fix up parent per register setting */
	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
@@ -510,14 +493,7 @@ static int clk_misc_init(void)
	reg |= 3 << BP_CLKCTRL_HBUS_DIV;
	reg |= 3 << BP_CLKCTRL_HBUS_DIV;
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);


	for (i = 10000; i; i--)
	ret = mxs_clkctrl_timeout(HW_CLKCTRL_HBUS, BM_CLKCTRL_HBUS_BUSY);
		if (!(__raw_readl(CLKCTRL_BASE_ADDR +
			HW_CLKCTRL_HBUS) & BM_CLKCTRL_HBUS_BUSY))
			break;
	if (!i) {
		pr_err("%s: divider writing timeout\n", __func__);
		return -ETIMEDOUT;
	}


	/* Gate off cpu clock in WFI for power saving */
	/* Gate off cpu clock in WFI for power saving */
	__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
	__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
@@ -532,7 +508,7 @@ static int clk_misc_init(void)
	reg |= 30 << BP_CLKCTRL_FRAC_IOFRAC;
	reg |= 30 << BP_CLKCTRL_FRAC_IOFRAC;
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);


	return 0;
	return ret;
}
}


int __init mx23_clocks_init(void)
int __init mx23_clocks_init(void)
+14 −43
Original line number Original line Diff line number Diff line
@@ -322,7 +322,6 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
{									\
{									\
	u32 reg, bm_busy, div_max, d, f, div, frac;			\
	u32 reg, bm_busy, div_max, d, f, div, frac;			\
	unsigned long diff, parent_rate, calc_rate;			\
	unsigned long diff, parent_rate, calc_rate;			\
	int i;								\
									\
									\
	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
	bm_busy = BM_CLKCTRL_##dr##_BUSY;				\
	bm_busy = BM_CLKCTRL_##dr##_BUSY;				\
@@ -396,16 +395,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
	}								\
	}								\
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
									\
									\
	for (i = 10000; i; i--)						\
	return mxs_clkctrl_timeout(HW_CLKCTRL_##dr, bm_busy);		\
		if (!(__raw_readl(CLKCTRL_BASE_ADDR +			\
			HW_CLKCTRL_##dr) & bm_busy))			\
			break;						\
	if (!i)	{							\
		pr_err("%s: divider writing timeout\n", __func__);	\
		return -ETIMEDOUT;					\
	}								\
									\
	return 0;							\
}
}


_CLK_SET_RATE(cpu_clk, CPU, FRAC0, CPU)
_CLK_SET_RATE(cpu_clk, CPU, FRAC0, CPU)
@@ -421,7 +411,6 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
{									\
{									\
	u32 reg, div_max, div;						\
	u32 reg, div_max, div;						\
	unsigned long parent_rate;					\
	unsigned long parent_rate;					\
	int i;								\
									\
									\
	parent_rate = clk_get_rate(clk->parent);			\
	parent_rate = clk_get_rate(clk->parent);			\
	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
@@ -439,16 +428,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
	}								\
	}								\
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);		\
									\
									\
	for (i = 10000; i; i--)						\
	return mxs_clkctrl_timeout(HW_CLKCTRL_##dr, BM_CLKCTRL_##dr##_BUSY);\
		if (!(__raw_readl(CLKCTRL_BASE_ADDR +			\
			HW_CLKCTRL_##dr) & BM_CLKCTRL_##dr##_BUSY))	\
			break;						\
	if (!i)	{							\
		pr_err("%s: divider writing timeout\n", __func__);	\
		return -ETIMEDOUT;					\
	}								\
									\
	return 0;							\
}
}


_CLK_SET_RATE1(xbus_clk, XBUS)
_CLK_SET_RATE1(xbus_clk, XBUS)
@@ -461,7 +441,6 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
	u32 reg;							\
	u32 reg;							\
	u64 lrate;							\
	u64 lrate;							\
	unsigned long parent_rate;					\
	unsigned long parent_rate;					\
	int i;								\
									\
									\
	parent_rate = clk_get_rate(clk->parent);			\
	parent_rate = clk_get_rate(clk->parent);			\
	if (rate > parent_rate)						\
	if (rate > parent_rate)						\
@@ -477,18 +456,13 @@ static int name##_set_rate(struct clk *clk, unsigned long rate) \
	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs);		\
	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs);		\
	reg &= ~BM_CLKCTRL_##rs##_DIV;					\
	reg &= ~BM_CLKCTRL_##rs##_DIV;					\
	reg |= div << BP_CLKCTRL_##rs##_DIV;				\
	reg |= div << BP_CLKCTRL_##rs##_DIV;				\
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs);		\
	if (reg & (1 << clk->enable_shift)) {				\
									\
		pr_err("%s: clock is gated\n", __func__);		\
	for (i = 10000; i; i--)						\
		return -EINVAL;						\
		if (!(__raw_readl(CLKCTRL_BASE_ADDR +			\
			HW_CLKCTRL_##rs) & BM_CLKCTRL_##rs##_BUSY))	\
			break;						\
	if (!i) {							\
		pr_err("%s: divider writing timeout\n", __func__);	\
		return -ETIMEDOUT;					\
	}								\
	}								\
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_##rs);		\
									\
									\
	return 0;							\
	return mxs_clkctrl_timeout(HW_CLKCTRL_##rs, BM_CLKCTRL_##rs##_BUSY);\
}
}


_CLK_SET_RATE_SAIF(saif0_clk, SAIF0)
_CLK_SET_RATE_SAIF(saif0_clk, SAIF0)
@@ -654,6 +628,8 @@ static struct clk_lookup lookups[] = {
	_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
	_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
	_REGISTER_CLOCK("mxs-mmc.0", NULL, ssp0_clk)
	_REGISTER_CLOCK("mxs-mmc.0", NULL, ssp0_clk)
	_REGISTER_CLOCK("mxs-mmc.1", NULL, ssp1_clk)
	_REGISTER_CLOCK("mxs-mmc.1", NULL, ssp1_clk)
	_REGISTER_CLOCK("mxs-mmc.2", NULL, ssp2_clk)
	_REGISTER_CLOCK("mxs-mmc.3", NULL, ssp3_clk)
	_REGISTER_CLOCK("flexcan.0", NULL, can0_clk)
	_REGISTER_CLOCK("flexcan.0", NULL, can0_clk)
	_REGISTER_CLOCK("flexcan.1", NULL, can1_clk)
	_REGISTER_CLOCK("flexcan.1", NULL, can1_clk)
	_REGISTER_CLOCK(NULL, "usb0", usb0_clk)
	_REGISTER_CLOCK(NULL, "usb0", usb0_clk)
@@ -676,7 +652,7 @@ static struct clk_lookup lookups[] = {
static int clk_misc_init(void)
static int clk_misc_init(void)
{
{
	u32 reg;
	u32 reg;
	int i;
	int ret;


	/* Fix up parent per register setting */
	/* Fix up parent per register setting */
	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ);
@@ -756,14 +732,7 @@ static int clk_misc_init(void)
	reg |= 3 << BP_CLKCTRL_HBUS_DIV;
	reg |= 3 << BP_CLKCTRL_HBUS_DIV;
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_HBUS);


	for (i = 10000; i; i--)
	ret = mxs_clkctrl_timeout(HW_CLKCTRL_HBUS, BM_CLKCTRL_HBUS_ASM_BUSY);
		if (!(__raw_readl(CLKCTRL_BASE_ADDR +
			HW_CLKCTRL_HBUS) & BM_CLKCTRL_HBUS_ASM_BUSY))
			break;
	if (!i) {
		pr_err("%s: divider writing timeout\n", __func__);
		return -ETIMEDOUT;
	}


	/* Gate off cpu clock in WFI for power saving */
	/* Gate off cpu clock in WFI for power saving */
	__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
	__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
@@ -790,7 +759,7 @@ static int clk_misc_init(void)
	reg |= 30 << BP_CLKCTRL_FRAC0_IO0FRAC;
	reg |= 30 << BP_CLKCTRL_FRAC0_IO0FRAC;
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0);
	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0);


	return 0;
	return ret;
}
}


int __init mx28_clocks_init(void)
int __init mx28_clocks_init(void)
@@ -803,6 +772,8 @@ int __init mx28_clocks_init(void)
	 */
	 */
	clk_set_parent(&ssp0_clk, &ref_io0_clk);
	clk_set_parent(&ssp0_clk, &ref_io0_clk);
	clk_set_parent(&ssp1_clk, &ref_io0_clk);
	clk_set_parent(&ssp1_clk, &ref_io0_clk);
	clk_set_parent(&ssp2_clk, &ref_io1_clk);
	clk_set_parent(&ssp3_clk, &ref_io1_clk);


	clk_prepare_enable(&cpu_clk);
	clk_prepare_enable(&cpu_clk);
	clk_prepare_enable(&hbus_clk);
	clk_prepare_enable(&hbus_clk);
+2 −0
Original line number Original line Diff line number Diff line
@@ -41,6 +41,8 @@ const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst = {
const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst = {
const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst = {
	mxs_mxs_mmc_data_entry(MX28, 0, 0),
	mxs_mxs_mmc_data_entry(MX28, 0, 0),
	mxs_mxs_mmc_data_entry(MX28, 1, 1),
	mxs_mxs_mmc_data_entry(MX28, 1, 1),
	mxs_mxs_mmc_data_entry(MX28, 2, 2),
	mxs_mxs_mmc_data_entry(MX28, 3, 3),
};
};
#endif
#endif


+2 −0
Original line number Original line Diff line number Diff line
@@ -31,4 +31,6 @@ extern void mx28_init_irq(void);


extern void icoll_init_irq(void);
extern void icoll_init_irq(void);


extern int mxs_clkctrl_timeout(unsigned int reg_offset, unsigned int mask);

#endif /* __MACH_MXS_COMMON_H__ */
#endif /* __MACH_MXS_COMMON_H__ */
+16 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,8 @@
#define MXS_MODULE_CLKGATE		(1 << 30)
#define MXS_MODULE_CLKGATE		(1 << 30)
#define MXS_MODULE_SFTRST		(1 << 31)
#define MXS_MODULE_SFTRST		(1 << 31)


#define CLKCTRL_TIMEOUT		10	/* 10 ms */

static void __iomem *mxs_clkctrl_reset_addr;
static void __iomem *mxs_clkctrl_reset_addr;


/*
/*
@@ -137,3 +139,17 @@ int mxs_reset_block(void __iomem *reset_addr)
	return -ETIMEDOUT;
	return -ETIMEDOUT;
}
}
EXPORT_SYMBOL(mxs_reset_block);
EXPORT_SYMBOL(mxs_reset_block);

int mxs_clkctrl_timeout(unsigned int reg_offset, unsigned int mask)
{
	unsigned long timeout = jiffies + msecs_to_jiffies(CLKCTRL_TIMEOUT);
	while (readl_relaxed(MXS_IO_ADDRESS(MXS_CLKCTRL_BASE_ADDR)
						+ reg_offset) & mask) {
		if (time_after(jiffies, timeout)) {
			pr_err("Timeout at CLKCTRL + 0x%x\n", reg_offset);
			return -ETIMEDOUT;
		}
	}

	return 0;
}