blob: 1bbc051b1e022b173453114b708c3c55c3ebdb96 [file] [log] [blame]
Channagoud Kadabi672c4c42012-12-20 17:51:45 -08001/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
Ajay Dudani232ce812009-12-02 00:14:11 -08002 *
3 * Redistribution and use in source and binary forms, with or without
Channagoud Kadabi672c4c42012-12-20 17:51:45 -08004 * modification, are permitted provided that the following conditions are
5 * 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
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
Ajay Dudani232ce812009-12-02 00:14:11 -080015 *
Channagoud Kadabi672c4c42012-12-20 17:51:45 -080016 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Ajay Dudani232ce812009-12-02 00:14:11 -080027 */
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))
Ajay Dudanib01e5062011-12-03 23:23:42 -080046#define VREG_CONFIG (BIT(7) | BIT(6)) /* Enable VREG, pull-down if disabled. */
Shashank Mittal0dab8f52010-11-03 16:40:30 -070047#define VREG_DATA (VREG_CONFIG | (VREF_SEL << 5))
Ajay Dudanib01e5062011-12-03 23:23:42 -080048#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. */
Shashank Mittal0dab8f52010-11-03 16:40:30 -070050#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/* enum for SDC CLK IDs */
Ajay Dudanib01e5062011-12-03 23:23:42 -080055enum {
56 SDC1_CLK = 19,
Amol Jadi82254562011-06-27 11:25:48 -070057 SDC1_PCLK = 20,
Ajay Dudanib01e5062011-12-03 23:23:42 -080058 SDC2_CLK = 21,
Amol Jadi82254562011-06-27 11:25:48 -070059 SDC2_PCLK = 22,
Ajay Dudanib01e5062011-12-03 23:23:42 -080060 SDC3_CLK = 23,
Amol Jadi82254562011-06-27 11:25:48 -070061 SDC3_PCLK = 24,
Ajay Dudanib01e5062011-12-03 23:23:42 -080062 SDC4_CLK = 25,
Amol Jadi82254562011-06-27 11:25:48 -070063 SDC4_PCLK = 26
64};
65
66/* Zero'th entry is dummy */
Ajay Dudanib01e5062011-12-03 23:23:42 -080067static uint8_t sdc_clk[] = { 0, SDC1_CLK, SDC2_CLK, SDC3_CLK, SDC4_CLK };
68static uint8_t sdc_pclk[] = { 0, SDC1_PCLK, SDC2_PCLK, SDC3_PCLK, SDC4_PCLK };
Amol Jadi82254562011-06-27 11:25:48 -070069
Shashank Mittal0dab8f52010-11-03 16:40:30 -070070void spm_init(void)
71{
Ajay Dudanib01e5062011-12-03 23:23:42 -080072 writel(0x05, MSM_SAW_BASE + 0x10); /* MSM_SPM_REG_SAW_CFG */
73 writel(0x18, MSM_SAW_BASE + 0x14); /* MSM_SPM_REG_SAW_SPM_CTL */
74 writel(0x00006666, MSM_SAW_BASE + 0x18); /* MSM_SPM_REG_SAW_SPM_SLP_TMR_DLY */
75 writel(0xFF000666, MSM_SAW_BASE + 0x1C); /* MSM_SPM_REG_SAW_SPM_WAKE_TMR_DLY */
Shashank Mittal0dab8f52010-11-03 16:40:30 -070076
Ajay Dudanib01e5062011-12-03 23:23:42 -080077 writel(0x01, MSM_SAW_BASE + 0x24); /* MSM_SPM_REG_SAW_SLP_CLK_EN */
78 writel(0x03, MSM_SAW_BASE + 0x28); /* MSM_SPM_REG_SAW_SLP_HSFS_PRECLMP_EN */
79 writel(0x00, MSM_SAW_BASE + 0x2C); /* MSM_SPM_REG_SAW_SLP_HSFS_POSTCLMP_EN */
Shashank Mittal0dab8f52010-11-03 16:40:30 -070080
Ajay Dudanib01e5062011-12-03 23:23:42 -080081 writel(0x01, MSM_SAW_BASE + 0x30); /* MSM_SPM_REG_SAW_SLP_CLMP_EN */
82 writel(0x00, MSM_SAW_BASE + 0x34); /* MSM_SPM_REG_SAW_SLP_RST_EN */
83 writel(0x00, MSM_SAW_BASE + 0x38); /* MSM_SPM_REG_SAW_SPM_MPM_CFG */
Shashank Mittal0dab8f52010-11-03 16:40:30 -070084}
85
86/* Configures msmc2 voltage. vlevel is in mV */
87void msmc2_config(unsigned vlevel)
88{
Ajay Dudanib01e5062011-12-03 23:23:42 -080089 unsigned val;
90 val = readl(MSM_SAW_BASE + 0x08); /* MSM_SPM_REG_SAW_VCTL */
91 val &= ~0xFF;
92 val |= VDD_RAW(vlevel);
93 writel(val, MSM_SAW_BASE + 0x08); /* MSM_SPM_REG_SAW_VCTL */
Shashank Mittal0dab8f52010-11-03 16:40:30 -070094
Ajay Dudanib01e5062011-12-03 23:23:42 -080095 /* Wait for PMIC state to return to idle and for VDD to stabilize */
96 while (((readl(MSM_SAW_BASE + 0x0C) >> 0x20) & 0x3) != 0) ;
97 udelay(160);
Shashank Mittal0dab8f52010-11-03 16:40:30 -070098}
99
100void enable_pll(unsigned num)
101{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800102 unsigned reg_val;
103 reg_val = readl(PLL_ENA_REG);
104 reg_val |= (1 << num);
105 writel(reg_val, PLL_ENA_REG);
106 /* Wait until PLL is enabled */
107 while ((readl(PLL2_STATUS_BASE_REG) & (1 << 16)) == 0) ;
Shashank Mittal0dab8f52010-11-03 16:40:30 -0700108}
109
Ajay Dudani232ce812009-12-02 00:14:11 -0800110void acpu_clock_init(void)
111{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800112 unsigned clk, reg_clksel, reg_clkctl, src_sel;
113 /* Fixing msmc2 voltage */
114 spm_init();
Ajay Dudani1c798cf2011-01-19 14:27:50 -0800115
Ajay Dudanib01e5062011-12-03 23:23:42 -0800116 clk = readl(PLL2_L_VAL_ADDR) & 0xFF;
117 if (clk == ACPU_806MHZ)
118 msmc2_config(1100);
119 else if (clk == ACPU_1024MHZ || clk == ACPU_1200MHZ)
120 msmc2_config(1200);
121 else if (clk == ACPU_1400MHZ)
122 msmc2_config(1250);
Shashank Mittal0dab8f52010-11-03 16:40:30 -0700123
Ajay Dudanib01e5062011-12-03 23:23:42 -0800124 /* Enable pll 2 */
125 enable_pll(2);
Shashank Mittal0dab8f52010-11-03 16:40:30 -0700126
Ajay Dudanib01e5062011-12-03 23:23:42 -0800127 reg_clksel = readl(SCSS_CLK_SEL);
Shashank Mittal0dab8f52010-11-03 16:40:30 -0700128
Ajay Dudanib01e5062011-12-03 23:23:42 -0800129 /* CLK_SEL_SRC1NO */
130 src_sel = reg_clksel & 1;
Shashank Mittal0dab8f52010-11-03 16:40:30 -0700131
Ajay Dudanib01e5062011-12-03 23:23:42 -0800132 /* Program clock source and divider. */
133 reg_clkctl = readl(SCSS_CLK_CTL);
134 reg_clkctl &= ~(0xFF << (8 * src_sel));
135 reg_clkctl |= ACPU_SRC_SEL << (4 + 8 * src_sel);
136 reg_clkctl |= ACPU_SRC_DIV << (0 + 8 * src_sel);
137 writel(reg_clkctl, SCSS_CLK_CTL);
Shashank Mittal0dab8f52010-11-03 16:40:30 -0700138
Ajay Dudanib01e5062011-12-03 23:23:42 -0800139 /* Toggle clock source. */
140 reg_clksel ^= 1;
Shashank Mittal0dab8f52010-11-03 16:40:30 -0700141
Ajay Dudanib01e5062011-12-03 23:23:42 -0800142 /* Program clock source selection. */
143 writel(reg_clksel, SCSS_CLK_SEL);
Chandan Uddaraju35f77182010-09-23 15:21:45 -0700144}
Ajay Dudani7d605522010-10-01 19:52:37 -0700145
146void hsusb_clock_init(void)
147{
148 int val = 0;
149 unsigned sh2_own_row2;
150 unsigned sh2_own_row2_hsusb_mask = (1 << 11);
151
152 sh2_own_row2 = readl(SH2_OWN_ROW2_BASE_REG);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800153 if (sh2_own_row2 & sh2_own_row2_hsusb_mask) {
Ajay Dudani7d605522010-10-01 19:52:37 -0700154 /* USB local clock control enabled */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800155 /* Set value in MD register */
156 val = 0x5DF;
157 writel(val, SH2_USBH_MD_REG);
Ajay Dudani7d605522010-10-01 19:52:37 -0700158
Ajay Dudanib01e5062011-12-03 23:23:42 -0800159 /* Set value in NS register */
160 val = 1 << 8;
161 val = val | readl(SH2_USBH_NS_REG);
162 writel(val, SH2_USBH_NS_REG);
Ajay Dudani7d605522010-10-01 19:52:37 -0700163
Ajay Dudanib01e5062011-12-03 23:23:42 -0800164 val = 1 << 11;
165 val = val | readl(SH2_USBH_NS_REG);
166 writel(val, SH2_USBH_NS_REG);
Ajay Dudani7d605522010-10-01 19:52:37 -0700167
Ajay Dudanib01e5062011-12-03 23:23:42 -0800168 val = 1 << 9;
169 val = val | readl(SH2_USBH_NS_REG);
170 writel(val, SH2_USBH_NS_REG);
Ajay Dudani7d605522010-10-01 19:52:37 -0700171
Ajay Dudanib01e5062011-12-03 23:23:42 -0800172 val = 1 << 13;
173 val = val | readl(SH2_USBH_NS_REG);
174 writel(val, SH2_USBH_NS_REG);
Ajay Dudani7d605522010-10-01 19:52:37 -0700175
Ajay Dudanib01e5062011-12-03 23:23:42 -0800176 /* Enable USBH_P_CLK */
177 val = 1 << 25;
178 val = val | readl(SH2_GLBL_CLK_ENA_SC);
179 writel(val, SH2_GLBL_CLK_ENA_SC);
180 } else {
Ajay Dudani7d605522010-10-01 19:52:37 -0700181 /* USB local clock control not enabled; use proc comm */
182 usb_clock_init();
183 }
184}
Subbaraman Narayanamurthy4cc29732010-10-18 15:57:58 -0700185
186void adm_enable_clock(void)
187{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800188 unsigned int val = 0;
Subbaraman Narayanamurthy4cc29732010-10-18 15:57:58 -0700189
190 /* Enable ADM_CLK */
191 val = 1 << 5;
192 val = val | readl(SH2_GLBL_CLK_ENA_SC);
193 writel(val, SH2_GLBL_CLK_ENA_SC);
194}
Subbaraman Narayanamurthyd962c792011-01-19 20:53:07 -0800195
196void mdp_lcdc_clock_init(void)
197{
198 unsigned int val = 0;
199 unsigned sh2_own_apps2;
200 unsigned sh2_own_apps2_lcdc_mask = (1 << 3);
201
202 sh2_own_apps2 = readl(SH2_OWN_APPS2_BASE_REG);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800203 if (sh2_own_apps2 & sh2_own_apps2_lcdc_mask) {
Subbaraman Narayanamurthyd962c792011-01-19 20:53:07 -0800204 /* MDP local clock control enabled */
205 /* Select clock source and divider */
206 val = 0x29;
207 val = val | readl(SH2_MDP_NS_REG);
208 writel(val, SH2_MDP_NS_REG);
209
210 /* Enable MDP source clock(root) */
211 val = 1 << 11;
212 val = val | readl(SH2_MDP_NS_REG);
213 writel(val, SH2_MDP_NS_REG);
214
215 /* Enable graphics clock(branch) */
216 val = 1 << 9;
217 val = val | readl(SH2_MDP_NS_REG);
218 writel(val, SH2_MDP_NS_REG);
219
220 /* Enable MDP_P_CLK */
221 val = 1 << 6;
222 val = val | readl(SH2_GLBL_CLK_ENA_2_SC);
223 writel(val, SH2_GLBL_CLK_ENA_2_SC);
224
225 /* Enable AXI_MDP_CLK */
226 val = 1 << 29;
227 val = val | readl(SH2_GLBL_CLK_ENA_2_SC);
228 writel(val, SH2_GLBL_CLK_ENA_2_SC);
229
230 /* LCDC local clock control enabled */
231 /* Set value in MD register */
232 val = 0x1FFF9;
233 writel(val, SH2_MDP_LCDC_MD_REG);
234
235 /* Set MDP_LCDC_N_VAL in NS register */
236 val = 0xFFFA << 16;
237 val = val | readl(SH2_MDP_LCDC_NS_REG);
238 writel(val, SH2_MDP_LCDC_NS_REG);
239
240 /* Set clock source */
241 val = 1;
242 val = val | readl(SH2_MDP_LCDC_NS_REG);
243 writel(val, SH2_MDP_LCDC_NS_REG);
244
245 /* Set divider */
246 val = 3 << 3;
247 val = val | readl(SH2_MDP_LCDC_NS_REG);
248 writel(val, SH2_MDP_LCDC_NS_REG);
249
250 /* Set MN counter mode */
251 val = 2 << 5;
252 val = val | readl(SH2_MDP_LCDC_NS_REG);
253 writel(val, SH2_MDP_LCDC_NS_REG);
254
255 /* Enable MN counter */
256 val = 1 << 8;
257 val = val | readl(SH2_MDP_LCDC_NS_REG);
258 writel(val, SH2_MDP_LCDC_NS_REG);
259
260 /* Enable mdp_lcdc_src(root) clock */
261 val = 1 << 11;
262 val = val | readl(SH2_MDP_LCDC_NS_REG);
263 writel(val, SH2_MDP_LCDC_NS_REG);
264
265 /* Enable mdp_lcdc_pclk(branch) clock */
266 val = 1 << 9;
267 val = val | readl(SH2_MDP_LCDC_NS_REG);
268 writel(val, SH2_MDP_LCDC_NS_REG);
269
270 /* Enable mdp_lcdc_pad_pclk(branch) clock */
271 val = 1 << 12;
272 val = val | readl(SH2_MDP_LCDC_NS_REG);
273 writel(val, SH2_MDP_LCDC_NS_REG);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800274 } else {
Subbaraman Narayanamurthyd962c792011-01-19 20:53:07 -0800275 /* MDP local clock control not enabled; use proc comm */
276 mdp_clock_init(122880000);
277
278 /* LCDC local clock control not enabled; use proc comm */
279 lcdc_clock_init(27648000);
280 }
281}
Subbaraman Narayanamurthy641dadc2011-01-20 13:44:51 -0800282
283void mddi_pmdh_clock_init(void)
284{
285 unsigned int val = 0;
286 unsigned sh2_own_row1;
287 unsigned sh2_own_row1_pmdh_mask = (1 << 19);
288
289 sh2_own_row1 = readl(SH2_OWN_ROW1_BASE_REG);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800290 if (sh2_own_row1 & sh2_own_row1_pmdh_mask) {
Subbaraman Narayanamurthy641dadc2011-01-20 13:44:51 -0800291 /* Select clock source and divider */
292 val = 1;
293 val |= (1 << 3);
294 val = val | readl(SH2_PMDH_NS_REG);
295 writel(val, SH2_PMDH_NS_REG);
296
297 /* Enable PMDH_SRC (root) signal */
298 val = 1 << 11;
299 val = val | readl(SH2_PMDH_NS_REG);
300 writel(val, SH2_PMDH_NS_REG);
301
302 /* Enable PMDH_P_CLK */
303 val = 1 << 4;
304 val = val | readl(SH2_GLBL_CLK_ENA_2_SC);
305 writel(val, SH2_GLBL_CLK_ENA_2_SC);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800306 } else {
Subbaraman Narayanamurthy641dadc2011-01-20 13:44:51 -0800307 /* MDDI local clock control not enabled; use proc comm */
308 mddi_clock_init(0, 480000000);
309 }
310}
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800311
Shashank Mittal1fcde7a2011-07-25 13:41:50 -0700312void ce_clock_init(void)
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800313{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800314 unsigned int val = 0;
Subbaraman Narayanamurthy9b7276c2011-01-25 17:25:30 -0800315
316 /* Enable CE_CLK */
317 val = 1 << 6;
318 val = val | readl(SH2_GLBL_CLK_ENA_SC);
319 writel(val, SH2_GLBL_CLK_ENA_SC);
320}
Amol Jadi82254562011-06-27 11:25:48 -0700321
322/* Configure MMC clock */
323void clock_config_mmc(uint32_t interface, uint32_t freq)
324{
325 uint32_t reg = 0;
326
Ajay Dudanib01e5062011-12-03 23:23:42 -0800327 if (mmc_clock_set_rate(sdc_clk[interface], freq) < 0) {
Amol Jadi82254562011-06-27 11:25:48 -0700328 dprintf(CRITICAL, "Failure setting clock rate for MCLK - "
Ajay Dudanib01e5062011-12-03 23:23:42 -0800329 "clk_rate: %d\n!", freq);
Amol Jadi82254562011-06-27 11:25:48 -0700330 ASSERT(0);
331 }
332
333 /* enable clock */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800334 if (mmc_clock_enable_disable(sdc_clk[interface], MMC_CLK_ENABLE) < 0) {
Amol Jadi82254562011-06-27 11:25:48 -0700335 dprintf(CRITICAL, "Failure enabling MMC Clock!\n");
336 ASSERT(0);
337 }
338
339 reg |= MMC_BOOT_MCI_CLK_ENABLE;
340 reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
341 reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800342 writel(reg, MMC_BOOT_MCI_CLK);
Channagoud Kadabi672c4c42012-12-20 17:51:45 -0800343
344 /* Wait for the MMC_BOOT_MCI_CLK write to go through. */
345 mmc_mclk_reg_wr_delay();
346
347 /* Wait 1 ms to provide the free running SD CLK to the card. */
348 mdelay(1);
Amol Jadi82254562011-06-27 11:25:48 -0700349}
350
351/* Intialize MMC clock */
352void clock_init_mmc(uint32_t interface)
353{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800354 if (mmc_clock_enable_disable(sdc_pclk[interface], MMC_CLK_ENABLE) < 0) {
355 dprintf(CRITICAL, "Failure enabling PCLK!\n");
Amol Jadi82254562011-06-27 11:25:48 -0700356 ASSERT(0);
357 }
358}