]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/board-rx51-sdram.c
Merge branch 'omap-fixes'
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / board-rx51-sdram.c
1 /*
2  * SDRC register values for the Samsung K4X1G323PC
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  *
6  * Lauri Leukkunen <lauri.leukkunen@nokia.com>
7  *
8  * Original code by Juha Yrjölä <juha.yrjola@solidboot.com>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  */
14
15 #include <linux/kernel.h>
16 #include <linux/clk.h>
17 #include <linux/err.h>
18 #include <linux/io.h>
19
20 #include <mach/io.h>
21 #include <mach/common.h>
22 #include <mach/clock.h>
23 #include <mach/sdrc.h>
24
25
26 /* In picoseconds, except for tREF */
27 struct sdram_timings {
28         u32 casl;
29         u32 tDAL;
30         u32 tDPL;
31         u32 tRRD;
32         u32 tRCD;
33         u32 tRP;
34         u32 tRAS;
35         u32 tRC;
36         u32 tRFC;
37         u32 tXSR;
38
39         u32 tREF; /* in ms */
40 };
41
42 struct sdram_info {
43         u8 row_lines;
44 };
45
46
47 struct omap_sdrc_params rx51_sdrc_params[2];
48
49 static const struct sdram_timings rx51_timings[] = {
50         {
51                 .casl = 3,
52                 .tDAL = 15000 + 18000,
53                 .tDPL = 15000,
54                 .tRRD = 12000,
55                 .tRCD = 18000,
56                 .tRP = 18000,
57                 .tRAS = 42000,
58                 .tRC = 66000,
59                 .tRFC = 97500,
60                 .tXSR = 120000,
61
62                 .tREF = 64,
63         },
64 };
65
66 static const struct sdram_info rx51_info = {
67         .row_lines = 13,
68 };
69
70 #define CM_BASE             0x48004000
71
72 #define CM_CLKSEL_CORE      0x0a40
73 #define CM_CLKSEL1_PLL      0x0d40
74
75 #define PRM_CLKSEL          0x48306d40
76 #define PRM_CLKSRC_CTRL     0x48307270
77
78 static u32 cm_base = CM_BASE;
79
80 static inline u32 cm_read_reg(int idx)
81 {
82         return *(u32 *)OMAP2_IO_ADDRESS(cm_base + idx);
83 }
84
85 static const unsigned long sys_clk_rate_table[] = {
86         12000, 13000, 19200, 26000, 38400, 16800
87 };
88
89 static unsigned long get_sys_clk_rate(void)
90 {
91         unsigned long rate;
92
93         rate = sys_clk_rate_table[*(u32 *)OMAP2_IO_ADDRESS(PRM_CLKSEL) & 0x07];
94         if (((*(u32 *)OMAP2_IO_ADDRESS(PRM_CLKSRC_CTRL) >> 6) & 0x03) == 0x02)
95                 rate /= 2;
96         return rate;
97 }
98
99 static unsigned long get_core_rate(void)
100 {
101         unsigned long rate;
102         u32 l;
103
104         l = cm_read_reg(CM_CLKSEL1_PLL);
105         rate = get_sys_clk_rate();
106         rate *= ((l >> 16) & 0x7ff);
107         rate /= ((l >> 8) & 0x7f) + 1;
108         rate /= (l >> 27) & 0x1f;
109
110         return rate;
111 }
112
113 static unsigned long get_l3_rate(void)
114 {
115         u32 l;
116
117         l = cm_read_reg(CM_CLKSEL_CORE);
118         return get_core_rate() / (l & 0x03);
119 }
120
121
122
123 static unsigned long sdrc_get_fclk_period(void)
124 {
125         /* In picoseconds */
126         return 1000000000 / get_l3_rate();
127 }
128
129 static unsigned int sdrc_ps_to_ticks(unsigned int time_ps)
130 {
131         unsigned long tick_ps;
132
133         /* Calculate in picosecs to yield more exact results */
134         tick_ps = sdrc_get_fclk_period();
135
136         return (time_ps + tick_ps - 1) / tick_ps;
137 }
138 #undef DEBUG
139 #ifdef DEBUG
140 static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
141                                int time, const char *name)
142 #else
143 static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
144                                int time)
145 #endif
146 {
147         int ticks, mask, nr_bits;
148
149         if (time == 0)
150                 ticks = 0;
151         else
152                 ticks = sdrc_ps_to_ticks(time);
153         nr_bits = end_bit - st_bit + 1;
154         if (ticks >= 1 << nr_bits)
155                 return -1;
156         mask = (1 << nr_bits) - 1;
157         *regval &= ~(mask << st_bit);
158         *regval |= ticks << st_bit;
159 #ifdef DEBUG
160         printk("SDRC %s: %i ticks %i ns\n", name, ticks,
161                         (unsigned int)sdrc_get_fclk_period() * ticks / 1000);
162 #endif
163
164         return 0;
165 }
166
167 #ifdef DEBUG
168 #define SDRC_SET_ONE(reg, st, end, field) \
169         if (set_sdrc_timing_regval((reg), (st), (end), rx51_timings->field, #field) < 0) \
170                 err = -1
171 #else
172 #define SDRC_SET_ONE(reg, st, end, field) \
173         if (set_sdrc_timing_regval((reg), (st), (end), rx51_timings->field) < 0) \
174                 err = -1
175 #endif
176
177 struct omap_sdrc_params *rx51_get_sdram_timings(void)
178 {
179         u32 ticks_per_ms;
180         u32 rfr, l;
181         u32 actim_ctrla, actim_ctrlb;
182         u32 rfr_ctrl;
183         int err = 0;
184
185         SDRC_SET_ONE(&actim_ctrla,  0,  4, tDAL);
186         SDRC_SET_ONE(&actim_ctrla,  6,  8, tDPL);
187         SDRC_SET_ONE(&actim_ctrla,  9, 11, tRRD);
188         SDRC_SET_ONE(&actim_ctrla, 12, 14, tRCD);
189         SDRC_SET_ONE(&actim_ctrla, 15, 17, tRP);
190         SDRC_SET_ONE(&actim_ctrla, 18, 21, tRAS);
191         SDRC_SET_ONE(&actim_ctrla, 22, 26, tRC);
192         SDRC_SET_ONE(&actim_ctrla, 27, 31, tRFC);
193
194         SDRC_SET_ONE(&actim_ctrlb,  0,  7, tXSR);
195
196         ticks_per_ms = sdrc_ps_to_ticks(1000000000);
197         rfr = rx51_timings[0].tREF * ticks_per_ms / (1 << rx51_info.row_lines);
198         if (rfr > 65535 + 50)
199                 rfr = 65535;
200         else
201                 rfr -= 50;
202
203         l = rfr << 8;
204         rfr_ctrl = l | 0x3; /* autorefresh, reload counter with 8xARCV */
205
206         rx51_sdrc_params[0].rate = 133333333;
207         rx51_sdrc_params[0].actim_ctrla = actim_ctrla;
208         rx51_sdrc_params[0].actim_ctrlb = actim_ctrlb;
209         rx51_sdrc_params[0].rfr_ctrl = rfr_ctrl;
210         rx51_sdrc_params[0].mr = 0x32;
211
212         rx51_sdrc_params[1].rate = 0;
213
214         if (err < 0)
215                 return NULL;
216
217         return &rx51_sdrc_params[0];
218 }
219