blob: c20381313d8c370bae0d15ae6e5d97d513558aff [file] [log] [blame]
Shashank Mittal246f8d02011-01-21 17:12:27 -08001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
4 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
5 *
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>
Shashank Mittal246f8d02011-01-21 17:12:27 -080035
36#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
Shashank Mittal83978442011-04-01 19:41:22 -070037#define BIT(x) (1 << (x))
Shashank Mittal246f8d02011-01-21 17:12:27 -080038
39#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
40#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
41#define VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124)
Shashank Mittal246f8d02011-01-21 17:12:27 -080042
Shashank Mittal83978442011-04-01 19:41:22 -070043#define PLL2_MODE_ADDR (MSM_CLK_CTL_BASE + 0x338)
44#define PLL4_MODE_ADDR (MSM_CLK_CTL_BASE + 0x374)
45
46#define PLL_RESET_N BIT(2)
47#define PLL_BYPASSNL BIT(1)
48#define PLL_OUTCTRL BIT(0)
49
50#define SRC_SEL_TCX0 0 /* TCXO */
51#define SRC_SEL_PLL1 1 /* PLL1: modem_pll */
52#define SRC_SEL_PLL2 2 /* PLL2: backup_pll_0 */
53#define SRC_SEL_PLL3 3 /* PLL3: backup_pll_1 */
54#define SRC_SEL_PLL4 6 /* PLL4: sparrow_pll */
55
56#define DIV_1 0
Shashank Mittal246f8d02011-01-21 17:12:27 -080057#define DIV_2 1
Shashank Mittal83978442011-04-01 19:41:22 -070058#define DIV_3 2
59#define DIV_4 3
60#define DIV_5 4
61#define DIV_6 5
62#define DIV_7 6
63#define DIV_8 7
64#define DIV_9 8
65#define DIV_10 9
66#define DIV_11 10
67#define DIV_12 11
68#define DIV_13 12
69#define DIV_14 13
70#define DIV_15 14
71#define DIV_16 15
72
Shashank Mittal246f8d02011-01-21 17:12:27 -080073#define WAIT_CNT 100
74#define VDD_LEVEL 7
75#define MIN_AXI_HZ 120000000
76#define ACPU_800MHZ 41
77
Shashank Mittal302a6332011-05-04 10:32:48 -070078#define A11S_CLK_SEL_MASK 0x7 /* bits 2:0 */
79
Shashank Mittal246f8d02011-01-21 17:12:27 -080080/* The stepping frequencies have been choosen to make sure the step
Shashank Mittal83978442011-04-01 19:41:22 -070081 * is <= 256 MHz for both 7x27a and 7x25a targets. The
Shashank Mittal246f8d02011-01-21 17:12:27 -080082 * table also assumes the ACPU is running at TCXO freq and AHB div is
83 * set to DIV_1.
84 *
85 * To use the tables:
86 * - Start at location 0/1 depending on clock source sel bit.
87 * - Set values till end of table skipping every other entry.
88 * - When you reach the end of the table, you are done scaling.
Shashank Mittal246f8d02011-01-21 17:12:27 -080089 */
90
Shashank Mittal83978442011-04-01 19:41:22 -070091uint32_t const clk_cntl_reg_val_7627A[] = {
92 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_16,
93 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_8 << 8),
94 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_4,
Shashank Mittal246f8d02011-01-21 17:12:27 -080095 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_2 << 8),
Shashank Mittal83978442011-04-01 19:41:22 -070096
97 /* TODO: Fix it for 800MHz */
98#if 0
99 (WAIT_CNT << 16) | (SRC_SEL_PLL4 << 4) | DIV_1,
100#endif
Shashank Mittal246f8d02011-01-21 17:12:27 -0800101};
102
Shashank Mittal83978442011-04-01 19:41:22 -0700103uint32_t const clk_cntl_reg_val_7625A[] = {
104 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_16,
105 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_8 << 8),
106 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_4,
107 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_2 << 8),
Shashank Mittal246f8d02011-01-21 17:12:27 -0800108};
109
Shashank Mittal302a6332011-05-04 10:32:48 -0700110/* Using DIV_1 for all cases to avoid worrying about turbo vs. normal
111 * mode. Able to use DIV_1 for all steps because it's the largest AND
Shashank Mittal246f8d02011-01-21 17:12:27 -0800112 * the final value. */
113uint32_t const clk_sel_reg_val[] = {
Shashank Mittal83978442011-04-01 19:41:22 -0700114 DIV_1 << 1 | 1, /* Switch to src1 */
115 DIV_1 << 1 | 0, /* Switch to src0 */
116};
117
118/*
119 * Mask to make sure current selected src frequency doesn't change.
120 */
121uint32_t const clk_cntl_mask[] = {
122 0x0000FF00, /* Mask to read src0 */
123 0x000000FF /* Mask to read src1 */
Shashank Mittal246f8d02011-01-21 17:12:27 -0800124};
125
126void mdelay(unsigned msecs);
Shashank Mittal83978442011-04-01 19:41:22 -0700127unsigned board_msm_id(void);
Shashank Mittal246f8d02011-01-21 17:12:27 -0800128
Shashank Mittal83978442011-04-01 19:41:22 -0700129void pll_enable(void *pll_mode_addr)
130{
131 /* TODO: Need to add spin-lock to avoid race conditions */
132
133 uint32_t nVal;
134 /* Check status */
135 nVal = readl(pll_mode_addr);
136 if(nVal & PLL_OUTCTRL)
137 return;
138
139 /* Put the PLL in reset mode */
140 nVal = 0;
141 nVal &= ~PLL_RESET_N;
142 nVal &= ~PLL_BYPASSNL;
143 nVal &= ~PLL_OUTCTRL;
144 writel(nVal, pll_mode_addr);
145
146 /* Put the PLL in warm-up mode */
147 nVal |= PLL_RESET_N;
148 nVal |= PLL_BYPASSNL;
149 writel(nVal, pll_mode_addr);
150
151 /* Wait for the PLL warm-up time */
152 udelay(50);
153
154 /* Put the PLL in active mode */
155 nVal |= PLL_RESET_N;
156 nVal |= PLL_BYPASSNL;
157 nVal |= PLL_OUTCTRL;
158 writel(nVal, pll_mode_addr);
159}
160
161void pll_request(unsigned pll, unsigned enable)
162{
163 int val = 0;
164 if(!enable) {
165 /* Disable not supported */
166 return;
167 }
168 switch(pll) {
169 case 2:
170 pll_enable(PLL2_MODE_ADDR);
171 return;
172 case 4:
173 pll_enable(PLL4_MODE_ADDR);
174 return;
175 default:
176 return;
177 };
178}
Shashank Mittal246f8d02011-01-21 17:12:27 -0800179
180void acpu_clock_init(void)
181{
Shashank Mittal83978442011-04-01 19:41:22 -0700182 uint32_t i,clk;
183 uint32_t val;
184 uint32_t *clk_cntl_reg_val, size;
185 unsigned msm_id;
Shashank Mittal246f8d02011-01-21 17:12:27 -0800186
187 /* Increase VDD level to the final value. */
188 writel((1 << 7) | (VDD_LEVEL << 3), VDD_SVS_PLEVEL_ADDR);
Shashank Mittal83978442011-04-01 19:41:22 -0700189
Shashank Mittal246f8d02011-01-21 17:12:27 -0800190#if (!ENABLE_NANDWRITE)
191 thread_sleep(1);
192#else
Shashank Mittal83978442011-04-01 19:41:22 -0700193 mdelay(1);
Shashank Mittal246f8d02011-01-21 17:12:27 -0800194#endif
195
Shashank Mittal83978442011-04-01 19:41:22 -0700196 msm_id = board_msm_id();
197 switch(msm_id) {
198 case MSM7227A:
199 case MSM7627A:
200 case ESM7227A:
201 clk_cntl_reg_val = clk_cntl_reg_val_7627A;
202 size = ARRAY_SIZE(clk_cntl_reg_val_7627A);
203 pll_request(2, 1);
Shashank Mittal5d564b62011-05-12 10:51:07 -0700204
205 /* TODO: Enable this PLL while switching to 800MHz */
206 #if 0
Shashank Mittal83978442011-04-01 19:41:22 -0700207 pll_request(4, 1);
Shashank Mittal5d564b62011-05-12 10:51:07 -0700208 #endif
Shashank Mittal83978442011-04-01 19:41:22 -0700209 break;
210
211 case MSM7225A:
212 case MSM7625A:
213 default:
214 clk_cntl_reg_val = clk_cntl_reg_val_7625A;
215 size = ARRAY_SIZE(clk_cntl_reg_val_7625A);
216 pll_request(2, 1);
217 break;
218 };
219
Shashank Mittal246f8d02011-01-21 17:12:27 -0800220 /* Read clock source select bit. */
Shashank Mittal83978442011-04-01 19:41:22 -0700221 val = readl(A11S_CLK_SEL_ADDR);
222 i = val & 1;
Shashank Mittal246f8d02011-01-21 17:12:27 -0800223
Shashank Mittal83978442011-04-01 19:41:22 -0700224 /* Jump into table and set every entry. */
225 for(; i < size; i++) {
226
227 val = readl(A11S_CLK_CNTL_ADDR);
228
229 /* Make sure not to disturb already used src */
230 val &= clk_cntl_mask[i%2];
231 val += clk_cntl_reg_val[i];
232 writel(val, A11S_CLK_CNTL_ADDR);
233
Shashank Mittal246f8d02011-01-21 17:12:27 -0800234 /* Would need a dmb() here but the whole address space is
235 * strongly ordered, so it should be fine.
236 */
Shashank Mittal302a6332011-05-04 10:32:48 -0700237 val = readl(A11S_CLK_SEL_ADDR);
238 val &= ~(A11S_CLK_SEL_MASK);
239 val |= (A11S_CLK_SEL_MASK & clk_sel_reg_val[i%2]);
240 writel(val, A11S_CLK_SEL_ADDR);
241
Shashank Mittal246f8d02011-01-21 17:12:27 -0800242#if (!ENABLE_NANDWRITE)
243 thread_sleep(1);
244#else
245 mdelay(1);
246#endif
247 }
248}
Shashank Mittalef325412011-04-01 13:48:26 -0700249
250void hsusb_clock_init(void)
251{
252 /* USB local clock control not enabled; use proc comm */
253 usb_clock_init();
254}