blob: 3e7602deb0e2c481a818a9dbf51cde441eae43be [file] [log] [blame]
Shashank Mittal246f8d02011-01-21 17:12:27 -08001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
Channagoud Kadabi672c4c42012-12-20 17:51:45 -08004 * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
Shashank Mittal246f8d02011-01-21 17:12:27 -08005 *
6 * Redistribution and use in source and binary forms, with or without
Channagoud Kadabi672c4c42012-12-20 17:51:45 -08007 * modification, are permitted provided that the following conditions are
8 * met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 * * Neither the name of The Linux Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
Shashank Mittal246f8d02011-01-21 17:12:27 -080018 *
Channagoud Kadabi672c4c42012-12-20 17:51:45 -080019 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Shashank Mittal246f8d02011-01-21 17:12:27 -080030 */
31
32#include <stdint.h>
33#include <kernel/thread.h>
34#include <platform/iomap.h>
35#include <reg.h>
Shashank Mittal83978442011-04-01 19:41:22 -070036#include <smem.h>
Amol Jadi82254562011-06-27 11:25:48 -070037#include <debug.h>
38#include <mmc.h>
Shashank Mittal246f8d02011-01-21 17:12:27 -080039
40#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
Shashank Mittal83978442011-04-01 19:41:22 -070041#define BIT(x) (1 << (x))
Shashank Mittal246f8d02011-01-21 17:12:27 -080042
43#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
44#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
45#define VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124)
Shashank Mittal246f8d02011-01-21 17:12:27 -080046
Shashank Mittal83978442011-04-01 19:41:22 -070047#define PLL2_MODE_ADDR (MSM_CLK_CTL_BASE + 0x338)
48#define PLL4_MODE_ADDR (MSM_CLK_CTL_BASE + 0x374)
49
50#define PLL_RESET_N BIT(2)
51#define PLL_BYPASSNL BIT(1)
52#define PLL_OUTCTRL BIT(0)
53
Ajay Dudanib01e5062011-12-03 23:23:42 -080054#define SRC_SEL_TCX0 0 /* TCXO */
55#define SRC_SEL_PLL1 1 /* PLL1: modem_pll */
56#define SRC_SEL_PLL2 2 /* PLL2: backup_pll_0 */
57#define SRC_SEL_PLL3 3 /* PLL3: backup_pll_1 */
58#define SRC_SEL_PLL4 6 /* PLL4: sparrow_pll */
Shashank Mittal83978442011-04-01 19:41:22 -070059
60#define DIV_1 0
Shashank Mittal246f8d02011-01-21 17:12:27 -080061#define DIV_2 1
Shashank Mittal83978442011-04-01 19:41:22 -070062#define DIV_3 2
63#define DIV_4 3
64#define DIV_5 4
65#define DIV_6 5
66#define DIV_7 6
67#define DIV_8 7
68#define DIV_9 8
69#define DIV_10 9
70#define DIV_11 10
71#define DIV_12 11
72#define DIV_13 12
73#define DIV_14 13
74#define DIV_15 14
75#define DIV_16 15
76
Shashank Mittal246f8d02011-01-21 17:12:27 -080077#define WAIT_CNT 100
Shashank Mittal246f8d02011-01-21 17:12:27 -080078#define MIN_AXI_HZ 120000000
79#define ACPU_800MHZ 41
80
Channagoud Kadabic0b0a362012-04-19 13:37:25 +053081#define A11S_CLK_SEL_MASK 0x1 /* bits 2:0 */
Shashank Mittal302a6332011-05-04 10:32:48 -070082
Shashank Mittal246f8d02011-01-21 17:12:27 -080083/* The stepping frequencies have been choosen to make sure the step
Shashank Mittal83978442011-04-01 19:41:22 -070084 * is <= 256 MHz for both 7x27a and 7x25a targets. The
Shashank Mittal246f8d02011-01-21 17:12:27 -080085 * table also assumes the ACPU is running at TCXO freq and AHB div is
86 * set to DIV_1.
87 *
88 * To use the tables:
89 * - Start at location 0/1 depending on clock source sel bit.
90 * - Set values till end of table skipping every other entry.
91 * - When you reach the end of the table, you are done scaling.
Shashank Mittal246f8d02011-01-21 17:12:27 -080092 */
93
Shashank Mittal83978442011-04-01 19:41:22 -070094uint32_t const clk_cntl_reg_val_7627A[] = {
Ajay Dudanib01e5062011-12-03 23:23:42 -080095 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_16,
Shashank Mittal83978442011-04-01 19:41:22 -070096 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_8 << 8),
Ajay Dudanib01e5062011-12-03 23:23:42 -080097 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_4,
Shashank Mittal246f8d02011-01-21 17:12:27 -080098 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_2 << 8),
Shashank Mittal83978442011-04-01 19:41:22 -070099
100 /* TODO: Fix it for 800MHz */
101#if 0
Ajay Dudanib01e5062011-12-03 23:23:42 -0800102 (WAIT_CNT << 16) | (SRC_SEL_PLL4 << 4) | DIV_1,
Shashank Mittal83978442011-04-01 19:41:22 -0700103#endif
Shashank Mittal246f8d02011-01-21 17:12:27 -0800104};
105
Channagoud Kadabi3acfb742011-11-15 18:19:32 +0530106/*
107 * Use PLL4 to run acpu @ 1.2 GHZ
108 */
109uint32_t const clk_cntl_reg_val_8X25[] = {
110 (WAIT_CNT << 16) | (SRC_SEL_PLL4 << 4) | DIV_2,
111 (WAIT_CNT << 16) | (SRC_SEL_PLL4 << 12) | (DIV_1 << 8),
112};
113
Shashank Mittal83978442011-04-01 19:41:22 -0700114uint32_t const clk_cntl_reg_val_7625A[] = {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800115 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_16,
Shashank Mittal83978442011-04-01 19:41:22 -0700116 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_8 << 8),
Ajay Dudanib01e5062011-12-03 23:23:42 -0800117 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_4,
Shashank Mittal83978442011-04-01 19:41:22 -0700118 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_2 << 8),
Shashank Mittal246f8d02011-01-21 17:12:27 -0800119};
120
Shashank Mittal302a6332011-05-04 10:32:48 -0700121/* Using DIV_1 for all cases to avoid worrying about turbo vs. normal
122 * mode. Able to use DIV_1 for all steps because it's the largest AND
Shashank Mittal246f8d02011-01-21 17:12:27 -0800123 * the final value. */
124uint32_t const clk_sel_reg_val[] = {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800125 DIV_1 << 1 | 1, /* Switch to src1 */
126 DIV_1 << 1 | 0, /* Switch to src0 */
Shashank Mittal83978442011-04-01 19:41:22 -0700127};
128
129/*
130 * Mask to make sure current selected src frequency doesn't change.
131 */
132uint32_t const clk_cntl_mask[] = {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800133 0x0000FF00, /* Mask to read src0 */
134 0x000000FF /* Mask to read src1 */
Shashank Mittal246f8d02011-01-21 17:12:27 -0800135};
136
Amol Jadi82254562011-06-27 11:25:48 -0700137/* enum for SDC CLK IDs */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800138enum {
139 SDC1_CLK = 19,
Amol Jadi82254562011-06-27 11:25:48 -0700140 SDC1_PCLK = 20,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800141 SDC2_CLK = 21,
Amol Jadi82254562011-06-27 11:25:48 -0700142 SDC2_PCLK = 22,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800143 SDC3_CLK = 23,
Amol Jadi82254562011-06-27 11:25:48 -0700144 SDC3_PCLK = 24,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800145 SDC4_CLK = 25,
Amol Jadi82254562011-06-27 11:25:48 -0700146 SDC4_PCLK = 26
147};
148
149/* Zero'th entry is dummy */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800150static uint8_t sdc_clk[] = { 0, SDC1_CLK, SDC2_CLK, SDC3_CLK, SDC4_CLK };
151static uint8_t sdc_pclk[] = { 0, SDC1_PCLK, SDC2_PCLK, SDC3_PCLK, SDC4_PCLK };
Amol Jadi82254562011-06-27 11:25:48 -0700152
Aparna Mallavarapuc1eb99b2012-09-24 20:13:42 +0530153/* VDD_PLEVEL */
154unsigned vdd_plevel = 0;
155
Shashank Mittal246f8d02011-01-21 17:12:27 -0800156void mdelay(unsigned msecs);
Shashank Mittal83978442011-04-01 19:41:22 -0700157unsigned board_msm_id(void);
Aparna Mallavarapuc1eb99b2012-09-24 20:13:42 +0530158unsigned board_msm_version(void);
Shashank Mittal246f8d02011-01-21 17:12:27 -0800159
Shashank Mittal83978442011-04-01 19:41:22 -0700160void pll_enable(void *pll_mode_addr)
161{
162 /* TODO: Need to add spin-lock to avoid race conditions */
163
164 uint32_t nVal;
165 /* Check status */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800166 nVal = readl(pll_mode_addr);
167 if (nVal & PLL_OUTCTRL)
Shashank Mittal83978442011-04-01 19:41:22 -0700168 return;
169
170 /* Put the PLL in reset mode */
171 nVal = 0;
172 nVal &= ~PLL_RESET_N;
173 nVal &= ~PLL_BYPASSNL;
174 nVal &= ~PLL_OUTCTRL;
175 writel(nVal, pll_mode_addr);
176
177 /* Put the PLL in warm-up mode */
178 nVal |= PLL_RESET_N;
179 nVal |= PLL_BYPASSNL;
180 writel(nVal, pll_mode_addr);
181
182 /* Wait for the PLL warm-up time */
183 udelay(50);
184
185 /* Put the PLL in active mode */
186 nVal |= PLL_RESET_N;
187 nVal |= PLL_BYPASSNL;
188 nVal |= PLL_OUTCTRL;
189 writel(nVal, pll_mode_addr);
190}
191
192void pll_request(unsigned pll, unsigned enable)
193{
194 int val = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800195 if (!enable) {
Shashank Mittal83978442011-04-01 19:41:22 -0700196 /* Disable not supported */
197 return;
198 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800199 switch (pll) {
200 case 2:
201 pll_enable(PLL2_MODE_ADDR);
202 return;
203 case 4:
204 pll_enable(PLL4_MODE_ADDR);
205 return;
206 default:
207 return;
Shashank Mittal83978442011-04-01 19:41:22 -0700208 };
209}
Shashank Mittal246f8d02011-01-21 17:12:27 -0800210
211void acpu_clock_init(void)
212{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800213 uint32_t i, clk;
Shashank Mittal83978442011-04-01 19:41:22 -0700214 uint32_t val;
215 uint32_t *clk_cntl_reg_val, size;
Aparna Mallavarapuc1eb99b2012-09-24 20:13:42 +0530216 unsigned msm_id, msm_version;
Shashank Mittal246f8d02011-01-21 17:12:27 -0800217
Aparna Mallavarapuc1eb99b2012-09-24 20:13:42 +0530218 msm_version = board_msm_version();
219 if (msm_version == 2)
220 vdd_plevel = 4;
221 else
222 vdd_plevel = 6;
Shashank Mittal83978442011-04-01 19:41:22 -0700223
Aparna Mallavarapuc1eb99b2012-09-24 20:13:42 +0530224 /* Set VDD plevel */
225 writel((1 << 7) | (vdd_plevel << 3), VDD_SVS_PLEVEL_ADDR);
Shashank Mittal246f8d02011-01-21 17:12:27 -0800226#if (!ENABLE_NANDWRITE)
227 thread_sleep(1);
228#else
Shashank Mittal83978442011-04-01 19:41:22 -0700229 mdelay(1);
Shashank Mittal246f8d02011-01-21 17:12:27 -0800230#endif
231
Shashank Mittal83978442011-04-01 19:41:22 -0700232 msm_id = board_msm_id();
Ajay Dudanib01e5062011-12-03 23:23:42 -0800233 switch (msm_id) {
234 case MSM7227A:
235 case MSM7627A:
236 case ESM7227A:
237 clk_cntl_reg_val = clk_cntl_reg_val_7627A;
238 size = ARRAY_SIZE(clk_cntl_reg_val_7627A);
239 pll_request(2, 1);
Shashank Mittal5d564b62011-05-12 10:51:07 -0700240
241 /* TODO: Enable this PLL while switching to 800MHz */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800242#if 0
243 pll_request(4, 1);
244#endif
245 break;
Channagoud Kadabi3acfb742011-11-15 18:19:32 +0530246 case MSM8625:
247 /* Fix me: Will move to PLL4 later */
248 clk_cntl_reg_val = clk_cntl_reg_val_7627A;
249 size = ARRAY_SIZE(clk_cntl_reg_val_7627A);
250 pll_request(2, 1);
251 break;
Shashank Mittal83978442011-04-01 19:41:22 -0700252
Ajay Dudanib01e5062011-12-03 23:23:42 -0800253 case MSM7225A:
254 case MSM7625A:
255 default:
256 clk_cntl_reg_val = clk_cntl_reg_val_7625A;
257 size = ARRAY_SIZE(clk_cntl_reg_val_7625A);
258 pll_request(2, 1);
259 break;
Shashank Mittal83978442011-04-01 19:41:22 -0700260 };
261
Shashank Mittal246f8d02011-01-21 17:12:27 -0800262 /* Read clock source select bit. */
Shashank Mittal83978442011-04-01 19:41:22 -0700263 val = readl(A11S_CLK_SEL_ADDR);
264 i = val & 1;
Shashank Mittal246f8d02011-01-21 17:12:27 -0800265
Shashank Mittal83978442011-04-01 19:41:22 -0700266 /* Jump into table and set every entry. */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800267 for (; i < size; i++) {
Shashank Mittal83978442011-04-01 19:41:22 -0700268
Channagoud Kadabic0b0a362012-04-19 13:37:25 +0530269 val = readl(A11S_CLK_SEL_ADDR);
270 val |= BIT(1) | BIT(2);
271 writel(val, A11S_CLK_SEL_ADDR);
272
Shashank Mittal83978442011-04-01 19:41:22 -0700273 val = readl(A11S_CLK_CNTL_ADDR);
274
275 /* Make sure not to disturb already used src */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800276 val &= clk_cntl_mask[i % 2];
Shashank Mittal83978442011-04-01 19:41:22 -0700277 val += clk_cntl_reg_val[i];
278 writel(val, A11S_CLK_CNTL_ADDR);
279
Shashank Mittal246f8d02011-01-21 17:12:27 -0800280 /* Would need a dmb() here but the whole address space is
281 * strongly ordered, so it should be fine.
282 */
Shashank Mittal302a6332011-05-04 10:32:48 -0700283 val = readl(A11S_CLK_SEL_ADDR);
284 val &= ~(A11S_CLK_SEL_MASK);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800285 val |= (A11S_CLK_SEL_MASK & clk_sel_reg_val[i % 2]);
Shashank Mittal302a6332011-05-04 10:32:48 -0700286 writel(val, A11S_CLK_SEL_ADDR);
287
Shashank Mittal246f8d02011-01-21 17:12:27 -0800288#if (!ENABLE_NANDWRITE)
289 thread_sleep(1);
290#else
291 mdelay(1);
292#endif
293 }
294}
Shashank Mittalef325412011-04-01 13:48:26 -0700295
296void hsusb_clock_init(void)
297{
298 /* USB local clock control not enabled; use proc comm */
299 usb_clock_init();
300}
Amol Jadi82254562011-06-27 11:25:48 -0700301
302/* Configure MMC clock */
303void clock_config_mmc(uint32_t interface, uint32_t freq)
304{
305 uint32_t reg = 0;
306
Ajay Dudanib01e5062011-12-03 23:23:42 -0800307 if (mmc_clock_set_rate(sdc_clk[interface], freq) < 0) {
Amol Jadi82254562011-06-27 11:25:48 -0700308 dprintf(CRITICAL, "Failure setting clock rate for MCLK - "
Ajay Dudanib01e5062011-12-03 23:23:42 -0800309 "clk_rate: %d\n!", freq);
Amol Jadi82254562011-06-27 11:25:48 -0700310 ASSERT(0);
311 }
312
313 /* enable clock */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800314 if (mmc_clock_enable_disable(sdc_clk[interface], MMC_CLK_ENABLE) < 0) {
Amol Jadi82254562011-06-27 11:25:48 -0700315 dprintf(CRITICAL, "Failure enabling MMC Clock!\n");
316 ASSERT(0);
317 }
318
319 reg |= MMC_BOOT_MCI_CLK_ENABLE;
320 reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
321 reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800322 writel(reg, MMC_BOOT_MCI_CLK);
Channagoud Kadabi672c4c42012-12-20 17:51:45 -0800323
324 /* Wait for the MMC_BOOT_MCI_CLK write to go through. */
325 mmc_mclk_reg_wr_delay();
326
327 /* Wait 1 ms to provide the free running SD CLK to the card. */
328 mdelay(1);
Amol Jadi82254562011-06-27 11:25:48 -0700329}
330
331/* Intialize MMC clock */
332void clock_init_mmc(uint32_t interface)
333{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800334 if (mmc_clock_enable_disable(sdc_pclk[interface], MMC_CLK_ENABLE) < 0) {
Amol Jadi82254562011-06-27 11:25:48 -0700335 dprintf(CRITICAL, "Failure enabling PCLK!\n");
336 ASSERT(0);
337 }
338}