blob: c1b13bbcece3009d83f0136af0c38f4aa3466fed [file] [log] [blame]
Channagoud Kadabied60a8b2014-06-27 15:35:09 -07001/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * 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
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <debug.h>
30#include <platform/iomap.h>
31#include <platform/irqs.h>
32#include <platform/gpio.h>
33#include <reg.h>
34#include <target.h>
35#include <platform.h>
36#include <dload_util.h>
37#include <uart_dm.h>
38#include <mmc.h>
39#include <spmi.h>
40#include <board.h>
41#include <smem.h>
42#include <baseband.h>
43#include <dev/keys.h>
44#include <pm8x41.h>
45#include <crypto5_wrapper.h>
46#include <clock.h>
47#include <partition_parser.h>
48#include <scm.h>
49#include <platform/clock.h>
50#include <platform/gpio.h>
51#include <platform/timer.h>
52#include <stdlib.h>
53#include <ufs.h>
54#include <boot_device.h>
55#include <qmp_phy.h>
56
57#define PMIC_ARB_CHANNEL_NUM 0
58#define PMIC_ARB_OWNER_ID 0
59
60static void set_sdc_power_ctrl(void);
61static uint32_t mmc_pwrctl_base[] =
62 { MSM_SDC1_BASE, MSM_SDC2_BASE };
63
64static uint32_t mmc_sdhci_base[] =
65 { MSM_SDC1_SDHCI_BASE, MSM_SDC2_SDHCI_BASE };
66
67static uint32_t mmc_sdc_pwrctl_irq[] =
68 { SDCC1_PWRCTL_IRQ, SDCC2_PWRCTL_IRQ };
69
70struct mmc_device *dev;
71struct ufs_dev ufs_device;
72
73extern void ulpi_write(unsigned val, unsigned reg);
74
75void target_early_init(void)
76{
77#if WITH_DEBUG_UART
78 uart_dm_init(2, 0, BLSP1_UART1_BASE);
79#endif
80}
81
82/* Return 1 if vol_up pressed */
83static int target_volume_up()
84{
85 uint8_t status = 0;
86 struct pm8x41_gpio gpio;
87
88 /* Configure the GPIO */
89 gpio.direction = PM_GPIO_DIR_IN;
90 gpio.function = 0;
91 gpio.pull = PM_GPIO_PULL_UP_30;
92 gpio.vin_sel = 2;
93
94 pm8x41_gpio_config(2, &gpio);
95
96 /* Wait for the pmic gpio config to take effect */
97 thread_sleep(1);
98
99 /* Get status of P_GPIO_5 */
100 pm8x41_gpio_get(3, &status);
101
102 return !status; /* active low */
103}
104
105/* Return 1 if vol_down pressed */
106uint32_t target_volume_down()
107{
108 return pm8x41_resin_status();
109}
110
111static void target_keystatus()
112{
113 keys_init();
114
115 if(target_volume_down())
116 keys_post_event(KEY_VOLUMEDOWN, 1);
117
118 if(target_volume_up())
119 keys_post_event(KEY_VOLUMEUP, 1);
120}
121
122void target_uninit(void)
123{
124 if (platform_boot_dev_isemmc())
125 {
126 mmc_put_card_to_sleep(dev);
127 /* Disable HC mode before jumping to kernel */
128 sdhci_mode_disable(&dev->host);
129 }
130}
131
132static void set_sdc_power_ctrl()
133{
134 /* Drive strength configs for sdc pins */
135 struct tlmm_cfgs sdc1_hdrv_cfg[] =
136 {
137 { SDC1_CLK_HDRV_CTL_OFF, TLMM_CUR_VAL_16MA, TLMM_HDRV_MASK, SDC1_HDRV_PULL_CTL },
138 { SDC1_CMD_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK, SDC1_HDRV_PULL_CTL },
139 { SDC1_DATA_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK, SDC1_HDRV_PULL_CTL },
140 };
141
142 /* Pull configs for sdc pins */
143 struct tlmm_cfgs sdc1_pull_cfg[] =
144 {
145 { SDC1_CLK_PULL_CTL_OFF, TLMM_NO_PULL, TLMM_PULL_MASK, SDC1_HDRV_PULL_CTL },
146 { SDC1_CMD_PULL_CTL_OFF, TLMM_PULL_UP, TLMM_PULL_MASK, SDC1_HDRV_PULL_CTL },
147 { SDC1_DATA_PULL_CTL_OFF, TLMM_PULL_UP, TLMM_PULL_MASK, SDC1_HDRV_PULL_CTL },
148 };
149
150 struct tlmm_cfgs sdc1_rclk_cfg[] =
151 {
152 { SDC1_RCLK_PULL_CTL_OFF, TLMM_PULL_DOWN, TLMM_PULL_MASK, SDC1_HDRV_PULL_CTL },
153 };
154
155 /* Set the drive strength & pull control values */
156 tlmm_set_hdrive_ctrl(sdc1_hdrv_cfg, ARRAY_SIZE(sdc1_hdrv_cfg));
157 tlmm_set_pull_ctrl(sdc1_pull_cfg, ARRAY_SIZE(sdc1_pull_cfg));
158 tlmm_set_pull_ctrl(sdc1_rclk_cfg, ARRAY_SIZE(sdc1_rclk_cfg));
159}
160
161void target_sdc_init()
162{
163 struct mmc_config_data config = {0};
164
165 /* Set drive strength & pull ctrl values */
166 set_sdc_power_ctrl();
167
168 config.bus_width = DATA_BUS_WIDTH_8BIT;
169 config.max_clk_rate = MMC_CLK_192MHZ;
170
171 /* Try slot 1*/
172 config.slot = 1;
173 config.sdhc_base = mmc_sdhci_base[config.slot - 1];
174 config.pwrctl_base = mmc_pwrctl_base[config.slot - 1];
175 config.pwr_irq = mmc_sdc_pwrctl_irq[config.slot - 1];
176
177 if (!(dev = mmc_init(&config)))
178 {
179 /* Try slot 2 */
180 config.slot = 2;
181 config.max_clk_rate = MMC_CLK_200MHZ;
182 config.sdhc_base = mmc_sdhci_base[config.slot - 1];
183 config.pwrctl_base = mmc_pwrctl_base[config.slot - 1];
184 config.pwr_irq = mmc_sdc_pwrctl_irq[config.slot - 1];
185
186 if (!(dev = mmc_init(&config)))
187 {
188 dprintf(CRITICAL, "mmc init failed!");
189 ASSERT(0);
190 }
191 }
192}
193
194void *target_mmc_device()
195{
196 if (platform_boot_dev_isemmc())
197 return (void *) dev;
198 else
199 return (void *) &ufs_device;
200}
201
202void target_init(void)
203{
204 dprintf(INFO, "target_init()\n");
205
206 spmi_init(PMIC_ARB_CHANNEL_NUM, PMIC_ARB_OWNER_ID);
207
208 target_keystatus();
209
210 if (target_use_signed_kernel())
211 target_crypto_init_params();
212
213 platform_read_boot_config();
214
215 if (platform_boot_dev_isemmc())
216 {
217 target_sdc_init();
218 }
219 else
220 {
221 ufs_device.base = UFS_BASE;
222 ufs_init(&ufs_device);
223 }
224
225 /* Storage initialization is complete, read the partition table info */
226 if (partition_read_table())
227 {
228 dprintf(CRITICAL, "Error reading the partition table info\n");
229 ASSERT(0);
230 }
231}
232
233unsigned board_machtype(void)
234{
235 return LINUX_MACHTYPE_UNKNOWN;
236}
237
238/* Detect the target type */
239void target_detect(struct board_data *board)
240{
241 /* This is filled from board.c */
242}
243
244/* Detect the modem type */
245void target_baseband_detect(struct board_data *board)
246{
247 uint32_t platform;
248
249 platform = board->platform;
250
251 switch(platform) {
252 case MSMTHULIUM:
253 board->baseband = BASEBAND_MSM;
254 break;
255 default:
256 dprintf(CRITICAL, "Platform type: %u is not supported\n",platform);
257 ASSERT(0);
258 };
259}
260unsigned target_baseband()
261{
262 return board_baseband();
263}
264
265void target_serialno(unsigned char *buf)
266{
267 unsigned int serialno;
268 if (target_is_emmc_boot()) {
269 serialno = mmc_get_psn();
270 snprintf((char *)buf, 13, "%x", serialno);
271 }
272}
273
274unsigned check_reboot_mode(void)
275{
276 uint32_t restart_reason = 0;
277 uint32_t restart_reason_addr;
278
279 restart_reason_addr = RESTART_REASON_ADDR;
280
281 /* Read reboot reason and scrub it */
282 restart_reason = readl(restart_reason_addr);
283 writel(0x00, restart_reason_addr);
284
285 return restart_reason;
286}
287
288void reboot_device(unsigned reboot_reason)
289{
290 uint8_t reset_type = 0;
291
292 /* Write the reboot reason */
293 writel(reboot_reason, RESTART_REASON_ADDR);
294
295 if(reboot_reason)
296 reset_type = PON_PSHOLD_WARM_RESET;
297 else
298 reset_type = PON_PSHOLD_HARD_RESET;
299
300 pm8x41_reset_configure(reset_type);
301
302 /* Drop PS_HOLD for MSM */
303 writel(0x00, MPM2_MPM_PS_HOLD);
304
305 mdelay(5000);
306
307 dprintf(CRITICAL, "Rebooting failed\n");
308}
309
310int emmc_recovery_init(void)
311{
312 return _emmc_recovery_init();
313}
314
315void target_usb_phy_reset()
316{
317 usb30_qmp_phy_reset();
318 qusb2_phy_reset();
319}
320
321target_usb_iface_t* target_usb30_init()
322{
323 target_usb_iface_t *t_usb_iface;
324
325 t_usb_iface = calloc(1, sizeof(target_usb_iface_t));
326 ASSERT(t_usb_iface);
327
328 t_usb_iface->phy_init = usb30_qmp_phy_init;
329 t_usb_iface->phy_reset = target_usb_phy_reset;
330 t_usb_iface->clock_init = clock_usb30_init;
331 t_usb_iface->vbus_override = 1;
332
333 return t_usb_iface;
334}
335
336/* identify the usb controller to be used for the target */
337const char * target_usb_controller()
338{
339 return "dwc";
340}
341
342uint32_t target_override_pll()
343{
344 return 1;
345}
346
347void target_fastboot_init(void)
348{
349 /* We are entering fastboot mode, so read partition table */
350 mmc_read_partition_table(1);
351}