blob: 42eb56bed98d3d651125bb09cad0f6e1a8c8ed99 [file] [log] [blame]
Ajay Dudani232ce812009-12-02 00:14:11 -08001/*
Ajay Dudani1c798cf2011-01-19 14:27:50 -08002 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
Ajay Dudani232ce812009-12-02 00:14:11 -08003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 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 copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
11 * * Neither the name of Code Aurora nor
12 * the names of its contributors may be used to endorse or promote
13 * products derived from this software without specific prior written
14 * permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdint.h>
30#include <kernel/thread.h>
31#include <platform/iomap.h>
32#include <reg.h>
33
Chandan Uddaraju35f77182010-09-23 15:21:45 -070034#define REG_BASE(off) (MSM_CLK_CTL_BASE + (off))
35#define REG(off) (MSM_CLK_CTL_SH2_BASE + (off))
36
Shashank Mittal0dab8f52010-11-03 16:40:30 -070037#define PLL_ENA_REG REG(0x0264)
38#define PLL2_STATUS_BASE_REG REG_BASE(0x0350)
39
Ajay Dudani1c798cf2011-01-19 14:27:50 -080040#define PLL2_L_VAL_ADDR REG_BASE(0x033C)
41#define ACPU_806MHZ 42
42#define ACPU_1024MHZ 53
43#define ACPU_1200MHZ 125
44#define ACPU_1400MHZ 73
45
Ajay Dudani7d605522010-10-01 19:52:37 -070046#define SH2_OWN_ROW2_BASE_REG REG_BASE(0x0424)
Subbaraman Narayanamurthyd962c792011-01-19 20:53:07 -080047#define SH2_OWN_APPS2_BASE_REG REG_BASE(0x0414)
Ajay Dudani7d605522010-10-01 19:52:37 -070048
Shashank Mittal0dab8f52010-11-03 16:40:30 -070049/* Macros to select PLL2 with divide by 1 */
50#define ACPU_SRC_SEL 3
51#define ACPU_SRC_DIV 0
52
53#define BIT(n) (1 << (n))
54#define VREG_CONFIG (BIT(7) | BIT(6)) /* Enable VREG, pull-down if disabled. */
55#define VREG_DATA (VREG_CONFIG | (VREF_SEL << 5))
56#define VREF_SEL 1 /* 0: 0.625V (50mV step), 1: 0.3125V (25mV step). */
57#define V_STEP (25 * (2 - VREF_SEL)) /* Minimum voltage step size. */
58#define MV(mv) ((mv) / (!((mv) % V_STEP)))
59/* mv = (750mV + (raw * 25mV)) * (2 - VREF_SEL) */
60#define VDD_RAW(mv) (((MV(mv) / V_STEP) - 30) | VREG_DATA)
61
62void spm_init(void)
63{
64 writel(0x05, MSM_SAW_BASE + 0x10); /* MSM_SPM_REG_SAW_CFG */
65 writel(0x18, MSM_SAW_BASE + 0x14); /* MSM_SPM_REG_SAW_SPM_CTL */
66 writel(0x00006666, MSM_SAW_BASE + 0x18); /* MSM_SPM_REG_SAW_SPM_SLP_TMR_DLY */
67 writel(0xFF000666, MSM_SAW_BASE + 0x1C); /* MSM_SPM_REG_SAW_SPM_WAKE_TMR_DLY */
68
69 writel(0x01, MSM_SAW_BASE + 0x24); /* MSM_SPM_REG_SAW_SLP_CLK_EN */
70 writel(0x03, MSM_SAW_BASE + 0x28); /* MSM_SPM_REG_SAW_SLP_HSFS_PRECLMP_EN */
71 writel(0x00, MSM_SAW_BASE + 0x2C); /* MSM_SPM_REG_SAW_SLP_HSFS_POSTCLMP_EN */
72
73 writel(0x01, MSM_SAW_BASE + 0x30); /* MSM_SPM_REG_SAW_SLP_CLMP_EN */
74 writel(0x00, MSM_SAW_BASE + 0x34); /* MSM_SPM_REG_SAW_SLP_RST_EN */
75 writel(0x00, MSM_SAW_BASE + 0x38); /* MSM_SPM_REG_SAW_SPM_MPM_CFG */
76}
77
78/* Configures msmc2 voltage. vlevel is in mV */
79void msmc2_config(unsigned vlevel)
80{
81 unsigned val;
82 val = readl(MSM_SAW_BASE + 0x08); /* MSM_SPM_REG_SAW_VCTL */
83 val &= ~0xFF;
84 val |= VDD_RAW(vlevel);
85 writel(val, MSM_SAW_BASE + 0x08); /* MSM_SPM_REG_SAW_VCTL */
86
87 /* Wait for PMIC state to return to idle and for VDD to stabilize */
88 while(((readl(MSM_SAW_BASE + 0x0C) >> 0x20) & 0x3) != 0);
89 udelay(160);
90}
91
92void enable_pll(unsigned num)
93{
94 unsigned reg_val;
95 reg_val = readl(PLL_ENA_REG);
96 reg_val |= (1 << num);
97 writel(reg_val, PLL_ENA_REG);
98 /* Wait until PLL is enabled */
99 while ((readl(PLL2_STATUS_BASE_REG) & (1 << 16)) == 0);
100}
101
Ajay Dudani232ce812009-12-02 00:14:11 -0800102void acpu_clock_init(void)
103{
Ajay Dudani1c798cf2011-01-19 14:27:50 -0800104 unsigned clk, reg_clksel, reg_clkctl, src_sel;
Shashank Mittal0dab8f52010-11-03 16:40:30 -0700105 /* Fixing msmc2 voltage */
106 spm_init();
Ajay Dudani1c798cf2011-01-19 14:27:50 -0800107
108 clk = readl(PLL2_L_VAL_ADDR) & 0xFF;
109 if (clk == ACPU_806MHZ)
110 msmc2_config(1100);
111 else if (clk == ACPU_1024MHZ || clk == ACPU_1200MHZ)
112 msmc2_config(1200);
113 else if (clk == ACPU_1400MHZ)
114 msmc2_config(1250);
Shashank Mittal0dab8f52010-11-03 16:40:30 -0700115
116 /* Enable pll 2 */
117 enable_pll(2);
118
119 reg_clksel = readl(SCSS_CLK_SEL);
120
121 /* CLK_SEL_SRC1NO */
122 src_sel = reg_clksel & 1;
123
124 /* Program clock source and divider. */
125 reg_clkctl = readl(SCSS_CLK_CTL);
126 reg_clkctl &= ~(0xFF << (8 * src_sel));
127 reg_clkctl |= ACPU_SRC_SEL<< (4 + 8 * src_sel);
128 reg_clkctl |= ACPU_SRC_DIV<< (0 + 8 * src_sel);
129 writel(reg_clkctl, SCSS_CLK_CTL);
130
131 /* Toggle clock source. */
132 reg_clksel ^= 1;
133
134 /* Program clock source selection. */
135 writel(reg_clksel, SCSS_CLK_SEL);
Chandan Uddaraju35f77182010-09-23 15:21:45 -0700136}
Ajay Dudani7d605522010-10-01 19:52:37 -0700137
138void hsusb_clock_init(void)
139{
140 int val = 0;
141 unsigned sh2_own_row2;
142 unsigned sh2_own_row2_hsusb_mask = (1 << 11);
143
144 sh2_own_row2 = readl(SH2_OWN_ROW2_BASE_REG);
145 if(sh2_own_row2 & sh2_own_row2_hsusb_mask)
146 {
147 /* USB local clock control enabled */
148 /* Set value in MD register */
149 val = 0x5DF;
150 writel(val, SH2_USBH_MD_REG);
151
152 /* Set value in NS register */
153 val = 1 << 8;
154 val = val | readl(SH2_USBH_NS_REG);
155 writel(val, SH2_USBH_NS_REG);
156
157 val = 1 << 11;
158 val = val | readl(SH2_USBH_NS_REG);
159 writel(val, SH2_USBH_NS_REG);
160
161 val = 1 << 9;
162 val = val | readl(SH2_USBH_NS_REG);
163 writel(val, SH2_USBH_NS_REG);
164
165 val = 1 << 13;
166 val = val | readl(SH2_USBH_NS_REG);
167 writel(val, SH2_USBH_NS_REG);
168
169 /* Enable USBH_P_CLK */
170 val = 1 << 25;
171 val = val | readl(SH2_GLBL_CLK_ENA_SC);
172 writel(val, SH2_GLBL_CLK_ENA_SC);
173 }
174 else
175 {
176 /* USB local clock control not enabled; use proc comm */
177 usb_clock_init();
178 }
179}
Subbaraman Narayanamurthy4cc29732010-10-18 15:57:58 -0700180
181void adm_enable_clock(void)
182{
183 unsigned int val=0;
184
185 /* Enable ADM_CLK */
186 val = 1 << 5;
187 val = val | readl(SH2_GLBL_CLK_ENA_SC);
188 writel(val, SH2_GLBL_CLK_ENA_SC);
189}
Subbaraman Narayanamurthyd962c792011-01-19 20:53:07 -0800190
191void mdp_lcdc_clock_init(void)
192{
193 unsigned int val = 0;
194 unsigned sh2_own_apps2;
195 unsigned sh2_own_apps2_lcdc_mask = (1 << 3);
196
197 sh2_own_apps2 = readl(SH2_OWN_APPS2_BASE_REG);
198 if(sh2_own_apps2 & sh2_own_apps2_lcdc_mask)
199 {
200 /* MDP local clock control enabled */
201 /* Select clock source and divider */
202 val = 0x29;
203 val = val | readl(SH2_MDP_NS_REG);
204 writel(val, SH2_MDP_NS_REG);
205
206 /* Enable MDP source clock(root) */
207 val = 1 << 11;
208 val = val | readl(SH2_MDP_NS_REG);
209 writel(val, SH2_MDP_NS_REG);
210
211 /* Enable graphics clock(branch) */
212 val = 1 << 9;
213 val = val | readl(SH2_MDP_NS_REG);
214 writel(val, SH2_MDP_NS_REG);
215
216 /* Enable MDP_P_CLK */
217 val = 1 << 6;
218 val = val | readl(SH2_GLBL_CLK_ENA_2_SC);
219 writel(val, SH2_GLBL_CLK_ENA_2_SC);
220
221 /* Enable AXI_MDP_CLK */
222 val = 1 << 29;
223 val = val | readl(SH2_GLBL_CLK_ENA_2_SC);
224 writel(val, SH2_GLBL_CLK_ENA_2_SC);
225
226 /* LCDC local clock control enabled */
227 /* Set value in MD register */
228 val = 0x1FFF9;
229 writel(val, SH2_MDP_LCDC_MD_REG);
230
231 /* Set MDP_LCDC_N_VAL in NS register */
232 val = 0xFFFA << 16;
233 val = val | readl(SH2_MDP_LCDC_NS_REG);
234 writel(val, SH2_MDP_LCDC_NS_REG);
235
236 /* Set clock source */
237 val = 1;
238 val = val | readl(SH2_MDP_LCDC_NS_REG);
239 writel(val, SH2_MDP_LCDC_NS_REG);
240
241 /* Set divider */
242 val = 3 << 3;
243 val = val | readl(SH2_MDP_LCDC_NS_REG);
244 writel(val, SH2_MDP_LCDC_NS_REG);
245
246 /* Set MN counter mode */
247 val = 2 << 5;
248 val = val | readl(SH2_MDP_LCDC_NS_REG);
249 writel(val, SH2_MDP_LCDC_NS_REG);
250
251 /* Enable MN counter */
252 val = 1 << 8;
253 val = val | readl(SH2_MDP_LCDC_NS_REG);
254 writel(val, SH2_MDP_LCDC_NS_REG);
255
256 /* Enable mdp_lcdc_src(root) clock */
257 val = 1 << 11;
258 val = val | readl(SH2_MDP_LCDC_NS_REG);
259 writel(val, SH2_MDP_LCDC_NS_REG);
260
261 /* Enable mdp_lcdc_pclk(branch) clock */
262 val = 1 << 9;
263 val = val | readl(SH2_MDP_LCDC_NS_REG);
264 writel(val, SH2_MDP_LCDC_NS_REG);
265
266 /* Enable mdp_lcdc_pad_pclk(branch) clock */
267 val = 1 << 12;
268 val = val | readl(SH2_MDP_LCDC_NS_REG);
269 writel(val, SH2_MDP_LCDC_NS_REG);
270 }
271 else
272 {
273 /* MDP local clock control not enabled; use proc comm */
274 mdp_clock_init(122880000);
275
276 /* LCDC local clock control not enabled; use proc comm */
277 lcdc_clock_init(27648000);
278 }
279}