blob: 695f18ee78d2666a8fb39e82c843cc3fd8989c12 [file] [log] [blame]
Chandan Uddarajufcc15f52009-11-17 21:02:46 -08001/*
Ajay Dudanib1b7d102009-11-25 14:47:20 -08002 * Copyright (c) 2008, Google Inc.
Chandan Uddarajufcc15f52009-11-17 21:02:46 -08003 * All rights reserved.
4 * Copyright (c) 2009, 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
Amol Jadi82254562011-06-27 11:25:48 -070013 * the documentation and/or other materials provided with the
Chandan Uddarajufcc15f52009-11-17 21:02:46 -080014 * 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
Amol Jadi82254562011-06-27 11:25:48 -070023 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
Chandan Uddarajufcc15f52009-11-17 21:02:46 -080024 * 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>
Amol Jadi82254562011-06-27 11:25:48 -070034#include <debug.h>
35#include <mmc.h>
Chandan Uddarajufcc15f52009-11-17 21:02:46 -080036
37#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
38
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)
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -070042#define PLL2_L_VAL_ADDR (MSM_CLK_CTL_BASE + 0x33C)
Chandan Uddarajufcc15f52009-11-17 21:02:46 -080043
Chandan Uddarajufcc15f52009-11-17 21:02:46 -080044#define SRC_SEL_PLL1 1 /* PLL1. */
45#define SRC_SEL_PLL2 2 /* PLL2. */
Manas Abichandania3898ff2010-02-10 15:28:31 -080046#define SRC_SEL_PLL3 3 /* PLL3. Used for 7x25. */
Chandan Uddarajufcc15f52009-11-17 21:02:46 -080047#define DIV_4 3
48#define DIV_2 1
49#define WAIT_CNT 100
50#define VDD_LEVEL 7
51#define MIN_AXI_HZ 120000000
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -070052#define ACPU_800MHZ 41
Chandan Uddarajufcc15f52009-11-17 21:02:46 -080053
54void pll_request(unsigned pll, unsigned enable);
55void axi_clock_init(unsigned rate);
56
57/* The stepping frequencies have been choosen to make sure the step
58 * is <= 256 MHz for both turbo mode and normal mode targets. The
59 * table also assumes the ACPU is running at TCXO freq and AHB div is
60 * set to DIV_1.
61 *
62 * To use the tables:
63 * - Start at location 0/1 depending on clock source sel bit.
64 * - Set values till end of table skipping every other entry.
65 * - When you reach the end of the table, you are done scaling.
66 *
67 * TODO: Need to fix SRC_SEL_PLL1 for 7x25.
68 */
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -070069
70uint32_t const clk_cntl_reg_val_7625[] = {
Chandan Uddarajufcc15f52009-11-17 21:02:46 -080071 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_4,
72 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_4 << 8),
73 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_2 << 8),
Subbaraman Narayanamurthy8282bdc2010-12-17 18:03:57 -080074 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_2,
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -070075 (WAIT_CNT << 16) | (SRC_SEL_PLL3 << 4) | DIV_2,
Manas Abichandania3898ff2010-02-10 15:28:31 -080076 (WAIT_CNT << 16) | (SRC_SEL_PLL3 << 12) | (DIV_2 << 8),
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -070077};
78
79uint32_t const clk_cntl_reg_val_7627[] = {
80 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_4,
81 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_4 << 8),
82 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_2 << 8),
Subbaraman Narayanamurthy8282bdc2010-12-17 18:03:57 -080083 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_2,
Chandan Uddarajufcc15f52009-11-17 21:02:46 -080084 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4) | DIV_2,
85 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12) | (DIV_2 << 8),
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -070086};
87
Subbaraman Narayanamurthy8282bdc2010-12-17 18:03:57 -080088uint32_t const clk_cntl_reg_val_7627T[] = {
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -070089 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_4,
90 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_4 << 8),
91 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 12) | (DIV_2 << 8),
Subbaraman Narayanamurthy8282bdc2010-12-17 18:03:57 -080092 (WAIT_CNT << 16) | (SRC_SEL_PLL1 << 4) | DIV_2,
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -070093 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 4),
94 (WAIT_CNT << 16) | (SRC_SEL_PLL2 << 12),
Chandan Uddarajufcc15f52009-11-17 21:02:46 -080095};
96
97/* Using DIV_4 for all cases to avoid worrying about turbo vs. normal
98 * mode. Able to use DIV_4 for all steps because it's the largest AND
99 * the final value. */
100uint32_t const clk_sel_reg_val[] = {
101 DIV_4 << 1 | 1,
102 DIV_4 << 1 | 0,
103 DIV_4 << 1 | 0,
104 DIV_4 << 1 | 1,
105 DIV_4 << 1 | 1,
106 DIV_4 << 1 | 0,
107};
108
Amol Jadi82254562011-06-27 11:25:48 -0700109/* enum for SDC CLK IDs */
110enum
111{
112 SDC1_CLK = 19,
113 SDC1_PCLK = 20,
114 SDC2_CLK = 21,
115 SDC2_PCLK = 22,
116 SDC3_CLK = 23,
117 SDC3_PCLK = 24,
118 SDC4_CLK = 25,
119 SDC4_PCLK = 26
120};
121
122/* Zero'th entry is dummy */
123static uint8_t sdc_clk[] = {0, SDC1_CLK, SDC2_CLK, SDC3_CLK, SDC4_CLK};
124static uint8_t sdc_pclk[] = {0, SDC1_PCLK, SDC2_PCLK, SDC3_PCLK, SDC4_PCLK};
125
Chandan Uddaraju852cd2c2009-12-17 14:28:28 -0800126void mdelay(unsigned msecs);
127
128
Chandan Uddarajufcc15f52009-11-17 21:02:46 -0800129void acpu_clock_init(void)
130{
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -0700131 unsigned i,clk;
Chandan Uddarajufcc15f52009-11-17 21:02:46 -0800132
Chandan Uddaraju96501972009-12-14 23:24:21 -0800133#if (!ENABLE_NANDWRITE)
134 int *modem_stat_check = (MSM_SHARED_BASE + 0x14);
135
136 /* Wait for modem to be ready before clock init */
137 while (readl(modem_stat_check) != 1);
138#endif
139
Chandan Uddarajufcc15f52009-11-17 21:02:46 -0800140 /* Increase VDD level to the final value. */
141 writel((1 << 7) | (VDD_LEVEL << 3), VDD_SVS_PLEVEL_ADDR);
Chandan Uddaraju852cd2c2009-12-17 14:28:28 -0800142#if (!ENABLE_NANDWRITE)
Chandan Uddarajufcc15f52009-11-17 21:02:46 -0800143 thread_sleep(1);
Chandan Uddaraju852cd2c2009-12-17 14:28:28 -0800144#else
145 mdelay(1);
146#endif
Chandan Uddarajufcc15f52009-11-17 21:02:46 -0800147
148 /* Read clock source select bit. */
149 i = readl(A11S_CLK_SEL_ADDR) & 1;
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -0700150 clk = readl(PLL2_L_VAL_ADDR) & 0x3F;
Chandan Uddarajufcc15f52009-11-17 21:02:46 -0800151
152 /* Jump into table and set every other entry. */
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -0700153 for(; i < ARRAY_SIZE(clk_cntl_reg_val_7627); i += 2) {
154#ifdef ENABLE_PLL3
155 writel(clk_cntl_reg_val_7625[i], A11S_CLK_CNTL_ADDR);
156#else
157 if(clk == ACPU_800MHZ)
Subbaraman Narayanamurthy8282bdc2010-12-17 18:03:57 -0800158 writel(clk_cntl_reg_val_7627T[i], A11S_CLK_CNTL_ADDR);
Subbaraman Narayanamurthybc089032010-08-27 18:28:28 -0700159 else
160 writel(clk_cntl_reg_val_7627[i], A11S_CLK_CNTL_ADDR);
161#endif
Chandan Uddarajufcc15f52009-11-17 21:02:46 -0800162 /* Would need a dmb() here but the whole address space is
163 * strongly ordered, so it should be fine.
164 */
165 writel(clk_sel_reg_val[i], A11S_CLK_SEL_ADDR);
Chandan Uddaraju852cd2c2009-12-17 14:28:28 -0800166#if (!ENABLE_NANDWRITE)
Chandan Uddarajufcc15f52009-11-17 21:02:46 -0800167 thread_sleep(1);
Chandan Uddaraju852cd2c2009-12-17 14:28:28 -0800168#else
169 mdelay(1);
170#endif
Chandan Uddarajufcc15f52009-11-17 21:02:46 -0800171 }
Chandan Uddarajufcc15f52009-11-17 21:02:46 -0800172}
Amol Jadi82254562011-06-27 11:25:48 -0700173
174/* Configure MMC clock */
175void clock_config_mmc(uint32_t interface, uint32_t freq)
176{
177 uint32_t reg = 0;
178
179 if( mmc_clock_set_rate(sdc_clk[interface], freq) < 0 )
180 {
181 dprintf(CRITICAL, "Failure setting clock rate for MCLK - "
182 "clk_rate: %d\n!", freq);
183 ASSERT(0);
184 }
185
186 /* enable clock */
187 if( mmc_clock_enable_disable(sdc_clk[interface], MMC_CLK_ENABLE) < 0 )
188 {
189 dprintf(CRITICAL, "Failure enabling MMC Clock!\n");
190 ASSERT(0);
191 }
192
193 reg |= MMC_BOOT_MCI_CLK_ENABLE;
194 reg |= MMC_BOOT_MCI_CLK_ENA_FLOW;
195 reg |= MMC_BOOT_MCI_CLK_IN_FEEDBACK;
196 writel( reg, MMC_BOOT_MCI_CLK );
197}
198
199/* Intialize MMC clock */
200void clock_init_mmc(uint32_t interface)
201{
202 if( mmc_clock_enable_disable(sdc_pclk[interface], MMC_CLK_ENABLE) < 0 )
203 {
204 dprintf(CRITICAL, "Failure enabling PCLK!\n");
205 ASSERT(0);
206 }
207}
208