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

Commit 1a0e8a52 authored by Kukjin Kim's avatar Kukjin Kim Committed by Ben Dooks
Browse files

ARM: S5P6440: Add Clock and PLL support



This patch adds clock and pll support for S5P6440. This patch are based on
Harald Welte's patches and Ben's plat-samsung.

Signed-off-by: default avatarThomas Abraham <thomas.ab@samsung.com>
Signed-off-by: default avatarKukjin Kim <kgene.kim@samsung.com>
Signed-off-by: default avatarBen Dooks <ben-linux@fluff.org>
parent 209fecd1
Loading
Loading
Loading
Loading
+130 −0
Original line number Diff line number Diff line
/* linux/arch/arm/mach-s5p6440/include/mach/regs-clock.h
 *
 * Copyright (c) 2009 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com/
 *
 * S5P6440 - Clock register definitions
 *
 * 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.
*/

#ifndef __ASM_ARCH_REGS_CLOCK_H
#define __ASM_ARCH_REGS_CLOCK_H __FILE__

#include <mach/map.h>

#define S5P_CLKREG(x)		(S5P_VA_CLK + (x))

#define S5P_APLL_LOCK		S5P_CLKREG(0x00)
#define S5P_MPLL_LOCK		S5P_CLKREG(0x04)
#define S5P_EPLL_LOCK		S5P_CLKREG(0x08)
#define S5P_APLL_CON		S5P_CLKREG(0x0C)
#define S5P_MPLL_CON		S5P_CLKREG(0x10)
#define S5P_EPLL_CON		S5P_CLKREG(0x14)
#define S5P_EPLL_CON_K		S5P_CLKREG(0x18)
#define S5P_CLK_SRC0		S5P_CLKREG(0x1C)
#define S5P_CLK_DIV0		S5P_CLKREG(0x20)
#define S5P_CLK_DIV1		S5P_CLKREG(0x24)
#define S5P_CLK_DIV2		S5P_CLKREG(0x28)
#define S5P_CLK_OUT		S5P_CLKREG(0x2C)
#define S5P_CLK_GATE_HCLK0	S5P_CLKREG(0x30)
#define S5P_CLK_GATE_PCLK	S5P_CLKREG(0x34)
#define S5P_CLK_GATE_SCLK0	S5P_CLKREG(0x38)
#define S5P_CLK_GATE_MEM0	S5P_CLKREG(0x3C)
#define S5P_CLK_DIV3		S5P_CLKREG(0x40)
#define S5P_CLK_GATE_HCLK1	S5P_CLKREG(0x44)
#define S5P_CLK_GATE_SCLK1	S5P_CLKREG(0x48)
#define S5P_AHB_CON0           	S5P_CLKREG(0x100)
#define S5P_CLK_SRC1           	S5P_CLKREG(0x10C)
#define S5P_SWRESET		S5P_CLKREG(0x114)
#define S5P_SYS_ID		S5P_CLKREG(0x118)
#define S5P_SYS_OTHERS		S5P_CLKREG(0x11C)
#define S5P_MEM_CFG_STAT	S5P_CLKREG(0x12C)
#define S5P_PWR_CFG		S5P_CLKREG(0x804)
#define S5P_EINT_WAKEUP_MASK	S5P_CLKREG(0x808)
#define S5P_NORMAL_CFG		S5P_CLKREG(0x810)
#define S5P_STOP_CFG		S5P_CLKREG(0x814)
#define S5P_SLEEP_CFG		S5P_CLKREG(0x818)
#define S5P_OSC_FREQ		S5P_CLKREG(0x820)
#define S5P_OSC_STABLE		S5P_CLKREG(0x824)
#define S5P_PWR_STABLE		S5P_CLKREG(0x828)
#define S5P_MTC_STABLE		S5P_CLKREG(0x830)
#define S5P_OTHERS		S5P_CLKREG(0x900)
#define S5P_RST_STAT		S5P_CLKREG(0x904)
#define S5P_WAKEUP_STAT		S5P_CLKREG(0x908)
#define S5P_SLPEN		S5P_CLKREG(0x930)
#define S5P_INFORM0		S5P_CLKREG(0xA00)
#define S5P_INFORM1		S5P_CLKREG(0xA04)
#define S5P_INFORM2		S5P_CLKREG(0xA08)
#define S5P_INFORM3		S5P_CLKREG(0xA0C)

