blob: 3cf93865fcb8bf5aeda453214b5b4ffaba1498c1 [file] [log] [blame]
Shashank Mittal246f8d02011-01-21 17:12:27 -08001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
Channagoud Kadabi3acfb742011-11-15 18:19:32 +05304 * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
Shashank Mittal246f8d02011-01-21 17:12:27 -08005 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are 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 copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <stdint.h>
31#include <kernel/thread.h>
32#include <platform/iomap.h>
33#include <reg.h>
Shashank Mittal83978442011-04-01 19:41:22 -070034#include <smem.h>
Amol Jadi82254562011-06-27 11:25:48 -070035#include <debug.h>
36#include <mmc.h>
Shashank Mittal246f8d02011-01-21 17:12:27 -080037
38#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
Shashank Mittal83978442011-04-01 19:41:22 -070039#define BIT(x) (1 << (x))
Shashank Mittal246f8d02011-01-21 17:12:27 -080040
41#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
42#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
43#define VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124)
Shashank Mittal246f8d02011-01-21 17:12:27 -080044
Shashank Mittal83978442011-04-01 19:41:22 -070045#define PLL2_MODE_ADDR (MSM_CLK_CTL_BASE + 0x338)
46#define PLL4_MODE_ADDR (MSM_CLK_CTL_BASE + 0x374)
47
48#define PLL_RESET_N BIT(2)
49#define PLL_BYPASSNL BIT(1)
50#define PLL_OUTCTRL BIT(0)
51
Ajay Dudanib01e5062011-12-03 23:23:42 -080052#define SRC_SEL_TCX0 0 /* TCXO */
53#define SRC_SEL_PLL1 1 /* PLL1: modem_pll */
54#define SRC_SEL_PLL2 2 /* PLL2: backup_pll_0 */
55#define SRC_SEL_PLL3 3 /* PLL3: backup_pll_1 */
56#define SRC_SEL_PLL4 6 /* PLL4: sparrow_pll */
Shashank Mittal83978442011-04-01 19:41:22 -070057
58#define DIV_1 0
Shashank Mittal246f8d02011-01-21 17:12:27 -080059#define DIV_2 1
Shashank Mittal83978442011-04-01 19:41:22 -070060#define DIV_3 2
61#define DIV_4 3
62#define DIV_5 4
63#define DIV_6 5
64#define DIV_7 6
65#define DIV_8 7
66#define DIV_9 8
67#define DIV_10 9
68#define DIV_11 10
69#define DIV_12 11
70#define DIV_13 12
71#define DIV_14 13
72#define DIV_15 14
73#define DIV_16 15
74
Shashank Mittal246f8d02011-01-21 17:12:27 -080075#define WAIT_CNT 100
76#define VDD_LEVEL 7
77#define MIN_AXI_HZ 120000000
78#define ACPU_800MHZ 41
79
Channagoud Kadabic0b0a362012-04-19 13:37:25 +053080#define A11S_CLK_SEL_MASK 0x1 /* bits 2:0 */
Shashank Mittal302a6332011-05-04 10:32:48 -070081
Shashank Mittal246f8d02011-01-21 17:12:27 -080082/* The stepping frequencies have been choosen to make sure the step
Shashank Mittal83978442011-04-01 19:41:22 -070083 * is <= 256 MHz for both 7x27a and 7x25a targets. The
Shashank Mittal246f8d02011-01-21 17:12:27 -080084 * table also assumes the ACPU is running at TCXO freq and AHB div is
85 * set to DIV_1.
86 *
87 * To use the tables:
88 * - Start at location 0/1 depending on clock source sel bit.
89 * - Set values till end of table skipping every other entry.
90 * - When you reach the end of the table, you are done scaling.
Shashank Mittal246f8d02011-01-21 17:12:27 -080091 */
92
Shashank Mittal83978442011-04-01 19:41:22 -070093uint32_t const clk_cntl_reg_val_7627A[] = {
Ajay Dudanib01e5062011-12-03 23:23:42 -080094 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_16,
Shashank Mittal83978442011-04-01 19:41:22 -070095 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_8 << 8),
Ajay Dudanib01e5062011-12-03 23:23:42 -080096 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_4,
Shashank Mittal246f8d02011-01-21 17:12:27 -080097 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_2 << 8),
Shashank Mittal83978442011-04-01 19:41:22 -070098
99 /* TODO: Fix it for 800MHz */
100#if 0
Ajay Dudanib01e5062011-12-03 23:23:42 -0800101 (WAIT_CNT << 16) | (SRC_SEL_PLL4 << 4) | DIV_1,
Shashank Mittal83978442011-04-01 19:41:22 -0700102#endif
Shashank Mittal246f8d02011-01-21 17:12:27 -0800103};
104
Channagoud Kadabi3acfb742011-11-15 18:19:32 +0530105/*
106 * Use PLL4 to run acpu @ 1.2 GHZ
107 */
108uint32_t const clk_cntl_reg_val_8X25[] = {
109 (WAIT_CNT << 16) | (SRC_SEL_PLL4 << 4) | DIV_2,
110 (WAIT_CNT << 16) | (SRC_SEL_PLL4 << 12) | (DIV_1 << 8),
111};
112
Shashank Mittal83978442011-04-01 19:41:22 -0700113uint32_t const clk_cntl_reg_val_7625A[] = {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800114 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_16,
Shashank Mittal83978442011-04-01 19:41:22 -0700115 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_8 << 8),
Ajay Dudanib01e5062011-12-03 23:23:42 -0800116 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_4,
Shashank Mittal83978442011-04-01 19:41:22 -0700117 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_2 << 8),
Shashank Mittal246f8d02011-01-21 17:12:27 -0800118};
119
Shashank Mittal302a6332011-05-04 10:32:48 -0700120/* Using DIV_1 for all cases to avoid worrying about turbo vs. normal
121 * mode. Able to use DIV_1 for all steps because it's the largest AND
Shashank Mittal246f8d02011-01-21 17:12:27 -0800122 * the final value. */
123uint32_t const clk_sel_reg_val[] = {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800124 DIV_1 << 1 | 1, /* Switch to src1 */
125 DIV_1 << 1 | 0, /* Switch to src0 */
Shashank Mittal83978442011-04-01 19:41:22 -0700126};
127
128/*
129 * Mask to make sure current selected src frequency doesn't change.
130 */
131uint32_t const clk_cntl_mask[] = {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800132 0x0000FF00, /* Mask to read src0 */
133 0x000000FF /* Mask to read src1 */
Shashank Mittal246f8d02011-01-21 17:12:27 -0800134};
135
Amol Jadi82254562011-06-27 11:25:48 -0700136/* enum for SDC CLK IDs */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800137enum {
138 SDC1_CLK = 19,
Amol Jadi82254562011-06-27 11:25:48 -0700139 SDC1_PCLK = 20,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800140 SDC2_CLK = 21,
Amol Jadi82254562011-06-27 11:25:48 -0700141 SDC2_PCLK = 22,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800142 SDC3_CLK = 23,
Amol Jadi82254562011-06-27 11:25:48 -0700143 SDC3_PCLK = 24,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800144 SDC4_CLK = 25,
Amol Jadi82254562011-06-27 11:25:48 -0700145 SDC4_PCLK = 26
146};
147
148/* Zero'th entry is dummy */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800149static uint8_t sdc_clk[] = { 0, SDC1_CLK, SDC2_CLK, SDC3_CLK, SDC4_CLK };
150static uint8_t sdc_pclk[] = { 0, SDC1_PCLK, SDC2_PCLK, SDC3_PCLK, SDC4_PCLK };
Amol Jadi82254562011-06-27 11:25:48 -0700151
Shashank Mittal246f8d02011-01-21 17:12:27 -0800152void mdelay(unsigned msecs);
Shashank Mittal83978442011-04-01 19:41:22 -0700153unsigned board_msm_id(void);
Shashank Mittal246f8d02011-01-21 17:12:27 -0800154
Shashank Mittal83978442011-04-01 19:41:22 -0700155void pll_enable(void *pll_mode_addr)
156{
157 /* TODO: Need to add spin-lock to avoid race conditions */
158
159 uint32_t nVal;
160 /* Check status */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800161 nVal = readl(pll_mode_addr);
162 if (nVal & PLL_OUTCTRL)
Shashank Mittal83978442011-04-01 19:41:22 -0700163 return;
164
165 /* Put the PLL in reset mode */
166 nVal = 0;
167 nVal &= ~PLL_RESET_N;
168 nVal &= ~PLL_BYPASSNL;
169 nVal &= ~PLL_OUTCTRL;
170 writel(nVal, pll_mode_addr);
171
172 /* Put the PLL in warm-up mode */
173 nVal |= PLL_RESET_N;
174 nVal |= PLL_BYPASSNL;
175 writel(nVal, pll_mode_addr);
176
177 /* Wait for the PLL warm-up time */
178 udelay(50);
179
180 /* Put the PLL in active mode */
181 nVal |= PLL_RESET_N;
182 nVal |= PLL_BYPASSNL;
183 nVal |= PLL_OUTCTRL;
184 writel(nVal, pll_mode_addr);
185}
186
187void pll_request(unsigned pll, unsigned enable)
188{
189 int val = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800190 if (!enable) {
Shashank Mittal83978442011-04-01 19:41:22 -0700191 /* Disable not supported */
192 return;
193 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800194 switch (pll) {
195 case 2:
196 pll_enable(PLL2_MODE_ADDR);
197 return;
198 case 4:
199 pll_enable(PLL4_MODE_ADDR);
200 return;
201 default:
202 return;
Shashank Mittal83978442011-04-01 19:41:22 -0700203 };
204}
Shashank Mittal246f8d02011-01-21 17:12:27 -0800205
206void acpu_clock_init(void)
207{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800208 uint32_t i, clk;
Shashank Mittal83978442011-04-01 19:41:22 -0700209 uint32_t val;
210 uint32_t *clk_cntl_reg_val, size;
211 unsigned msm_id;
Shashank Mittal246f8d02011-01-21 17:12:27 -0800212
213 /* Increase VDD level to the final value. */
214 writel((1 << 7) | (VDD_LEVEL << 3), VDD_SVS_PLEVEL_ADDR);
Shashank Mittal83978442011-04-01 19:41:22 -0700215
Shashank Mittal246f8d02011-01-21 17:12:27 -0800216#if (!ENABLE_NANDWRITE)
217 thread_sleep(1);
218#else
Shashank Mittal83978442011-04-01 19:41:22 -0700219 mdelay(1);
Shashank Mittal246f8d02011-01-21 17:12:27 -0800220#endif
221
Shashank Mittal83978442011-04-01 19:41:22 -0700222 msm_id = board_msm_id();
Ajay Dudanib01e5062011-12-03 23:23:42 -0800223 switch (msm_id) {
224 case MSM7227A:
225 case MSM7627A:
226 case ESM7227A:
227 clk_cntl_reg_val = clk_cntl_reg_val_7627A;
228 size = ARRAY_SIZE(clk_cntl_reg_val_7627A);
229 pll_request(2, 1);
Shashank Mittal5d564b62011-05-12 10:51:07 -0700230
231 /* TODO: Enable this PLL while switching to 800MHz */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800232#if 0
233 pll_request(4, 1);
234#endif
235 break;
Channagoud Kadabi3acfb742011-11-15 18:19:32 +0530236 case MSM8625:
237 /* Fix me: Will move to PLL4 later */
238 clk_cntl_reg_val = clk_cntl_reg_val_7627A;
239 size = ARRAY_SIZE(clk_cntl_reg_val_7627A);
240 pll_request(2, 1);
241 break;
Shashank Mittal83978442011-04-01 19:41:22 -0700242
Ajay Dudanib01e5062011-12-03 23:23:42 -0800243 case MSM7225A:
244 case MSM7625A:
245 default:
246 clk_cntl_reg_val = clk_cntl_reg_val_7625A;
247 size = ARRAY_SIZE(clk_cntl_reg_val_7625A);
248 pll_request(2, 1);
249 break;
Shashank Mittal83978442011-04-01 19:41:22 -0700250 };
251
Shashank Mittal246f8d02011-01-21 17:12:27 -0800252 /* Read clock source select bit. */
Shashank Mittal83978442011-04-01 19:41:22 -0700253 val = readl(A11S_CLK_SEL_ADDR);
254 i = val & 1;
Shashank Mittal246f8d02011-01-21 17:12:27 -0800255
Shashank Mittal83978442011-04-01 19:41:22 -0700256 /* Jump into table and set every entry. */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800257 for (; i < size; i++) {
Shashank Mittal83978442011-04-01 19:41:22 -0700258
Channagoud Kadabic0b0a362012-04-19 13:37:25 +0530259 val = readl(A11S_CLK_SEL_ADDR);
260 val |= BIT(1) | BIT(2);
261 writel(val, A11S_CLK_SEL_ADDR);
262
Shashank Mittal83978442011-04-01 19:41:22 -0700263 val = readl(A11S_CLK_CNTL_ADDR);
264
265 /* Make sure not to disturb already used src */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800266 val &= clk_cntl_mask[i % 2];
Shashank Mittal83978442011-04-01 19:41:22 -0700267 val += clk_cntl_reg_val[i];
268 writel(val, A11S_CLK_CNTL_ADDR);
269
Shashank Mittal246f8d02011-01-21 17:12:27 -0800270 /* Would need a dmb() here but the whole address space is
271 * strongly ordered, so it should be fine.
272 */
Shashank Mittal302a6332011-05-04 10:32:48 -0700273 val = readl(A11S_CLK_SEL_ADDR);
274 val &= ~(A11S_CLK_SEL_MASK);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800275 val |= (A11S_CLK_SEL_MASK & clk_sel_reg_val[i % 2]);
Shashank Mittal302a6332011-05-04 10:32:48 -0700276 writel(val, A11S_CLK_SEL_ADDR);
277
Shashank Mittal246f8d02011-01-21 17:12:27 -0800278#if (!ENABLE_NANDWRITE)
279 thread_sleep(1);
280#else
281 mdelay(1);
282#endif
283 }
284}
Shashank Mittalef325412011-04-01 13:48:26 -0700285
286void hsusb_clock_init(void)
287{
288 /* USB local clock control not enabled; use proc comm */
289 usb_clock_init();
290}
Amol Jadi82254562011-06-27 11:25:48 -0700291
292/* Configure MMC clock */
293void clock_config_mmc(uint32_t interface, uint32_t freq)
294{
295 uint32_t reg = 0;
296
Ajay Dudanib01e5062011-12-03 23:23:42 -0800297 if (mmc_clock_set_rate(sdc_clk[interface], freq) < 0) {
Amol Jadi82254562011-06-27 11:25:48 -0700298 dprintf(CRITICAL, "Failure setting clock rate for MCLK - "
Ajay Dudanib01e5062011-12-03 23:23:42 -0800299 "clk_rate: %d\n!", freq);
Amol Jadi82254562011-06-27 11:25:48 -0700300 ASSERT(0);
301 }
302
303 /* enable clock */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800304 if (mmc_clock_enable_disable(sdc_clk[interface], MMC_CLK_ENABLE) < 0) {
Amol Jadi82254562011-06-27 11:25:48 -0700305 dprintf(CRITICAL, "Failure enabling MMC Clock!\n");
306 ASSERT(0);
307 }
308
309 reg |= MMC_BOOT_MCI_CLK_ENABLE;
310 reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
311 reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800312 writel(reg, MMC_BOOT_MCI_CLK);
Amol Jadi82254562011-06-27 11:25:48 -0700313}
314
315/* Intialize MMC clock */
316void clock_init_mmc(uint32_t interface)
317{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800318 if (mmc_clock_enable_disable(sdc_pclk[interface], MMC_CLK_ENABLE) < 0) {
Amol Jadi82254562011-06-27 11:25:48 -0700319 dprintf(CRITICAL, "Failure enabling PCLK!\n");
320 ASSERT(0);
321 }
322}