12bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim/*
2a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
32bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim *		http://www.samsung.com
42bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim *
52bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim * EXYNOS4212 - Clock support
62bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim *
72bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim * This program is free software; you can redistribute it and/or modify
82bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim * it under the terms of the GNU General Public License version 2 as
92bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim * published by the Free Software Foundation.
102bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim*/
112bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
122bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <linux/kernel.h>
132bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <linux/err.h>
142bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <linux/clk.h>
152bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <linux/io.h>
16acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi#include <linux/syscore_ops.h>
172bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
182bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <plat/cpu-freq.h>
192bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <plat/clock.h>
202bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <plat/cpu.h>
212bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <plat/pll.h>
222bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <plat/s5p-clock.h>
232bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <plat/clock-clksrc.h>
24acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi#include <plat/pm.h>
252bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
262bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <mach/hardware.h>
272bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <mach/map.h>
282bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim#include <mach/regs-clock.h>
292bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
30cc511b8d84d88ab788cddbfe8d21485b1c387493Kukjin Kim#include "common.h"
31ce9c00eea187f0c54971caec477f721c2dc5cd3dKukjin Kim#include "clock-exynos4.h"
32cc511b8d84d88ab788cddbfe8d21485b1c387493Kukjin Kim
337cdf04d7d4c0b5b205817ceb7a21c6e07d09ce11Kukjin Kim#ifdef CONFIG_PM_SLEEP
34acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choistatic struct sleep_save exynos4212_clock_save[] = {
35a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
36a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
37a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	SAVE_ITEM(EXYNOS4212_CLKGATE_IP_IMAGE),
38a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	SAVE_ITEM(EXYNOS4212_CLKGATE_IP_PERIR),
39acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi};
407cdf04d7d4c0b5b205817ceb7a21c6e07d09ce11Kukjin Kim#endif
41acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi
422bc02c0daae146283ce1b20da6864a27c848812eKukjin Kimstatic struct clk *clk_src_mpll_user_list[] = {
432bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	[0] = &clk_fin_mpll,
44a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	[1] = &exynos4_clk_mout_mpll.clk,
452bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim};
462bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
472bc02c0daae146283ce1b20da6864a27c848812eKukjin Kimstatic struct clksrc_sources clk_src_mpll_user = {
482bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	.sources	= clk_src_mpll_user_list,
492bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	.nr_sources	= ARRAY_SIZE(clk_src_mpll_user_list),
502bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim};
512bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
522bc02c0daae146283ce1b20da6864a27c848812eKukjin Kimstatic struct clksrc_clk clk_mout_mpll_user = {
532bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	.clk = {
542bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim		.name		= "mout_mpll_user",
552bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	},
562bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	.sources	= &clk_src_mpll_user,
57a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	.reg_src	= { .reg = EXYNOS4_CLKSRC_CPU, .shift = 24, .size = 1 },
582bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim};
592bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
602bc02c0daae146283ce1b20da6864a27c848812eKukjin Kimstatic struct clksrc_clk *sysclks[] = {
612bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	&clk_mout_mpll_user,
622bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim};
632bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
642bc02c0daae146283ce1b20da6864a27c848812eKukjin Kimstatic struct clksrc_clk clksrcs[] = {
652bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	/* nothing here yet */
662bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim};
672bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
682bc02c0daae146283ce1b20da6864a27c848812eKukjin Kimstatic struct clk init_clocks_off[] = {
692bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	/* nothing here yet */
702bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim};
712bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
72acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi#ifdef CONFIG_PM_SLEEP
73acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choistatic int exynos4212_clock_suspend(void)
74acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi{
75acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi	s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
76acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi
77acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi	return 0;
78acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi}
79acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi
80acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choistatic void exynos4212_clock_resume(void)
81acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi{
82acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi	s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
83acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi}
84acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi
85acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi#else
86acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi#define exynos4212_clock_suspend NULL
87acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi#define exynos4212_clock_resume NULL
88acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi#endif
89acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi
90e745e06fbdf697ed7d611ea596e77278eeecd417Kukjin Kimstatic struct syscore_ops exynos4212_clock_syscore_ops = {
91acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi	.suspend	= exynos4212_clock_suspend,
92acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi	.resume		= exynos4212_clock_resume,
93acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi};
94acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi
952bc02c0daae146283ce1b20da6864a27c848812eKukjin Kimvoid __init exynos4212_register_clocks(void)
962bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim{
972bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	int ptr;
982bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
992bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	/* usbphy1 is removed */
100a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	exynos4_clkset_group_list[4] = NULL;
1012bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
1022bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	/* mout_mpll_user is used */
103a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	exynos4_clkset_group_list[6] = &clk_mout_mpll_user.clk;
104a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	exynos4_clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk;
1052bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
106a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_DMC;
107a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	exynos4_clk_mout_mpll.reg_src.shift = 12;
108a855039ee4b814782aebe2448d838944d2d29fcbKukjin Kim	exynos4_clk_mout_mpll.reg_src.size = 1;
1092bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
1102bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
1112bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim		s3c_register_clksrc(sysclks[ptr], 1);
1122bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
1132bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
1142bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim
1152bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
1162bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
117acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi
118acd35616c7a30130d3b43ae1c1bb0b7fd121ffb9Jonghwan Choi	register_syscore_ops(&exynos4212_clock_syscore_ops);
1192bc02c0daae146283ce1b20da6864a27c848812eKukjin Kim}
120