Blame view

arch/arm/mach-s3c2440/s3c2442.c 4.4 KB
a21765a70   Ben Dooks   [ARM] 4157/2: S3C...
1
  /* linux/arch/arm/mach-s3c2442/s3c2442.c
96ce2385d   Ben Dooks   [ARM] 3559/1: S3C...
2
   *
491547d43   Ben Dooks   ARM: S3C2442: Mer...
3
4
5
   * Copyright (c) 2004-2005 Simtec Electronics
   *	http://armlinux.simtec.co.uk/
   *	Ben Dooks <ben@simtec.co.uk>
96ce2385d   Ben Dooks   [ARM] 3559/1: S3C...
6
   *
491547d43   Ben Dooks   ARM: S3C2442: Mer...
7
   * S3C2442 core and lock support
96ce2385d   Ben Dooks   [ARM] 3559/1: S3C...
8
9
   *
   * This program is free software; you can redistribute it and/or modify
491547d43   Ben Dooks   ARM: S3C2442: Mer...
10
11
12
13
14
15
16
17
18
19
20
21
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
96ce2385d   Ben Dooks   [ARM] 3559/1: S3C...
22
  */
491547d43   Ben Dooks   ARM: S3C2442: Mer...
23
24
  #include <linux/init.h>
  #include <linux/module.h>
96ce2385d   Ben Dooks   [ARM] 3559/1: S3C...
25
  #include <linux/kernel.h>
96ce2385d   Ben Dooks   [ARM] 3559/1: S3C...
26
  #include <linux/list.h>
491547d43   Ben Dooks   ARM: S3C2442: Mer...
27
28
29
  #include <linux/errno.h>
  #include <linux/err.h>
  #include <linux/device.h>
bb072c3cf   Rafael J. Wysocki   ARM / Samsung: Us...
30
  #include <linux/syscore_ops.h>
491547d43   Ben Dooks   ARM: S3C2442: Mer...
31
32
33
  #include <linux/interrupt.h>
  #include <linux/ioport.h>
  #include <linux/mutex.h>
812c4e40c   Vasily Khoruzhick   ARM: S3C24XX: Fix...
34
  #include <linux/gpio.h>
491547d43   Ben Dooks   ARM: S3C2442: Mer...
35
36
  #include <linux/clk.h>
  #include <linux/io.h>
96ce2385d   Ben Dooks   [ARM] 3559/1: S3C...
37

491547d43   Ben Dooks   ARM: S3C2442: Mer...
38
  #include <mach/hardware.h>
60063497a   Arun Sharma   atomic: use <linu...
39
  #include <linux/atomic.h>
491547d43   Ben Dooks   ARM: S3C2442: Mer...
40
41
42
43
44
  #include <asm/irq.h>
  
  #include <mach/regs-clock.h>
  
  #include <plat/clock.h>
a2b7ba9ca   Ben Dooks   [ARM] S3C24XX: Mo...
45
  #include <plat/cpu.h>
812c4e40c   Vasily Khoruzhick   ARM: S3C24XX: Fix...
46
  #include <plat/s3c244x.h>
bb072c3cf   Rafael J. Wysocki   ARM / Samsung: Us...
47
  #include <plat/pm.h>
812c4e40c   Vasily Khoruzhick   ARM: S3C24XX: Fix...
48
49
50
51
  
  #include <plat/gpio-core.h>
  #include <plat/gpio-cfg.h>
  #include <plat/gpio-cfg-helpers.h>
96ce2385d   Ben Dooks   [ARM] 3559/1: S3C...
52

491547d43   Ben Dooks   ARM: S3C2442: Mer...
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  /* S3C2442 extended clock support */
  
  static unsigned long s3c2442_camif_upll_round(struct clk *clk,
  					      unsigned long rate)
  {
  	unsigned long parent_rate = clk_get_rate(clk->parent);
  	int div;
  
  	if (rate > parent_rate)
  		return parent_rate;
  
  	div = parent_rate / rate;
  
  	if (div == 3)
  		return parent_rate / 3;
  
  	/* note, we remove the +/- 1 calculations for the divisor */
  
  	div /= 2;
  
  	if (div < 1)
  		div = 1;
  	else if (div > 16)
  		div = 16;
  
  	return parent_rate / (div * 2);
  }
  
  static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
  {
  	unsigned long parent_rate = clk_get_rate(clk->parent);
  	unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
  
  	rate = s3c2442_camif_upll_round(clk, rate);
  
  	camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
  
  	if (rate == parent_rate) {
  		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
  	} else if ((parent_rate / rate) == 3) {
  		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
  		camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
  	} else {
  		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
  		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
  		camdivn |= (((parent_rate / rate) / 2) - 1);
  	}
  
  	__raw_writel(camdivn, S3C2440_CAMDIVN);
  
  	return 0;
  }
  
  /* Extra S3C2442 clocks */
  
  static struct clk s3c2442_clk_cam = {
  	.name		= "camif",
  	.id		= -1,
  	.enable		= s3c2410_clkcon_enable,
  	.ctrlbit	= S3C2440_CLKCON_CAMERA,
  };
  
  static struct clk s3c2442_clk_cam_upll = {
  	.name		= "camif-upll",
  	.id		= -1,
  	.ops		= &(struct clk_ops) {
  		.set_rate	= s3c2442_camif_upll_setrate,
  		.round_rate	= s3c2442_camif_upll_round,
  	},
  };