/* CLKDIV0 */
#define S5P_CLKDIV0_PCLK_MASK		(0xf << 12)
#define S5P_CLKDIV0_PCLK_SHIFT		(12)
#define S5P_CLKDIV0_HCLK_MASK		(0xf << 8)
#define S5P_CLKDIV0_HCLK_SHIFT		(8)
#define S5P_CLKDIV0_MPLL_MASK		(0x1 << 4)
#define S5P_CLKDIV0_ARM_MASK		(0xf << 0)
#define S5P_CLKDIV0_ARM_SHIFT		(0)

/* CLKDIV3 */
#define S5P_CLKDIV3_PCLK_LOW_MASK	(0xf << 12)
#define S5P_CLKDIV3_PCLK_LOW_SHIFT	(12)
#define S5P_CLKDIV3_HCLK_LOW_MASK	(0xf << 8)
#define S5P_CLKDIV3_HCLK_LOW_SHIFT	(8)

/* HCLK0 GATE Registers */
#define S5P_CLKCON_HCLK0_USB		(1<<20)
#define S5P_CLKCON_HCLK0_HSMMC2		(1<<19)
#define S5P_CLKCON_HCLK0_HSMMC1		(1<<18)
#define S5P_CLKCON_HCLK0_HSMMC0		(1<<17)
#define S5P_CLKCON_HCLK0_POST0		(1<<5)

/* HCLK1 GATE Registers */
#define S5P_CLKCON_HCLK1_DISPCON	(1<<1)

/* PCLK GATE Registers */
#define S5P_CLKCON_PCLK_IIS2		(1<<26)
#define S5P_CLKCON_PCLK_SPI1		(1<<22)
#define S5P_CLKCON_PCLK_SPI0		(1<<21)
#define S5P_CLKCON_PCLK_GPIO		(1<<18)
#define S5P_CLKCON_PCLK_IIC0		(1<<17)
#define S5P_CLKCON_PCLK_TSADC		(1<<12)
#define S5P_CLKCON_PCLK_PWM		(1<<7)
#define S5P_CLKCON_PCLK_RTC		(1<<6)
#define S5P_CLKCON_PCLK_WDT		(1<<5)
#define S5P_CLKCON_PCLK_UART3		(1<<4)
#define S5P_CLKCON_PCLK_UART2		(1<<3)
#define S5P_CLKCON_PCLK_UART1		(1<<2)
#define S5P_CLKCON_PCLK_UART0		(1<<1)

/* SCLK0 GATE Registers */
#define S5P_CLKCON_SCLK0_MMC2_48	(1<<29)
#define S5P_CLKCON_SCLK0_MMC1_48	(1<<28)
#define S5P_CLKCON_SCLK0_MMC0_48	(1<<27)
#define S5P_CLKCON_SCLK0_MMC2		(1<<26)
#define S5P_CLKCON_SCLK0_MMC1		(1<<25)
#define S5P_CLKCON_SCLK0_MMC0		(1<<24)
#define S5P_CLKCON_SCLK0_SPI1_48 	(1<<23)
#define S5P_CLKCON_SCLK0_SPI0_48 	(1<<22)
#define S5P_CLKCON_SCLK0_SPI1		(1<<21)
#define S5P_CLKCON_SCLK0_SPI0		(1<<20)
#define S5P_CLKCON_SCLK0_UART		(1<<5)

/* SCLK1 GATE Registers */

/* MEM0 GATE Registers */
#define S5P_CLKCON_MEM0_HCLK_NFCON	(1<<2)

/*OTHERS Resgister */
#define S5P_OTHERS_USB_SIG_MASK		(1<<16)
#define S5P_OTHERS_HCLK_LOW_SEL_MPLL	(1<<6)

