1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/kernel.h>
19#include <linux/clk.h>
20#include <linux/err.h>
21#include <linux/io.h>
22#include <linux/module.h>
23
24#include <mach/iomap.h>
25
26#include "tegra2_emc.h"
27
28#ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE
29static bool emc_enable = true;
30#else
31static bool emc_enable;
32#endif
33module_param(emc_enable, bool, 0644);
34
35static void __iomem *emc = IO_ADDRESS(TEGRA_EMC_BASE);
36static const struct tegra_emc_table *tegra_emc_table;
37static int tegra_emc_table_size;
38
39static inline void emc_writel(u32 val, unsigned long addr)
40{
41 writel(val, emc + addr);
42}
43
44static inline u32 emc_readl(unsigned long addr)
45{
46 return readl(emc + addr);
47}
48
49static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
50 0x2c,
51 0x30,
52 0x34,
53 0x38,
54 0x3c,
55 0x40,
56 0x44,
57 0x48,
58 0x4c,
59 0x50,
60 0x54,
61 0x58,
62 0x5c,
63 0x60,
64 0x64,
65 0x68,
66 0x6c,
67 0x70,
68 0x74,
69 0x78,
70 0x7c,
71 0x80,
72 0x84,
73 0x88,
74 0x8c,
75 0x90,
76 0x94,
77 0x98,
78 0x9c,
79 0xa0,
80 0xa4,
81 0xa8,
82 0xac,
83 0x114,
84 0xb0,
85 0xb4,
86 0x104,
87 0x2bc,
88 0x2c0,
89 0x2c4,
90 0x2e0,
91 0x2e4,
92 0x2a8,
93 0x2d0,
94 0x2d4,
95 0x2d8,
96};
97
98
99long tegra_emc_round_rate(unsigned long rate)
100{
101 int i;
102 int best = -1;
103 unsigned long distance = ULONG_MAX;
104
105 if (!tegra_emc_table)
106 return -EINVAL;
107
108 if (!emc_enable)
109 return -EINVAL;
110
111 pr_debug("%s: %lu\n", __func__, rate);
112
113
114
115
116
117 rate = rate / 2 / 1000;
118
119 for (i = 0; i < tegra_emc_table_size; i++) {
120 if (tegra_emc_table[i].rate >= rate &&
121 (tegra_emc_table[i].rate - rate) < distance) {
122 distance = tegra_emc_table[i].rate - rate;
123 best = i;
124 }
125 }
126
127 if (best < 0)
128 return -EINVAL;
129
130 pr_debug("%s: using %lu\n", __func__, tegra_emc_table[best].rate);
131
132 return tegra_emc_table[best].rate * 2 * 1000;
133}
134
135
136
137
138
139
140
141
142
143int tegra_emc_set_rate(unsigned long rate)
144{
145 int i;
146 int j;
147
148 if (!tegra_emc_table)
149 return -EINVAL;
150
151
152
153
154
155 rate = rate / 2 / 1000;
156
157 for (i = 0; i < tegra_emc_table_size; i++)
158 if (tegra_emc_table[i].rate == rate)
159 break;
160
161 if (i >= tegra_emc_table_size)
162 return -EINVAL;
163
164 pr_debug("%s: setting to %lu\n", __func__, rate);
165
166 for (j = 0; j < TEGRA_EMC_NUM_REGS; j++)
167 emc_writel(tegra_emc_table[i].regs[j], emc_reg_addr[j]);
168
169 emc_readl(tegra_emc_table[i].regs[TEGRA_EMC_NUM_REGS - 1]);
170
171 return 0;
172}
173
174void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
175{
176 tegra_emc_table = table;
177 tegra_emc_table_size = table_size;
178}
179