4a858cfc9   Kay Sievers   arm: convert sysd...
123
  static int s3c2442_clk_add(struct device *dev)
491547d43   Ben Dooks   ARM: S3C2442: Mer...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  {
  	struct clk *clock_upll;
  	struct clk *clock_h;
  	struct clk *clock_p;
  
  	clock_p = clk_get(NULL, "pclk");
  	clock_h = clk_get(NULL, "hclk");
  	clock_upll = clk_get(NULL, "upll");
  
  	if (IS_ERR(clock_p) || IS_ERR(clock_h) || IS_ERR(clock_upll)) {
  		printk(KERN_ERR "S3C2442: Failed to get parent clocks
  ");
  		return -EINVAL;
  	}
  
  	s3c2442_clk_cam.parent = clock_h;
  	s3c2442_clk_cam_upll.parent = clock_upll;
  
  	s3c24xx_register_clock(&s3c2442_clk_cam);
  	s3c24xx_register_clock(&s3c2442_clk_cam_upll);
  
  	clk_disable(&s3c2442_clk_cam);
  
  	return 0;
  }
4a858cfc9   Kay Sievers   arm: convert sysd...
149
150
151
  static struct subsys_interface s3c2442_clk_interface = {
  	.name		= "s3c2442_clk",
  	.subsys		= &s3c2442_subsys,
ea04018e6   Kukjin Kim   arm: fix up some ...
152
  	.add_dev	= s3c2442_clk_add,
491547d43   Ben Dooks   ARM: S3C2442: Mer...
153
154
155
156
  };
  
  static __init int s3c2442_clk_init(void)
  {
4a858cfc9   Kay Sievers   arm: convert sysd...
157
  	return subsys_interface_register(&s3c2442_clk_interface);
491547d43   Ben Dooks   ARM: S3C2442: Mer...
158
159
160
  }
  
  arch_initcall(s3c2442_clk_init);
4a858cfc9   Kay Sievers   arm: convert sysd...
161
162
  static struct device s3c2442_dev = {
  	.bus		= &s3c2442_subsys,
96ce2385d   Ben Dooks   [ARM] 3559/1: S3C...
163
164
165
166
167
168
  };
  
  int __init s3c2442_init(void)
  {
  	printk("S3C2442: Initialising architecture
  ");
fb630b9fc   Domenico Andreoli   ARM: S3C24XX: Fix...
169
  #ifdef CONFIG_PM
bb072c3cf   Rafael J. Wysocki   ARM / Samsung: Us...
170
  	register_syscore_ops(&s3c2410_pm_syscore_ops);
fb630b9fc   Domenico Andreoli   ARM: S3C24XX: Fix...
171
  #endif
bb072c3cf   Rafael J. Wysocki   ARM / Samsung: Us...
172
173
  	register_syscore_ops(&s3c244x_pm_syscore_ops);
  	register_syscore_ops(&s3c24xx_irq_syscore_ops);
4a858cfc9   Kay Sievers   arm: convert sysd...
174
  	return device_register(&s3c2442_dev);
96ce2385d   Ben Dooks   [ARM] 3559/1: S3C...
175
  }
812c4e40c   Vasily Khoruzhick   ARM: S3C24XX: Fix...
176
177
178
179
  
  void __init s3c2442_map_io(void)
  {
  	s3c244x_map_io();
782d8a3c0   Kukjin Kim   ARM: SAMSUNG: Upd...
180
181
  	s3c24xx_gpiocfg_default.set_pull = s3c24xx_gpio_setpull_1down;
  	s3c24xx_gpiocfg_default.get_pull = s3c24xx_gpio_getpull_1down;
812c4e40c   Vasily Khoruzhick   ARM: S3C24XX: Fix...
182
  }