| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 | /* linux/arch/arm/mach-s5pv210/clock.c * * Copyright (c) 2010 Samsung Electronics Co., Ltd. *		http://www.samsung.com/ * * S5PV210 - 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/device.h>#include <linux/io.h>#include <mach/map.h>#include <plat/cpu-freq.h>#include <mach/regs-clock.h>#include <plat/clock.h>#include <plat/cpu.h>#include <plat/pll.h>#include <plat/s5p-clock.h>#include <plat/clock-clksrc.h>#include "common.h"static unsigned long xtal;static struct clksrc_clk clk_mout_apll = {	.clk	= {		.name		= "mout_apll",	},	.sources	= &clk_src_apll,	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },};static struct clksrc_clk clk_mout_epll = {	.clk	= {		.name		= "mout_epll",	},	.sources	= &clk_src_epll,	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 },};static struct clksrc_clk clk_mout_mpll = {	.clk = {		.name		= "mout_mpll",	},	.sources	= &clk_src_mpll,	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 },};static struct clk *clkset_armclk_list[] = {	[0] = &clk_mout_apll.clk,	[1] = &clk_mout_mpll.clk,};static struct clksrc_sources clkset_armclk = {	.sources	= clkset_armclk_list,	.nr_sources	= ARRAY_SIZE(clkset_armclk_list),};static struct clksrc_clk clk_armclk = {	.clk	= {		.name		= "armclk",	},	.sources	= &clkset_armclk,	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 },	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 0, .size = 3 },};static struct clksrc_clk clk_hclk_msys = {	.clk	= {		.name		= "hclk_msys",		.parent		= &clk_armclk.clk,	},	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 },};static struct clksrc_clk clk_pclk_msys = {	.clk	= {		.name		= "pclk_msys",		.parent		= &clk_hclk_msys.clk,	},	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 },};static struct clksrc_clk clk_sclk_a2m = {	.clk	= {		.name		= "sclk_a2m",		.parent		= &clk_mout_apll.clk,	},	.reg_div	= { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 },};static struct clk *clkset_hclk_sys_list[] = {	[0] = &clk_mout_mpll.clk,	[1] = &clk_sclk_a2m.clk,};static struct clksrc_sources clkset_hclk_sys = {	.sources	= clkset_hclk_sys_list,	.nr_sources	= ARRAY_SIZE(clkset_hclk_sys_list),};static struct clksrc_clk clk_hclk_dsys = {	.clk	= {		.name	= "hclk_dsys",	},	.sources	= &clkset_hclk_sys,	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 },	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 4 },};static struct clksrc_clk clk_pclk_dsys = {	.clk	= {		.name	= "pclk_dsys",		.parent	= &clk_hclk_dsys.clk,	},	.reg_div = { .reg = S5P_CLK_DIV0, .shift = 20, .size = 3 },};static struct clksrc_clk clk_hclk_psys = {	.clk	= {		.name	= "hclk_psys",	},	.sources	= &clkset_hclk_sys,	.reg_src        = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 },	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 24, .size = 4 },};static struct clksrc_clk clk_pclk_psys = {	.clk	= {		.name	= "pclk_psys",		.parent	= &clk_hclk_psys.clk,	},	.reg_div        = { .reg = S5P_CLK_DIV0, .shift = 28, .size = 3 },};static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable){	return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable);}static int s5pv210_clk_ip1_ctrl(struct clk *clk, int enable){	return s5p_gatectrl(S5P_CLKGATE_IP1, clk, enable);}static int s5pv210_clk_ip2_ctrl(struct clk *clk, int enable){	return s5p_gatectrl(S5P_CLKGATE_IP2, clk, enable);}static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable){	return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable);}static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable){	return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable);}static int s5pv210_clk_mask1_ctrl(struct clk *clk, int enable){	return s5p_gatectrl(S5P_CLK_SRC_MASK1, clk, enable);}static int s5pv210_clk_hdmiphy_ctrl(struct clk *clk, int enable){	return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);}static int exynos4_clk_dac_ctrl(struct clk *clk, int enable){	return s5p_gatectrl(S5P_DAC_PHY_CONTROL, clk, enable);}static struct clk clk_sclk_hdmi27m = {	.name		= "sclk_hdmi27m",	.rate		= 27000000,};static struct clk clk_sclk_hdmiphy = {	.name		= "sclk_hdmiphy",};static struct clk clk_sclk_usbphy0 = {	.name		= "sclk_usbphy0",};static struct clk clk_sclk_usbphy1 = {	.name		= "sclk_usbphy1",};static struct clk clk_pcmcdclk0 = {	.name		= "pcmcdclk",};static struct clk clk_pcmcdclk1 = {	.name		= "pcmcdclk",};static struct clk clk_pcmcdclk2 = {	.name		= "pcmcdclk",};static struct clk dummy_apb_pclk = {	.name		= "apb_pclk",	.id		= -1,};static struct clk *clkset_vpllsrc_list[] = {	[0] = &clk_fin_vpll,	[1] = &clk_sclk_hdmi27m,};static struct clksrc_sources clkset_vpllsrc = {	.sources	= clkset_vpllsrc_list,	.nr_sources	= ARRAY_SIZE(clkset_vpllsrc_list),};static struct clksrc_clk clk_vpllsrc = {	.clk	= {		.name		= "vpll_src",		.enable		= s5pv210_clk_mask0_ctrl,		.ctrlbit	= (1 << 7),	},	.sources	= &clkset_vpllsrc,	.reg_src	= { .reg = S5P_CLK_SRC1, .shift = 28, .size = 1 },};static struct clk *clkset_sclk_vpll_list[] = {	[0] = &clk_vpllsrc.clk,	[1] = &clk_fout_vpll,};static struct clksrc_sources clkset_sclk_vpll = {	.sources	= clkset_sclk_vpll_list,	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),};static struct clksrc_clk clk_sclk_vpll = {	.clk	= {		.name		= "sclk_vpll",	},	.sources	= &clkset_sclk_vpll,	.reg_src	= { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 },};static struct clk *clkset_moutdmc0src_list[] = {	[0] = &clk_sclk_a2m.clk,	[1] = &clk_mout_mpll.clk,	[2] = NULL,	[3] = NULL,};static struct clksrc_sources clkset_moutdmc0src = {	.sources	= clkset_moutdmc0src_list,	.nr_sources	= ARRAY_SIZE(clkset_moutdmc0src_list),};static struct clksrc_clk clk_mout_dmc0 = {	.clk	= {		.name		= "mout_dmc0",	},	.sources	= &clkset_moutdmc0src,	.reg_src	= { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 },};static struct clksrc_clk clk_sclk_dmc0 = {	.clk	= {		.name		= "sclk_dmc0",		.parent		= &clk_mout_dmc0.clk,	},	.reg_div	= { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 },};static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk){	return clk_get_rate(clk->parent) / 2;}static struct clk_ops clk_hclk_imem_ops = {	.get_rate	= s5pv210_clk_imem_get_rate,};static unsigned long s5pv210_clk_fout_apll_get_rate(struct clk *clk){	return s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508);}static struct clk_ops clk_fout_apll_ops = {	.get_rate	= s5pv210_clk_fout_apll_get_rate,};static struct clk init_clocks_off[] = {	{		.name		= "dma",		.devname	= "dma-pl330.0",		.parent		= &clk_hclk_psys.clk,		.enable		= s5pv210_clk_ip0_ctrl,		.ctrlbit	= (1 << 3),	}, {		.name		= "dma",		.devname	= "dma-pl330.1",		.parent		= &clk_hclk_psys.clk,		.enable		= s5pv210_clk_ip0_ctrl,		.ctrlbit	= (1 << 4),	}, {		.name		= "rot",		.parent		= &clk_hclk_dsys.clk,		.enable		= s5pv210_clk_ip0_ctrl,		.ctrlbit	= (1<<29),	}, {		.name		= "fimc",		.devname	= "s5pv210-fimc.0",		.parent		= &clk_hclk_dsys.clk,		.enable		= s5pv210_clk_ip0_ctrl,		.ctrlbit	= (1 << 24),	}, {		.name		= "fimc",		.devname	= "s5pv210-fimc.1",		.parent		= &clk_hclk_dsys.clk,		.enable		= s5pv210_clk_ip0_ctrl,		.ctrlbit	= (1 << 25),	}, {		.name		= "fimc",		.devname	= "s5pv210-fimc.2",		.parent		= &clk_hclk_dsys.clk,		.enable		= s5pv210_clk_ip0_ctrl,		.ctrlbit	= (1 << 26),	}, {		.name		= "jpeg",		.parent		= &clk_hclk_dsys.clk,		.enable		= s5pv210_clk_ip0_ctrl,		.ctrlbit	= (1 << 28),	}, {		.name		= "mfc",		.devname	= "s5p-mfc",		.parent		= &clk_pclk_psys.clk,		.enable		= s5pv210_clk_ip0_ctrl,		.ctrlbit	= (1 << 16),	}, {		.name		= "dac",		.devname	= "s5p-sdo",		.parent		= &clk_hclk_dsys.clk,		.enable		= s5pv210_clk_ip1_ctrl,		.ctrlbit	= (1 << 10),	}, {		.name		= "mixer",		.devname	= "s5p-mixer",		.parent		= &clk_hclk_dsys.clk,		.enable		= s5pv210_clk_ip1_ctrl,		.ctrlbit	= (1 << 9),	}, {		.name		= "vp",		.devname	= "s5p-mixer",		.parent		= &clk_hclk_dsys.clk,		.enable		= s5pv210_clk_ip1_ctrl,		.ctrlbit	= (1 << 8),	}, {		.name		= "hdmi",		.devname	= "s5pv210-hdmi",		.parent		= &clk_hclk_dsys.clk,		.enable		= s5pv210_clk_ip1_ctrl,		.ctrlbit	= (1 << 11),	}, {		.name		= "hdmiphy",		.devname	= "s5pv210-hdmi",		.enable		= s5pv210_clk_hdmiphy_ctrl,		.ctrlbit	= (1 << 0),	}, {		.name		= "dacphy",		.devname	= "s5p-sdo",		.enable		= exynos4_clk_dac_ctrl,		.ctrlbit	= (1 << 0),	}, {		.name		= "otg",		.parent		= &clk_hclk_psys.clk,		.enable		= s5pv210_clk_ip1_ctrl,		.ctrlbit	= (1<<16),	}, {		.name		= "usb-host",		.parent		= &clk_hclk_psys.clk,		.enable		= s5pv210_clk_ip1_ctrl,		.ctrlbit	= (1<<17),	}, {		.name		= "lcd",		.parent		= &clk_hclk_dsys.clk,		.enable		= s5pv210_clk_ip1_ctrl,		.ctrlbit	= (1<<0),	}, {		.name		= "cfcon",		.parent		= &clk_hclk_psys.clk,		.enable		= s5pv210_clk_ip1_ctrl,		.ctrlbit	= (1<<25),	}, {		.name		= "systimer",		.parent		= &clk_pclk_psys.clk,		.enable		= s5pv210_clk_ip3_ctrl,		.ctrlbit	= (1<<16),	}, {		.name		= "watchdog",		.parent		= &clk_pclk_psys.clk,		.enable		= s5pv210_clk_ip3_ctrl,		.ctrlbit	= (1<<22),	}, {		.name		= "rtc",		.parent		= &clk_pclk_psys.clk,		.enable		= s5pv210_clk_ip3_ctrl,		.ctrlbit	= (1<<15),	}, {		.name		= "i2c",		.devname	= "s3c2440-i2c.0",		.parent		= &clk_pclk_psys.clk,		.enable		= s5pv210_clk_ip3_ctrl,		.ctrlbit	= (1<<7),	}, {		.name		= "i2c",		.devname	= "s3c2440-i2c.1",		.parent		= &clk_pclk_psys.clk,		.enable		= s5pv210_clk_ip3_ctrl,		.ctrlbit	= (1 << 10),	}, {		.name		= "i2c",		.devname	= "s3c2440-i2c.2",		.parent		= &clk_pclk_psys.clk,
 |