/* * Copyright (c) 2008, Google Inc. * All rights reserved. * * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #define ACPU_CLK 0 /* Applications processor clock */ #define ADM_CLK 1 /* Applications data mover clock */ #define ADSP_CLK 2 /* ADSP clock */ #define EBI1_CLK 3 /* External bus interface 1 clock */ #define EBI2_CLK 4 /* External bus interface 2 clock */ #define ECODEC_CLK 5 /* External CODEC clock */ #define EMDH_CLK 6 /* External MDDI host clock */ #define GP_CLK 7 /* General purpose clock */ #define GRP_CLK 8 /* Graphics clock */ #define I2C_CLK 9 /* I2C clock */ #define ICODEC_RX_CLK 10 /* Internal CODEX RX clock */ #define ICODEC_TX_CLK 11 /* Internal CODEX TX clock */ #define IMEM_CLK 12 /* Internal graphics memory clock */ #define MDC_CLK 13 /* MDDI client clock */ #define MDP_CLK 14 /* Mobile display processor clock */ #define PBUS_CLK 15 /* Peripheral bus clock */ #define PCM_CLK 16 /* PCM clock */ #define PMDH_CLK 17 /* Primary MDDI host clock */ #define SDAC_CLK 18 /* Stereo DAC clock */ #define SDC1_CLK 19 /* Secure Digital Card clocks */ #define SDC1_PCLK 20 #define SDC2_CLK 21 #define SDC2_PCLK 22 #define SDC3_CLK 23 #define SDC3_PCLK 24 #define SDC4_CLK 25 #define SDC4_PCLK 26 #define TSIF_CLK 27 /* Transport Stream Interface clocks */ #define TSIF_REF_CLK 28 #define TV_DAC_CLK 29 /* TV clocks */ #define TV_ENC_CLK 30 #define UART1_CLK 31 /* UART clocks */ #define UART2_CLK 32 #define UART3_CLK 33 #define UART1DM_CLK 34 #define UART2DM_CLK 35 #define USB_HS_CLK 36 /* High speed USB core clock */ #define USB_HS_PCLK 37 /* High speed USB pbus clock */ #define USB_OTG_CLK 38 /* Full speed USB clock */ #define VDC_CLK 39 /* Video controller clock */ #define VFE_CLK 40 /* Camera / Video Front End clock */ #define VFE_MDC_CLK 41 /* VFE MDDI client clock */ /* qsd8k adds... */ #define MDP_LCDC_PCLK_CLK 42 #define MDP_LCDC_PAD_PCLK_CLK 43 #define MDP_VSYNC_CLK 44 #define P_USB_HS_CORE_CLK 53 /* High speed USB 1 core clock */ /* msm7x30 adds... */ #define PMDH_P_CLK 82 #define MDP_P_CLK 86 enum { PCOM_CMD_IDLE = 0x0, PCOM_CMD_DONE, PCOM_RESET_APPS, PCOM_RESET_CHIP, PCOM_CONFIG_NAND_MPU, PCOM_CONFIG_USB_CLKS, PCOM_GET_POWER_ON_STATUS, PCOM_GET_WAKE_UP_STATUS, PCOM_GET_BATT_LEVEL, PCOM_CHG_IS_CHARGING, PCOM_POWER_DOWN, PCOM_USB_PIN_CONFIG, PCOM_USB_PIN_SEL, PCOM_SET_RTC_ALARM, PCOM_NV_READ, PCOM_NV_WRITE, PCOM_GET_UUID_HIGH, PCOM_GET_UUID_LOW, PCOM_GET_HW_ENTROPY, PCOM_RPC_GPIO_TLMM_CONFIG_REMOTE, PCOM_CLKCTL_RPC_ENABLE, PCOM_CLKCTL_RPC_DISABLE, PCOM_CLKCTL_RPC_RESET, PCOM_CLKCTL_RPC_SET_FLAGS, PCOM_CLKCTL_RPC_SET_RATE, PCOM_CLKCTL_RPC_MIN_RATE, PCOM_CLKCTL_RPC_MAX_RATE, PCOM_CLKCTL_RPC_RATE, PCOM_CLKCTL_RPC_PLL_REQUEST, PCOM_CLKCTL_RPC_ENABLED, PCOM_VREG_SWITCH, PCOM_VREG_SET_LEVEL, PCOM_GPIO_TLMM_CONFIG_GROUP, PCOM_GPIO_TLMM_UNCONFIG_GROUP, PCOM_NV_READ_HIGH_BITS, PCOM_NV_WRITE_HIGH_BITS, PCOM_RPC_GPIO_TLMM_CONFIG_EX = 0x25, PCOM_NUM_CMDS, PCOM_KERNEL_SEC_BOOT = 0x7A, }; enum { PCOM_INVALID_STATUS = 0x0, PCOM_READY, PCOM_CMD_RUNNING, PCOM_CMD_SUCCESS, PCOM_CMD_FAIL, }; #ifndef PLATFORM_MSM7X30 #define MSM_A2M_INT(n) (MSM_CSR_BASE + 0x400 + (n) * 4) #endif static inline void notify_other_proc_comm(void) { #ifndef PLATFORM_MSM7X30 writel(1, MSM_A2M_INT(6)); #else writel(1 << 6, (MSM_GCC_BASE + 0x8)); #endif } #define APP_COMMAND (MSM_SHARED_BASE + 0x00) #define APP_STATUS (MSM_SHARED_BASE + 0x04) #define APP_DATA1 (MSM_SHARED_BASE + 0x08) #define APP_DATA2 (MSM_SHARED_BASE + 0x0C) #define MDM_COMMAND (MSM_SHARED_BASE + 0x10) #define MDM_STATUS (MSM_SHARED_BASE + 0x14) #define MDM_DATA1 (MSM_SHARED_BASE + 0x18) #define MDM_DATA2 (MSM_SHARED_BASE + 0x1C) int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2) { int ret = -1; unsigned status; // dprintf(INFO, "proc_comm(%d,%d,%d)\n", // cmd, data1 ? *data1 : 0, data2 ? *data2 : 0); while (readl(MDM_STATUS) != PCOM_READY) { /* XXX check for A9 reset */ } if (data1) writel(*data1, APP_DATA1); if (data2) writel(*data2, APP_DATA2); /* * As per the specs write data, cmd, interrupt for * proc comm processing */ writel(cmd, APP_COMMAND); // dprintf(INFO, "proc_comm tx\n"); notify_other_proc_comm(); while (readl(APP_COMMAND) != PCOM_CMD_DONE) { /* XXX check for A9 reset */ } status = readl(APP_STATUS); // dprintf(INFO, "proc_comm status %d\n", status); if (status != PCOM_CMD_FAIL) { if (data1) *data1 = readl(APP_DATA1); if (data2) *data2 = readl(APP_DATA2); ret = 0; /* * Write command idle to indicate non HLOS that * apps has finished reading the status & data * of proc comm command */ writel(PCOM_CMD_IDLE, APP_COMMAND); } return ret; } static int clock_enable(unsigned id) { return msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, 0); } static int clock_disable(unsigned id) { return msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, 0); } static int clock_set_rate(unsigned id, unsigned rate) { return msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate); } static int clock_get_rate(unsigned id) { if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, 0)) { return -1; } else { return (int)id; } } void usb_clock_init() { clock_enable(USB_HS_PCLK); clock_enable(USB_HS_CLK); clock_enable(P_USB_HS_CORE_CLK); } void lcdc_clock_init(unsigned rate) { clock_set_rate(MDP_LCDC_PCLK_CLK, rate); clock_enable(MDP_LCDC_PCLK_CLK); clock_enable(MDP_LCDC_PAD_PCLK_CLK); } void mdp_clock_init(unsigned rate) { clock_set_rate(MDP_CLK, rate); clock_enable(MDP_CLK); } void mdp_clock_disable(void) { if(!target_cont_splash_screen()) clock_disable(MDP_CLK); } void lcdc_clock_disable(void) { clock_disable(MDP_LCDC_PAD_PCLK_CLK); clock_disable(MDP_LCDC_PCLK_CLK); } void uart3_clock_init(void) { clock_enable(UART3_CLK); clock_set_rate(UART3_CLK, 19200000 / 4); } void uart2_clock_init(void) { clock_enable(UART2_CLK); clock_set_rate(UART2_CLK, 19200000); } void uart1_clock_init(void) { clock_enable(UART1_CLK); clock_set_rate(UART1_CLK, 19200000 / 4); } void mddi_clock_init(unsigned num, unsigned rate) { unsigned clock_id; if (num == 0) clock_id = PMDH_CLK; else clock_id = EMDH_CLK; clock_enable(clock_id); clock_set_rate(clock_id, rate); #ifdef PLATFORM_MSM7X30 clock_enable(PMDH_P_CLK); #endif } void reboot(unsigned reboot_reason) { msm_proc_comm(PCOM_RESET_CHIP, &reboot_reason, 0); for (;;) ; } int mmc_clock_enable_disable(unsigned id, unsigned enable) { if (enable) { return clock_enable(id); //Enable mmc clock rate } else { return clock_disable(id); //Disable mmc clock rate } } int mmc_clock_set_rate(unsigned id, unsigned rate) { return clock_set_rate(id, rate); //Set mmc clock rate } int mmc_clock_get_rate(unsigned id) { return clock_get_rate(id); //Get mmc clock rate } int gpio_tlmm_config(unsigned config, unsigned disable) { return msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, &disable); } int vreg_set_level(unsigned id, unsigned mv) { return msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv); } int vreg_enable(unsigned id) { int enable = 1; return msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable); } int vreg_disable(unsigned id) { int enable = 0; return msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable); } void set_tamper_flag(int tamper) { return msm_proc_comm(PCOM_KERNEL_SEC_BOOT, &tamper, 0); }