blob: af16c88dac7d6eebb726d00dbbc096b9903972b7 [file] [log] [blame]
Ajay Dudani232ce812009-12-02 00:14:11 -08001/*
Ajay Dudani1c798cf2011-01-19 14:27:50 -08002 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
Ajay Dudani232ce812009-12-02 00:14:11 -08003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of Code Aurora nor
12 * the names of its contributors may be used to endorse or promote
13 * products derived from this software without specific prior written
14 * permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdint.h>
30#include <kernel/thread.h>
31#include <platform/iomap.h>
32#include <reg.h>
Amol Jadi82254562011-06-27 11:25:48 -070033#include <debug.h>
34#include <mmc.h>
Ajay Dudani232ce812009-12-02 00:14:11 -080035
Ajay Dudani1c798cf2011-01-19 14:27:50 -080036#define ACPU_806MHZ 42
37#define ACPU_1024MHZ 53
38#define ACPU_1200MHZ 125
39#define ACPU_1400MHZ 73
40
Shashank Mittal0dab8f52010-11-03 16:40:30 -070041/* Macros to select PLL2 with divide by 1 */
42#define ACPU_SRC_SEL 3
43#define ACPU_SRC_DIV 0
44
45#define BIT(n) (1 << (n))
46#define VREG_CONFIG (BIT(7) | BIT(6)) /* Enable VREG, pull-down if disabled. */
47#define VREG_DATA (VREG_CONFIG | (VREF_SEL << 5))
48#define VREF_SEL 1 /* 0: 0.625V (50mV step), 1: 0.3125V (25mV step). */
49#define V_STEP (25 * (2 - VREF_SEL)) /* Minimum voltage step size. */
50#define MV(mv) ((mv) / (!((mv) % V_STEP)))
51/* mv = (750mV + (raw * 25mV)) * (2 - VREF_SEL) */
52#define VDD_RAW(mv) (((MV(mv) / V_STEP) - 30) | VREG_DATA)
53
Amol Jadi82254562011-06-27 11:25:48 -070054
55/* enum for SDC CLK IDs */
56enum
57{
58 SDC1_CLK = 19,
59 SDC1_PCLK = 20,
60 SDC2_CLK = 21,
61 SDC2_PCLK = 22,
62 SDC3_CLK = 23,
63 SDC3_PCLK = 24,
64 SDC4_CLK = 25,
65 SDC4_PCLK = 26
66};
67
68/* Zero'th entry is dummy */
69static uint8_t sdc_clk[] = {0, SDC1_CLK, SDC2_CLK, SDC3_CLK, SDC4_CLK};
70static uint8_t sdc_pclk[] = {0, SDC1_PCLK, SDC2_PCLK, SDC3_PCLK, SDC4_PCLK};
71
Shashank Mittal0dab8f52010-11-03 16:40:30 -070072void spm_init(void)
73{
74 writel(0x05, MSM_SAW_BASE + 0x10); /* MSM_SPM_REG_SAW_CFG */
75 writel(0x18, MSM_SAW_BASE + 0x14); /* MSM_SPM_REG_SAW_SPM_CTL */
76 writel(0x00006666, MSM_SAW_BASE + 0x18); /* MSM_SPM_REG_SAW_SPM_SLP_TMR_DLY */
77 writel(0xFF000666, MSM_SAW_BASE + 0x1C); /* MSM_SPM_REG_SAW_SPM_WAKE_TMR_DLY */
78
79 writel(0x01, MSM_SAW_BASE + 0x24); /* MSM_SPM_REG_SAW_SLP_CLK_EN */
80 writel(0x03, MSM_SAW_BASE + 0x28); /* MSM_SPM_REG_SAW_SLP_HSFS_PRECLMP_EN */
81 writel(0x00, MSM_SAW_BASE + 0x2C); /* MSM_SPM_REG_SAW_SLP_HSFS_POSTCLMP_EN */
82
83 writel(0x01, MSM_SAW_BASE + 0x30); /* MSM_SPM_REG_SAW_SLP_CLMP_EN */
84 writel(0x00, MSM_SAW_BASE + 0x34); /* MSM_SPM_REG_SAW_SLP_RST_EN */
85 writel(0x00, MSM_SAW_BASE + 0x38); /* MSM_SPM_REG_SAW_SPM_MPM_CFG */
86}
87
88/* Configures msmc2 voltage. vlevel is in mV */
89void msmc2_config(unsigned vlevel)
90{
91 unsigned val;
92 val = readl(MSM_SAW_BASE + 0x08); /* MSM_SPM_REG_SAW_VCTL */
93 val &= ~0xFF;
94 val |= VDD_RAW(vlevel);
95 writel(val, MSM_SAW_BASE + 0x08); /* MSM_SPM_REG_SAW_VCTL */
96
97 /* Wait for PMIC state to return to idle and for VDD to stabilize */
98 while(((readl(MSM_SAW_BASE + 0x0C) >> 0x20) & 0x3) != 0);
99 udelay(160);
100}
101
102void enable_pll(unsigned num)
103{
104 unsigned reg_val;
105 reg_val = readl(PLL_ENA_REG);
106 reg_val |= (1 << num);
107 writel(reg_val, PLL_ENA_REG);
108 /* Wait until PLL is enabled */
109 while ((readl(PLL2_STATUS_BASE_REG) & (1 << 16)) == 0);
110}
111
Ajay Dudani232ce812009-12-02 00:14:11 -0800112void acpu_clock_init(void)
113{
Ajay Dudani1c798cf2011-01-19 14:27:50 -0800114 unsigned clk, reg_clksel, reg_clkctl, src_sel;
Shashank Mittal0dab8f52010-11-03 16:40:30 -0700115 /* Fixing msmc2 voltage */
116 spm_init();
Ajay Dudani1c798cf2011-01-19 14:27:50 -0800117
118 clk = readl(PLL2_L_VAL_ADDR) & 0xFF;
119 if (clk == ACPU_806MHZ)
120 msmc2_config(1100);
121 else if (clk == ACPU_1024MHZ || clk == ACPU_1200MHZ)
122 msmc2_config(1200);
123 else if (clk == ACPU_1400MHZ)
124 msmc2_config(1250);
Shashank Mittal0dab8f52010-11-03 16:40:30 -0700125
126 /* Enable pll 2 */
127 enable_pll(2);
128
129 reg_clksel = readl(SCSS_CLK_SEL);
130
131 /* CLK_SEL_SRC1NO */
132 src_sel = reg_clksel & 1;
133
134 /* Program clock source and divider. */
135 reg_clkctl = readl(SCSS_CLK_CTL);
136 reg_clkctl &= ~(0xFF << (8 * src_sel));
137 reg_clkctl |= ACPU_SRC_SEL<< (4 + 8 * src_sel);
138 reg_clkctl |= ACPU_SRC_DIV<< (0 + 8 * src_sel);
139 writel(reg_clkctl, SCSS_CLK_CTL);
140
141 /* Toggle clock source. */
142 reg_clksel ^= 1;
143
144 /* Program clock source selection. */
145 writel(reg_clksel, SCSS_CLK_SEL);
Chandan Uddaraju35f77182010-09-23 15:21:45 -0700146}
Ajay Dudani7d605522010-10-01 19:52:37 -0700147
148void hsusb_clock_init(void)
149{
150 int val = 0;
151 unsigned sh2_own_row2;
152 unsigned sh2_own_row2_hsusb_mask = (1 << 11);
153
154 sh2_own_row2 = readl(SH2_OWN_ROW2_BASE_REG);
155 if(sh2_own_row2 & sh2_own_row2_hsusb_mask)
156 {
157 /* USB local clock control enabled */
158 /* Set value in MD register */
159 val = 0x5DF;
160 writel(val, SH2_USBH_MD_REG);
161
162 /* Set value in NS register */
163 val = 1 << 8;
164 val = val | readl(SH2_USBH_NS_REG);
165 writel(val, SH2_USBH_NS_REG);
166
167 val = 1 << 11;
168 val = val | readl(SH2_USBH_NS_REG);
169 writel(val, SH2_USBH_NS_REG);
170
171 val = 1 << 9;
172 val = val | readl(SH2_USBH_NS_REG);
173 writel(val, SH2_USBH_NS_REG);
174
175 val = 1 << 13;
176 val = val | readl(SH2_USBH_NS_REG);
177 writel(val, SH2_USBH_NS_REG);
178
179 /* Enable USBH_P_CLK */
180 val = 1 << 25;
181 val = val | readl(SH2_GLBL_CLK_ENA_SC);
182 writel(val, SH2_GLBL_CLK_ENA_SC);
183 }
184 else
185 {
186 /* USB local clock control not enabled; use proc comm */
187 usb_clock_init();
188 }
189}
Subbaraman Narayanamurthy4cc29732010-10-18 15:57:58 -0700190
191void adm_enable_clock(void)
192{
193 unsigned int val=0;
194
195 /* Enable ADM_CLK */
196 val = 1 << 5;
197 val = val | readl(SH2_GLBL_CLK_ENA_SC);
198 writel(val, SH2_GLBL_CLK_ENA_SC);
199}
Subbaraman Narayanamurthyd962c792011-01-19 20:53:07 -0800200
201void mdp_lcdc_clock_init(void)
202{
203 unsigned int val = 0;
204 unsigned sh2_own_apps2;
205 unsigned sh2_own_apps2_lcdc_mask = (1 << 3);
206
207 sh2_own_apps2 = readl(SH2_OWN_APPS2_BASE_REG);
208 if(sh2_own_apps2 & sh2_own_apps2_lcdc_mask)
209 {
210 /* MDP local clock control enabled */
211 /* Select clock source and divider */
212 val = 0x29;
213 val = val | readl(SH2_MDP_NS_REG);
214 writel(val, SH2_MDP_NS_REG);
215
216 /* Enable MDP source clock(root) */
217 val = 1 << 11;
218 val = val | readl(SH2_MDP_NS_REG);
219 writel(val, SH2_MDP_NS_REG);
220
221 /* Enable graphics clock(branch) */
222 val = 1 << 9;
223 val = val | readl(SH2_MDP_NS_REG);
224 writel(val, SH2_MDP_NS_REG);
225
226 /* Enable MDP_P_CLK */
227 val = 1 << 6;
228 val = val | readl(SH2_GLBL_CLK_ENA_2_SC);
229 writel(val, SH2_GLBL_CLK_ENA_2_SC);
230
231 /* Enable AXI_MDP_CLK */
232 val = 1 << 29;
233 val = val | readl(SH2_GLBL_CLK_ENA_2_SC);
234 writel(val, SH2_GLBL_CLK_ENA_2_SC);
235
236 /* LCDC local clock control enabled */
237 /* Set value in MD register */
238 val = 0x1FFF9;
239 writel(val, SH2_MDP_LCDC_MD_REG);
240
241 /* Set MDP_LCDC_N_VAL in NS register */
242 val = 0xFFFA << 16;
243 val = val | readl(SH2_MDP_LCDC_NS_REG);
244 writel(val, SH2_MDP_LCDC_NS_REG);
245
246 /* Set clock source */
247 val = 1;
248 val = val | readl(SH2_MDP_LCDC_NS_REG);
249 writel(val, SH2_MDP_LCDC_NS_REG);
250
251 /* Set divider */
252 val = 3 << 3;
253 val = val | readl(SH2_MDP_LCDC_NS_REG);
254 writel(val, SH2_MDP_LCDC_NS_REG);
255
256 /* Set MN counter mode */
257 val = 2 << 5;
258 val = val | readl(SH2_MDP_LCDC_NS_REG);
259 writel(val, SH2_MDP_LCDC_NS_REG);
260
261 /* Enable MN counter */
262 val = 1 << 8;
263 val = val | readl(SH2_MDP_LCDC_NS_REG);
264 writel(val, SH2_MDP_LCDC_NS_REG);
265
266 /* Enable mdp_lcdc_src(root) clock */
267 val = 1 << 11;
268 val = val | readl(SH2_MDP_LCDC_NS_REG);
269 writel(val, SH2_MDP_LCDC_NS_REG);
270
271 /* Enable mdp_lcdc_pclk(branch) clock */
272 val = 1 << 9;
273 val = val | readl(SH2_MDP_LCDC_NS_REG);
274 writel(val, SH2_MDP_LCDC_NS_REG);
275
276 /* Enable mdp_lcdc_pad_pclk(branch) clock */
277 val = 1 << 12;
278 val = val | readl(SH2_MDP_LCDC_NS_REG);
279 writel(val, SH2_MDP_LCDC_NS_REG);
280 }
281 else
282 {
283 /* MDP local clock control not enabled; use proc comm */
284 mdp_clock_init(122880000);
285
286 /* LCDC local clock control not enabled; use proc comm */
287 lcdc_clock_init(27648000);
288 }
289}
Subbaraman Narayanamurthy641dadc2011-01-20 13:44:51 -0800290
291void mddi_pmdh_clock_init(void)
292{
293 unsigned int val = 0;
294 unsigned sh2_own_row1;
295 unsigned sh2_own_row1_pmdh_mask = (1 << 19);
296
297 sh2_own_row1 = readl(SH2_OWN_ROW1_BASE_REG);
298 if(sh2_own_row1 & sh2_own_row1_pmdh_mask)
299 {
300 /* Select clock source and divider */
301 val = 1;
302 val |= (1 << 3);
303 val = val | readl(SH2_PMDH_NS_REG);
304 writel(val, SH2_PMDH_NS_REG);
305
306 /* Enable PMDH_SRC (root) signal */
307 val = 1 << 11;
308 val = val | readl(SH2_PMDH_NS_REG);
309 writel(val, SH2_PMDH_NS_REG);
310
311 /* Enable PMDH_P_CLK */
312 val = 1 << 4;
313 val = val | readl(SH2_GLBL_CLK_ENA_2_SC);
314 writel(val, SH2_GLBL_CLK_ENA_2_SC);
315 }
316 else
317 {
318 /* MDDI local clock control not enabled; use proc comm */
319 mddi_clock_init(0, 480000000);
320 }
321}
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800322
Shashank Mittal1fcde7a2011-07-25 13:41:50 -0700323void ce_clock_init(void)
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800324{
325 unsigned int val=0;
326
327 /* Enable CE_CLK */
328 val = 1 << 6;
329 val = val | readl(SH2_GLBL_CLK_ENA_SC);
330 writel(val, SH2_GLBL_CLK_ENA_SC);
331}
Amol Jadi82254562011-06-27 11:25:48 -0700332
333/* Configure MMC clock */
334void clock_config_mmc(uint32_t interface, uint32_t freq)
335{
336 uint32_t reg = 0;
337
338 if( mmc_clock_set_rate(sdc_clk[interface], freq) < 0 )
339 {
340 dprintf(CRITICAL, "Failure setting clock rate for MCLK - "
341 "clk_rate: %d\n!", freq);
342 ASSERT(0);
343 }
344
345 /* enable clock */
346 if( mmc_clock_enable_disable(sdc_clk[interface], MMC_CLK_ENABLE) < 0 )
347 {
348 dprintf(CRITICAL, "Failure enabling MMC Clock!\n");
349 ASSERT(0);
350 }
351
352 reg |= MMC_BOOT_MCI_CLK_ENABLE;
353 reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
354 reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
355 writel( reg, MMC_BOOT_MCI_CLK );
356}
357
358/* Intialize MMC clock */
359void clock_init_mmc(uint32_t interface)
360{
361 if( mmc_clock_enable_disable(sdc_pclk[interface], MMC_CLK_ENABLE) < 0 )
362 {
363 dprintf(CRITICAL, "Failure enabling PCLK!\n");
364 ASSERT(0);
365 }
366}
367