/* Compatibility defines */
#define ARM_CLK_DIV			S5P_CLK_DIV0
#define ARM_DIV_RATIO_SHIFT		0
#define ARM_DIV_MASK			(0xf << ARM_DIV_RATIO_SHIFT)

#endif /* __ASM_ARCH_REGS_CLOCK_H */
+136 −0
Original line number Diff line number Diff line
/* linux/arch/arm/plat-s5p/clock.c
 *
 * Copyright 2009 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com/
 *
 * S5P - Common clock support
 *
 * 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.
*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/sysdev.h>
#include <linux/io.h>
#include <asm/div64.h>

#include <plat/clock.h>
#include <plat/clock-clksrc.h>
#include <plat/s5p-clock.h>

/* fin_apll, fin_mpll and fin_epll are all the same clock, which we call
 * clk_ext_xtal_mux.
*/
struct clk clk_ext_xtal_mux = {
	.name		= "ext_xtal",
	.id		= -1,
};

/* 48MHz USB Phy clock output */
struct clk clk_48m = {
	.name		= "clk_48m",
	.id		= -1,
	.rate		= 48000000,
};

/* APLL clock output
 * No need .ctrlbit, this is always on
*/
struct clk clk_fout_apll = {
	.name		= "fout_apll",
	.id		= -1,
};

/* MPLL clock output
 * No need .ctrlbit, this is always on
*/
struct clk clk_fout_mpll = {
	.name		= "fout_mpll",
	.id		= -1,
};

/* EPLL clock output */
struct clk clk_fout_epll = {
	.name		= "fout_epll",
	.id		= -1,
	.ctrlbit	= (1 << 31),
};

/* ARM clock */
struct clk clk_arm = {
	.name		= "armclk",
	.id		= -1,
	.rate		= 0,
	.ctrlbit	= 0,
};

/* Possible clock sources for APLL Mux */
static struct clk *clk_src_apll_list[] = {
	[0] = &clk_fin_apll,
	[1] = &clk_fout_apll,
};

struct clksrc_sources clk_src_apll = {
	.sources	= clk_src_apll_list,
	.nr_sources	= ARRAY_SIZE(clk_src_apll_list),
};

/* Possible clock sources for MPLL Mux */
static struct clk *clk_src_mpll_list[] = {
	[0] = &clk_fin_mpll,
	[1] = &clk_fout_mpll,
};

struct clksrc_sources clk_src_mpll = {
	.sources	= clk_src_mpll_list,
	.nr_sources	= ARRAY_SIZE(clk_src_mpll_list),
};

/* Possible clock sources for EPLL Mux */
static struct clk *clk_src_epll_list[] = {
	[0] = &clk_fin_epll,
	[1] = &clk_fout_epll,
};

struct clksrc_sources clk_src_epll = {
	.sources	= clk_src_epll_list,
	.nr_sources	= ARRAY_SIZE(clk_src_epll_list),
};

int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable)
{
	unsigned int ctrlbit = clk->ctrlbit;
	u32 con;

	con = __raw_readl(reg);
	con = enable ? (con | ctrlbit) : (con & ~ctrlbit);
	__raw_writel(con, reg);
	return 0;
}

static struct clk *s5p_clks[] __initdata = {
	&clk_ext_xtal_mux,
	&clk_48m,
	&clk_fout_apll,
	&clk_fout_mpll,
	&clk_fout_epll,
	&clk_arm,
};

void __init s5p_register_clocks(unsigned long xtal_freq)
{
	int ret;

	clk_ext_xtal_mux.rate = xtal_freq;

	ret = s3c24xx_register_clocks(s5p_clks, ARRAY_SIZE(s5p_clks));
	if (ret > 0)
		printk(KERN_ERR "Failed to register s5p clocks\n");
}
+83 −0
Original line number Diff line number Diff line
/* arch/arm/plat-s5p/include/plat/pll.h
 *
 * Copyright (c) 2009 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com/
 *
 * S5P PLL code
 *
 * Based on arch/arm/plat-s3c64xx/include/plat/pll.h
 *
 * 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.
*/

