/* * Copyright (c) 2008, Google Inc. * 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 static void get_version(char *s, unsigned id) { unsigned *ver = (unsigned*) MSM7K_VERSION; unsigned n = ver[id]; snprintf(s, 32, "%d.%d", n >> 16, n & 0xffff); } void get_version_modem(char *s) { get_version(s, VERSION_MODEM); } void get_version_modem_sbl(char *s) { get_version(s, VERSION_MODEM_SBL); } #define MSM_CSR_BASE 0xC0100000 #define MSM_A2M_INT(n) (MSM_CSR_BASE + 0x400 + (n) * 4) static inline void notify_other_proc_comm(void) { writel(1, MSM_A2M_INT(6)); } #define APP_COMMAND (MSM7K_SHARED_PHYS + 0x00) #define APP_STATUS (MSM7K_SHARED_PHYS + 0x04) #define APP_DATA1 (MSM7K_SHARED_PHYS + 0x08) #define APP_DATA2 (MSM7K_SHARED_PHYS + 0x0C) #define MDM_COMMAND (MSM7K_SHARED_PHYS + 0x10) #define MDM_STATUS (MSM7K_SHARED_PHYS + 0x14) #define MDM_DATA1 (MSM7K_SHARED_PHYS + 0x18) #define MDM_DATA2 (MSM7K_SHARED_PHYS + 0x1C) 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_NUM_CMDS, }; enum { PCOM_INVALID_STATUS = 0x0, PCOM_READY, PCOM_CMD_RUNNING, PCOM_CMD_SUCCESS, PCOM_CMD_FAIL, }; int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2) { int ret = -1; while (readl(MDM_STATUS) != PCOM_READY) { /* XXX check for A9 reset */ } writel(cmd, APP_COMMAND); if (data1) writel(*data1, APP_DATA1); if (data2) writel(*data2, APP_DATA2); notify_other_proc_comm(); while (readl(APP_COMMAND) != PCOM_CMD_DONE) { /* XXX check for A9 reset */ } if (readl(APP_STATUS) != PCOM_CMD_FAIL) { if (data1) *data1 = readl(APP_DATA1); if (data2) *data2 = readl(APP_DATA2); ret = 0; } return ret; } int clock_enable(unsigned id) { return msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, 0); } int clock_disable(unsigned id) { return msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, 0); } int clock_set_rate(unsigned id, unsigned rate) { return msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate); } int clock_get_rate(unsigned id) { if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, 0)) { return -1; } else { return (int) id; } } void reboot(void) { msm_proc_comm(PCOM_RESET_CHIP, 0, 0); for (;;) ; } int vreg_enable(unsigned id) { unsigned n = 1; return msm_proc_comm(PCOM_VREG_SWITCH, &id, &n); } int vreg_disable(unsigned id) { unsigned n = 0; return msm_proc_comm(PCOM_VREG_SWITCH, &id, &n); } int vreg_set_level(unsigned id, unsigned level) { return msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &level); }