aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci
diff options
context:
space:
mode:
authorNageswari Srinivasan <nageswari@ti.com>2010-01-06 06:49:48 -0500
committerKevin Hilman <khilman@deeprootsystems.com>2010-02-04 16:29:58 -0500
commit5b8972d1b6461d0081d2d49dde4d129290da26f0 (patch)
tree04294ee57ea7c893417fb6a7b7f51cd31dfa2477 /arch/arm/mach-davinci
parent635344436385bbdca24b57ef14f2dde53e9af082 (diff)
davinci: add support for CDCE949 clock synthesizer
This patch adds support for TI's CDCE949 - a clock synthesizer with 4 PLLs and 9 outputs. It is used on DM6467 EVM. On the EVM, it generates clocks required for VPIF, TSIF and Audio modules. This patch adds it as part of the DaVinci clock framework. Testing: The various frequency outputs on Y1 have been tested using a out-of-tree VPIF video driver supporting HD video. The register values for Y5 frequency outputs have been derived from TSIF driver sources in MontaVista LSP kernel, but actual output has not been tested for lack of TSIF driver which actually works on the latest kernel. Signed-off-by: Nageswari Srinivasan <nageswari@ti.com> Signed-off-by: Sekhar Nori <nsekhar@ti.com> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
Diffstat (limited to 'arch/arm/mach-davinci')
-rw-r--r--arch/arm/mach-davinci/cdce949.c289
-rw-r--r--arch/arm/mach-davinci/include/mach/cdce949.h19
2 files changed, 308 insertions, 0 deletions
diff --git a/arch/arm/mach-davinci/cdce949.c b/arch/arm/mach-davinci/cdce949.c
new file mode 100644
index 000000000000..6af3289e0527
--- /dev/null
+++ b/arch/arm/mach-davinci/cdce949.c
@@ -0,0 +1,289 @@
1/*
2 * TI CDCE949 clock synthesizer driver
3 *
4 * Note: This implementation assumes an input of 27MHz to the CDCE.
5 * This is by no means constrained by CDCE hardware although the datasheet
6 * does use this as an example for all illustrations and more importantly:
7 * that is the crystal input on boards it is currently used on.
8 *
9 * Copyright (C) 2009 Texas Instruments Incorporated. http://www.ti.com/
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 */
16#include <linux/kernel.h>
17#include <linux/clk.h>
18#include <linux/platform_device.h>
19#include <linux/i2c.h>
20
21#include <mach/clock.h>
22
23#include "clock.h"
24
25static struct i2c_client *cdce_i2c_client;
26
27/* CDCE register descriptor */
28struct cdce_reg {
29 u8 addr;
30 u8 val;
31};
32
33/* Per-Output (Y1, Y2 etc.) frequency descriptor */
34struct cdce_freq {
35 /* Frequency in KHz */
36 unsigned long frequency;
37 /*
38 * List of registers to program to obtain a particular frequency.
39 * 0x0 in register address and value is the end of list marker.
40 */
41 struct cdce_reg *reglist;
42};
43
44#define CDCE_FREQ_TABLE_ENTRY(line, out) \
45{ \
46 .reglist = cdce_y ##line## _ ##out, \
47 .frequency = out, \
48}
49
50/* List of CDCE outputs */
51struct cdce_output {
52 /* List of frequencies on this output */
53 struct cdce_freq *freq_table;
54 /* Number of possible frequencies */
55 int size;
56};
57
58/*
59 * Finding out the values to program into CDCE949 registers for a particular
60 * frequency output is not a simple calculation. Have a look at the datasheet
61 * for the details. There is desktop software available to help users with
62 * the calculations. Here, we just depend on the output of that software
63 * (or hand calculations) instead trying to runtime calculate the register
64 * values and inflicting misery on ourselves.
65 */
66static struct cdce_reg cdce_y1_148500[] = {
67 { 0x13, 0x00 },
68 /* program PLL1_0 multiplier */
69 { 0x18, 0xaf },
70 { 0x19, 0x50 },
71 { 0x1a, 0x02 },
72 { 0x1b, 0xc9 },
73 /* program PLL1_11 multiplier */
74 { 0x1c, 0x00 },
75 { 0x1d, 0x40 },
76 { 0x1e, 0x02 },
77 { 0x1f, 0xc9 },
78 /* output state selection */
79 { 0x15, 0x00 },
80 { 0x14, 0xef },
81 /* switch MUX to PLL1 output */
82 { 0x14, 0x6f },
83 { 0x16, 0x06 },
84 /* set P2DIV divider, P3DIV and input crystal */
85 { 0x17, 0x06 },
86 { 0x01, 0x00 },
87 { 0x05, 0x48 },
88 { 0x02, 0x80 },
89 /* enable and disable PLL */
90 { 0x02, 0xbc },
91 { 0x03, 0x01 },
92 { },
93};
94
95static struct cdce_reg cdce_y1_74250[] = {
96 { 0x13, 0x00 },
97 { 0x18, 0xaf },
98 { 0x19, 0x50 },
99 { 0x1a, 0x02 },
100 { 0x1b, 0xc9 },
101 { 0x1c, 0x00 },
102 { 0x1d, 0x40 },
103 { 0x1e, 0x02 },
104 { 0x1f, 0xc9 },
105 /* output state selection */
106 { 0x15, 0x00 },
107 { 0x14, 0xef },
108 /* switch MUX to PLL1 output */
109 { 0x14, 0x6f },
110 { 0x16, 0x06 },
111 /* set P2DIV divider, P3DIV and input crystal */
112 { 0x17, 0x06 },
113 { 0x01, 0x00 },
114 { 0x05, 0x48 },
115 { 0x02, 0x80 },
116 /* enable and disable PLL */
117 { 0x02, 0xbc },
118 { 0x03, 0x02 },
119 { },
120};
121
122static struct cdce_reg cdce_y1_27000[] = {
123 { 0x13, 0x00 },
124 { 0x18, 0x00 },
125 { 0x19, 0x40 },
126 { 0x1a, 0x02 },
127 { 0x1b, 0x08 },
128 { 0x1c, 0x00 },
129 { 0x1d, 0x40 },
130 { 0x1e, 0x02 },
131 { 0x1f, 0x08 },
132 { 0x15, 0x02 },
133 { 0x14, 0xed },
134 { 0x16, 0x01 },
135 { 0x17, 0x01 },
136 { 0x01, 0x00 },
137 { 0x05, 0x50 },
138 { 0x02, 0xb4 },
139 { 0x03, 0x01 },
140 { },
141};
142
143static struct cdce_freq cdce_y1_freqs[] = {
144 CDCE_FREQ_TABLE_ENTRY(1, 148500),
145 CDCE_FREQ_TABLE_ENTRY(1, 74250),
146 CDCE_FREQ_TABLE_ENTRY(1, 27000),
147};
148
149static struct cdce_reg cdce_y5_13500[] = {
150 { 0x27, 0x08 },
151 { 0x28, 0x00 },
152 { 0x29, 0x40 },
153 { 0x2a, 0x02 },
154 { 0x2b, 0x08 },
155 { 0x24, 0x6f },
156 { },
157};
158
159static struct cdce_reg cdce_y5_16875[] = {
160 { 0x27, 0x08 },
161 { 0x28, 0x9f },
162 { 0x29, 0xb0 },
163 { 0x2a, 0x02 },
164 { 0x2b, 0x89 },
165 { 0x24, 0x6f },
166 { },
167};
168
169static struct cdce_reg cdce_y5_27000[] = {
170 { 0x27, 0x04 },
171 { 0x28, 0x00 },
172 { 0x29, 0x40 },
173 { 0x2a, 0x02 },
174 { 0x2b, 0x08 },
175 { 0x24, 0x6f },
176 { },
177};
178static struct cdce_reg cdce_y5_54000[] = {
179 { 0x27, 0x04 },
180 { 0x28, 0xff },
181 { 0x29, 0x80 },
182 { 0x2a, 0x02 },
183 { 0x2b, 0x07 },
184 { 0x24, 0x6f },
185 { },
186};
187
188static struct cdce_reg cdce_y5_81000[] = {
189 { 0x27, 0x02 },
190 { 0x28, 0xbf },
191 { 0x29, 0xa0 },
192 { 0x2a, 0x03 },
193 { 0x2b, 0x0a },
194 { 0x24, 0x6f },
195 { },
196};
197
198static struct cdce_freq cdce_y5_freqs[] = {
199 CDCE_FREQ_TABLE_ENTRY(5, 13500),
200 CDCE_FREQ_TABLE_ENTRY(5, 16875),
201 CDCE_FREQ_TABLE_ENTRY(5, 27000),
202 CDCE_FREQ_TABLE_ENTRY(5, 54000),
203 CDCE_FREQ_TABLE_ENTRY(5, 81000),
204};
205
206
207static struct cdce_output output_list[] = {
208 [1] = { cdce_y1_freqs, ARRAY_SIZE(cdce_y1_freqs) },
209 [5] = { cdce_y5_freqs, ARRAY_SIZE(cdce_y5_freqs) },
210};
211
212int cdce_set_rate(struct clk *clk, unsigned long rate)
213{
214 int i, ret = 0;
215 struct cdce_freq *freq_table = output_list[clk->lpsc].freq_table;
216 struct cdce_reg *regs = NULL;
217
218 if (!cdce_i2c_client)
219 return -ENODEV;
220
221 if (!freq_table)
222 return -EINVAL;
223
224 for (i = 0; i < output_list[clk->lpsc].size; i++) {
225 if (freq_table[i].frequency == rate / 1000) {
226 regs = freq_table[i].reglist;
227 break;
228 }
229 }
230
231 if (!regs)
232 return -EINVAL;
233
234 for (i = 0; regs[i].addr; i++) {
235 ret = i2c_smbus_write_byte_data(cdce_i2c_client,
236 regs[i].addr | 0x80, regs[i].val);
237 if (ret)
238 return ret;
239 }
240
241 clk->rate = rate;
242
243 return 0;
244}
245
246static int cdce_probe(struct i2c_client *client,
247 const struct i2c_device_id *id)
248{
249 cdce_i2c_client = client;
250 return 0;
251}
252
253static int __devexit cdce_remove(struct i2c_client *client)
254{
255 cdce_i2c_client = NULL;
256 return 0;
257}
258
259static const struct i2c_device_id cdce_id[] = {
260 {"cdce949", 0},
261 {},
262};
263MODULE_DEVICE_TABLE(i2c, cdce_id);
264
265static struct i2c_driver cdce_driver = {
266 .driver = {
267 .owner = THIS_MODULE,
268 .name = "cdce949",
269 },
270 .probe = cdce_probe,
271 .remove = __devexit_p(cdce_remove),
272 .id_table = cdce_id,
273};
274
275static int __init cdce_init(void)
276{
277 return i2c_add_driver(&cdce_driver);
278}
279subsys_initcall(cdce_init);
280
281static void __exit cdce_exit(void)
282{
283 i2c_del_driver(&cdce_driver);
284}
285module_exit(cdce_exit);
286
287MODULE_AUTHOR("Texas Instruments");
288MODULE_DESCRIPTION("CDCE949 clock synthesizer driver");
289MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-davinci/include/mach/cdce949.h b/arch/arm/mach-davinci/include/mach/cdce949.h
new file mode 100644
index 000000000000..c73331fae341
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/cdce949.h
@@ -0,0 +1,19 @@
1/*
2 * TI CDCE949 off-chip clock synthesizer support
3 *
4 * 2009 (C) Texas Instruments, Inc. http://www.ti.com/
5 *
6 * This file is licensed under the terms of the GNU General Public License
7 * version 2. This program is licensed "as is" without any warranty of any
8 * kind, whether express or implied.
9 */
10#ifndef _MACH_DAVINCI_CDCE949_H
11#define _MACH_DAVINCI_CDCE949_H
12
13#include <linux/clk.h>
14
15#include <mach/clock.h>
16
17int cdce_set_rate(struct clk *clk, unsigned long rate);
18
19#endif