#define PLL45XX_MDIV_MASK	(0x3FF)
#define PLL45XX_PDIV_MASK	(0x3F)
#define PLL45XX_SDIV_MASK	(0x7)
#define PLL45XX_MDIV_SHIFT	(16)
#define PLL45XX_PDIV_SHIFT	(8)
#define PLL45XX_SDIV_SHIFT	(0)

#include <asm/div64.h>

enum pll45xx_type_t {
	pll_4500,
	pll_4502,
	pll_4508
};

static inline unsigned long s5p_get_pll45xx(unsigned long baseclk, u32 pll_con,
					    enum pll45xx_type_t pll_type)
{
	u32 mdiv, pdiv, sdiv;
	u64 fvco = baseclk;

	mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
	pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
	sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;

	if (pll_type == pll_4508)
		sdiv = sdiv - 1;

	fvco *= mdiv;
	do_div(fvco, (pdiv << sdiv));

	return (unsigned long)fvco;
}

#define PLL90XX_MDIV_MASK	(0xFF)
#define PLL90XX_PDIV_MASK	(0x3F)
#define PLL90XX_SDIV_MASK	(0x7)
#define PLL90XX_KDIV_MASK	(0xffff)
#define PLL90XX_MDIV_SHIFT	(16)
#define PLL90XX_PDIV_SHIFT	(8)
#define PLL90XX_SDIV_SHIFT	(0)
#define PLL90XX_KDIV_SHIFT	(0)

static inline unsigned long s5p_get_pll90xx(unsigned long baseclk,
					    u32 pll_con, u32 pll_conk)
{
	unsigned long result;
	u32 mdiv, pdiv, sdiv, kdiv;
	u64 tmp;

	mdiv = (pll_con >> PLL90XX_MDIV_SHIFT) & PLL90XX_MDIV_MASK;
	pdiv = (pll_con >> PLL90XX_PDIV_SHIFT) & PLL90XX_PDIV_MASK;
	sdiv = (pll_con >> PLL90XX_SDIV_SHIFT) & PLL90XX_SDIV_MASK;
	kdiv = pll_conk & PLL90XX_KDIV_MASK;

	/* We need to multiple baseclk by mdiv (the integer part) and kdiv
	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
	 * add kdiv before multiplying. The use of tmp is to avoid any
	 * overflows before shifting bac down into result when multipling
	 * by the mdiv and kdiv pair.
	 */

	tmp = baseclk;
	tmp *= (mdiv << 16) + kdiv;
	do_div(tmp, (pdiv << sdiv));
	result = tmp >> 16;

	return result;
}
+38 −0
Original line number Diff line number Diff line
/* linux/arch/arm/plat-s5p/include/plat/s5p-clock.h
 *
 * Copyright 2009 Samsung Electronics Co., Ltd.
 *		http://www.samsung.com/
 *
 * Header file for s5p clock support
 *
 * 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.
*/

#ifndef __ASM_PLAT_S5P_CLOCK_H
#define __ASM_PLAT_S5P_CLOCK_H __FILE__

#include <linux/clk.h>

#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)

#define clk_fin_apll clk_ext_xtal_mux
#define clk_fin_mpll clk_ext_xtal_mux
#define clk_fin_epll clk_ext_xtal_mux

extern struct clk clk_ext_xtal_mux;
extern struct clk clk_48m;
extern struct clk clk_fout_apll;
extern struct clk clk_fout_mpll;
extern struct clk clk_fout_epll;
extern struct clk clk_arm;

extern struct clksrc_sources clk_src_apll;
extern struct clksrc_sources clk_src_mpll;
extern struct clksrc_sources clk_src_epll;

extern int s5p6440_clk48m_ctrl(struct clk *clk, int enable);
extern int s5p_gatectrl(void __iomem *reg, struct clk *clk, int enable);

#endif /* __ASM_PLAT_S5P_CLOCK_H */
+698 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading