/*
* 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 <boot/boot.h>
#include <msm7k/shared.h>
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);
}