diff options
Diffstat (limited to 'arch/arm/mach-msm')
90 files changed, 15175 insertions, 0 deletions
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig new file mode 100644 index 00000000..1cd40ad3 --- /dev/null +++ b/arch/arm/mach-msm/Kconfig @@ -0,0 +1,170 @@ +if ARCH_MSM + +choice + prompt "Qualcomm MSM SoC Type" + default ARCH_MSM7X00A + +config ARCH_MSM7X00A + bool "MSM7x00A / MSM7x01A" + select MACH_TROUT if !MACH_HALIBUT + select ARCH_MSM_ARM11 + select MSM_SMD + select MSM_SMD_PKG3 + select CPU_V6 + select GPIO_MSM_V1 + select MSM_PROC_COMM + +config ARCH_MSM7X30 + bool "MSM7x30" + select MACH_MSM7X30_SURF # if ! + select ARCH_MSM_SCORPION + select MSM_SMD + select MSM_VIC + select CPU_V7 + select MSM_GPIOMUX + select GPIO_MSM_V1 + select MSM_PROC_COMM + +config ARCH_QSD8X50 + bool "QSD8X50" + select MACH_QSD8X50_SURF if !MACH_QSD8X50A_ST1_5 + select ARCH_MSM_SCORPION + select MSM_SMD + select MSM_VIC + select CPU_V7 + select MSM_GPIOMUX + select GPIO_MSM_V1 + select MSM_PROC_COMM + +config ARCH_MSM8X60 + bool "MSM8X60" + select MACH_MSM8X60_SURF if (!MACH_MSM8X60_RUMI3 && !MACH_MSM8X60_SIM \ + && !MACH_MSM8X60_FFA) + select ARCH_MSM_SCORPIONMP + select ARM_GIC + select CPU_V7 + select MSM_V2_TLMM + select GPIO_MSM_V2 + select MSM_GPIOMUX + select MSM_SCM if SMP + +config ARCH_MSM8960 + bool "MSM8960" + select ARCH_MSM_SCORPIONMP + select MACH_MSM8960_SIM if (!MACH_MSM8960_RUMI3) + select ARM_GIC + select CPU_V7 + select MSM_V2_TLMM + select MSM_GPIOMUX + select MSM_SCM if SMP + +endchoice + +config MSM_HAS_DEBUG_UART_HS + bool + +config MSM_SOC_REV_A + bool +config ARCH_MSM_SCORPIONMP + bool + select HAVE_SMP + +config ARCH_MSM_ARM11 + bool +config ARCH_MSM_SCORPION + bool + +config MSM_VIC + bool + +menu "Qualcomm MSM Board Type" + +config MACH_HALIBUT + depends on ARCH_MSM + depends on ARCH_MSM7X00A + bool "Halibut Board (QCT SURF7201A)" + help + Support for the Qualcomm SURF7201A eval board. + +config MACH_TROUT + depends on ARCH_MSM + depends on ARCH_MSM7X00A + bool "HTC Dream (aka trout)" + help + Support for the HTC Dream, T-Mobile G1, Android ADP1 devices. + +config MACH_MSM7X30_SURF + depends on ARCH_MSM7X30 + bool "MSM7x30 SURF" + help + Support for the Qualcomm MSM7x30 SURF eval board. + +config MACH_QSD8X50_SURF + depends on ARCH_QSD8X50 + bool "QSD8x50 SURF" + help + Support for the Qualcomm QSD8x50 SURF eval board. + +config MACH_QSD8X50A_ST1_5 + depends on ARCH_QSD8X50 + select MSM_SOC_REV_A + bool "QSD8x50A ST1.5" + help + Support for the Qualcomm ST1.5. + +config MACH_MSM8X60_RUMI3 + depends on ARCH_MSM8X60 + bool "MSM8x60 RUMI3" + help + Support for the Qualcomm MSM8x60 RUMI3 emulator. + +config MACH_MSM8X60_SURF + depends on ARCH_MSM8X60 + bool "MSM8x60 SURF" + help + Support for the Qualcomm MSM8x60 SURF eval board. + +config MACH_MSM8X60_SIM + depends on ARCH_MSM8X60 + bool "MSM8x60 Simulator" + help + Support for the Qualcomm MSM8x60 simulator. + +config MACH_MSM8X60_FFA + depends on ARCH_MSM8X60 + bool "MSM8x60 FFA" + help + Support for the Qualcomm MSM8x60 FFA eval board. + +config MACH_MSM8960_SIM + depends on ARCH_MSM8960 + bool "MSM8960 Simulator" + help + Support for the Qualcomm MSM8960 simulator. + +config MACH_MSM8960_RUMI3 + depends on ARCH_MSM8960 + bool "MSM8960 RUMI3" + help + Support for the Qualcomm MSM8960 RUMI3 emulator. + +endmenu + +config MSM_SMD_PKG3 + bool + +config MSM_PROC_COMM + bool + +config MSM_SMD + bool + +config MSM_GPIOMUX + bool + +config MSM_V2_TLMM + bool + +config MSM_SCM + bool +endif diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile new file mode 100644 index 00000000..4ad3969b --- /dev/null +++ b/arch/arm/mach-msm/Makefile @@ -0,0 +1,33 @@ +obj-y += io.o idle.o timer.o +obj-y += clock.o +obj-$(CONFIG_DEBUG_FS) += clock-debug.o + +obj-$(CONFIG_MSM_VIC) += irq-vic.o +obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o + +obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o acpuclock-arm11.o +obj-$(CONFIG_ARCH_MSM7X30) += dma.o +obj-$(CONFIG_ARCH_QSD8X50) += dma.o sirc.o + +obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o + +obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o +obj-$(CONFIG_MSM_SMD) += last_radio_log.o +obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o + +CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) + +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-$(CONFIG_SMP) += headsmp.o platsmp.o + +obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o +obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o +obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o +obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o +obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o +obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60.o +obj-$(CONFIG_ARCH_MSM8960) += board-msm8960.o devices-msm8960.o + +obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-v1.o gpiomux.o +obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o +obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot new file mode 100644 index 00000000..9b803a57 --- /dev/null +++ b/arch/arm/mach-msm/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y += 0x10008000 +params_phys-y := 0x10000100 +initrd_phys-y := 0x10800000 diff --git a/arch/arm/mach-msm/acpuclock-arm11.c b/arch/arm/mach-msm/acpuclock-arm11.c new file mode 100644 index 00000000..805d4ee5 --- /dev/null +++ b/arch/arm/mach-msm/acpuclock-arm11.c @@ -0,0 +1,525 @@ +/* arch/arm/mach-msm/acpuclock.c + * + * MSM architecture clock driver + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2007 QUALCOMM Incorporated + * Author: San Mehat <san@android.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/delay.h> +#include <linux/clk.h> +#include <linux/cpufreq.h> +#include <linux/mutex.h> +#include <linux/io.h> +#include <mach/board.h> +#include <mach/msm_iomap.h> + +#include "proc_comm.h" +#include "acpuclock.h" + + +#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100) +#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104) +#define A11S_VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124) + +/* + * ARM11 clock configuration for specific ACPU speeds + */ + +#define ACPU_PLL_TCXO -1 +#define ACPU_PLL_0 0 +#define ACPU_PLL_1 1 +#define ACPU_PLL_2 2 +#define ACPU_PLL_3 3 + +#define PERF_SWITCH_DEBUG 0 +#define PERF_SWITCH_STEP_DEBUG 0 + +struct clock_state +{ + struct clkctl_acpu_speed *current_speed; + struct mutex lock; + uint32_t acpu_switch_time_us; + uint32_t max_speed_delta_khz; + uint32_t vdd_switch_time_us; + unsigned long power_collapse_khz; + unsigned long wait_for_irq_khz; +}; + +static struct clk *ebi1_clk; +static struct clock_state drv_state = { 0 }; + +static void __init acpuclk_init(void); + +/* MSM7201A Levels 3-6 all correspond to 1.2V, level 7 corresponds to 1.325V. */ +enum { + VDD_0 = 0, + VDD_1 = 1, + VDD_2 = 2, + VDD_3 = 3, + VDD_4 = 3, + VDD_5 = 3, + VDD_6 = 3, + VDD_7 = 7, + VDD_END +}; + +struct clkctl_acpu_speed { + unsigned int a11clk_khz; + int pll; + unsigned int a11clk_src_sel; + unsigned int a11clk_src_div; + unsigned int ahbclk_khz; + unsigned int ahbclk_div; + int vdd; + unsigned int axiclk_khz; + unsigned long lpj; /* loops_per_jiffy */ +/* Index in acpu_freq_tbl[] for steppings. */ + short down; + short up; +}; + +/* + * ACPU speed table. Complete table is shown but certain speeds are commented + * out to optimized speed switching. Initialize loops_per_jiffy to 0. + * + * Table stepping up/down is optimized for 256mhz jumps while staying on the + * same PLL. + */ +#if (0) +static struct clkctl_acpu_speed acpu_freq_tbl[] = { + { 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, VDD_0, 30720, 0, 0, 8 }, + { 61440, ACPU_PLL_0, 4, 3, 61440, 0, VDD_0, 30720, 0, 0, 8 }, + { 81920, ACPU_PLL_0, 4, 2, 40960, 1, VDD_0, 61440, 0, 0, 8 }, + { 96000, ACPU_PLL_1, 1, 7, 48000, 1, VDD_0, 61440, 0, 0, 9 }, + { 122880, ACPU_PLL_0, 4, 1, 61440, 1, VDD_3, 61440, 0, 0, 8 }, + { 128000, ACPU_PLL_1, 1, 5, 64000, 1, VDD_3, 61440, 0, 0, 12 }, + { 176000, ACPU_PLL_2, 2, 5, 88000, 1, VDD_3, 61440, 0, 0, 11 }, + { 192000, ACPU_PLL_1, 1, 3, 64000, 2, VDD_3, 61440, 0, 0, 12 }, + { 245760, ACPU_PLL_0, 4, 0, 81920, 2, VDD_4, 61440, 0, 0, 12 }, + { 256000, ACPU_PLL_1, 1, 2, 128000, 2, VDD_5, 128000, 0, 0, 12 }, + { 264000, ACPU_PLL_2, 2, 3, 88000, 2, VDD_5, 128000, 0, 6, 13 }, + { 352000, ACPU_PLL_2, 2, 2, 88000, 3, VDD_5, 128000, 0, 6, 13 }, + { 384000, ACPU_PLL_1, 1, 1, 128000, 2, VDD_6, 128000, 0, 5, -1 }, + { 528000, ACPU_PLL_2, 2, 1, 132000, 3, VDD_7, 128000, 0, 11, -1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, +}; +#else /* Table of freq we currently use. */ +static struct clkctl_acpu_speed acpu_freq_tbl[] = { + { 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, VDD_0, 30720, 0, 0, 4 }, + { 122880, ACPU_PLL_0, 4, 1, 61440, 1, VDD_3, 61440, 0, 0, 4 }, + { 128000, ACPU_PLL_1, 1, 5, 64000, 1, VDD_3, 61440, 0, 0, 6 }, + { 176000, ACPU_PLL_2, 2, 5, 88000, 1, VDD_3, 61440, 0, 0, 5 }, + { 245760, ACPU_PLL_0, 4, 0, 81920, 2, VDD_4, 61440, 0, 0, 5 }, + { 352000, ACPU_PLL_2, 2, 2, 88000, 3, VDD_5, 128000, 0, 3, 7 }, + { 384000, ACPU_PLL_1, 1, 1, 128000, 2, VDD_6, 128000, 0, 2, -1 }, + { 528000, ACPU_PLL_2, 2, 1, 132000, 3, VDD_7, 128000, 0, 5, -1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, +}; +#endif + + +#ifdef CONFIG_CPU_FREQ_TABLE +static struct cpufreq_frequency_table freq_table[] = { + { 0, 122880 }, + { 1, 128000 }, + { 2, 245760 }, + { 3, 384000 }, + { 4, 528000 }, + { 5, CPUFREQ_TABLE_END }, +}; +#endif + +static int pc_pll_request(unsigned id, unsigned on) +{ + int res; + on = !!on; + +#if PERF_SWITCH_DEBUG + if (on) + printk(KERN_DEBUG "Enabling PLL %d\n", id); + else + printk(KERN_DEBUG "Disabling PLL %d\n", id); +#endif + + res = msm_proc_comm(PCOM_CLKCTL_RPC_PLL_REQUEST, &id, &on); + if (res < 0) + return res; + +#if PERF_SWITCH_DEBUG + if (on) + printk(KERN_DEBUG "PLL %d enabled\n", id); + else + printk(KERN_DEBUG "PLL %d disabled\n", id); +#endif + return res; +} + + +/*---------------------------------------------------------------------------- + * ARM11 'owned' clock control + *---------------------------------------------------------------------------*/ + +unsigned long acpuclk_power_collapse(void) { + int ret = acpuclk_get_rate(); + ret *= 1000; + if (ret > drv_state.power_collapse_khz) + acpuclk_set_rate(drv_state.power_collapse_khz, 1); + return ret; +} + +unsigned long acpuclk_get_wfi_rate(void) +{ + return drv_state.wait_for_irq_khz; +} + +unsigned long acpuclk_wait_for_irq(void) { + int ret = acpuclk_get_rate(); + ret *= 1000; + if (ret > drv_state.wait_for_irq_khz) + acpuclk_set_rate(drv_state.wait_for_irq_khz, 1); + return ret; +} + +static int acpuclk_set_vdd_level(int vdd) +{ + uint32_t current_vdd; + + current_vdd = readl(A11S_VDD_SVS_PLEVEL_ADDR) & 0x07; + +#if PERF_SWITCH_DEBUG + printk(KERN_DEBUG "acpuclock: Switching VDD from %u -> %d\n", + current_vdd, vdd); +#endif + writel((1 << 7) | (vdd << 3), A11S_VDD_SVS_PLEVEL_ADDR); + udelay(drv_state.vdd_switch_time_us); + if ((readl(A11S_VDD_SVS_PLEVEL_ADDR) & 0x7) != vdd) { +#if PERF_SWITCH_DEBUG + printk(KERN_ERR "acpuclock: VDD set failed\n"); +#endif + return -EIO; + } + +#if PERF_SWITCH_DEBUG + printk(KERN_DEBUG "acpuclock: VDD switched\n"); +#endif + return 0; +} + +/* Set proper dividers for the given clock speed. */ +static void acpuclk_set_div(const struct clkctl_acpu_speed *hunt_s) { + uint32_t reg_clkctl, reg_clksel, clk_div; + + /* AHB_CLK_DIV */ + clk_div = (readl(A11S_CLK_SEL_ADDR) >> 1) & 0x03; + /* + * If the new clock divider is higher than the previous, then + * program the divider before switching the clock + */ + if (hunt_s->ahbclk_div > clk_div) { + reg_clksel = readl(A11S_CLK_SEL_ADDR); + reg_clksel &= ~(0x3 << 1); + reg_clksel |= (hunt_s->ahbclk_div << 1); + writel(reg_clksel, A11S_CLK_SEL_ADDR); + } + if ((readl(A11S_CLK_SEL_ADDR) & 0x01) == 0) { + /* SRC0 */ + + /* Program clock source */ + reg_clkctl = readl(A11S_CLK_CNTL_ADDR); + reg_clkctl &= ~(0x07 << 4); + reg_clkctl |= (hunt_s->a11clk_src_sel << 4); + writel(reg_clkctl, A11S_CLK_CNTL_ADDR); + + /* Program clock divider */ + reg_clkctl = readl(A11S_CLK_CNTL_ADDR); + reg_clkctl &= ~0xf; + reg_clkctl |= hunt_s->a11clk_src_div; + writel(reg_clkctl, A11S_CLK_CNTL_ADDR); + + /* Program clock source selection */ + reg_clksel = readl(A11S_CLK_SEL_ADDR); + reg_clksel |= 1; /* CLK_SEL_SRC1NO == SRC1 */ + writel(reg_clksel, A11S_CLK_SEL_ADDR); + } else { + /* SRC1 */ + + /* Program clock source */ + reg_clkctl = readl(A11S_CLK_CNTL_ADDR); + reg_clkctl &= ~(0x07 << 12); + reg_clkctl |= (hunt_s->a11clk_src_sel << 12); + writel(reg_clkctl, A11S_CLK_CNTL_ADDR); + + /* Program clock divider */ + reg_clkctl = readl(A11S_CLK_CNTL_ADDR); + reg_clkctl &= ~(0xf << 8); + reg_clkctl |= (hunt_s->a11clk_src_div << 8); + writel(reg_clkctl, A11S_CLK_CNTL_ADDR); + + /* Program clock source selection */ + reg_clksel = readl(A11S_CLK_SEL_ADDR); + reg_clksel &= ~1; /* CLK_SEL_SRC1NO == SRC0 */ + writel(reg_clksel, A11S_CLK_SEL_ADDR); + } + + /* + * If the new clock divider is lower than the previous, then + * program the divider after switching the clock + */ + if (hunt_s->ahbclk_div < clk_div) { + reg_clksel = readl(A11S_CLK_SEL_ADDR); + reg_clksel &= ~(0x3 << 1); + reg_clksel |= (hunt_s->ahbclk_div << 1); + writel(reg_clksel, A11S_CLK_SEL_ADDR); + } +} + +int acpuclk_set_rate(unsigned long rate, int for_power_collapse) +{ + uint32_t reg_clkctl; + struct clkctl_acpu_speed *cur_s, *tgt_s, *strt_s; + int rc = 0; + unsigned int plls_enabled = 0, pll; + + strt_s = cur_s = drv_state.current_speed; + + WARN_ONCE(cur_s == NULL, "acpuclk_set_rate: not initialized\n"); + if (cur_s == NULL) + return -ENOENT; + + if (rate == (cur_s->a11clk_khz * 1000)) + return 0; + + for (tgt_s = acpu_freq_tbl; tgt_s->a11clk_khz != 0; tgt_s++) { + if (tgt_s->a11clk_khz == (rate / 1000)) + break; + } + + if (tgt_s->a11clk_khz == 0) + return -EINVAL; + + /* Choose the highest speed speed at or below 'rate' with same PLL. */ + if (for_power_collapse && tgt_s->a11clk_khz < cur_s->a11clk_khz) { + while (tgt_s->pll != ACPU_PLL_TCXO && tgt_s->pll != cur_s->pll) + tgt_s--; + } + + if (strt_s->pll != ACPU_PLL_TCXO) + plls_enabled |= 1 << strt_s->pll; + + if (!for_power_collapse) { + mutex_lock(&drv_state.lock); + if (strt_s->pll != tgt_s->pll && tgt_s->pll != ACPU_PLL_TCXO) { + rc = pc_pll_request(tgt_s->pll, 1); + if (rc < 0) { + pr_err("PLL%d enable failed (%d)\n", + tgt_s->pll, rc); + goto out; + } + plls_enabled |= 1 << tgt_s->pll; + } + /* Increase VDD if needed. */ + if (tgt_s->vdd > cur_s->vdd) { + if ((rc = acpuclk_set_vdd_level(tgt_s->vdd)) < 0) { + printk(KERN_ERR "Unable to switch ACPU vdd\n"); + goto out; + } + } + } + + /* Set wait states for CPU between frequency changes */ + reg_clkctl = readl(A11S_CLK_CNTL_ADDR); + reg_clkctl |= (100 << 16); /* set WT_ST_CNT */ + writel(reg_clkctl, A11S_CLK_CNTL_ADDR); + +#if PERF_SWITCH_DEBUG + printk(KERN_INFO "acpuclock: Switching from ACPU rate %u -> %u\n", + strt_s->a11clk_khz * 1000, tgt_s->a11clk_khz * 1000); +#endif + + while (cur_s != tgt_s) { + /* + * Always jump to target freq if within 256mhz, regulardless of + * PLL. If differnece is greater, use the predefinied + * steppings in the table. + */ + int d = abs((int)(cur_s->a11clk_khz - tgt_s->a11clk_khz)); + if (d > drv_state.max_speed_delta_khz) { + /* Step up or down depending on target vs current. */ + int clk_index = tgt_s->a11clk_khz > cur_s->a11clk_khz ? + cur_s->up : cur_s->down; + if (clk_index < 0) { /* This should not happen. */ + printk(KERN_ERR "cur:%u target: %u\n", + cur_s->a11clk_khz, tgt_s->a11clk_khz); + rc = -EINVAL; + goto out; + } + cur_s = &acpu_freq_tbl[clk_index]; + } else { + cur_s = tgt_s; + } +#if PERF_SWITCH_STEP_DEBUG + printk(KERN_DEBUG "%s: STEP khz = %u, pll = %d\n", + __FUNCTION__, cur_s->a11clk_khz, cur_s->pll); +#endif + if (!for_power_collapse&& cur_s->pll != ACPU_PLL_TCXO + && !(plls_enabled & (1 << cur_s->pll))) { + rc = pc_pll_request(cur_s->pll, 1); + if (rc < 0) { + pr_err("PLL%d enable failed (%d)\n", + cur_s->pll, rc); + goto out; + } + plls_enabled |= 1 << cur_s->pll; + } + + acpuclk_set_div(cur_s); + drv_state.current_speed = cur_s; + /* Re-adjust lpj for the new clock speed. */ + loops_per_jiffy = cur_s->lpj; + udelay(drv_state.acpu_switch_time_us); + } + + /* Nothing else to do for power collapse. */ + if (for_power_collapse) + return 0; + + /* Disable PLLs we are not using anymore. */ + plls_enabled &= ~(1 << tgt_s->pll); + for (pll = ACPU_PLL_0; pll <= ACPU_PLL_2; pll++) + if (plls_enabled & (1 << pll)) { + rc = pc_pll_request(pll, 0); + if (rc < 0) { + pr_err("PLL%d disable failed (%d)\n", pll, rc); + goto out; + } + } + + /* Change the AXI bus frequency if we can. */ + if (strt_s->axiclk_khz != tgt_s->axiclk_khz) { + rc = clk_set_rate(ebi1_clk, tgt_s->axiclk_khz * 1000); + if (rc < 0) + pr_err("Setting AXI min rate failed!\n"); + } + + /* Drop VDD level if we can. */ + if (tgt_s->vdd < strt_s->vdd) { + if (acpuclk_set_vdd_level(tgt_s->vdd) < 0) + printk(KERN_ERR "acpuclock: Unable to drop ACPU vdd\n"); + } + +#if PERF_SWITCH_DEBUG + printk(KERN_DEBUG "%s: ACPU speed change complete\n", __FUNCTION__); +#endif +out: + if (!for_power_collapse) + mutex_unlock(&drv_state.lock); + return rc; +} + +static void __init acpuclk_init(void) +{ + struct clkctl_acpu_speed *speed; + uint32_t div, sel; + int rc; + + /* + * Determine the rate of ACPU clock + */ + + if (!(readl(A11S_CLK_SEL_ADDR) & 0x01)) { /* CLK_SEL_SRC1N0 */ + /* CLK_SRC0_SEL */ + sel = (readl(A11S_CLK_CNTL_ADDR) >> 12) & 0x7; + /* CLK_SRC0_DIV */ + div = (readl(A11S_CLK_CNTL_ADDR) >> 8) & 0x0f; + } else { + /* CLK_SRC1_SEL */ + sel = (readl(A11S_CLK_CNTL_ADDR) >> 4) & 0x07; + /* CLK_SRC1_DIV */ + div = readl(A11S_CLK_CNTL_ADDR) & 0x0f; + } + + for (speed = acpu_freq_tbl; speed->a11clk_khz != 0; speed++) { + if (speed->a11clk_src_sel == sel + && (speed->a11clk_src_div == div)) + break; + } + if (speed->a11clk_khz == 0) { + printk(KERN_WARNING "Warning - ACPU clock reports invalid speed\n"); + return; + } + + drv_state.current_speed = speed; + + rc = clk_set_rate(ebi1_clk, speed->axiclk_khz * 1000); + if (rc < 0) + pr_err("Setting AXI min rate failed!\n"); + + printk(KERN_INFO "ACPU running at %d KHz\n", speed->a11clk_khz); +} + +unsigned long acpuclk_get_rate(void) +{ + WARN_ONCE(drv_state.current_speed == NULL, + "acpuclk_get_rate: not initialized\n"); + if (drv_state.current_speed) + return drv_state.current_speed->a11clk_khz; + else + return 0; +} + +uint32_t acpuclk_get_switch_time(void) +{ + return drv_state.acpu_switch_time_us; +} + +/*---------------------------------------------------------------------------- + * Clock driver initialization + *---------------------------------------------------------------------------*/ + +/* Initialize the lpj field in the acpu_freq_tbl. */ +static void __init lpj_init(void) +{ + int i; + const struct clkctl_acpu_speed *base_clk = drv_state.current_speed; + for (i = 0; acpu_freq_tbl[i].a11clk_khz; i++) { + acpu_freq_tbl[i].lpj = cpufreq_scale(loops_per_jiffy, + base_clk->a11clk_khz, + acpu_freq_tbl[i].a11clk_khz); + } +} + +void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *clkdata) +{ + pr_info("acpu_clock_init()\n"); + + ebi1_clk = clk_get(NULL, "ebi1_clk"); + + mutex_init(&drv_state.lock); + drv_state.acpu_switch_time_us = clkdata->acpu_switch_time_us; + drv_state.max_speed_delta_khz = clkdata->max_speed_delta_khz; + drv_state.vdd_switch_time_us = clkdata->vdd_switch_time_us; + drv_state.power_collapse_khz = clkdata->power_collapse_khz; + drv_state.wait_for_irq_khz = clkdata->wait_for_irq_khz; + acpuclk_init(); + lpj_init(); +#ifdef CONFIG_CPU_FREQ_TABLE + cpufreq_frequency_table_get_attr(freq_table, smp_processor_id()); +#endif +} diff --git a/arch/arm/mach-msm/acpuclock.h b/arch/arm/mach-msm/acpuclock.h new file mode 100644 index 00000000..415de2eb --- /dev/null +++ b/arch/arm/mach-msm/acpuclock.h @@ -0,0 +1,32 @@ +/* arch/arm/mach-msm/acpuclock.h + * + * MSM architecture clock driver header + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2007 QUALCOMM Incorporated + * Author: San Mehat <san@android.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ARCH_ARM_MACH_MSM_ACPUCLOCK_H +#define __ARCH_ARM_MACH_MSM_ACPUCLOCK_H + +int acpuclk_set_rate(unsigned long rate, int for_power_collapse); +unsigned long acpuclk_get_rate(void); +uint32_t acpuclk_get_switch_time(void); +unsigned long acpuclk_wait_for_irq(void); +unsigned long acpuclk_power_collapse(void); +unsigned long acpuclk_get_wfi_rate(void); + + +#endif + diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c new file mode 100644 index 00000000..26aac363 --- /dev/null +++ b/arch/arm/mach-msm/board-halibut.c @@ -0,0 +1,105 @@ +/* linux/arch/arm/mach-msm/board-halibut.c + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/input.h> +#include <linux/io.h> +#include <linux/delay.h> + +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/flash.h> +#include <asm/setup.h> + +#include <mach/irqs.h> +#include <mach/board.h> +#include <mach/msm_iomap.h> + +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> + +#include "devices.h" + +static struct resource smc91x_resources[] = { + [0] = { + .start = 0x9C004300, + .end = 0x9C004400, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MSM_GPIO_TO_INT(49), + .end = MSM_GPIO_TO_INT(49), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + +static struct platform_device *devices[] __initdata = { + &msm_device_uart3, + &msm_device_smd, + &msm_device_nand, + &msm_device_hsusb, + &msm_device_i2c, + &smc91x_device, +}; + +extern struct sys_timer msm_timer; + +static void __init halibut_init_early(void) +{ + arch_ioremap_caller = __msm_ioremap_caller; +} + +static void __init halibut_init_irq(void) +{ + msm_init_irq(); +} + +static void __init halibut_init(void) +{ + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +static void __init halibut_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) +{ +} + +static void __init halibut_map_io(void) +{ + msm_map_common_io(); + msm_clock_init(msm_clocks_7x01a, msm_num_clocks_7x01a); +} + +MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)") + .atag_offset = 0x100, + .fixup = halibut_fixup, + .map_io = halibut_map_io, + .init_early = halibut_init_early, + .init_irq = halibut_init_irq, + .init_machine = halibut_init, + .timer = &msm_timer, +MACHINE_END diff --git a/arch/arm/mach-msm/board-mahimahi.c b/arch/arm/mach-msm/board-mahimahi.c new file mode 100644 index 00000000..5a4882fc --- /dev/null +++ b/arch/arm/mach-msm/board-mahimahi.c @@ -0,0 +1,83 @@ +/* linux/arch/arm/mach-msm/board-mahimahi.c + * + * Copyright (C) 2009 Google, Inc. + * Copyright (C) 2009 HTC Corporation. + * Author: Dima Zavin <dima@android.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/setup.h> + +#include <mach/board.h> +#include <mach/hardware.h> +#include <mach/system.h> + +#include "board-mahimahi.h" +#include "devices.h" +#include "proc_comm.h" + +static uint debug_uart; + +module_param_named(debug_uart, debug_uart, uint, 0); + +static struct platform_device *devices[] __initdata = { +#if !defined(CONFIG_MSM_SERIAL_DEBUGGER) + &msm_device_uart1, +#endif + &msm_device_uart_dm1, + &msm_device_nand, +}; + +static void __init mahimahi_init(void) +{ + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +static void __init mahimahi_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) +{ + mi->nr_banks = 2; + mi->bank[0].start = PHYS_OFFSET; + mi->bank[0].node = PHYS_TO_NID(PHYS_OFFSET); + mi->bank[0].size = (219*1024*1024); + mi->bank[1].start = MSM_HIGHMEM_BASE; + mi->bank[1].node = PHYS_TO_NID(MSM_HIGHMEM_BASE); + mi->bank[1].size = MSM_HIGHMEM_SIZE; +} + +static void __init mahimahi_map_io(void) +{ + msm_map_common_io(); + msm_clock_init(); +} + +extern struct sys_timer msm_timer; + +MACHINE_START(MAHIMAHI, "mahimahi") + .atag_offset = 0x100, + .fixup = mahimahi_fixup, + .map_io = mahimahi_map_io, + .init_irq = msm_init_irq, + .init_machine = mahimahi_init, + .timer = &msm_timer, +MACHINE_END diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c new file mode 100644 index 00000000..6d84ee74 --- /dev/null +++ b/arch/arm/mach-msm/board-msm7x27.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <linux/gpio.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/input.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/power_supply.h> + +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/flash.h> +#include <asm/setup.h> +#ifdef CONFIG_CACHE_L2X0 +#include <asm/hardware/cache-l2x0.h> +#endif + +#include <mach/vreg.h> +#include <mach/mpp.h> +#include <mach/board.h> +#include <mach/msm_iomap.h> + +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> + +#include "devices.h" +#include "socinfo.h" +#include "clock.h" + +static struct resource smc91x_resources[] = { + [0] = { + .start = 0x9C004300, + .end = 0x9C0043ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MSM_GPIO_TO_INT(132), + .end = MSM_GPIO_TO_INT(132), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + +static struct platform_device *devices[] __initdata = { + &msm_device_uart3, + &msm_device_smd, + &msm_device_dmov, + &msm_device_nand, + &smc91x_device, +}; + +extern struct sys_timer msm_timer; + +static void __init msm7x2x_init_irq(void) +{ + msm_init_irq(); +} + +static void __init msm7x2x_init(void) +{ + if (socinfo_init() < 0) + BUG(); + + if (machine_is_msm7x25_ffa() || machine_is_msm7x27_ffa()) { + smc91x_resources[0].start = 0x98000300; + smc91x_resources[0].end = 0x980003ff; + smc91x_resources[1].start = MSM_GPIO_TO_INT(85); + smc91x_resources[1].end = MSM_GPIO_TO_INT(85); + if (gpio_tlmm_config(GPIO_CFG(85, 0, + GPIO_INPUT, + GPIO_PULL_DOWN, + GPIO_2MA), + GPIO_ENABLE)) { + printk(KERN_ERR + "%s: Err: Config GPIO-85 INT\n", + __func__); + } + } + + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +static void __init msm7x2x_map_io(void) +{ + msm_map_common_io(); + /* Technically dependent on the SoC but using machine_is + * macros since socinfo is not available this early and there + * are plans to restructure the code which will eliminate the + * need for socinfo. + */ + if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa()) + msm_clock_init(msm_clocks_7x27, msm_num_clocks_7x27); + + if (machine_is_msm7x25_surf() || machine_is_msm7x25_ffa()) + msm_clock_init(msm_clocks_7x25, msm_num_clocks_7x25); + +#ifdef CONFIG_CACHE_L2X0 + if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa()) { + /* 7x27 has 256KB L2 cache: + 64Kb/Way and 4-Way Associativity; + R/W latency: 3 cycles; + evmon/parity/share disabled. */ + l2x0_init(MSM_L2CC_BASE, 0x00068012, 0xfe000000); + } +#endif +} + +MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF") + .atag_offset = 0x100, + .map_io = msm7x2x_map_io, + .init_irq = msm7x2x_init_irq, + .init_machine = msm7x2x_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA") + .atag_offset = 0x100, + .map_io = msm7x2x_map_io, + .init_irq = msm7x2x_init_irq, + .init_machine = msm7x2x_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF") + .atag_offset = 0x100, + .map_io = msm7x2x_map_io, + .init_irq = msm7x2x_init_irq, + .init_machine = msm7x2x_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA") + .atag_offset = 0x100, + .map_io = msm7x2x_map_io, + .init_irq = msm7x2x_init_irq, + .init_machine = msm7x2x_init, + .timer = &msm_timer, +MACHINE_END diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c new file mode 100644 index 00000000..db81ed53 --- /dev/null +++ b/arch/arm/mach-msm/board-msm7x30.c @@ -0,0 +1,151 @@ +/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <linux/gpio.h> +#include <linux/kernel.h> +#include <linux/irq.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/smsc911x.h> +#include <linux/usb/msm_hsusb.h> +#include <linux/clkdev.h> +#include <linux/memblock.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/memory.h> +#include <asm/setup.h> + +#include <mach/board.h> +#include <mach/msm_iomap.h> +#include <mach/dma.h> + +#include <mach/vreg.h> +#include "devices.h" +#include "gpiomux.h" +#include "proc_comm.h" + +extern struct sys_timer msm_timer; + +static void __init msm7x30_fixup(struct tag *tag, char **cmdline, + struct meminfo *mi) +{ + for (; tag->hdr.size; tag = tag_next(tag)) + if (tag->hdr.tag == ATAG_MEM && tag->u.mem.start == 0x200000) { + tag->u.mem.start = 0; + tag->u.mem.size += SZ_2M; + } +} + +static void __init msm7x30_reserve(void) +{ + memblock_remove(0x0, SZ_2M); +} + +static int hsusb_phy_init_seq[] = { + 0x30, 0x32, /* Enable and set Pre-Emphasis Depth to 20% */ + 0x02, 0x36, /* Disable CDR Auto Reset feature */ + -1 +}; + +static struct msm_otg_platform_data msm_otg_pdata = { + .phy_init_seq = hsusb_phy_init_seq, + .mode = USB_PERIPHERAL, + .otg_control = OTG_PHY_CONTROL, +}; + +struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = { +#ifdef CONFIG_SERIAL_MSM_CONSOLE + [49] = { /* UART2 RFR */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_2 | GPIOMUX_VALID, + }, + [50] = { /* UART2 CTS */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_2 | GPIOMUX_VALID, + }, + [51] = { /* UART2 RX */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_2 | GPIOMUX_VALID, + }, + [52] = { /* UART2 TX */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_2 | GPIOMUX_VALID, + }, +#endif +}; + +static struct platform_device *devices[] __initdata = { +#if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER) + &msm_device_uart2, +#endif + &msm_device_smd, + &msm_device_otg, + &msm_device_hsusb, + &msm_device_hsusb_host, +}; + +static void __init msm7x30_init_irq(void) +{ + msm_init_irq(); +} + +static void __init msm7x30_init(void) +{ + msm_device_otg.dev.platform_data = &msm_otg_pdata; + msm_device_hsusb.dev.parent = &msm_device_otg.dev; + msm_device_hsusb_host.dev.parent = &msm_device_otg.dev; + + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +static void __init msm7x30_map_io(void) +{ + msm_map_msm7x30_io(); + msm_clock_init(msm_clocks_7x30, msm_num_clocks_7x30); +} + +MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF") + .atag_offset = 0x100, + .fixup = msm7x30_fixup, + .reserve = msm7x30_reserve, + .map_io = msm7x30_map_io, + .init_irq = msm7x30_init_irq, + .init_machine = msm7x30_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA") + .atag_offset = 0x100, + .fixup = msm7x30_fixup, + .reserve = msm7x30_reserve, + .map_io = msm7x30_map_io, + .init_irq = msm7x30_init_irq, + .init_machine = msm7x30_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID") + .atag_offset = 0x100, + .fixup = msm7x30_fixup, + .reserve = msm7x30_reserve, + .map_io = msm7x30_map_io, + .init_irq = msm7x30_init_irq, + .init_machine = msm7x30_init, + .timer = &msm_timer, +MACHINE_END diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c new file mode 100644 index 00000000..ed359812 --- /dev/null +++ b/arch/arm/mach-msm/board-msm8960.c @@ -0,0 +1,115 @@ +/* Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/clkdev.h> +#include <linux/memblock.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/hardware/gic.h> +#include <asm/setup.h> + +#include <mach/board.h> +#include <mach/msm_iomap.h> + +#include "devices.h" + +static void __init msm8960_fixup(struct tag *tag, char **cmdline, + struct meminfo *mi) +{ + for (; tag->hdr.size; tag = tag_next(tag)) + if (tag->hdr.tag == ATAG_MEM && + tag->u.mem.start == 0x40200000) { + tag->u.mem.start = 0x40000000; + tag->u.mem.size += SZ_2M; + } +} + +static void __init msm8960_reserve(void) +{ + memblock_remove(0x40000000, SZ_2M); +} + +static void __init msm8960_map_io(void) +{ + msm_map_msm8960_io(); +} + +static void __init msm8960_init_irq(void) +{ + unsigned int i; + gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, + (void *)MSM_QGIC_CPU_BASE); + + /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */ + writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4); + + if (machine_is_msm8960_rumi3()) + writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET); + + /* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet + * as they are configured as level, which does not play nice with + * handle_percpu_irq. + */ + for (i = GIC_PPI_START; i < GIC_SPI_START; i++) { + if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE) + irq_set_handler(i, handle_percpu_irq); + } +} + +static struct platform_device *sim_devices[] __initdata = { + &msm8960_device_uart_gsbi2, +}; + +static struct platform_device *rumi3_devices[] __initdata = { + &msm8960_device_uart_gsbi5, +}; + +static void __init msm8960_sim_init(void) +{ + platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices)); +} + +static void __init msm8960_rumi3_init(void) +{ + platform_add_devices(rumi3_devices, ARRAY_SIZE(rumi3_devices)); +} + +MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR") + .fixup = msm8960_fixup, + .reserve = msm8960_reserve, + .map_io = msm8960_map_io, + .init_irq = msm8960_init_irq, + .timer = &msm_timer, + .handle_irq = gic_handle_irq, + .init_machine = msm8960_sim_init, +MACHINE_END + +MACHINE_START(MSM8960_RUMI3, "QCT MSM8960 RUMI3") + .fixup = msm8960_fixup, + .reserve = msm8960_reserve, + .map_io = msm8960_map_io, + .init_irq = msm8960_init_irq, + .timer = &msm_timer, + .handle_irq = gic_handle_irq, + .init_machine = msm8960_rumi3_init, +MACHINE_END + diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c new file mode 100644 index 00000000..fb3496a5 --- /dev/null +++ b/arch/arm/mach-msm/board-msm8x60.c @@ -0,0 +1,156 @@ +/* Copyright (c) 2010, 2011, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/memblock.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/hardware/gic.h> +#include <asm/setup.h> + +#include <mach/board.h> +#include <mach/msm_iomap.h> + +static void __init msm8x60_fixup(struct tag *tag, char **cmdline, + struct meminfo *mi) +{ + for (; tag->hdr.size; tag = tag_next(tag)) + if (tag->hdr.tag == ATAG_MEM && + tag->u.mem.start == 0x40200000) { + tag->u.mem.start = 0x40000000; + tag->u.mem.size += SZ_2M; + } +} + +static void __init msm8x60_reserve(void) +{ + memblock_remove(0x40000000, SZ_2M); +} + +static void __init msm8x60_map_io(void) +{ + msm_map_msm8x60_io(); +} + +#ifdef CONFIG_OF +static struct of_device_id msm_dt_gic_match[] __initdata = { + { .compatible = "qcom,msm-8660-qgic", .data = gic_of_init }, + {} +}; +#endif + +static void __init msm8x60_init_irq(void) +{ + if (!of_have_populated_dt()) + gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE, + (void *)MSM_QGIC_CPU_BASE); +#ifdef CONFIG_OF + else + of_irq_init(msm_dt_gic_match); +#endif + + /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */ + writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4); + + /* RUMI does not adhere to GIC spec by enabling STIs by default. + * Enable/clear is supposed to be RO for STIs, but is RW on RUMI. + */ + if (!machine_is_msm8x60_sim()) + writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET); +} + +static void __init msm8x60_init(void) +{ +} + +#ifdef CONFIG_OF +static struct of_dev_auxdata msm_auxdata_lookup[] __initdata = { + {} +}; + +static void __init msm8x60_dt_init(void) +{ + if (of_machine_is_compatible("qcom,msm8660-surf")) { + printk(KERN_INFO "Init surf UART registers\n"); + msm8x60_init_uart12dm(); + } + + of_platform_populate(NULL, of_default_bus_match_table, + msm_auxdata_lookup, NULL); +} + +static const char *msm8x60_fluid_match[] __initdata = { + "qcom,msm8660-fluid", + "qcom,msm8660-surf", + NULL +}; +#endif /* CONFIG_OF */ + +MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3") + .fixup = msm8x60_fixup, + .reserve = msm8x60_reserve, + .map_io = msm8x60_map_io, + .init_irq = msm8x60_init_irq, + .handle_irq = gic_handle_irq, + .init_machine = msm8x60_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF") + .fixup = msm8x60_fixup, + .reserve = msm8x60_reserve, + .map_io = msm8x60_map_io, + .init_irq = msm8x60_init_irq, + .handle_irq = gic_handle_irq, + .init_machine = msm8x60_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR") + .fixup = msm8x60_fixup, + .reserve = msm8x60_reserve, + .map_io = msm8x60_map_io, + .init_irq = msm8x60_init_irq, + .handle_irq = gic_handle_irq, + .init_machine = msm8x60_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA") + .fixup = msm8x60_fixup, + .reserve = msm8x60_reserve, + .map_io = msm8x60_map_io, + .init_irq = msm8x60_init_irq, + .handle_irq = gic_handle_irq, + .init_machine = msm8x60_init, + .timer = &msm_timer, +MACHINE_END + +#ifdef CONFIG_OF +/* TODO: General device tree support for all MSM. */ +DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)") + .map_io = msm8x60_map_io, + .init_irq = msm8x60_init_irq, + .init_machine = msm8x60_dt_init, + .timer = &msm_timer, + .dt_compat = msm8x60_fluid_match, +MACHINE_END +#endif /* CONFIG_OF */ diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c new file mode 100644 index 00000000..7e8909c9 --- /dev/null +++ b/arch/arm/mach-msm/board-qsd8x50.c @@ -0,0 +1,208 @@ +/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <linux/gpio.h> +#include <linux/kernel.h> +#include <linux/irq.h> +#include <linux/gpio.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/usb/msm_hsusb.h> +#include <linux/err.h> +#include <linux/clkdev.h> + +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/io.h> +#include <asm/setup.h> + +#include <mach/board.h> +#include <mach/irqs.h> +#include <mach/sirc.h> +#include <mach/vreg.h> +#include <mach/mmc.h> + +#include "devices.h" + +extern struct sys_timer msm_timer; + +static const resource_size_t qsd8x50_surf_smc91x_base __initdata = 0x70000300; +static const unsigned qsd8x50_surf_smc91x_gpio __initdata = 156; + +/* Leave smc91x resources empty here, as we'll fill them in + * at run-time: they vary from board to board, and the true + * configuration won't be known until boot. + */ +static struct resource smc91x_resources[] = { + [0] = { + .flags = IORESOURCE_MEM, + }, + [1] = { + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + +static int __init msm_init_smc91x(void) +{ + if (machine_is_qsd8x50_surf()) { + smc91x_resources[0].start = qsd8x50_surf_smc91x_base; + smc91x_resources[0].end = qsd8x50_surf_smc91x_base + 0xff; + smc91x_resources[1].start = + gpio_to_irq(qsd8x50_surf_smc91x_gpio); + smc91x_resources[1].end = + gpio_to_irq(qsd8x50_surf_smc91x_gpio); + platform_device_register(&smc91x_device); + } + + return 0; +} +module_init(msm_init_smc91x); + +static int hsusb_phy_init_seq[] = { + 0x08, 0x31, /* Increase HS Driver Amplitude */ + 0x20, 0x32, /* Enable and set Pre-Emphasis Depth to 10% */ + -1 +}; + +static struct msm_otg_platform_data msm_otg_pdata = { + .phy_init_seq = hsusb_phy_init_seq, + .mode = USB_PERIPHERAL, + .otg_control = OTG_PHY_CONTROL, +}; + +static struct platform_device *devices[] __initdata = { + &msm_device_uart3, + &msm_device_smd, + &msm_device_otg, + &msm_device_hsusb, + &msm_device_hsusb_host, +}; + +static struct msm_mmc_gpio sdc1_gpio_cfg[] = { + {51, "sdc1_dat_3"}, + {52, "sdc1_dat_2"}, + {53, "sdc1_dat_1"}, + {54, "sdc1_dat_0"}, + {55, "sdc1_cmd"}, + {56, "sdc1_clk"} +}; + +static struct vreg *vreg_mmc; +static unsigned long vreg_sts; + +static uint32_t msm_sdcc_setup_power(struct device *dv, unsigned int vdd) +{ + int rc = 0; + struct platform_device *pdev; + + pdev = container_of(dv, struct platform_device, dev); + + if (vdd == 0) { + if (!vreg_sts) + return 0; + + clear_bit(pdev->id, &vreg_sts); + + if (!vreg_sts) { + rc = vreg_disable(vreg_mmc); + if (rc) + pr_err("vreg_mmc disable failed for slot " + "%d: %d\n", pdev->id, rc); + } + return 0; + } + + if (!vreg_sts) { + rc = vreg_set_level(vreg_mmc, 2900); + if (rc) + pr_err("vreg_mmc set level failed for slot %d: %d\n", + pdev->id, rc); + rc = vreg_enable(vreg_mmc); + if (rc) + pr_err("vreg_mmc enable failed for slot %d: %d\n", + pdev->id, rc); + } + set_bit(pdev->id, &vreg_sts); + return 0; +} + +static struct msm_mmc_gpio_data sdc1_gpio = { + .gpio = sdc1_gpio_cfg, + .size = ARRAY_SIZE(sdc1_gpio_cfg), +}; + +static struct msm_mmc_platform_data qsd8x50_sdc1_data = { + .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29, + .translate_vdd = msm_sdcc_setup_power, + .gpio_data = &sdc1_gpio, +}; + +static void __init qsd8x50_init_mmc(void) +{ + vreg_mmc = vreg_get(NULL, "gp5"); + + if (IS_ERR(vreg_mmc)) { + pr_err("vreg get for vreg_mmc failed (%ld)\n", + PTR_ERR(vreg_mmc)); + return; + } + + msm_add_sdcc(1, &qsd8x50_sdc1_data, 0, 0); +} + +static void __init qsd8x50_map_io(void) +{ + msm_map_qsd8x50_io(); + msm_clock_init(msm_clocks_8x50, msm_num_clocks_8x50); +} + +static void __init qsd8x50_init_irq(void) +{ + msm_init_irq(); + msm_init_sirc(); +} + +static void __init qsd8x50_init(void) +{ + msm_device_otg.dev.platform_data = &msm_otg_pdata; + msm_device_hsusb.dev.parent = &msm_device_otg.dev; + msm_device_hsusb_host.dev.parent = &msm_device_otg.dev; + platform_add_devices(devices, ARRAY_SIZE(devices)); + qsd8x50_init_mmc(); +} + +MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF") + .atag_offset = 0x100, + .map_io = qsd8x50_map_io, + .init_irq = qsd8x50_init_irq, + .init_machine = qsd8x50_init, + .timer = &msm_timer, +MACHINE_END + +MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5") + .atag_offset = 0x100, + .map_io = qsd8x50_map_io, + .init_irq = qsd8x50_init_irq, + .init_machine = qsd8x50_init, + .timer = &msm_timer, +MACHINE_END diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c new file mode 100644 index 00000000..4a8ea0d4 --- /dev/null +++ b/arch/arm/mach-msm/board-sapphire.c @@ -0,0 +1,112 @@ +/* linux/arch/arm/mach-msm/board-sapphire.c + * Copyright (C) 2007-2009 HTC Corporation. + * Author: Thomas Tsai <thomas_tsai@htc.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. +*/ +#include <linux/gpio.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/device.h> + +#include <linux/delay.h> + +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/flash.h> +#include <mach/system.h> +#include <mach/vreg.h> +#include <mach/board.h> + +#include <asm/io.h> +#include <asm/delay.h> +#include <asm/setup.h> + +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> + +#include "gpio_chip.h" +#include "board-sapphire.h" +#include "proc_comm.h" +#include "devices.h" + +void msm_init_irq(void); +void msm_init_gpio(void); + +static struct platform_device *devices[] __initdata = { + &msm_device_smd, + &msm_device_dmov, + &msm_device_nand, + &msm_device_uart1, + &msm_device_uart3, +}; + +extern struct sys_timer msm_timer; + +static void __init sapphire_init_irq(void) +{ + msm_init_irq(); +} + +static void __init sapphire_init(void) +{ + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +static struct map_desc sapphire_io_desc[] __initdata = { + { + .virtual = SAPPHIRE_CPLD_BASE, + .pfn = __phys_to_pfn(SAPPHIRE_CPLD_START), + .length = SAPPHIRE_CPLD_SIZE, + .type = MT_DEVICE_NONSHARED + } +}; + +static void __init sapphire_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) +{ + int smi_sz = parse_tag_smi((const struct tag *)tags); + + mi->nr_banks = 1; + mi->bank[0].start = PHYS_OFFSET; + mi->bank[0].node = PHYS_TO_NID(PHYS_OFFSET); + if (smi_sz == 32) { + mi->bank[0].size = (84*1024*1024); + } else if (smi_sz == 64) { + mi->bank[0].size = (101*1024*1024); + } else { + /* Give a default value when not get smi size */ + smi_sz = 64; + mi->bank[0].size = (101*1024*1024); + } +} + +static void __init sapphire_map_io(void) +{ + msm_map_common_io(); + iotable_init(sapphire_io_desc, ARRAY_SIZE(sapphire_io_desc)); + msm_clock_init(); +} + +MACHINE_START(SAPPHIRE, "sapphire") +/* Maintainer: Brian Swetland <swetland@google.com> */ + .atag_offset = 0x100, + .fixup = sapphire_fixup, + .map_io = sapphire_map_io, + .init_irq = sapphire_init_irq, + .init_machine = sapphire_init, + .timer = &msm_timer, +MACHINE_END diff --git a/arch/arm/mach-msm/board-trout-gpio.c b/arch/arm/mach-msm/board-trout-gpio.c new file mode 100644 index 00000000..87e1d01e --- /dev/null +++ b/arch/arm/mach-msm/board-trout-gpio.c @@ -0,0 +1,233 @@ +/* + * linux/arch/arm/mach-msm/gpio.c + * + * Copyright (C) 2005 HP Labs + * Copyright (C) 2008 Google, Inc. + * Copyright (C) 2009 Pavel Machek <pavel@ucw.cz> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> + +#include "board-trout.h" + +static uint8_t trout_int_mask[2] = { + [0] = 0xff, /* mask all interrupts */ + [1] = 0xff, +}; +static uint8_t trout_sleep_int_mask[] = { + [0] = 0xff, + [1] = 0xff, +}; + +struct msm_gpio_chip { + struct gpio_chip chip; + void __iomem *reg; /* Base of register bank */ + u8 shadow; +}; + +#define to_msm_gpio_chip(c) container_of(c, struct msm_gpio_chip, chip) + +static int msm_gpiolib_get(struct gpio_chip *chip, unsigned offset) +{ + struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip); + unsigned mask = 1 << offset; + + return !!(readb(msm_gpio->reg) & mask); +} + +static void msm_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val) +{ + struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip); + unsigned mask = 1 << offset; + + if (val) + msm_gpio->shadow |= mask; + else + msm_gpio->shadow &= ~mask; + + writeb(msm_gpio->shadow, msm_gpio->reg); +} + +static int msm_gpiolib_direction_input(struct gpio_chip *chip, + unsigned offset) +{ + msm_gpiolib_set(chip, offset, 0); + return 0; +} + +static int msm_gpiolib_direction_output(struct gpio_chip *chip, + unsigned offset, int val) +{ + msm_gpiolib_set(chip, offset, val); + return 0; +} + +static int trout_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +{ + return TROUT_GPIO_TO_INT(offset + chip->base); +} + +#define TROUT_GPIO_BANK(name, reg_num, base_gpio, shadow_val) \ + { \ + .chip = { \ + .label = name, \ + .direction_input = msm_gpiolib_direction_input,\ + .direction_output = msm_gpiolib_direction_output, \ + .get = msm_gpiolib_get, \ + .set = msm_gpiolib_set, \ + .to_irq = trout_gpio_to_irq, \ + .base = base_gpio, \ + .ngpio = 8, \ + }, \ + .reg = (void *) reg_num + TROUT_CPLD_BASE, \ + .shadow = shadow_val, \ + } + +static struct msm_gpio_chip msm_gpio_banks[] = { +#if defined(CONFIG_MSM_DEBUG_UART1) + /* H2W pins <-> UART1 */ + TROUT_GPIO_BANK("MISC2", 0x00, TROUT_GPIO_MISC2_BASE, 0x40), +#else + /* H2W pins <-> UART3, Bluetooth <-> UART1 */ + TROUT_GPIO_BANK("MISC2", 0x00, TROUT_GPIO_MISC2_BASE, 0x80), +#endif + /* I2C pull */ + TROUT_GPIO_BANK("MISC3", 0x02, TROUT_GPIO_MISC3_BASE, 0x04), + TROUT_GPIO_BANK("MISC4", 0x04, TROUT_GPIO_MISC4_BASE, 0), + /* mmdi 32k en */ + TROUT_GPIO_BANK("MISC5", 0x06, TROUT_GPIO_MISC5_BASE, 0x04), + TROUT_GPIO_BANK("INT2", 0x08, TROUT_GPIO_INT2_BASE, 0), + TROUT_GPIO_BANK("MISC1", 0x0a, TROUT_GPIO_MISC1_BASE, 0), + TROUT_GPIO_BANK("VIRTUAL", 0x12, TROUT_GPIO_VIRTUAL_BASE, 0), +}; + +static void trout_gpio_irq_ack(struct irq_data *d) +{ + int bank = TROUT_INT_TO_BANK(d->irq); + uint8_t mask = TROUT_INT_TO_MASK(d->irq); + int reg = TROUT_BANK_TO_STAT_REG(bank); + /*printk(KERN_INFO "trout_gpio_irq_ack irq %d\n", d->irq);*/ + writeb(mask, TROUT_CPLD_BASE + reg); +} + +static void trout_gpio_irq_mask(struct irq_data *d) +{ + unsigned long flags; + uint8_t reg_val; + int bank = TROUT_INT_TO_BANK(d->irq); + uint8_t mask = TROUT_INT_TO_MASK(d->irq); + int reg = TROUT_BANK_TO_MASK_REG(bank); + + local_irq_save(flags); + reg_val = trout_int_mask[bank] |= mask; + /*printk(KERN_INFO "trout_gpio_irq_mask irq %d => %d:%02x\n", + d->irq, bank, reg_val);*/ + writeb(reg_val, TROUT_CPLD_BASE + reg); + local_irq_restore(flags); +} + +static void trout_gpio_irq_unmask(struct irq_data *d) +{ + unsigned long flags; + uint8_t reg_val; + int bank = TROUT_INT_TO_BANK(d->irq); + uint8_t mask = TROUT_INT_TO_MASK(d->irq); + int reg = TROUT_BANK_TO_MASK_REG(bank); + + local_irq_save(flags); + reg_val = trout_int_mask[bank] &= ~mask; + /*printk(KERN_INFO "trout_gpio_irq_unmask irq %d => %d:%02x\n", + d->irq, bank, reg_val);*/ + writeb(reg_val, TROUT_CPLD_BASE + reg); + local_irq_restore(flags); +} + +int trout_gpio_irq_set_wake(struct irq_data *d, unsigned int on) +{ + unsigned long flags; + int bank = TROUT_INT_TO_BANK(d->irq); + uint8_t mask = TROUT_INT_TO_MASK(d->irq); + + local_irq_save(flags); + if(on) + trout_sleep_int_mask[bank] &= ~mask; + else + trout_sleep_int_mask[bank] |= mask; + local_irq_restore(flags); + return 0; +} + +static void trout_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + int j, m; + unsigned v; + int bank; + int stat_reg; + int int_base = TROUT_INT_START; + uint8_t int_mask; + + for (bank = 0; bank < 2; bank++) { + stat_reg = TROUT_BANK_TO_STAT_REG(bank); + v = readb(TROUT_CPLD_BASE + stat_reg); + int_mask = trout_int_mask[bank]; + if (v & int_mask) { + writeb(v & int_mask, TROUT_CPLD_BASE + stat_reg); + printk(KERN_ERR "trout_gpio_irq_handler: got masked " + "interrupt: %d:%02x\n", bank, v & int_mask); + } + v &= ~int_mask; + while (v) { + m = v & -v; + j = fls(m) - 1; + /*printk(KERN_INFO "msm_gpio_irq_handler %d:%02x %02x b" + "it %d irq %d\n", bank, v, m, j, int_base + j);*/ + v &= ~m; + generic_handle_irq(int_base + j); + } + int_base += TROUT_INT_BANK0_COUNT; + } + desc->irq_data.chip->irq_ack(&desc->irq_data); +} + +static struct irq_chip trout_gpio_irq_chip = { + .name = "troutgpio", + .irq_ack = trout_gpio_irq_ack, + .irq_mask = trout_gpio_irq_mask, + .irq_unmask = trout_gpio_irq_unmask, + .irq_set_wake = trout_gpio_irq_set_wake, +}; + +/* + * Called from the processor-specific init to enable GPIO pin support. + */ +int __init trout_init_gpio(void) +{ + int i; + for(i = TROUT_INT_START; i <= TROUT_INT_END; i++) { + irq_set_chip_and_handler(i, &trout_gpio_irq_chip, + handle_edge_irq); + set_irq_flags(i, IRQF_VALID); + } + + for (i = 0; i < ARRAY_SIZE(msm_gpio_banks); i++) + gpiochip_add(&msm_gpio_banks[i].chip); + + irq_set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH); + irq_set_chained_handler(MSM_GPIO_TO_INT(17), trout_gpio_irq_handler); + irq_set_irq_wake(MSM_GPIO_TO_INT(17), 1); + + return 0; +} + +postcore_initcall(trout_init_gpio); + diff --git a/arch/arm/mach-msm/board-trout-mmc.c b/arch/arm/mach-msm/board-trout-mmc.c new file mode 100644 index 00000000..8650342b --- /dev/null +++ b/arch/arm/mach-msm/board-trout-mmc.c @@ -0,0 +1,185 @@ +/* linux/arch/arm/mach-msm/board-trout-mmc.c +** Author: Brian Swetland <swetland@google.com> +*/ +#include <linux/gpio.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/mmc/host.h> +#include <linux/mmc/sdio_ids.h> +#include <linux/err.h> +#include <linux/debugfs.h> + +#include <asm/io.h> + +#include <mach/vreg.h> + +#include <mach/mmc.h> + +#include "devices.h" + +#include "board-trout.h" + +#include "proc_comm.h" + +#define DEBUG_SDSLOT_VDD 1 + +/* ---- COMMON ---- */ +static void config_gpio_table(uint32_t *table, int len) +{ + int n; + unsigned id; + for(n = 0; n < len; n++) { + id = table[n]; + msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &id, 0); + } +} + +/* ---- SDCARD ---- */ + +static uint32_t sdcard_on_gpio_table[] = { + PCOM_GPIO_CFG(62, 2, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA), /* CLK */ + PCOM_GPIO_CFG(63, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* CMD */ + PCOM_GPIO_CFG(64, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* DAT3 */ + PCOM_GPIO_CFG(65, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_8MA), /* DAT2 */ + PCOM_GPIO_CFG(66, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_4MA), /* DAT1 */ + PCOM_GPIO_CFG(67, 2, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_4MA), /* DAT0 */ +}; + +static uint32_t sdcard_off_gpio_table[] = { + PCOM_GPIO_CFG(62, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* CLK */ + PCOM_GPIO_CFG(63, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* CMD */ + PCOM_GPIO_CFG(64, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT3 */ + PCOM_GPIO_CFG(65, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT2 */ + PCOM_GPIO_CFG(66, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT1 */ + PCOM_GPIO_CFG(67, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_4MA), /* DAT0 */ +}; + +static uint opt_disable_sdcard; + +static int __init trout_disablesdcard_setup(char *str) +{ + int cal = simple_strtol(str, NULL, 0); + + opt_disable_sdcard = cal; + return 1; +} + +__setup("board_trout.disable_sdcard=", trout_disablesdcard_setup); + +static struct vreg *vreg_sdslot; /* SD slot power */ + +struct mmc_vdd_xlat { + int mask; + int level; +}; + +static struct mmc_vdd_xlat mmc_vdd_table[] = { + { MMC_VDD_165_195, 1800 }, + { MMC_VDD_20_21, 2050 }, + { MMC_VDD_21_22, 2150 }, + { MMC_VDD_22_23, 2250 }, + { MMC_VDD_23_24, 2350 }, + { MMC_VDD_24_25, 2450 }, + { MMC_VDD_25_26, 2550 }, + { MMC_VDD_26_27, 2650 }, + { MMC_VDD_27_28, 2750 }, + { MMC_VDD_28_29, 2850 }, + { MMC_VDD_29_30, 2950 }, +}; + +static unsigned int sdslot_vdd = 0xffffffff; +static unsigned int sdslot_vreg_enabled; + +static uint32_t trout_sdslot_switchvdd(struct device *dev, unsigned int vdd) +{ + int i, rc; + + BUG_ON(!vreg_sdslot); + + if (vdd == sdslot_vdd) + return 0; + + sdslot_vdd = vdd; + + if (vdd == 0) { +#if DEBUG_SDSLOT_VDD + printk("%s: Disabling SD slot power\n", __func__); +#endif + config_gpio_table(sdcard_off_gpio_table, + ARRAY_SIZE(sdcard_off_gpio_table)); + vreg_disable(vreg_sdslot); + sdslot_vreg_enabled = 0; + return 0; + } + + if (!sdslot_vreg_enabled) { + rc = vreg_enable(vreg_sdslot); + if (rc) { + printk(KERN_ERR "%s: Error enabling vreg (%d)\n", + __func__, rc); + } + config_gpio_table(sdcard_on_gpio_table, + ARRAY_SIZE(sdcard_on_gpio_table)); + sdslot_vreg_enabled = 1; + } + + for (i = 0; i < ARRAY_SIZE(mmc_vdd_table); i++) { + if (mmc_vdd_table[i].mask == (1 << vdd)) { +#if DEBUG_SDSLOT_VDD + printk("%s: Setting level to %u\n", + __func__, mmc_vdd_table[i].level); +#endif + rc = vreg_set_level(vreg_sdslot, + mmc_vdd_table[i].level); + if (rc) { + printk(KERN_ERR + "%s: Error setting vreg level (%d)\n", + __func__, rc); + } + return 0; + } + } + + printk(KERN_ERR "%s: Invalid VDD %d specified\n", __func__, vdd); + return 0; +} + +static unsigned int trout_sdslot_status(struct device *dev) +{ + unsigned int status; + + status = (unsigned int) gpio_get_value(TROUT_GPIO_SDMC_CD_N); + return (!status); +} + +#define TROUT_MMC_VDD MMC_VDD_165_195 | MMC_VDD_20_21 | MMC_VDD_21_22 \ + | MMC_VDD_22_23 | MMC_VDD_23_24 | MMC_VDD_24_25 \ + | MMC_VDD_25_26 | MMC_VDD_26_27 | MMC_VDD_27_28 \ + | MMC_VDD_28_29 | MMC_VDD_29_30 + +static struct msm_mmc_platform_data trout_sdslot_data = { + .ocr_mask = TROUT_MMC_VDD, + .status = trout_sdslot_status, + .translate_vdd = trout_sdslot_switchvdd, +}; + +int __init trout_init_mmc(unsigned int sys_rev) +{ + sdslot_vreg_enabled = 0; + + vreg_sdslot = vreg_get(0, "gp6"); + if (IS_ERR(vreg_sdslot)) + return PTR_ERR(vreg_sdslot); + + irq_set_irq_wake(TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 1); + + if (!opt_disable_sdcard) + msm_add_sdcc(2, &trout_sdslot_data, + TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 0); + else + printk(KERN_INFO "trout: SD-Card interface disabled\n"); + return 0; +} + diff --git a/arch/arm/mach-msm/board-trout-panel.c b/arch/arm/mach-msm/board-trout-panel.c new file mode 100644 index 00000000..89bf6b42 --- /dev/null +++ b/arch/arm/mach-msm/board-trout-panel.c @@ -0,0 +1,297 @@ +/* linux/arch/arm/mach-msm/board-trout-mddi.c +** Author: Brian Swetland <swetland@google.com> +*/ +#include <linux/gpio.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/leds.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <asm/io.h> +#include <asm/mach-types.h> +#include <asm/system_info.h> + +#include <mach/msm_fb.h> +#include <mach/vreg.h> + +#include "board-trout.h" +#include "proc_comm.h" +#include "devices.h" + +#define TROUT_DEFAULT_BACKLIGHT_BRIGHTNESS 255 + +#define MDDI_CLIENT_CORE_BASE 0x108000 +#define LCD_CONTROL_BLOCK_BASE 0x110000 +#define SPI_BLOCK_BASE 0x120000 +#define I2C_BLOCK_BASE 0x130000 +#define PWM_BLOCK_BASE 0x140000 +#define GPIO_BLOCK_BASE 0x150000 +#define SYSTEM_BLOCK1_BASE 0x160000 +#define SYSTEM_BLOCK2_BASE 0x170000 + + +#define DPSUS (MDDI_CLIENT_CORE_BASE|0x24) +#define SYSCLKENA (MDDI_CLIENT_CORE_BASE|0x2C) +#define PWM0OFF (PWM_BLOCK_BASE|0x1C) + +#define V_VDDE2E_VDD2_GPIO 0 +#define MDDI_RST_N 82 + +#define MDDICAP0 (MDDI_CLIENT_CORE_BASE|0x00) +#define MDDICAP1 (MDDI_CLIENT_CORE_BASE|0x04) +#define MDDICAP2 (MDDI_CLIENT_CORE_BASE|0x08) +#define MDDICAP3 (MDDI_CLIENT_CORE_BASE|0x0C) +#define MDCAPCHG (MDDI_CLIENT_CORE_BASE|0x10) +#define MDCRCERC (MDDI_CLIENT_CORE_BASE|0x14) +#define TTBUSSEL (MDDI_CLIENT_CORE_BASE|0x18) +#define DPSET0 (MDDI_CLIENT_CORE_BASE|0x1C) +#define DPSET1 (MDDI_CLIENT_CORE_BASE|0x20) +#define DPSUS (MDDI_CLIENT_CORE_BASE|0x24) +#define DPRUN (MDDI_CLIENT_CORE_BASE|0x28) +#define SYSCKENA (MDDI_CLIENT_CORE_BASE|0x2C) +#define TESTMODE (MDDI_CLIENT_CORE_BASE|0x30) +#define FIFOMONI (MDDI_CLIENT_CORE_BASE|0x34) +#define INTMONI (MDDI_CLIENT_CORE_BASE|0x38) +#define MDIOBIST (MDDI_CLIENT_CORE_BASE|0x3C) +#define MDIOPSET (MDDI_CLIENT_CORE_BASE|0x40) +#define BITMAP0 (MDDI_CLIENT_CORE_BASE|0x44) +#define BITMAP1 (MDDI_CLIENT_CORE_BASE|0x48) +#define BITMAP2 (MDDI_CLIENT_CORE_BASE|0x4C) +#define BITMAP3 (MDDI_CLIENT_CORE_BASE|0x50) +#define BITMAP4 (MDDI_CLIENT_CORE_BASE|0x54) + +#define SRST (LCD_CONTROL_BLOCK_BASE|0x00) +#define PORT_ENB (LCD_CONTROL_BLOCK_BASE|0x04) +#define START (LCD_CONTROL_BLOCK_BASE|0x08) +#define PORT (LCD_CONTROL_BLOCK_BASE|0x0C) +#define CMN (LCD_CONTROL_BLOCK_BASE|0x10) +#define GAMMA (LCD_CONTROL_BLOCK_BASE|0x14) +#define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18) +#define INTMSK (LCD_CONTROL_BLOCK_BASE|0x1C) +#define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20) +#define HDE_LEFT (LCD_CONTROL_BLOCK_BASE|0x24) +#define VDE_TOP (LCD_CONTROL_BLOCK_BASE|0x28) +#define PXL (LCD_CONTROL_BLOCK_BASE|0x30) +#define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34) +#define HSW (LCD_CONTROL_BLOCK_BASE|0x38) +#define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C) +#define HDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x40) +#define VCYCLE (LCD_CONTROL_BLOCK_BASE|0x44) +#define VSW (LCD_CONTROL_BLOCK_BASE|0x48) +#define VDE_START (LCD_CONTROL_BLOCK_BASE|0x4C) +#define VDE_SIZE (LCD_CONTROL_BLOCK_BASE|0x50) +#define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54) +#define WSYN_DLY (LCD_CONTROL_BLOCK_BASE|0x58) +#define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C) +#define VSYNIF (LCD_CONTROL_BLOCK_BASE|0x60) +#define WRSTB (LCD_CONTROL_BLOCK_BASE|0x64) +#define RDSTB (LCD_CONTROL_BLOCK_BASE|0x68) +#define ASY_DATA (LCD_CONTROL_BLOCK_BASE|0x6C) +#define ASY_DATB (LCD_CONTROL_BLOCK_BASE|0x70) +#define ASY_DATC (LCD_CONTROL_BLOCK_BASE|0x74) +#define ASY_DATD (LCD_CONTROL_BLOCK_BASE|0x78) +#define ASY_DATE (LCD_CONTROL_BLOCK_BASE|0x7C) +#define ASY_DATF (LCD_CONTROL_BLOCK_BASE|0x80) +#define ASY_DATG (LCD_CONTROL_BLOCK_BASE|0x84) +#define ASY_DATH (LCD_CONTROL_BLOCK_BASE|0x88) +#define ASY_CMDSET (LCD_CONTROL_BLOCK_BASE|0x8C) + +#define SSICTL (SPI_BLOCK_BASE|0x00) +#define SSITIME (SPI_BLOCK_BASE|0x04) +#define SSITX (SPI_BLOCK_BASE|0x08) +#define SSIRX (SPI_BLOCK_BASE|0x0C) +#define SSIINTC (SPI_BLOCK_BASE|0x10) +#define SSIINTS (SPI_BLOCK_BASE|0x14) +#define SSIDBG1 (SPI_BLOCK_BASE|0x18) +#define SSIDBG2 (SPI_BLOCK_BASE|0x1C) +#define SSIID (SPI_BLOCK_BASE|0x20) + +#define WKREQ (SYSTEM_BLOCK1_BASE|0x00) +#define CLKENB (SYSTEM_BLOCK1_BASE|0x04) +#define DRAMPWR (SYSTEM_BLOCK1_BASE|0x08) +#define INTMASK (SYSTEM_BLOCK1_BASE|0x0C) +#define GPIOSEL (SYSTEM_BLOCK2_BASE|0x00) + +#define GPIODATA (GPIO_BLOCK_BASE|0x00) +#define GPIODIR (GPIO_BLOCK_BASE|0x04) +#define GPIOIS (GPIO_BLOCK_BASE|0x08) +#define GPIOIBE (GPIO_BLOCK_BASE|0x0C) +#define GPIOIEV (GPIO_BLOCK_BASE|0x10) +#define GPIOIE (GPIO_BLOCK_BASE|0x14) +#define GPIORIS (GPIO_BLOCK_BASE|0x18) +#define GPIOMIS (GPIO_BLOCK_BASE|0x1C) +#define GPIOIC (GPIO_BLOCK_BASE|0x20) +#define GPIOOMS (GPIO_BLOCK_BASE|0x24) +#define GPIOPC (GPIO_BLOCK_BASE|0x28) +#define GPIOID (GPIO_BLOCK_BASE|0x30) + +#define SPI_WRITE(reg, val) \ + { SSITX, 0x00010000 | (((reg) & 0xff) << 8) | ((val) & 0xff) }, \ + { 0, 5 }, + +#define SPI_WRITE1(reg) \ + { SSITX, (reg) & 0xff }, \ + { 0, 5 }, + +struct mddi_table { + uint32_t reg; + uint32_t value; +}; +static struct mddi_table mddi_toshiba_init_table[] = { + { DPSET0, 0x09e90046 }, + { DPSET1, 0x00000118 }, + { DPSUS, 0x00000000 }, + { DPRUN, 0x00000001 }, + { 1, 14 }, /* msleep 14 */ + { SYSCKENA, 0x00000001 }, + { CLKENB, 0x0000A1EF }, /* # SYS.CLKENB # Enable clocks for each module (without DCLK , i2cCLK) */ + + { GPIODATA, 0x02000200 }, /* # GPI .GPIODATA # GPIO2(RESET_LCD_N) set to 0 , GPIO3(eDRAM_Power) set to 0 */ + { GPIODIR, 0x000030D }, /* 24D # GPI .GPIODIR # Select direction of GPIO port (0,2,3,6,9 output) */ + { GPIOSEL, 0/*0x00000173*/}, /* # SYS.GPIOSEL # GPIO port multiplexing control */ + { GPIOPC, 0x03C300C0 }, /* # GPI .GPIOPC # GPIO2,3 PD cut */ + { WKREQ, 0x00000000 }, /* # SYS.WKREQ # Wake-up request event is VSYNC alignment */ + + { GPIOIBE, 0x000003FF }, + { GPIOIS, 0x00000000 }, + { GPIOIC, 0x000003FF }, + { GPIOIE, 0x00000000 }, + + { GPIODATA, 0x00040004 }, /* # GPI .GPIODATA # eDRAM VD supply */ + { 1, 1 }, /* msleep 1 */ + { GPIODATA, 0x02040004 }, /* # GPI .GPIODATA # eDRAM VD supply */ + { DRAMPWR, 0x00000001 }, /* eDRAM power */ +}; + +#define GPIOSEL_VWAKEINT (1U << 0) +#define INTMASK_VWAKEOUT (1U << 0) + + +static struct clk *gp_clk; +static int trout_new_backlight = 1; +static struct vreg *vreg_mddi_1v5; +static struct vreg *vreg_lcm_2v85; + +static void trout_process_mddi_table(struct msm_mddi_client_data *client_data, + struct mddi_table *table, size_t count) +{ + int i; + for (i = 0; i < count; i++) { + uint32_t reg = table[i].reg; + uint32_t value = table[i].value; + + if (reg == 0) + udelay(value); + else if (reg == 1) + msleep(value); + else + client_data->remote_write(client_data, value, reg); + } +} + +static int trout_mddi_toshiba_client_init( + struct msm_mddi_bridge_platform_data *bridge_data, + struct msm_mddi_client_data *client_data) +{ + int panel_id; + + client_data->auto_hibernate(client_data, 0); + trout_process_mddi_table(client_data, mddi_toshiba_init_table, + ARRAY_SIZE(mddi_toshiba_init_table)); + client_data->auto_hibernate(client_data, 1); + panel_id = (client_data->remote_read(client_data, GPIODATA) >> 4) & 3; + if (panel_id > 1) { + printk(KERN_WARNING "unknown panel id at mddi_enable\n"); + return -1; + } + return 0; +} + +static int trout_mddi_toshiba_client_uninit( + struct msm_mddi_bridge_platform_data *bridge_data, + struct msm_mddi_client_data *client_data) +{ + return 0; +} + +static struct resource resources_msm_fb[] = { + { + .start = MSM_FB_BASE, + .end = MSM_FB_BASE + MSM_FB_SIZE, + .flags = IORESOURCE_MEM, + }, +}; + +struct msm_mddi_bridge_platform_data toshiba_client_data = { + .init = trout_mddi_toshiba_client_init, + .uninit = trout_mddi_toshiba_client_uninit, + .fb_data = { + .xres = 320, + .yres = 480, + .width = 45, + .height = 67, + .output_format = 0, + }, +}; + +static struct msm_mddi_platform_data mddi_pdata = { + .clk_rate = 122880000, + .fb_resource = resources_msm_fb, + .num_clients = 1, + .client_platform_data = { + { + .product_id = (0xd263 << 16 | 0), + .name = "mddi_c_d263_0000", + .id = 0, + .client_data = &toshiba_client_data, + .clk_rate = 0, + }, + }, +}; + +int __init trout_init_panel(void) +{ + int rc; + + if (!machine_is_trout()) + return 0; + vreg_mddi_1v5 = vreg_get(0, "gp2"); + if (IS_ERR(vreg_mddi_1v5)) + return PTR_ERR(vreg_mddi_1v5); + vreg_lcm_2v85 = vreg_get(0, "gp4"); + if (IS_ERR(vreg_lcm_2v85)) + return PTR_ERR(vreg_lcm_2v85); + + trout_new_backlight = system_rev >= 5; + if (trout_new_backlight) { + uint32_t config = PCOM_GPIO_CFG(27, 0, GPIO_OUTPUT, + GPIO_NO_PULL, GPIO_8MA); + msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, 0); + } else { + uint32_t config = PCOM_GPIO_CFG(27, 1, GPIO_OUTPUT, + GPIO_NO_PULL, GPIO_8MA); + msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, 0); + + gp_clk = clk_get(NULL, "gp_clk"); + if (IS_ERR(gp_clk)) { + printk(KERN_ERR "trout_init_panel: could not get gp" + "clock\n"); + gp_clk = NULL; + } + rc = clk_set_rate(gp_clk, 19200000); + if (rc) + printk(KERN_ERR "trout_init_panel: set clock rate " + "failed\n"); + } + + rc = platform_device_register(&msm_device_mdp); + if (rc) + return rc; + msm_device_mddi0.dev.platform_data = &mddi_pdata; + return platform_device_register(&msm_device_mddi0); +} + +device_initcall(trout_init_panel); diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c new file mode 100644 index 00000000..d4060a37 --- /dev/null +++ b/arch/arm/mach-msm/board-trout.c @@ -0,0 +1,109 @@ +/* linux/arch/arm/mach-msm/board-trout.c + * + * Copyright (C) 2009 Google, Inc. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/clkdev.h> + +#include <asm/system_info.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/setup.h> + +#include <mach/board.h> +#include <mach/hardware.h> +#include <mach/msm_iomap.h> + +#include "devices.h" +#include "board-trout.h" + +extern int trout_init_mmc(unsigned int); + +static struct platform_device *devices[] __initdata = { + &msm_device_uart3, + &msm_device_smd, + &msm_device_nand, + &msm_device_hsusb, + &msm_device_i2c, +}; + +extern struct sys_timer msm_timer; + +static void __init trout_init_early(void) +{ + arch_ioremap_caller = __msm_ioremap_caller; +} + +static void __init trout_init_irq(void) +{ + msm_init_irq(); +} + +static void __init trout_fixup(struct tag *tags, char **cmdline, + struct meminfo *mi) +{ + mi->nr_banks = 1; + mi->bank[0].start = PHYS_OFFSET; + mi->bank[0].size = (101*1024*1024); +} + +static void __init trout_init(void) +{ + int rc; + + platform_add_devices(devices, ARRAY_SIZE(devices)); + +#ifdef CONFIG_MMC + rc = trout_init_mmc(system_rev); + if (rc) + printk(KERN_CRIT "%s: MMC init failure (%d)\n", __func__, rc); +#endif + +} + +static struct map_desc trout_io_desc[] __initdata = { + { + .virtual = TROUT_CPLD_BASE, + .pfn = __phys_to_pfn(TROUT_CPLD_START), + .length = TROUT_CPLD_SIZE, + .type = MT_DEVICE_NONSHARED + } +}; + +static void __init trout_map_io(void) +{ + msm_map_common_io(); + iotable_init(trout_io_desc, ARRAY_SIZE(trout_io_desc)); + +#ifdef CONFIG_MSM_DEBUG_UART3 + /* route UART3 to the "H2W" extended usb connector */ + writeb(0x80, TROUT_CPLD_BASE + 0x00); +#endif + + msm_clock_init(msm_clocks_7x01a, msm_num_clocks_7x01a); +} + +MACHINE_START(TROUT, "HTC Dream") + .atag_offset = 0x100, + .fixup = trout_fixup, + .map_io = trout_map_io, + .init_early = trout_init_early, + .init_irq = trout_init_irq, + .init_machine = trout_init, + .timer = &msm_timer, +MACHINE_END diff --git a/arch/arm/mach-msm/board-trout.h b/arch/arm/mach-msm/board-trout.h new file mode 100644 index 00000000..651851c3 --- /dev/null +++ b/arch/arm/mach-msm/board-trout.h @@ -0,0 +1,162 @@ +/* linux/arch/arm/mach-msm/board-trout.h +** Author: Brian Swetland <swetland@google.com> +*/ +#ifndef __ARCH_ARM_MACH_MSM_BOARD_TROUT_H +#define __ARCH_ARM_MACH_MSM_BOARD_TROUT_H + +#include <mach/board.h> + +#define MSM_SMI_BASE 0x00000000 +#define MSM_SMI_SIZE 0x00800000 + +#define MSM_EBI_BASE 0x10000000 +#define MSM_EBI_SIZE 0x06e00000 + +#define MSM_PMEM_GPU0_BASE 0x00000000 +#define MSM_PMEM_GPU0_SIZE 0x00700000 + +#define MSM_PMEM_MDP_BASE 0x02000000 +#define MSM_PMEM_MDP_SIZE 0x00800000 + +#define MSM_PMEM_ADSP_BASE 0x02800000 +#define MSM_PMEM_ADSP_SIZE 0x00800000 + +#define MSM_PMEM_CAMERA_BASE 0x03000000 +#define MSM_PMEM_CAMERA_SIZE 0x00800000 + +#define MSM_FB_BASE 0x03800000 +#define MSM_FB_SIZE 0x00100000 + +#define MSM_LINUX_BASE MSM_EBI_BASE +#define MSM_LINUX_SIZE 0x06500000 + +#define MSM_PMEM_GPU1_SIZE 0x800000 +#define MSM_PMEM_GPU1_BASE (MSM_RAM_CONSOLE_BASE - MSM_PMEM_GPU1_SIZE) + +#define MSM_RAM_CONSOLE_BASE (MSM_EBI_BASE + 0x6d00000) +#define MSM_RAM_CONSOLE_SIZE (128 * SZ_1K) + +#if (MSM_FB_BASE + MSM_FB_SIZE) >= (MSM_PMEM_GPU1_BASE) +#error invalid memory map +#endif + +#define DECLARE_MSM_IOMAP +#include <mach/msm_iomap.h> + +#define TROUT_4_BALL_UP_0 1 +#define TROUT_4_BALL_LEFT_0 18 +#define TROUT_4_BALL_DOWN_0 57 +#define TROUT_4_BALL_RIGHT_0 91 + +#define TROUT_5_BALL_UP_0 94 +#define TROUT_5_BALL_LEFT_0 18 +#define TROUT_5_BALL_DOWN_0 90 +#define TROUT_5_BALL_RIGHT_0 19 + +#define TROUT_POWER_KEY 20 + +#define TROUT_4_TP_LS_EN 19 +#define TROUT_5_TP_LS_EN 1 + +#define TROUT_CPLD_BASE 0xE8100000 +#define TROUT_CPLD_START 0x98000000 +#define TROUT_CPLD_SIZE SZ_4K + +#define TROUT_GPIO_CABLE_IN1 (83) +#define TROUT_GPIO_CABLE_IN2 (49) + +#define TROUT_GPIO_START (128) + +#define TROUT_GPIO_INT_MASK0_REG (0x0c) +#define TROUT_GPIO_INT_STAT0_REG (0x0e) +#define TROUT_GPIO_INT_MASK1_REG (0x14) +#define TROUT_GPIO_INT_STAT1_REG (0x10) + +#define TROUT_GPIO_HAPTIC_PWM (28) +#define TROUT_GPIO_PS_HOLD (25) + +#define TROUT_GPIO_MISC2_BASE (TROUT_GPIO_START + 0x00) +#define TROUT_GPIO_MISC3_BASE (TROUT_GPIO_START + 0x08) +#define TROUT_GPIO_MISC4_BASE (TROUT_GPIO_START + 0x10) +#define TROUT_GPIO_MISC5_BASE (TROUT_GPIO_START + 0x18) +#define TROUT_GPIO_INT2_BASE (TROUT_GPIO_START + 0x20) +#define TROUT_GPIO_MISC1_BASE (TROUT_GPIO_START + 0x28) +#define TROUT_GPIO_VIRTUAL_BASE (TROUT_GPIO_START + 0x30) +#define TROUT_GPIO_INT5_BASE (TROUT_GPIO_START + 0x48) + +#define TROUT_GPIO_CHARGER_EN (TROUT_GPIO_MISC2_BASE + 0) +#define TROUT_GPIO_ISET (TROUT_GPIO_MISC2_BASE + 1) +#define TROUT_GPIO_H2W_DAT_DIR (TROUT_GPIO_MISC2_BASE + 2) +#define TROUT_GPIO_H2W_CLK_DIR (TROUT_GPIO_MISC2_BASE + 3) +#define TROUT_GPIO_H2W_DAT_GPO (TROUT_GPIO_MISC2_BASE + 4) +#define TROUT_GPIO_H2W_CLK_GPO (TROUT_GPIO_MISC2_BASE + 5) +#define TROUT_GPIO_H2W_SEL0 (TROUT_GPIO_MISC2_BASE + 6) +#define TROUT_GPIO_H2W_SEL1 (TROUT_GPIO_MISC2_BASE + 7) + +#define TROUT_GPIO_SPOTLIGHT_EN (TROUT_GPIO_MISC3_BASE + 0) +#define TROUT_GPIO_FLASH_EN (TROUT_GPIO_MISC3_BASE + 1) +#define TROUT_GPIO_I2C_PULL (TROUT_GPIO_MISC3_BASE + 2) +#define TROUT_GPIO_TP_I2C_PULL (TROUT_GPIO_MISC3_BASE + 3) +#define TROUT_GPIO_TP_EN (TROUT_GPIO_MISC3_BASE + 4) +#define TROUT_GPIO_JOG_EN (TROUT_GPIO_MISC3_BASE + 5) +#define TROUT_GPIO_UI_LED_EN (TROUT_GPIO_MISC3_BASE + 6) +#define TROUT_GPIO_QTKEY_LED_EN (TROUT_GPIO_MISC3_BASE + 7) + +#define TROUT_GPIO_VCM_PWDN (TROUT_GPIO_MISC4_BASE + 0) +#define TROUT_GPIO_USB_H2W_SW (TROUT_GPIO_MISC4_BASE + 1) +#define TROUT_GPIO_COMPASS_RST_N (TROUT_GPIO_MISC4_BASE + 2) +#define TROUT_GPIO_HAPTIC_EN_UP (TROUT_GPIO_MISC4_BASE + 3) +#define TROUT_GPIO_HAPTIC_EN_MAIN (TROUT_GPIO_MISC4_BASE + 4) +#define TROUT_GPIO_USB_PHY_RST_N (TROUT_GPIO_MISC4_BASE + 5) +#define TROUT_GPIO_WIFI_PA_RESETX (TROUT_GPIO_MISC4_BASE + 6) +#define TROUT_GPIO_WIFI_EN (TROUT_GPIO_MISC4_BASE + 7) + +#define TROUT_GPIO_BT_32K_EN (TROUT_GPIO_MISC5_BASE + 0) +#define TROUT_GPIO_MAC_32K_EN (TROUT_GPIO_MISC5_BASE + 1) +#define TROUT_GPIO_MDDI_32K_EN (TROUT_GPIO_MISC5_BASE + 2) +#define TROUT_GPIO_COMPASS_32K_EN (TROUT_GPIO_MISC5_BASE + 3) + +#define TROUT_GPIO_NAVI_ACT_N (TROUT_GPIO_INT2_BASE + 0) +#define TROUT_GPIO_COMPASS_IRQ (TROUT_GPIO_INT2_BASE + 1) +#define TROUT_GPIO_SLIDING_DET (TROUT_GPIO_INT2_BASE + 2) +#define TROUT_GPIO_AUD_HSMIC_DET_N (TROUT_GPIO_INT2_BASE + 3) +#define TROUT_GPIO_SD_DOOR_N (TROUT_GPIO_INT2_BASE + 4) +#define TROUT_GPIO_CAM_BTN_STEP1_N (TROUT_GPIO_INT2_BASE + 5) +#define TROUT_GPIO_CAM_BTN_STEP2_N (TROUT_GPIO_INT2_BASE + 6) +#define TROUT_GPIO_TP_ATT_N (TROUT_GPIO_INT2_BASE + 7) +#define TROUT_GPIO_BANK0_FIRST_INT_SOURCE (TROUT_GPIO_NAVI_ACT_N) +#define TROUT_GPIO_BANK0_LAST_INT_SOURCE (TROUT_GPIO_TP_ATT_N) + +#define TROUT_GPIO_H2W_DAT_GPI (TROUT_GPIO_MISC1_BASE + 0) +#define TROUT_GPIO_H2W_CLK_GPI (TROUT_GPIO_MISC1_BASE + 1) +#define TROUT_GPIO_CPLD128_VER_0 (TROUT_GPIO_MISC1_BASE + 4) +#define TROUT_GPIO_CPLD128_VER_1 (TROUT_GPIO_MISC1_BASE + 5) +#define TROUT_GPIO_CPLD128_VER_2 (TROUT_GPIO_MISC1_BASE + 6) +#define TROUT_GPIO_CPLD128_VER_3 (TROUT_GPIO_MISC1_BASE + 7) + +#define TROUT_GPIO_SDMC_CD_N (TROUT_GPIO_VIRTUAL_BASE + 0) +#define TROUT_GPIO_END (TROUT_GPIO_SDMC_CD_N) +#define TROUT_GPIO_BANK1_FIRST_INT_SOURCE (TROUT_GPIO_SDMC_CD_N) +#define TROUT_GPIO_BANK1_LAST_INT_SOURCE (TROUT_GPIO_SDMC_CD_N) + +#define TROUT_GPIO_VIRTUAL_TO_REAL_OFFSET \ + (TROUT_GPIO_INT5_BASE - TROUT_GPIO_VIRTUAL_BASE) + +#define TROUT_INT_START (NR_MSM_IRQS + NR_GPIO_IRQS) +#define TROUT_INT_BANK0_COUNT (8) +#define TROUT_INT_BANK1_START (TROUT_INT_START + TROUT_INT_BANK0_COUNT) +#define TROUT_INT_BANK1_COUNT (1) +#define TROUT_INT_END (TROUT_INT_START + TROUT_INT_BANK0_COUNT + \ + TROUT_INT_BANK1_COUNT - 1) +#define TROUT_GPIO_TO_INT(n) (((n) <= TROUT_GPIO_BANK0_LAST_INT_SOURCE) ? \ + (TROUT_INT_START - TROUT_GPIO_BANK0_FIRST_INT_SOURCE + (n)) : \ + (TROUT_INT_BANK1_START - TROUT_GPIO_BANK1_FIRST_INT_SOURCE + (n))) + +#define TROUT_INT_TO_BANK(n) ((n - TROUT_INT_START) / TROUT_INT_BANK0_COUNT) +#define TROUT_INT_TO_MASK(n) (1U << ((n - TROUT_INT_START) & 7)) +#define TROUT_BANK_TO_MASK_REG(bank) \ + (bank ? TROUT_GPIO_INT_MASK1_REG : TROUT_GPIO_INT_MASK0_REG) +#define TROUT_BANK_TO_STAT_REG(bank) \ + (bank ? TROUT_GPIO_INT_STAT1_REG : TROUT_GPIO_INT_STAT0_REG) + +#endif /* GUARD */ diff --git a/arch/arm/mach-msm/clock-7x30.h b/arch/arm/mach-msm/clock-7x30.h new file mode 100644 index 00000000..14104453 --- /dev/null +++ b/arch/arm/mach-msm/clock-7x30.h @@ -0,0 +1,155 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ARCH_ARM_MACH_MSM_CLOCK_7X30_H +#define __ARCH_ARM_MACH_MSM_CLOCK_7X30_H + +enum { + L_7X30_NONE_CLK = -1, + L_7X30_ADM_CLK, + L_7X30_I2C_CLK, + L_7X30_I2C_2_CLK, + L_7X30_QUP_I2C_CLK, + L_7X30_UART1DM_CLK, + L_7X30_UART1DM_P_CLK, + L_7X30_UART2DM_CLK, + L_7X30_UART2DM_P_CLK, + L_7X30_EMDH_CLK, + L_7X30_EMDH_P_CLK, + L_7X30_PMDH_CLK, + L_7X30_PMDH_P_CLK, + L_7X30_GRP_2D_CLK, + L_7X30_GRP_2D_P_CLK, + L_7X30_GRP_3D_SRC_CLK, + L_7X30_GRP_3D_CLK, + L_7X30_GRP_3D_P_CLK, + L_7X30_IMEM_CLK, + L_7X30_SDC1_CLK, + L_7X30_SDC1_P_CLK, + L_7X30_SDC2_CLK, + L_7X30_SDC2_P_CLK, + L_7X30_SDC3_CLK, + L_7X30_SDC3_P_CLK, + L_7X30_SDC4_CLK, + L_7X30_SDC4_P_CLK, + L_7X30_MDP_CLK, + L_7X30_MDP_P_CLK, + L_7X30_MDP_LCDC_PCLK_CLK, + L_7X30_MDP_LCDC_PAD_PCLK_CLK, + L_7X30_MDP_VSYNC_CLK, + L_7X30_MI2S_CODEC_RX_M_CLK, + L_7X30_MI2S_CODEC_RX_S_CLK, + L_7X30_MI2S_CODEC_TX_M_CLK, + L_7X30_MI2S_CODEC_TX_S_CLK, + L_7X30_MI2S_M_CLK, + L_7X30_MI2S_S_CLK, + L_7X30_LPA_CODEC_CLK, + L_7X30_LPA_CORE_CLK, + L_7X30_LPA_P_CLK, + L_7X30_MIDI_CLK, + L_7X30_MDC_CLK, + L_7X30_ROTATOR_IMEM_CLK, + L_7X30_ROTATOR_P_CLK, + L_7X30_SDAC_M_CLK, + L_7X30_SDAC_CLK, + L_7X30_UART1_CLK, + L_7X30_UART2_CLK, + L_7X30_UART3_CLK, + L_7X30_TV_CLK, + L_7X30_TV_DAC_CLK, + L_7X30_TV_ENC_CLK, + L_7X30_HDMI_CLK, + L_7X30_TSIF_REF_CLK, + L_7X30_TSIF_P_CLK, + L_7X30_USB_HS_SRC_CLK, + L_7X30_USB_HS_CLK, + L_7X30_USB_HS_CORE_CLK, + L_7X30_USB_HS_P_CLK, + L_7X30_USB_HS2_CLK, + L_7X30_USB_HS2_CORE_CLK, + L_7X30_USB_HS2_P_CLK, + L_7X30_USB_HS3_CLK, + L_7X30_USB_HS3_CORE_CLK, + L_7X30_USB_HS3_P_CLK, + L_7X30_VFE_CLK, + L_7X30_VFE_P_CLK, + L_7X30_VFE_MDC_CLK, + L_7X30_VFE_CAMIF_CLK, + L_7X30_CAMIF_PAD_P_CLK, + L_7X30_CAM_M_CLK, + L_7X30_JPEG_CLK, + L_7X30_JPEG_P_CLK, + L_7X30_VPE_CLK, + L_7X30_MFC_CLK, + L_7X30_MFC_DIV2_CLK, + L_7X30_MFC_P_CLK, + L_7X30_SPI_CLK, + L_7X30_SPI_P_CLK, + L_7X30_CSI0_CLK, + L_7X30_CSI0_VFE_CLK, + L_7X30_CSI0_P_CLK, + L_7X30_CSI1_CLK, + L_7X30_CSI1_VFE_CLK, + L_7X30_CSI1_P_CLK, + L_7X30_GLBL_ROOT_CLK, + + L_7X30_AXI_LI_VG_CLK, + L_7X30_AXI_LI_GRP_CLK, + L_7X30_AXI_LI_JPEG_CLK, + L_7X30_AXI_GRP_2D_CLK, + L_7X30_AXI_MFC_CLK, + L_7X30_AXI_VPE_CLK, + L_7X30_AXI_LI_VFE_CLK, + L_7X30_AXI_LI_APPS_CLK, + L_7X30_AXI_MDP_CLK, + L_7X30_AXI_IMEM_CLK, + L_7X30_AXI_LI_ADSP_A_CLK, + L_7X30_AXI_ROTATOR_CLK, + + L_7X30_NR_CLKS +}; + +struct clk_ops; +extern struct clk_ops clk_ops_7x30; + +struct clk_ops *clk_7x30_is_local(uint32_t id); +int clk_7x30_init(void); + +void pll_enable(uint32_t pll); +void pll_disable(uint32_t pll); + +extern int internal_pwr_rail_ctl_auto(unsigned rail_id, bool enable); + +#define CLK_7X30(clk_name, clk_id, clk_dev, clk_flags) { \ + .con_id = clk_name, \ + .dev_id = clk_dev, \ + .clk = &(struct clk){ \ + .id = L_7X30_##clk_id, \ + .remote_id = P_##clk_id, \ + .flags = clk_flags, \ + .dbg_name = #clk_id, \ + }, \ + } + +#define CLK_7X30S(clk_name, l_id, r_id, clk_dev, clk_flags) { \ + .con_id = clk_name, \ + .dev_id = clk_dev, \ + .clk = &(struct clk){ \ + .id = L_7X30_##l_id, \ + .remote_id = P_##r_id, \ + .flags = clk_flags, \ + .dbg_name = #l_id, \ + .ops = &clk_ops_pcom, \ + }, \ + } + +#endif diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c new file mode 100644 index 00000000..4886404d --- /dev/null +++ b/arch/arm/mach-msm/clock-debug.c @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/ctype.h> +#include <linux/debugfs.h> +#include <linux/clk.h> +#include "clock.h" + +static int clock_debug_rate_set(void *data, u64 val) +{ + struct clk *clock = data; + int ret; + + /* Only increases to max rate will succeed, but that's actually good + * for debugging purposes so we don't check for error. */ + if (clock->flags & CLK_MAX) + clk_set_max_rate(clock, val); + if (clock->flags & CLK_MIN) + ret = clk_set_min_rate(clock, val); + else + ret = clk_set_rate(clock, val); + if (ret != 0) + printk(KERN_ERR "clk_set%s_rate failed (%d)\n", + (clock->flags & CLK_MIN) ? "_min" : "", ret); + return ret; +} + +static int clock_debug_rate_get(void *data, u64 *val) +{ + struct clk *clock = data; + *val = clk_get_rate(clock); + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get, + clock_debug_rate_set, "%llu\n"); + +static int clock_debug_enable_set(void *data, u64 val) +{ + struct clk *clock = data; + int rc = 0; + + if (val) + rc = clock->ops->enable(clock->id); + else + clock->ops->disable(clock->id); + + return rc; +} + +static int clock_debug_enable_get(void *data, u64 *val) +{ + struct clk *clock = data; + + *val = clock->ops->is_enabled(clock->id); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get, + clock_debug_enable_set, "%llu\n"); + +static int clock_debug_local_get(void *data, u64 *val) +{ + struct clk *clock = data; + + *val = clock->ops->is_local(clock->id); + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get, + NULL, "%llu\n"); + +static struct dentry *debugfs_base; + +int __init clock_debug_init(void) +{ + debugfs_base = debugfs_create_dir("clk", NULL); + if (!debugfs_base) + return -ENOMEM; + return 0; +} + +int __init clock_debug_add(struct clk *clock) +{ + char temp[50], *ptr; + struct dentry *clk_dir; + + if (!debugfs_base) + return -ENOMEM; + + strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1); + for (ptr = temp; *ptr; ptr++) + *ptr = tolower(*ptr); + + clk_dir = debugfs_create_dir(temp, debugfs_base); + if (!clk_dir) + return -ENOMEM; + + if (!debugfs_create_file("rate", S_IRUGO | S_IWUSR, clk_dir, + clock, &clock_rate_fops)) + goto error; + + if (!debugfs_create_file("enable", S_IRUGO | S_IWUSR, clk_dir, + clock, &clock_enable_fops)) + goto error; + + if (!debugfs_create_file("is_local", S_IRUGO, clk_dir, clock, + &clock_local_fops)) + goto error; + return 0; +error: + debugfs_remove_recursive(clk_dir); + return -ENOMEM; +} diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c new file mode 100644 index 00000000..63b71131 --- /dev/null +++ b/arch/arm/mach-msm/clock-pcom.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/err.h> +#include <linux/ctype.h> +#include <linux/stddef.h> +#include <mach/clk.h> + +#include "proc_comm.h" +#include "clock.h" +#include "clock-pcom.h" + +/* + * glue for the proc_comm interface + */ +int pc_clk_enable(unsigned id) +{ + int rc = msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL); + if (rc < 0) + return rc; + else + return (int)id < 0 ? -EINVAL : 0; +} + +void pc_clk_disable(unsigned id) +{ + msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL); +} + +int pc_clk_reset(unsigned id, enum clk_reset_action action) +{ + int rc; + + if (action == CLK_RESET_ASSERT) + rc = msm_proc_comm(PCOM_CLKCTL_RPC_RESET_ASSERT, &id, NULL); + else + rc = msm_proc_comm(PCOM_CLKCTL_RPC_RESET_DEASSERT, &id, NULL); + + if (rc < 0) + return rc; + else + return (int)id < 0 ? -EINVAL : 0; +} + +int pc_clk_set_rate(unsigned id, unsigned rate) +{ + /* The rate _might_ be rounded off to the nearest KHz value by the + * remote function. So a return value of 0 doesn't necessarily mean + * that the exact rate was set successfully. + */ + int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate); + if (rc < 0) + return rc; + else + return (int)id < 0 ? -EINVAL : 0; +} + +int pc_clk_set_min_rate(unsigned id, unsigned rate) +{ + int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate); + if (rc < 0) + return rc; + else + return (int)id < 0 ? -EINVAL : 0; +} + +int pc_clk_set_max_rate(unsigned id, unsigned rate) +{ + int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &rate); + if (rc < 0) + return rc; + else + return (int)id < 0 ? -EINVAL : 0; +} + +int pc_clk_set_flags(unsigned id, unsigned flags) +{ + int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_FLAGS, &id, &flags); + if (rc < 0) + return rc; + else + return (int)id < 0 ? -EINVAL : 0; +} + +unsigned pc_clk_get_rate(unsigned id) +{ + if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL)) + return 0; + else + return id; +} + +unsigned pc_clk_is_enabled(unsigned id) +{ + if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL)) + return 0; + else + return id; +} + +long pc_clk_round_rate(unsigned id, unsigned rate) +{ + + /* Not really supported; pc_clk_set_rate() does rounding on it's own. */ + return rate; +} + +static bool pc_clk_is_local(unsigned id) +{ + return false; +} + +struct clk_ops clk_ops_pcom = { + .enable = pc_clk_enable, + .disable = pc_clk_disable, + .auto_off = pc_clk_disable, + .reset = pc_clk_reset, + .set_rate = pc_clk_set_rate, + .set_min_rate = pc_clk_set_min_rate, + .set_max_rate = pc_clk_set_max_rate, + .set_flags = pc_clk_set_flags, + .get_rate = pc_clk_get_rate, + .is_enabled = pc_clk_is_enabled, + .round_rate = pc_clk_round_rate, + .is_local = pc_clk_is_local, +}; diff --git a/arch/arm/mach-msm/clock-pcom.h b/arch/arm/mach-msm/clock-pcom.h new file mode 100644 index 00000000..974d0032 --- /dev/null +++ b/arch/arm/mach-msm/clock-pcom.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ARCH_ARM_MACH_MSM_CLOCK_PCOM_H +#define __ARCH_ARM_MACH_MSM_CLOCK_PCOM_H + +/* clock IDs used by the modem processor */ + +#define P_ACPU_CLK 0 /* Applications processor clock */ +#define P_ADM_CLK 1 /* Applications data mover clock */ +#define P_ADSP_CLK 2 /* ADSP clock */ +#define P_EBI1_CLK 3 /* External bus interface 1 clock */ +#define P_EBI2_CLK 4 /* External bus interface 2 clock */ +#define P_ECODEC_CLK 5 /* External CODEC clock */ +#define P_EMDH_CLK 6 /* External MDDI host clock */ +#define P_GP_CLK 7 /* General purpose clock */ +#define P_GRP_3D_CLK 8 /* Graphics clock */ +#define P_I2C_CLK 9 /* I2C clock */ +#define P_ICODEC_RX_CLK 10 /* Internal CODEX RX clock */ +#define P_ICODEC_TX_CLK 11 /* Internal CODEX TX clock */ +#define P_IMEM_CLK 12 /* Internal graphics memory clock */ +#define P_MDC_CLK 13 /* MDDI client clock */ +#define P_MDP_CLK 14 /* Mobile display processor clock */ +#define P_PBUS_CLK 15 /* Peripheral bus clock */ +#define P_PCM_CLK 16 /* PCM clock */ +#define P_PMDH_CLK 17 /* Primary MDDI host clock */ +#define P_SDAC_CLK 18 /* Stereo DAC clock */ +#define P_SDC1_CLK 19 /* Secure Digital Card clocks */ +#define P_SDC1_P_CLK 20 +#define P_SDC2_CLK 21 +#define P_SDC2_P_CLK 22 +#define P_SDC3_CLK 23 +#define P_SDC3_P_CLK 24 +#define P_SDC4_CLK 25 +#define P_SDC4_P_CLK 26 +#define P_TSIF_CLK 27 /* Transport Stream Interface clocks */ +#define P_TSIF_REF_CLK 28 +#define P_TV_DAC_CLK 29 /* TV clocks */ +#define P_TV_ENC_CLK 30 +#define P_UART1_CLK 31 /* UART clocks */ +#define P_UART2_CLK 32 +#define P_UART3_CLK 33 +#define P_UART1DM_CLK 34 +#define P_UART2DM_CLK 35 +#define P_USB_HS_CLK 36 /* High speed USB core clock */ +#define P_USB_HS_P_CLK 37 /* High speed USB pbus clock */ +#define P_USB_OTG_CLK 38 /* Full speed USB clock */ +#define P_VDC_CLK 39 /* Video controller clock */ +#define P_VFE_MDC_CLK 40 /* Camera / Video Front End clock */ +#define P_VFE_CLK 41 /* VFE MDDI client clock */ +#define P_MDP_LCDC_PCLK_CLK 42 +#define P_MDP_LCDC_PAD_PCLK_CLK 43 +#define P_MDP_VSYNC_CLK 44 +#define P_SPI_CLK 45 +#define P_VFE_AXI_CLK 46 +#define P_USB_HS2_CLK 47 /* High speed USB 2 core clock */ +#define P_USB_HS2_P_CLK 48 /* High speed USB 2 pbus clock */ +#define P_USB_HS3_CLK 49 /* High speed USB 3 core clock */ +#define P_USB_HS3_P_CLK 50 /* High speed USB 3 pbus clock */ +#define P_GRP_3D_P_CLK 51 /* Graphics pbus clock */ +#define P_USB_PHY_CLK 52 /* USB PHY clock */ +#define P_USB_HS_CORE_CLK 53 /* High speed USB 1 core clock */ +#define P_USB_HS2_CORE_CLK 54 /* High speed USB 2 core clock */ +#define P_USB_HS3_CORE_CLK 55 /* High speed USB 3 core clock */ +#define P_CAM_M_CLK 56 +#define P_CAMIF_PAD_P_CLK 57 +#define P_GRP_2D_CLK 58 +#define P_GRP_2D_P_CLK 59 +#define P_I2S_CLK 60 +#define P_JPEG_CLK 61 +#define P_JPEG_P_CLK 62 +#define P_LPA_CODEC_CLK 63 +#define P_LPA_CORE_CLK 64 +#define P_LPA_P_CLK 65 +#define P_MDC_IO_CLK 66 +#define P_MDC_P_CLK 67 +#define P_MFC_CLK 68 +#define P_MFC_DIV2_CLK 69 +#define P_MFC_P_CLK 70 +#define P_QUP_I2C_CLK 71 +#define P_ROTATOR_IMEM_CLK 72 +#define P_ROTATOR_P_CLK 73 +#define P_VFE_CAMIF_CLK 74 +#define P_VFE_P_CLK 75 +#define P_VPE_CLK 76 +#define P_I2C_2_CLK 77 +#define P_MI2S_CODEC_RX_S_CLK 78 +#define P_MI2S_CODEC_RX_M_CLK 79 +#define P_MI2S_CODEC_TX_S_CLK 80 +#define P_MI2S_CODEC_TX_M_CLK 81 +#define P_PMDH_P_CLK 82 +#define P_EMDH_P_CLK 83 +#define P_SPI_P_CLK 84 +#define P_TSIF_P_CLK 85 +#define P_MDP_P_CLK 86 +#define P_SDAC_M_CLK 87 +#define P_MI2S_S_CLK 88 +#define P_MI2S_M_CLK 89 +#define P_AXI_ROTATOR_CLK 90 +#define P_HDMI_CLK 91 +#define P_CSI0_CLK 92 +#define P_CSI0_VFE_CLK 93 +#define P_CSI0_P_CLK 94 +#define P_CSI1_CLK 95 +#define P_CSI1_VFE_CLK 96 +#define P_CSI1_P_CLK 97 +#define P_GSBI_CLK 98 +#define P_GSBI_P_CLK 99 +#define P_CE_CLK 100 /* Crypto engine */ +#define P_CODEC_SSBI_CLK 101 + +#define P_NR_CLKS 102 + +struct clk_ops; +extern struct clk_ops clk_ops_pcom; + +int pc_clk_reset(unsigned id, enum clk_reset_action action); + +#define CLK_PCOM(clk_name, clk_id, clk_dev, clk_flags) { \ + .con_id = clk_name, \ + .dev_id = clk_dev, \ + .clk = &(struct clk){ \ + .id = P_##clk_id, \ + .remote_id = P_##clk_id, \ + .ops = &clk_ops_pcom, \ + .flags = clk_flags, \ + .dbg_name = #clk_id, \ + }, \ + } + +#endif diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c new file mode 100644 index 00000000..d9145dfc --- /dev/null +++ b/arch/arm/mach-msm/clock.c @@ -0,0 +1,184 @@ +/* arch/arm/mach-msm/clock.c + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/err.h> +#include <linux/spinlock.h> +#include <linux/pm_qos.h> +#include <linux/mutex.h> +#include <linux/clk.h> +#include <linux/string.h> +#include <linux/module.h> +#include <linux/clkdev.h> + +#include "clock.h" + +static DEFINE_MUTEX(clocks_mutex); +static DEFINE_SPINLOCK(clocks_lock); +static LIST_HEAD(clocks); + +/* + * Standard clock functions defined in include/linux/clk.h + */ +int clk_enable(struct clk *clk) +{ + unsigned long flags; + spin_lock_irqsave(&clocks_lock, flags); + clk->count++; + if (clk->count == 1) + clk->ops->enable(clk->id); + spin_unlock_irqrestore(&clocks_lock, flags); + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + spin_lock_irqsave(&clocks_lock, flags); + BUG_ON(clk->count == 0); + clk->count--; + if (clk->count == 0) + clk->ops->disable(clk->id); + spin_unlock_irqrestore(&clocks_lock, flags); +} +EXPORT_SYMBOL(clk_disable); + +int clk_reset(struct clk *clk, enum clk_reset_action action) +{ + return clk->ops->reset(clk->remote_id, action); +} +EXPORT_SYMBOL(clk_reset); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->ops->get_rate(clk->id); +} +EXPORT_SYMBOL(clk_get_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret; + if (clk->flags & CLKFLAG_MAX) { + ret = clk->ops->set_max_rate(clk->id, rate); + if (ret) + return ret; + } + if (clk->flags & CLKFLAG_MIN) { + ret = clk->ops->set_min_rate(clk->id, rate); + if (ret) + return ret; + } + + if (clk->flags & CLKFLAG_MAX || clk->flags & CLKFLAG_MIN) + return ret; + + return clk->ops->set_rate(clk->id, rate); +} +EXPORT_SYMBOL(clk_set_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + return clk->ops->round_rate(clk->id, rate); +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_min_rate(struct clk *clk, unsigned long rate) +{ + return clk->ops->set_min_rate(clk->id, rate); +} +EXPORT_SYMBOL(clk_set_min_rate); + +int clk_set_max_rate(struct clk *clk, unsigned long rate) +{ + return clk->ops->set_max_rate(clk->id, rate); +} +EXPORT_SYMBOL(clk_set_max_rate); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + return -ENOSYS; +} +EXPORT_SYMBOL(clk_set_parent); + +struct clk *clk_get_parent(struct clk *clk) +{ + return ERR_PTR(-ENOSYS); +} +EXPORT_SYMBOL(clk_get_parent); + +int clk_set_flags(struct clk *clk, unsigned long flags) +{ + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + return clk->ops->set_flags(clk->id, flags); +} +EXPORT_SYMBOL(clk_set_flags); + +/* EBI1 is the only shared clock that several clients want to vote on as of + * this commit. If this changes in the future, then it might be better to + * make clk_min_rate handle the voting or make ebi1_clk_set_min_rate more + * generic to support different clocks. + */ +static struct clk *ebi1_clk; + +void __init msm_clock_init(struct clk_lookup *clock_tbl, unsigned num_clocks) +{ + unsigned n; + + mutex_lock(&clocks_mutex); + for (n = 0; n < num_clocks; n++) { + clkdev_add(&clock_tbl[n]); + list_add_tail(&clock_tbl[n].clk->list, &clocks); + } + mutex_unlock(&clocks_mutex); + + ebi1_clk = clk_get(NULL, "ebi1_clk"); + BUG_ON(ebi1_clk == NULL); + +} + +/* The bootloader and/or AMSS may have left various clocks enabled. + * Disable any clocks that belong to us (CLKFLAG_AUTO_OFF) but have + * not been explicitly enabled by a clk_enable() call. + */ +static int __init clock_late_init(void) +{ + unsigned long flags; + struct clk *clk; + unsigned count = 0; + + clock_debug_init(); + mutex_lock(&clocks_mutex); + list_for_each_entry(clk, &clocks, list) { + clock_debug_add(clk); + if (clk->flags & CLKFLAG_AUTO_OFF) { + spin_lock_irqsave(&clocks_lock, flags); + if (!clk->count) { + count++; + clk->ops->auto_off(clk->id); + } + spin_unlock_irqrestore(&clocks_lock, flags); + } + } + mutex_unlock(&clocks_mutex); + pr_info("clock_late_init() disabled %d unused clocks\n", count); + return 0; +} + +late_initcall(clock_late_init); + diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h new file mode 100644 index 00000000..2c007f60 --- /dev/null +++ b/arch/arm/mach-msm/clock.h @@ -0,0 +1,72 @@ +/* arch/arm/mach-msm/clock.h + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ARCH_ARM_MACH_MSM_CLOCK_H +#define __ARCH_ARM_MACH_MSM_CLOCK_H + +#include <linux/init.h> +#include <linux/list.h> +#include <mach/clk.h> + +#define CLKFLAG_INVERT 0x00000001 +#define CLKFLAG_NOINVERT 0x00000002 +#define CLKFLAG_NONEST 0x00000004 +#define CLKFLAG_NORESET 0x00000008 + +#define CLK_FIRST_AVAILABLE_FLAG 0x00000100 +#define CLKFLAG_AUTO_OFF 0x00000200 +#define CLKFLAG_MIN 0x00000400 +#define CLKFLAG_MAX 0x00000800 + +struct clk_ops { + int (*enable)(unsigned id); + void (*disable)(unsigned id); + void (*auto_off)(unsigned id); + int (*reset)(unsigned id, enum clk_reset_action action); + int (*set_rate)(unsigned id, unsigned rate); + int (*set_min_rate)(unsigned id, unsigned rate); + int (*set_max_rate)(unsigned id, unsigned rate); + int (*set_flags)(unsigned id, unsigned flags); + unsigned (*get_rate)(unsigned id); + unsigned (*is_enabled)(unsigned id); + long (*round_rate)(unsigned id, unsigned rate); + bool (*is_local)(unsigned id); +}; + +struct clk { + uint32_t id; + uint32_t remote_id; + uint32_t count; + uint32_t flags; + struct clk_ops *ops; + const char *dbg_name; + struct list_head list; +}; + +#define OFF CLKFLAG_AUTO_OFF +#define CLK_MIN CLKFLAG_MIN +#define CLK_MAX CLKFLAG_MAX +#define CLK_MINMAX (CLK_MIN | CLK_MAX) + +#ifdef CONFIG_DEBUG_FS +int __init clock_debug_init(void); +int __init clock_debug_add(struct clk *clock); +#else +static inline int __init clock_debug_init(void) { return 0; } +static inline int __init clock_debug_add(struct clk *clock) { return 0; } +#endif + +#endif diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c new file mode 100644 index 00000000..0fb7a17d --- /dev/null +++ b/arch/arm/mach-msm/devices-iommu.c @@ -0,0 +1,912 @@ +/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/bootmem.h> +#include <linux/module.h> +#include <mach/irqs.h> +#include <mach/iommu.h> + +static struct resource msm_iommu_jpegd_resources[] = { + { + .start = 0x07300000, + .end = 0x07300000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ, + .end = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_JPEGD_CB_SC_SECURE_IRQ, + .end = SMMU_JPEGD_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_vpe_resources[] = { + { + .start = 0x07400000, + .end = 0x07400000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_VPE_CB_SC_NON_SECURE_IRQ, + .end = SMMU_VPE_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_VPE_CB_SC_SECURE_IRQ, + .end = SMMU_VPE_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_mdp0_resources[] = { + { + .start = 0x07500000, + .end = 0x07500000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_MDP0_CB_SC_NON_SECURE_IRQ, + .end = SMMU_MDP0_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_MDP0_CB_SC_SECURE_IRQ, + .end = SMMU_MDP0_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_mdp1_resources[] = { + { + .start = 0x07600000, + .end = 0x07600000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_MDP1_CB_SC_NON_SECURE_IRQ, + .end = SMMU_MDP1_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_MDP1_CB_SC_SECURE_IRQ, + .end = SMMU_MDP1_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_rot_resources[] = { + { + .start = 0x07700000, + .end = 0x07700000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_ROT_CB_SC_NON_SECURE_IRQ, + .end = SMMU_ROT_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_ROT_CB_SC_SECURE_IRQ, + .end = SMMU_ROT_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_ijpeg_resources[] = { + { + .start = 0x07800000, + .end = 0x07800000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ, + .end = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_IJPEG_CB_SC_SECURE_IRQ, + .end = SMMU_IJPEG_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_vfe_resources[] = { + { + .start = 0x07900000, + .end = 0x07900000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_VFE_CB_SC_NON_SECURE_IRQ, + .end = SMMU_VFE_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_VFE_CB_SC_SECURE_IRQ, + .end = SMMU_VFE_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_vcodec_a_resources[] = { + { + .start = 0x07A00000, + .end = 0x07A00000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ, + .end = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_VCODEC_A_CB_SC_SECURE_IRQ, + .end = SMMU_VCODEC_A_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_vcodec_b_resources[] = { + { + .start = 0x07B00000, + .end = 0x07B00000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ, + .end = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_VCODEC_B_CB_SC_SECURE_IRQ, + .end = SMMU_VCODEC_B_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_gfx3d_resources[] = { + { + .start = 0x07C00000, + .end = 0x07C00000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ, + .end = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_GFX3D_CB_SC_SECURE_IRQ, + .end = SMMU_GFX3D_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_gfx2d0_resources[] = { + { + .start = 0x07D00000, + .end = 0x07D00000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ, + .end = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_GFX2D0_CB_SC_SECURE_IRQ, + .end = SMMU_GFX2D0_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource msm_iommu_gfx2d1_resources[] = { + { + .start = 0x07E00000, + .end = 0x07E00000 + SZ_1M - 1, + .name = "physbase", + .flags = IORESOURCE_MEM, + }, + { + .name = "nonsecure_irq", + .start = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ, + .end = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .name = "secure_irq", + .start = SMMU_GFX2D1_CB_SC_SECURE_IRQ, + .end = SMMU_GFX2D1_CB_SC_SECURE_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device msm_root_iommu_dev = { + .name = "msm_iommu", + .id = -1, +}; + +static struct msm_iommu_dev jpegd_iommu = { + .name = "jpegd", + .ncb = 2, +}; + +static struct msm_iommu_dev vpe_iommu = { + .name = "vpe", + .ncb = 2, +}; + +static struct msm_iommu_dev mdp0_iommu = { + .name = "mdp0", + .ncb = 2, +}; + +static struct msm_iommu_dev mdp1_iommu = { + .name = "mdp1", + .ncb = 2, +}; + +static struct msm_iommu_dev rot_iommu = { + .name = "rot", + .ncb = 2, +}; + +static struct msm_iommu_dev ijpeg_iommu = { + .name = "ijpeg", + .ncb = 2, +}; + +static struct msm_iommu_dev vfe_iommu = { + .name = "vfe", + .ncb = 2, +}; + +static struct msm_iommu_dev vcodec_a_iommu = { + .name = "vcodec_a", + .ncb = 2, +}; + +static struct msm_iommu_dev vcodec_b_iommu = { + .name = "vcodec_b", + .ncb = 2, +}; + +static struct msm_iommu_dev gfx3d_iommu = { + .name = "gfx3d", + .ncb = 3, +}; + +static struct msm_iommu_dev gfx2d0_iommu = { + .name = "gfx2d0", + .ncb = 2, +}; + +static struct msm_iommu_dev gfx2d1_iommu = { + .name = "gfx2d1", + .ncb = 2, +}; + +static struct platform_device msm_device_iommu_jpegd = { + .name = "msm_iommu", + .id = 0, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources), + .resource = msm_iommu_jpegd_resources, +}; + +static struct platform_device msm_device_iommu_vpe = { + .name = "msm_iommu", + .id = 1, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_vpe_resources), + .resource = msm_iommu_vpe_resources, +}; + +static struct platform_device msm_device_iommu_mdp0 = { + .name = "msm_iommu", + .id = 2, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources), + .resource = msm_iommu_mdp0_resources, +}; + +static struct platform_device msm_device_iommu_mdp1 = { + .name = "msm_iommu", + .id = 3, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources), + .resource = msm_iommu_mdp1_resources, +}; + +static struct platform_device msm_device_iommu_rot = { + .name = "msm_iommu", + .id = 4, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_rot_resources), + .resource = msm_iommu_rot_resources, +}; + +static struct platform_device msm_device_iommu_ijpeg = { + .name = "msm_iommu", + .id = 5, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources), + .resource = msm_iommu_ijpeg_resources, +}; + +static struct platform_device msm_device_iommu_vfe = { + .name = "msm_iommu", + .id = 6, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_vfe_resources), + .resource = msm_iommu_vfe_resources, +}; + +static struct platform_device msm_device_iommu_vcodec_a = { + .name = "msm_iommu", + .id = 7, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources), + .resource = msm_iommu_vcodec_a_resources, +}; + +static struct platform_device msm_device_iommu_vcodec_b = { + .name = "msm_iommu", + .id = 8, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources), + .resource = msm_iommu_vcodec_b_resources, +}; + +static struct platform_device msm_device_iommu_gfx3d = { + .name = "msm_iommu", + .id = 9, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources), + .resource = msm_iommu_gfx3d_resources, +}; + +static struct platform_device msm_device_iommu_gfx2d0 = { + .name = "msm_iommu", + .id = 10, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources), + .resource = msm_iommu_gfx2d0_resources, +}; + +struct platform_device msm_device_iommu_gfx2d1 = { + .name = "msm_iommu", + .id = 11, + .dev = { + .parent = &msm_root_iommu_dev.dev, + }, + .num_resources = ARRAY_SIZE(msm_iommu_gfx2d1_resources), + .resource = msm_iommu_gfx2d1_resources, +}; + +static struct msm_iommu_ctx_dev jpegd_src_ctx = { + .name = "jpegd_src", + .num = 0, + .mids = {0, -1} +}; + +static struct msm_iommu_ctx_dev jpegd_dst_ctx = { + .name = "jpegd_dst", + .num = 1, + .mids = {1, -1} +}; + +static struct msm_iommu_ctx_dev vpe_src_ctx = { + .name = "vpe_src", + .num = 0, + .mids = {0, -1} +}; + +static struct msm_iommu_ctx_dev vpe_dst_ctx = { + .name = "vpe_dst", + .num = 1, + .mids = {1, -1} +}; + +static struct msm_iommu_ctx_dev mdp_vg1_ctx = { + .name = "mdp_vg1", + .num = 0, + .mids = {0, 2, -1} +}; + +static struct msm_iommu_ctx_dev mdp_rgb1_ctx = { + .name = "mdp_rgb1", + .num = 1, + .mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1} +}; + +static struct msm_iommu_ctx_dev mdp_vg2_ctx = { + .name = "mdp_vg2", + .num = 0, + .mids = {0, 2, -1} +}; + +static struct msm_iommu_ctx_dev mdp_rgb2_ctx = { + .name = "mdp_rgb2", + .num = 1, + .mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1} +}; + +static struct msm_iommu_ctx_dev rot_src_ctx = { + .name = "rot_src", + .num = 0, + .mids = {0, -1} +}; + +static struct msm_iommu_ctx_dev rot_dst_ctx = { + .name = "rot_dst", + .num = 1, + .mids = {1, -1} +}; + +static struct msm_iommu_ctx_dev ijpeg_src_ctx = { + .name = "ijpeg_src", + .num = 0, + .mids = {0, -1} +}; + +static struct msm_iommu_ctx_dev ijpeg_dst_ctx = { + .name = "ijpeg_dst", + .num = 1, + .mids = {1, -1} +}; + +static struct msm_iommu_ctx_dev vfe_imgwr_ctx = { + .name = "vfe_imgwr", + .num = 0, + .mids = {2, 3, 4, 5, 6, 7, 8, -1} +}; + +static struct msm_iommu_ctx_dev vfe_misc_ctx = { + .name = "vfe_misc", + .num = 1, + .mids = {0, 1, 9, -1} +}; + +static struct msm_iommu_ctx_dev vcodec_a_stream_ctx = { + .name = "vcodec_a_stream", + .num = 0, + .mids = {2, 5, -1} +}; + +static struct msm_iommu_ctx_dev vcodec_a_mm1_ctx = { + .name = "vcodec_a_mm1", + .num = 1, + .mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1} +}; + +static struct msm_iommu_ctx_dev vcodec_b_mm2_ctx = { + .name = "vcodec_b_mm2", + .num = 0, + .mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1} +}; + +static struct msm_iommu_ctx_dev gfx3d_user_ctx = { + .name = "gfx3d_user", + .num = 0, + .mids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1} +}; + +static struct msm_iommu_ctx_dev gfx3d_priv_ctx = { + .name = "gfx3d_priv", + .num = 1, + .mids = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, -1} +}; + +static struct msm_iommu_ctx_dev gfx2d0_2d0_ctx = { + .name = "gfx2d0_2d0", + .num = 0, + .mids = {0, 1, 2, 3, 4, 5, 6, 7, -1} +}; + +static struct msm_iommu_ctx_dev gfx2d1_2d1_ctx = { + .name = "gfx2d1_2d1", + .num = 0, + .mids = {0, 1, 2, 3, 4, 5, 6, 7, -1} +}; + +static struct platform_device msm_device_jpegd_src_ctx = { + .name = "msm_iommu_ctx", + .id = 0, + .dev = { + .parent = &msm_device_iommu_jpegd.dev, + }, +}; + +static struct platform_device msm_device_jpegd_dst_ctx = { + .name = "msm_iommu_ctx", + .id = 1, + .dev = { + .parent = &msm_device_iommu_jpegd.dev, + }, +}; + +static struct platform_device msm_device_vpe_src_ctx = { + .name = "msm_iommu_ctx", + .id = 2, + .dev = { + .parent = &msm_device_iommu_vpe.dev, + }, +}; + +static struct platform_device msm_device_vpe_dst_ctx = { + .name = "msm_iommu_ctx", + .id = 3, + .dev = { + .parent = &msm_device_iommu_vpe.dev, + }, +}; + +static struct platform_device msm_device_mdp_vg1_ctx = { + .name = "msm_iommu_ctx", + .id = 4, + .dev = { + .parent = &msm_device_iommu_mdp0.dev, + }, +}; + +static struct platform_device msm_device_mdp_rgb1_ctx = { + .name = "msm_iommu_ctx", + .id = 5, + .dev = { + .parent = &msm_device_iommu_mdp0.dev, + }, +}; + +static struct platform_device msm_device_mdp_vg2_ctx = { + .name = "msm_iommu_ctx", + .id = 6, + .dev = { + .parent = &msm_device_iommu_mdp1.dev, + }, +}; + +static struct platform_device msm_device_mdp_rgb2_ctx = { + .name = "msm_iommu_ctx", + .id = 7, + .dev = { + .parent = &msm_device_iommu_mdp1.dev, + }, +}; + +static struct platform_device msm_device_rot_src_ctx = { + .name = "msm_iommu_ctx", + .id = 8, + .dev = { + .parent = &msm_device_iommu_rot.dev, + }, +}; + +static struct platform_device msm_device_rot_dst_ctx = { + .name = "msm_iommu_ctx", + .id = 9, + .dev = { + .parent = &msm_device_iommu_rot.dev, + }, +}; + +static struct platform_device msm_device_ijpeg_src_ctx = { + .name = "msm_iommu_ctx", + .id = 10, + .dev = { + .parent = &msm_device_iommu_ijpeg.dev, + }, +}; + +static struct platform_device msm_device_ijpeg_dst_ctx = { + .name = "msm_iommu_ctx", + .id = 11, + .dev = { + .parent = &msm_device_iommu_ijpeg.dev, + }, +}; + +static struct platform_device msm_device_vfe_imgwr_ctx = { + .name = "msm_iommu_ctx", + .id = 12, + .dev = { + .parent = &msm_device_iommu_vfe.dev, + }, +}; + +static struct platform_device msm_device_vfe_misc_ctx = { + .name = "msm_iommu_ctx", + .id = 13, + .dev = { + .parent = &msm_device_iommu_vfe.dev, + }, +}; + +static struct platform_device msm_device_vcodec_a_stream_ctx = { + .name = "msm_iommu_ctx", + .id = 14, + .dev = { + .parent = &msm_device_iommu_vcodec_a.dev, + }, +}; + +static struct platform_device msm_device_vcodec_a_mm1_ctx = { + .name = "msm_iommu_ctx", + .id = 15, + .dev = { + .parent = &msm_device_iommu_vcodec_a.dev, + }, +}; + +static struct platform_device msm_device_vcodec_b_mm2_ctx = { + .name = "msm_iommu_ctx", + .id = 16, + .dev = { + .parent = &msm_device_iommu_vcodec_b.dev, + }, +}; + +static struct platform_device msm_device_gfx3d_user_ctx = { + .name = "msm_iommu_ctx", + .id = 17, + .dev = { + .parent = &msm_device_iommu_gfx3d.dev, + }, +}; + +static struct platform_device msm_device_gfx3d_priv_ctx = { + .name = "msm_iommu_ctx", + .id = 18, + .dev = { + .parent = &msm_device_iommu_gfx3d.dev, + }, +}; + +static struct platform_device msm_device_gfx2d0_2d0_ctx = { + .name = "msm_iommu_ctx", + .id = 19, + .dev = { + .parent = &msm_device_iommu_gfx2d0.dev, + }, +}; + +static struct platform_device msm_device_gfx2d1_2d1_ctx = { + .name = "msm_iommu_ctx", + .id = 20, + .dev = { + .parent = &msm_device_iommu_gfx2d1.dev, + }, +}; + +static struct platform_device *msm_iommu_devs[] = { + &msm_device_iommu_jpegd, + &msm_device_iommu_vpe, + &msm_device_iommu_mdp0, + &msm_device_iommu_mdp1, + &msm_device_iommu_rot, + &msm_device_iommu_ijpeg, + &msm_device_iommu_vfe, + &msm_device_iommu_vcodec_a, + &msm_device_iommu_vcodec_b, + &msm_device_iommu_gfx3d, + &msm_device_iommu_gfx2d0, + &msm_device_iommu_gfx2d1, +}; + +static struct msm_iommu_dev *msm_iommu_data[] = { + &jpegd_iommu, + &vpe_iommu, + &mdp0_iommu, + &mdp1_iommu, + &rot_iommu, + &ijpeg_iommu, + &vfe_iommu, + &vcodec_a_iommu, + &vcodec_b_iommu, + &gfx3d_iommu, + &gfx2d0_iommu, + &gfx2d1_iommu, +}; + +static struct platform_device *msm_iommu_ctx_devs[] = { + &msm_device_jpegd_src_ctx, + &msm_device_jpegd_dst_ctx, + &msm_device_vpe_src_ctx, + &msm_device_vpe_dst_ctx, + &msm_device_mdp_vg1_ctx, + &msm_device_mdp_rgb1_ctx, + &msm_device_mdp_vg2_ctx, + &msm_device_mdp_rgb2_ctx, + &msm_device_rot_src_ctx, + &msm_device_rot_dst_ctx, + &msm_device_ijpeg_src_ctx, + &msm_device_ijpeg_dst_ctx, + &msm_device_vfe_imgwr_ctx, + &msm_device_vfe_misc_ctx, + &msm_device_vcodec_a_stream_ctx, + &msm_device_vcodec_a_mm1_ctx, + &msm_device_vcodec_b_mm2_ctx, + &msm_device_gfx3d_user_ctx, + &msm_device_gfx3d_priv_ctx, + &msm_device_gfx2d0_2d0_ctx, + &msm_device_gfx2d1_2d1_ctx, +}; + +static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = { + &jpegd_src_ctx, + &jpegd_dst_ctx, + &vpe_src_ctx, + &vpe_dst_ctx, + &mdp_vg1_ctx, + &mdp_rgb1_ctx, + &mdp_vg2_ctx, + &mdp_rgb2_ctx, + &rot_src_ctx, + &rot_dst_ctx, + &ijpeg_src_ctx, + &ijpeg_dst_ctx, + &vfe_imgwr_ctx, + &vfe_misc_ctx, + &vcodec_a_stream_ctx, + &vcodec_a_mm1_ctx, + &vcodec_b_mm2_ctx, + &gfx3d_user_ctx, + &gfx3d_priv_ctx, + &gfx2d0_2d0_ctx, + &gfx2d1_2d1_ctx, +}; + +static int __init msm8x60_iommu_init(void) +{ + int ret, i; + + ret = platform_device_register(&msm_root_iommu_dev); + if (ret != 0) { + pr_err("Failed to register root IOMMU device!\n"); + goto failure; + } + + for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); i++) { + ret = platform_device_add_data(msm_iommu_devs[i], + msm_iommu_data[i], + sizeof(struct msm_iommu_dev)); + if (ret != 0) { + pr_err("platform_device_add_data failed, " + "i = %d\n", i); + goto failure_unwind; + } + + ret = platform_device_register(msm_iommu_devs[i]); + + if (ret != 0) { + pr_err("platform_device_register iommu failed, " + "i = %d\n", i); + goto failure_unwind; + } + } + + for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) { + ret = platform_device_add_data(msm_iommu_ctx_devs[i], + msm_iommu_ctx_data[i], + sizeof(*msm_iommu_ctx_devs[i])); + if (ret != 0) { + pr_err("platform_device_add_data iommu failed, " + "i = %d\n", i); + goto failure_unwind2; + } + + ret = platform_device_register(msm_iommu_ctx_devs[i]); + if (ret != 0) { + pr_err("platform_device_register ctx failed, " + "i = %d\n", i); + goto failure_unwind2; + } + } + return 0; + +failure_unwind2: + while (--i >= 0) + platform_device_unregister(msm_iommu_ctx_devs[i]); +failure_unwind: + while (--i >= 0) + platform_device_unregister(msm_iommu_devs[i]); + + platform_device_unregister(&msm_root_iommu_dev); +failure: + return ret; +} + +static void __exit msm8x60_iommu_exit(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) + platform_device_unregister(msm_iommu_ctx_devs[i]); + + for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); ++i) + platform_device_unregister(msm_iommu_devs[i]); + + platform_device_unregister(&msm_root_iommu_dev); +} + +subsys_initcall(msm8x60_iommu_init); +module_exit(msm8x60_iommu_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>"); diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c new file mode 100644 index 00000000..993780f4 --- /dev/null +++ b/arch/arm/mach-msm/devices-msm7x00.c @@ -0,0 +1,441 @@ +/* linux/arch/arm/mach-msm/devices.c + * + * Copyright (C) 2008 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/clkdev.h> + +#include <mach/irqs.h> +#include <mach/msm_iomap.h> +#include "devices.h" + +#include <asm/mach/flash.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> + +#include "clock.h" +#include "clock-pcom.h" +#include <mach/mmc.h> + +static struct resource resources_uart1[] = { + { + .start = INT_UART1, + .end = INT_UART1, + .flags = IORESOURCE_IRQ, + }, + { + .start = MSM_UART1_PHYS, + .end = MSM_UART1_PHYS + MSM_UART1_SIZE - 1, + .flags = IORESOURCE_MEM, + .name = "uart_resource" + }, +}; + +static struct resource resources_uart2[] = { + { + .start = INT_UART2, + .end = INT_UART2, + .flags = IORESOURCE_IRQ, + }, + { + .start = MSM_UART2_PHYS, + .end = MSM_UART2_PHYS + MSM_UART2_SIZE - 1, + .flags = IORESOURCE_MEM, + .name = "uart_resource" + }, +}; + +static struct resource resources_uart3[] = { + { + .start = INT_UART3, + .end = INT_UART3, + .flags = IORESOURCE_IRQ, + }, + { + .start = MSM_UART3_PHYS, + .end = MSM_UART3_PHYS + MSM_UART3_SIZE - 1, + .flags = IORESOURCE_MEM, + .name = "uart_resource" + }, +}; + +struct platform_device msm_device_uart1 = { + .name = "msm_serial", + .id = 0, + .num_resources = ARRAY_SIZE(resources_uart1), + .resource = resources_uart1, +}; + +struct platform_device msm_device_uart2 = { + .name = "msm_serial", + .id = 1, + .num_resources = ARRAY_SIZE(resources_uart2), + .resource = resources_uart2, +}; + +struct platform_device msm_device_uart3 = { + .name = "msm_serial", + .id = 2, + .num_resources = ARRAY_SIZE(resources_uart3), + .resource = resources_uart3, +}; + +static struct resource resources_i2c[] = { + { + .start = MSM_I2C_PHYS, + .end = MSM_I2C_PHYS + MSM_I2C_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_PWB_I2C, + .end = INT_PWB_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device msm_device_i2c = { + .name = "msm_i2c", + .id = 0, + .num_resources = ARRAY_SIZE(resources_i2c), + .resource = resources_i2c, +}; + +static struct resource resources_hsusb[] = { + { + .start = MSM_HSUSB_PHYS, + .end = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_USB_HS, + .end = INT_USB_HS, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device msm_device_hsusb = { + .name = "msm_hsusb", + .id = -1, + .num_resources = ARRAY_SIZE(resources_hsusb), + .resource = resources_hsusb, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +struct flash_platform_data msm_nand_data = { + .parts = NULL, + .nr_parts = 0, +}; + +static struct resource resources_nand[] = { + [0] = { + .start = 7, + .end = 7, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device msm_device_nand = { + .name = "msm_nand", + .id = -1, + .num_resources = ARRAY_SIZE(resources_nand), + .resource = resources_nand, + .dev = { + .platform_data = &msm_nand_data, + }, +}; + +struct platform_device msm_device_smd = { + .name = "msm_smd", + .id = -1, +}; + +static struct resource resources_sdc1[] = { + { + .start = MSM_SDC1_PHYS, + .end = MSM_SDC1_PHYS + MSM_SDC1_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_SDC1_0, + .end = INT_SDC1_0, + .flags = IORESOURCE_IRQ, + .name = "cmd_irq", + }, + { + .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED, + .name = "status_irq" + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_DMA, + }, +}; + +static struct resource resources_sdc2[] = { + { + .start = MSM_SDC2_PHYS, + .end = MSM_SDC2_PHYS + MSM_SDC2_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_SDC2_0, + .end = INT_SDC2_0, + .flags = IORESOURCE_IRQ, + .name = "cmd_irq", + }, + { + .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED, + .name = "status_irq" + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_DMA, + }, +}; + +static struct resource resources_sdc3[] = { + { + .start = MSM_SDC3_PHYS, + .end = MSM_SDC3_PHYS + MSM_SDC3_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_SDC3_0, + .end = INT_SDC3_0, + .flags = IORESOURCE_IRQ, + .name = "cmd_irq", + }, + { + .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED, + .name = "status_irq" + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_DMA, + }, +}; + +static struct resource resources_sdc4[] = { + { + .start = MSM_SDC4_PHYS, + .end = MSM_SDC4_PHYS + MSM_SDC4_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_SDC4_0, + .end = INT_SDC4_0, + .flags = IORESOURCE_IRQ, + .name = "cmd_irq", + }, + { + .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED, + .name = "status_irq" + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device msm_device_sdc1 = { + .name = "msm_sdcc", + .id = 1, + .num_resources = ARRAY_SIZE(resources_sdc1), + .resource = resources_sdc1, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +struct platform_device msm_device_sdc2 = { + .name = "msm_sdcc", + .id = 2, + .num_resources = ARRAY_SIZE(resources_sdc2), + .resource = resources_sdc2, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +struct platform_device msm_device_sdc3 = { + .name = "msm_sdcc", + .id = 3, + .num_resources = ARRAY_SIZE(resources_sdc3), + .resource = resources_sdc3, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +struct platform_device msm_device_sdc4 = { + .name = "msm_sdcc", + .id = 4, + .num_resources = ARRAY_SIZE(resources_sdc4), + .resource = resources_sdc4, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +static struct platform_device *msm_sdcc_devices[] __initdata = { + &msm_device_sdc1, + &msm_device_sdc2, + &msm_device_sdc3, + &msm_device_sdc4, +}; + +int __init msm_add_sdcc(unsigned int controller, + struct msm_mmc_platform_data *plat, + unsigned int stat_irq, unsigned long stat_irq_flags) +{ + struct platform_device *pdev; + struct resource *res; + + if (controller < 1 || controller > 4) + return -EINVAL; + + pdev = msm_sdcc_devices[controller-1]; + pdev->dev.platform_data = plat; + + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "status_irq"); + if (!res) + return -EINVAL; + else if (stat_irq) { + res->start = res->end = stat_irq; + res->flags &= ~IORESOURCE_DISABLED; + res->flags |= stat_irq_flags; + } + + return platform_device_register(pdev); +} + +static struct resource resources_mddi0[] = { + { + .start = MSM_PMDH_PHYS, + .end = MSM_PMDH_PHYS + MSM_PMDH_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_MDDI_PRI, + .end = INT_MDDI_PRI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource resources_mddi1[] = { + { + .start = MSM_EMDH_PHYS, + .end = MSM_EMDH_PHYS + MSM_EMDH_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_MDDI_EXT, + .end = INT_MDDI_EXT, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device msm_device_mddi0 = { + .name = "msm_mddi", + .id = 0, + .num_resources = ARRAY_SIZE(resources_mddi0), + .resource = resources_mddi0, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +struct platform_device msm_device_mddi1 = { + .name = "msm_mddi", + .id = 1, + .num_resources = ARRAY_SIZE(resources_mddi1), + .resource = resources_mddi1, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +static struct resource resources_mdp[] = { + { + .start = MSM_MDP_PHYS, + .end = MSM_MDP_PHYS + MSM_MDP_SIZE - 1, + .name = "mdp", + .flags = IORESOURCE_MEM + }, + { + .start = INT_MDP, + .end = INT_MDP, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device msm_device_mdp = { + .name = "msm_mdp", + .id = 0, + .num_resources = ARRAY_SIZE(resources_mdp), + .resource = resources_mdp, +}; + +struct clk_lookup msm_clocks_7x01a[] = { + CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), + CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0), + CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, 0), + CLK_PCOM("ebi2_clk", EBI2_CLK, NULL, 0), + CLK_PCOM("ecodec_clk", ECODEC_CLK, NULL, 0), + CLK_PCOM("emdh_clk", EMDH_CLK, NULL, OFF), + CLK_PCOM("gp_clk", GP_CLK, NULL, 0), + CLK_PCOM("grp_clk", GRP_3D_CLK, NULL, OFF), + CLK_PCOM("i2c_clk", I2C_CLK, "msm_i2c.0", 0), + CLK_PCOM("icodec_rx_clk", ICODEC_RX_CLK, NULL, 0), + CLK_PCOM("icodec_tx_clk", ICODEC_TX_CLK, NULL, 0), + CLK_PCOM("imem_clk", IMEM_CLK, NULL, OFF), + CLK_PCOM("mdc_clk", MDC_CLK, NULL, 0), + CLK_PCOM("mdp_clk", MDP_CLK, NULL, OFF), + CLK_PCOM("pbus_clk", PBUS_CLK, NULL, 0), + CLK_PCOM("pcm_clk", PCM_CLK, NULL, 0), + CLK_PCOM("mddi_clk", PMDH_CLK, NULL, OFF | CLK_MINMAX), + CLK_PCOM("sdac_clk", SDAC_CLK, NULL, OFF), + CLK_PCOM("sdc_clk", SDC1_CLK, "msm_sdcc.1", OFF), + CLK_PCOM("sdc_pclk", SDC1_P_CLK, "msm_sdcc.1", OFF), + CLK_PCOM("sdc_clk", SDC2_CLK, "msm_sdcc.2", OFF), + CLK_PCOM("sdc_pclk", SDC2_P_CLK, "msm_sdcc.2", OFF), + CLK_PCOM("sdc_clk", SDC3_CLK, "msm_sdcc.3", OFF), + CLK_PCOM("sdc_pclk", SDC3_P_CLK, "msm_sdcc.3", OFF), + CLK_PCOM("sdc_clk", SDC4_CLK, "msm_sdcc.4", OFF), + CLK_PCOM("sdc_pclk", SDC4_P_CLK, "msm_sdcc.4", OFF), + CLK_PCOM("tsif_clk", TSIF_CLK, NULL, 0), + CLK_PCOM("tsif_ref_clk", TSIF_REF_CLK, NULL, 0), + CLK_PCOM("tv_dac_clk", TV_DAC_CLK, NULL, 0), + CLK_PCOM("tv_enc_clk", TV_ENC_CLK, NULL, 0), + CLK_PCOM("uart_clk", UART1_CLK, "msm_serial.0", OFF), + CLK_PCOM("uart_clk", UART2_CLK, "msm_serial.1", 0), + CLK_PCOM("uart_clk", UART3_CLK, "msm_serial.2", OFF), + CLK_PCOM("uart1dm_clk", UART1DM_CLK, NULL, OFF), + CLK_PCOM("uart2dm_clk", UART2DM_CLK, NULL, 0), + CLK_PCOM("usb_hs_clk", USB_HS_CLK, "msm_hsusb", OFF), + CLK_PCOM("usb_hs_pclk", USB_HS_P_CLK, "msm_hsusb", OFF), + CLK_PCOM("usb_otg_clk", USB_OTG_CLK, NULL, 0), + CLK_PCOM("vdc_clk", VDC_CLK, NULL, OFF ), + CLK_PCOM("vfe_clk", VFE_CLK, NULL, OFF), + CLK_PCOM("vfe_mdc_clk", VFE_MDC_CLK, NULL, OFF), +}; + +unsigned msm_num_clocks_7x01a = ARRAY_SIZE(msm_clocks_7x01a); diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c new file mode 100644 index 00000000..09b4f140 --- /dev/null +++ b/arch/arm/mach-msm/devices-msm7x30.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2008 Google, Inc. + * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include <linux/dma-mapping.h> +#include <linux/clkdev.h> +#include <mach/irqs.h> +#include <mach/msm_iomap.h> +#include <mach/dma.h> +#include <mach/board.h> + +#include "devices.h" +#include "smd_private.h" + +#include <asm/mach/flash.h> + +#include "clock-pcom.h" +#include "clock-7x30.h" + +#include <mach/mmc.h> + +static struct resource resources_uart2[] = { + { + .start = INT_UART2, + .end = INT_UART2, + .flags = IORESOURCE_IRQ, + }, + { + .start = MSM_UART2_PHYS, + .end = MSM_UART2_PHYS + MSM_UART2_SIZE - 1, + .flags = IORESOURCE_MEM, + .name = "uart_resource" + }, +}; + +struct platform_device msm_device_uart2 = { + .name = "msm_serial", + .id = 1, + .num_resources = ARRAY_SIZE(resources_uart2), + .resource = resources_uart2, +}; + +struct platform_device msm_device_smd = { + .name = "msm_smd", + .id = -1, +}; + +static struct resource resources_otg[] = { + { + .start = MSM_HSUSB_PHYS, + .end = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_USB_HS, + .end = INT_USB_HS, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device msm_device_otg = { + .name = "msm_otg", + .id = -1, + .num_resources = ARRAY_SIZE(resources_otg), + .resource = resources_otg, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +static struct resource resources_hsusb[] = { + { + .start = MSM_HSUSB_PHYS, + .end = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_USB_HS, + .end = INT_USB_HS, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device msm_device_hsusb = { + .name = "msm_hsusb", + .id = -1, + .num_resources = ARRAY_SIZE(resources_hsusb), + .resource = resources_hsusb, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +static u64 dma_mask = 0xffffffffULL; +static struct resource resources_hsusb_host[] = { + { + .start = MSM_HSUSB_PHYS, + .end = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_USB_HS, + .end = INT_USB_HS, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device msm_device_hsusb_host = { + .name = "msm_hsusb_host", + .id = -1, + .num_resources = ARRAY_SIZE(resources_hsusb_host), + .resource = resources_hsusb_host, + .dev = { + .dma_mask = &dma_mask, + .coherent_dma_mask = 0xffffffffULL, + }, +}; + +struct clk_lookup msm_clocks_7x30[] = { + CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), + CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0), + CLK_PCOM("cam_m_clk", CAM_M_CLK, NULL, 0), + CLK_PCOM("camif_pad_pclk", CAMIF_PAD_P_CLK, NULL, OFF), + CLK_PCOM("ce_clk", CE_CLK, NULL, 0), + CLK_PCOM("codec_ssbi_clk", CODEC_SSBI_CLK, NULL, 0), + CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN), + CLK_PCOM("ecodec_clk", ECODEC_CLK, NULL, 0), + CLK_PCOM("emdh_clk", EMDH_CLK, NULL, OFF | CLK_MINMAX), + CLK_PCOM("emdh_pclk", EMDH_P_CLK, NULL, OFF), + CLK_PCOM("gp_clk", GP_CLK, NULL, 0), + CLK_PCOM("grp_2d_clk", GRP_2D_CLK, NULL, 0), + CLK_PCOM("grp_2d_pclk", GRP_2D_P_CLK, NULL, 0), + CLK_PCOM("grp_clk", GRP_3D_CLK, NULL, 0), + CLK_PCOM("grp_pclk", GRP_3D_P_CLK, NULL, 0), + CLK_7X30S("grp_src_clk", GRP_3D_SRC_CLK, GRP_3D_CLK, NULL, 0), + CLK_PCOM("hdmi_clk", HDMI_CLK, NULL, 0), + CLK_PCOM("imem_clk", IMEM_CLK, NULL, OFF), + CLK_PCOM("jpeg_clk", JPEG_CLK, NULL, OFF), + CLK_PCOM("jpeg_pclk", JPEG_P_CLK, NULL, OFF), + CLK_PCOM("lpa_codec_clk", LPA_CODEC_CLK, NULL, 0), + CLK_PCOM("lpa_core_clk", LPA_CORE_CLK, NULL, 0), + CLK_PCOM("lpa_pclk", LPA_P_CLK, NULL, 0), + CLK_PCOM("mdc_clk", MDC_CLK, NULL, 0), + CLK_PCOM("mddi_clk", PMDH_CLK, NULL, OFF | CLK_MINMAX), + CLK_PCOM("mddi_pclk", PMDH_P_CLK, NULL, 0), + CLK_PCOM("mdp_clk", MDP_CLK, NULL, OFF), + CLK_PCOM("mdp_pclk", MDP_P_CLK, NULL, 0), + CLK_PCOM("mdp_lcdc_pclk_clk", MDP_LCDC_PCLK_CLK, NULL, 0), + CLK_PCOM("mdp_lcdc_pad_pclk_clk", MDP_LCDC_PAD_PCLK_CLK, NULL, 0), + CLK_PCOM("mdp_vsync_clk", MDP_VSYNC_CLK, NULL, 0), + CLK_PCOM("mfc_clk", MFC_CLK, NULL, 0), + CLK_PCOM("mfc_div2_clk", MFC_DIV2_CLK, NULL, 0), + CLK_PCOM("mfc_pclk", MFC_P_CLK, NULL, 0), + CLK_PCOM("mi2s_m_clk", MI2S_M_CLK, NULL, 0), + CLK_PCOM("mi2s_s_clk", MI2S_S_CLK, NULL, 0), + CLK_PCOM("mi2s_codec_rx_m_clk", MI2S_CODEC_RX_M_CLK, NULL, 0), + CLK_PCOM("mi2s_codec_rx_s_clk", MI2S_CODEC_RX_S_CLK, NULL, 0), + CLK_PCOM("mi2s_codec_tx_m_clk", MI2S_CODEC_TX_M_CLK, NULL, 0), + CLK_PCOM("mi2s_codec_tx_s_clk", MI2S_CODEC_TX_S_CLK, NULL, 0), + CLK_PCOM("pbus_clk", PBUS_CLK, NULL, CLK_MIN), + CLK_PCOM("pcm_clk", PCM_CLK, NULL, 0), + CLK_PCOM("rotator_clk", AXI_ROTATOR_CLK, NULL, 0), + CLK_PCOM("rotator_imem_clk", ROTATOR_IMEM_CLK, NULL, OFF), + CLK_PCOM("rotator_pclk", ROTATOR_P_CLK, NULL, OFF), + CLK_PCOM("sdac_clk", SDAC_CLK, NULL, OFF), + CLK_PCOM("spi_clk", SPI_CLK, NULL, 0), + CLK_PCOM("spi_pclk", SPI_P_CLK, NULL, 0), + CLK_7X30S("tv_src_clk", TV_CLK, TV_ENC_CLK, NULL, 0), + CLK_PCOM("tv_dac_clk", TV_DAC_CLK, NULL, 0), + CLK_PCOM("tv_enc_clk", TV_ENC_CLK, NULL, 0), + CLK_PCOM("uart_clk", UART2_CLK, "msm_serial.1", 0), + CLK_PCOM("usb_phy_clk", USB_PHY_CLK, NULL, 0), + CLK_PCOM("usb_hs_clk", USB_HS_CLK, NULL, OFF), + CLK_PCOM("usb_hs_pclk", USB_HS_P_CLK, NULL, OFF), + CLK_PCOM("usb_hs_core_clk", USB_HS_CORE_CLK, NULL, OFF), + CLK_PCOM("usb_hs2_clk", USB_HS2_CLK, NULL, OFF), + CLK_PCOM("usb_hs2_pclk", USB_HS2_P_CLK, NULL, OFF), + CLK_PCOM("usb_hs2_core_clk", USB_HS2_CORE_CLK, NULL, OFF), + CLK_PCOM("usb_hs3_clk", USB_HS3_CLK, NULL, OFF), + CLK_PCOM("usb_hs3_pclk", USB_HS3_P_CLK, NULL, OFF), + CLK_PCOM("usb_hs3_core_clk", USB_HS3_CORE_CLK, NULL, OFF), + CLK_PCOM("vdc_clk", VDC_CLK, NULL, OFF | CLK_MIN), + CLK_PCOM("vfe_camif_clk", VFE_CAMIF_CLK, NULL, 0), + CLK_PCOM("vfe_clk", VFE_CLK, NULL, 0), + CLK_PCOM("vfe_mdc_clk", VFE_MDC_CLK, NULL, 0), + CLK_PCOM("vfe_pclk", VFE_P_CLK, NULL, OFF), + CLK_PCOM("vpe_clk", VPE_CLK, NULL, 0), + + /* 7x30 v2 hardware only. */ + CLK_PCOM("csi_clk", CSI0_CLK, NULL, 0), + CLK_PCOM("csi_pclk", CSI0_P_CLK, NULL, 0), + CLK_PCOM("csi_vfe_clk", CSI0_VFE_CLK, NULL, 0), +}; + +unsigned msm_num_clocks_7x30 = ARRAY_SIZE(msm_clocks_7x30); + diff --git a/arch/arm/mach-msm/devices-msm8960.c b/arch/arm/mach-msm/devices-msm8960.c new file mode 100644 index 00000000..d9e1f264 --- /dev/null +++ b/arch/arm/mach-msm/devices-msm8960.c @@ -0,0 +1,85 @@ +/* Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> + +#include <linux/dma-mapping.h> +#include <mach/irqs-8960.h> +#include <mach/board.h> + +#include "devices.h" + +#define MSM_GSBI2_PHYS 0x16100000 +#define MSM_UART2DM_PHYS (MSM_GSBI2_PHYS + 0x40000) + +#define MSM_GSBI5_PHYS 0x16400000 +#define MSM_UART5DM_PHYS (MSM_GSBI5_PHYS + 0x40000) + +static struct resource resources_uart_gsbi2[] = { + { + .start = GSBI2_UARTDM_IRQ, + .end = GSBI2_UARTDM_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .start = MSM_UART2DM_PHYS, + .end = MSM_UART2DM_PHYS + PAGE_SIZE - 1, + .name = "uart_resource", + .flags = IORESOURCE_MEM, + }, + { + .start = MSM_GSBI2_PHYS, + .end = MSM_GSBI2_PHYS + PAGE_SIZE - 1, + .name = "gsbi_resource", + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device msm8960_device_uart_gsbi2 = { + .name = "msm_serial", + .id = 0, + .num_resources = ARRAY_SIZE(resources_uart_gsbi2), + .resource = resources_uart_gsbi2, +}; + +static struct resource resources_uart_gsbi5[] = { + { + .start = GSBI5_UARTDM_IRQ, + .end = GSBI5_UARTDM_IRQ, + .flags = IORESOURCE_IRQ, + }, + { + .start = MSM_UART5DM_PHYS, + .end = MSM_UART5DM_PHYS + PAGE_SIZE - 1, + .name = "uart_resource", + .flags = IORESOURCE_MEM, + }, + { + .start = MSM_GSBI5_PHYS, + .end = MSM_GSBI5_PHYS + PAGE_SIZE - 1, + .name = "gsbi_resource", + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device msm8960_device_uart_gsbi5 = { + .name = "msm_serial", + .id = 0, + .num_resources = ARRAY_SIZE(resources_uart_gsbi5), + .resource = resources_uart_gsbi5, +}; diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c new file mode 100644 index 00000000..131633b1 --- /dev/null +++ b/arch/arm/mach-msm/devices-qsd8x50.c @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2008 Google, Inc. + * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/clkdev.h> +#include <linux/dma-mapping.h> + +#include <mach/irqs.h> +#include <mach/msm_iomap.h> +#include <mach/dma.h> +#include <mach/board.h> + +#include "devices.h" + +#include <asm/mach/flash.h> + +#include <mach/mmc.h> +#include "clock-pcom.h" + +static struct resource resources_uart3[] = { + { + .start = INT_UART3, + .end = INT_UART3, + .flags = IORESOURCE_IRQ, + }, + { + .start = MSM_UART3_PHYS, + .end = MSM_UART3_PHYS + MSM_UART3_SIZE - 1, + .flags = IORESOURCE_MEM, + .name = "uart_resource" + }, +}; + +struct platform_device msm_device_uart3 = { + .name = "msm_serial", + .id = 2, + .num_resources = ARRAY_SIZE(resources_uart3), + .resource = resources_uart3, +}; + +struct platform_device msm_device_smd = { + .name = "msm_smd", + .id = -1, +}; + +static struct resource resources_otg[] = { + { + .start = MSM_HSUSB_PHYS, + .end = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_USB_HS, + .end = INT_USB_HS, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device msm_device_otg = { + .name = "msm_otg", + .id = -1, + .num_resources = ARRAY_SIZE(resources_otg), + .resource = resources_otg, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +static struct resource resources_hsusb[] = { + { + .start = MSM_HSUSB_PHYS, + .end = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_USB_HS, + .end = INT_USB_HS, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device msm_device_hsusb = { + .name = "msm_hsusb", + .id = -1, + .num_resources = ARRAY_SIZE(resources_hsusb), + .resource = resources_hsusb, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +static u64 dma_mask = 0xffffffffULL; +static struct resource resources_hsusb_host[] = { + { + .start = MSM_HSUSB_PHYS, + .end = MSM_HSUSB_PHYS + MSM_HSUSB_SIZE, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_USB_HS, + .end = INT_USB_HS, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device msm_device_hsusb_host = { + .name = "msm_hsusb_host", + .id = -1, + .num_resources = ARRAY_SIZE(resources_hsusb_host), + .resource = resources_hsusb_host, + .dev = { + .dma_mask = &dma_mask, + .coherent_dma_mask = 0xffffffffULL, + }, +}; + +static struct resource resources_sdc1[] = { + { + .start = MSM_SDC1_PHYS, + .end = MSM_SDC1_PHYS + MSM_SDC1_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_SDC1_0, + .end = INT_SDC1_0, + .flags = IORESOURCE_IRQ, + .name = "cmd_irq", + }, + { + .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED, + .name = "status_irq" + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_DMA, + }, +}; + +static struct resource resources_sdc2[] = { + { + .start = MSM_SDC2_PHYS, + .end = MSM_SDC2_PHYS + MSM_SDC2_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_SDC2_0, + .end = INT_SDC2_0, + .flags = IORESOURCE_IRQ, + .name = "cmd_irq", + }, + { + .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED, + .name = "status_irq" + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_DMA, + }, +}; + +static struct resource resources_sdc3[] = { + { + .start = MSM_SDC3_PHYS, + .end = MSM_SDC3_PHYS + MSM_SDC3_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_SDC3_0, + .end = INT_SDC3_0, + .flags = IORESOURCE_IRQ, + .name = "cmd_irq", + }, + { + .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED, + .name = "status_irq" + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_DMA, + }, +}; + +static struct resource resources_sdc4[] = { + { + .start = MSM_SDC4_PHYS, + .end = MSM_SDC4_PHYS + MSM_SDC4_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = INT_SDC4_0, + .end = INT_SDC4_0, + .flags = IORESOURCE_IRQ, + .name = "cmd_irq", + }, + { + .flags = IORESOURCE_IRQ | IORESOURCE_DISABLED, + .name = "status_irq" + }, + { + .start = 8, + .end = 8, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device msm_device_sdc1 = { + .name = "msm_sdcc", + .id = 1, + .num_resources = ARRAY_SIZE(resources_sdc1), + .resource = resources_sdc1, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +struct platform_device msm_device_sdc2 = { + .name = "msm_sdcc", + .id = 2, + .num_resources = ARRAY_SIZE(resources_sdc2), + .resource = resources_sdc2, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +struct platform_device msm_device_sdc3 = { + .name = "msm_sdcc", + .id = 3, + .num_resources = ARRAY_SIZE(resources_sdc3), + .resource = resources_sdc3, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +struct platform_device msm_device_sdc4 = { + .name = "msm_sdcc", + .id = 4, + .num_resources = ARRAY_SIZE(resources_sdc4), + .resource = resources_sdc4, + .dev = { + .coherent_dma_mask = 0xffffffff, + }, +}; + +static struct platform_device *msm_sdcc_devices[] __initdata = { + &msm_device_sdc1, + &msm_device_sdc2, + &msm_device_sdc3, + &msm_device_sdc4, +}; + +int __init msm_add_sdcc(unsigned int controller, + struct msm_mmc_platform_data *plat, + unsigned int stat_irq, unsigned long stat_irq_flags) +{ + struct platform_device *pdev; + struct resource *res; + + if (controller < 1 || controller > 4) + return -EINVAL; + + pdev = msm_sdcc_devices[controller-1]; + pdev->dev.platform_data = plat; + + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "status_irq"); + if (!res) + return -EINVAL; + else if (stat_irq) { + res->start = res->end = stat_irq; + res->flags &= ~IORESOURCE_DISABLED; + res->flags |= stat_irq_flags; + } + + return platform_device_register(pdev); +} + +struct clk_lookup msm_clocks_8x50[] = { + CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), + CLK_PCOM("ce_clk", CE_CLK, NULL, 0), + CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN), + CLK_PCOM("ebi2_clk", EBI2_CLK, NULL, 0), + CLK_PCOM("ecodec_clk", ECODEC_CLK, NULL, 0), + CLK_PCOM("emdh_clk", EMDH_CLK, NULL, OFF | CLK_MINMAX), + CLK_PCOM("gp_clk", GP_CLK, NULL, 0), + CLK_PCOM("grp_clk", GRP_3D_CLK, NULL, 0), + CLK_PCOM("i2c_clk", I2C_CLK, NULL, 0), + CLK_PCOM("icodec_rx_clk", ICODEC_RX_CLK, NULL, 0), + CLK_PCOM("icodec_tx_clk", ICODEC_TX_CLK, NULL, 0), + CLK_PCOM("imem_clk", IMEM_CLK, NULL, OFF), + CLK_PCOM("mdc_clk", MDC_CLK, NULL, 0), + CLK_PCOM("mddi_clk", PMDH_CLK, NULL, OFF | CLK_MINMAX), + CLK_PCOM("mdp_clk", MDP_CLK, NULL, OFF), + CLK_PCOM("mdp_lcdc_pclk_clk", MDP_LCDC_PCLK_CLK, NULL, 0), + CLK_PCOM("mdp_lcdc_pad_pclk_clk", MDP_LCDC_PAD_PCLK_CLK, NULL, 0), + CLK_PCOM("mdp_vsync_clk", MDP_VSYNC_CLK, NULL, 0), + CLK_PCOM("pbus_clk", PBUS_CLK, NULL, CLK_MIN), + CLK_PCOM("pcm_clk", PCM_CLK, NULL, 0), + CLK_PCOM("sdac_clk", SDAC_CLK, NULL, OFF), + CLK_PCOM("sdc_clk", SDC1_CLK, "msm_sdcc.1", OFF), + CLK_PCOM("sdc_pclk", SDC1_P_CLK, "msm_sdcc.1", OFF), + CLK_PCOM("sdc_clk", SDC2_CLK, "msm_sdcc.2", OFF), + CLK_PCOM("sdc_pclk", SDC2_P_CLK, "msm_sdcc.2", OFF), + CLK_PCOM("sdc_clk", SDC3_CLK, "msm_sdcc.3", OFF), + CLK_PCOM("sdc_pclk", SDC3_P_CLK, "msm_sdcc.3", OFF), + CLK_PCOM("sdc_clk", SDC4_CLK, "msm_sdcc.4", OFF), + CLK_PCOM("sdc_pclk", SDC4_P_CLK, "msm_sdcc.4", OFF), + CLK_PCOM("spi_clk", SPI_CLK, NULL, 0), + CLK_PCOM("tsif_clk", TSIF_CLK, NULL, 0), + CLK_PCOM("tsif_ref_clk", TSIF_REF_CLK, NULL, 0), + CLK_PCOM("tv_dac_clk", TV_DAC_CLK, NULL, 0), + CLK_PCOM("tv_enc_clk", TV_ENC_CLK, NULL, 0), + CLK_PCOM("uart_clk", UART1_CLK, NULL, OFF), + CLK_PCOM("uart_clk", UART2_CLK, NULL, 0), + CLK_PCOM("uart_clk", UART3_CLK, "msm_serial.2", OFF), + CLK_PCOM("uartdm_clk", UART1DM_CLK, NULL, OFF), + CLK_PCOM("uartdm_clk", UART2DM_CLK, NULL, 0), + CLK_PCOM("usb_hs_clk", USB_HS_CLK, NULL, OFF), + CLK_PCOM("usb_hs_pclk", USB_HS_P_CLK, NULL, OFF), + CLK_PCOM("usb_otg_clk", USB_OTG_CLK, NULL, 0), + CLK_PCOM("vdc_clk", VDC_CLK, NULL, OFF | CLK_MIN), + CLK_PCOM("vfe_clk", VFE_CLK, NULL, OFF), + CLK_PCOM("vfe_mdc_clk", VFE_MDC_CLK, NULL, OFF), + CLK_PCOM("vfe_axi_clk", VFE_AXI_CLK, NULL, OFF), + CLK_PCOM("usb_hs2_clk", USB_HS2_CLK, NULL, OFF), + CLK_PCOM("usb_hs2_pclk", USB_HS2_P_CLK, NULL, OFF), + CLK_PCOM("usb_hs3_clk", USB_HS3_CLK, NULL, OFF), + CLK_PCOM("usb_hs3_pclk", USB_HS3_P_CLK, NULL, OFF), + CLK_PCOM("usb_phy_clk", USB_PHY_CLK, NULL, 0), +}; + +unsigned msm_num_clocks_8x50 = ARRAY_SIZE(msm_clocks_8x50); + diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h new file mode 100644 index 00000000..9545c196 --- /dev/null +++ b/arch/arm/mach-msm/devices.h @@ -0,0 +1,58 @@ +/* linux/arch/arm/mach-msm/devices.h + * + * Copyright (C) 2008 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ARCH_ARM_MACH_MSM_DEVICES_H +#define __ARCH_ARM_MACH_MSM_DEVICES_H + +#include <linux/clkdev.h> + +#include "clock.h" + +extern struct platform_device msm_device_uart1; +extern struct platform_device msm_device_uart2; +extern struct platform_device msm_device_uart3; + +extern struct platform_device msm8960_device_uart_gsbi2; +extern struct platform_device msm8960_device_uart_gsbi5; + +extern struct platform_device msm_device_sdc1; +extern struct platform_device msm_device_sdc2; +extern struct platform_device msm_device_sdc3; +extern struct platform_device msm_device_sdc4; + +extern struct platform_device msm_device_hsusb; +extern struct platform_device msm_device_otg; +extern struct platform_device msm_device_hsusb_host; + +extern struct platform_device msm_device_i2c; + +extern struct platform_device msm_device_smd; + +extern struct platform_device msm_device_nand; + +extern struct platform_device msm_device_mddi0; +extern struct platform_device msm_device_mddi1; +extern struct platform_device msm_device_mdp; + +extern struct clk_lookup msm_clocks_7x01a[]; +extern unsigned msm_num_clocks_7x01a; + +extern struct clk_lookup msm_clocks_7x30[]; +extern unsigned msm_num_clocks_7x30; + +extern struct clk_lookup msm_clocks_8x50[]; +extern unsigned msm_num_clocks_8x50; + +#endif diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c new file mode 100644 index 00000000..02cae5e2 --- /dev/null +++ b/arch/arm/mach-msm/dma.c @@ -0,0 +1,271 @@ +/* linux/arch/arm/mach-msm/dma.c + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/completion.h> +#include <mach/dma.h> + +#define MSM_DMOV_CHANNEL_COUNT 16 + +enum { + MSM_DMOV_PRINT_ERRORS = 1, + MSM_DMOV_PRINT_IO = 2, + MSM_DMOV_PRINT_FLOW = 4 +}; + +static DEFINE_SPINLOCK(msm_dmov_lock); +static struct clk *msm_dmov_clk; +static unsigned int channel_active; +static struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT]; +static struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT]; +unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS; + +#define MSM_DMOV_DPRINTF(mask, format, args...) \ + do { \ + if ((mask) & msm_dmov_print_mask) \ + printk(KERN_ERR format, args); \ + } while (0) +#define PRINT_ERROR(format, args...) \ + MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_ERRORS, format, args); +#define PRINT_IO(format, args...) \ + MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_IO, format, args); +#define PRINT_FLOW(format, args...) \ + MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_FLOW, format, args); + +void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful) +{ + writel((graceful << 31), DMOV_FLUSH0(id)); +} + +void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) +{ + unsigned long irq_flags; + unsigned int status; + + spin_lock_irqsave(&msm_dmov_lock, irq_flags); + if (!channel_active) + clk_enable(msm_dmov_clk); + dsb(); + status = readl(DMOV_STATUS(id)); + if (list_empty(&ready_commands[id]) && + (status & DMOV_STATUS_CMD_PTR_RDY)) { +#if 0 + if (list_empty(&active_commands[id])) { + PRINT_FLOW("msm_dmov_enqueue_cmd(%d), enable interrupt\n", id); + writel(DMOV_CONFIG_IRQ_EN, DMOV_CONFIG(id)); + } +#endif + if (cmd->execute_func) + cmd->execute_func(cmd); + PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n", id, status); + list_add_tail(&cmd->list, &active_commands[id]); + if (!channel_active) + enable_irq(INT_ADM_AARM); + channel_active |= 1U << id; + writel(cmd->cmdptr, DMOV_CMD_PTR(id)); + } else { + if (!channel_active) + clk_disable(msm_dmov_clk); + if (list_empty(&active_commands[id])) + PRINT_ERROR("msm_dmov_enqueue_cmd(%d), error datamover stalled, status %x\n", id, status); + + PRINT_IO("msm_dmov_enqueue_cmd(%d), enqueue command, status %x\n", id, status); + list_add_tail(&cmd->list, &ready_commands[id]); + } + spin_unlock_irqrestore(&msm_dmov_lock, irq_flags); +} + +struct msm_dmov_exec_cmdptr_cmd { + struct msm_dmov_cmd dmov_cmd; + struct completion complete; + unsigned id; + unsigned int result; + struct msm_dmov_errdata err; +}; + +static void +dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd, + unsigned int result, + struct msm_dmov_errdata *err) +{ + struct msm_dmov_exec_cmdptr_cmd *cmd = container_of(_cmd, struct msm_dmov_exec_cmdptr_cmd, dmov_cmd); + cmd->result = result; + if (result != 0x80000002 && err) + memcpy(&cmd->err, err, sizeof(struct msm_dmov_errdata)); + + complete(&cmd->complete); +} + +int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) +{ + struct msm_dmov_exec_cmdptr_cmd cmd; + + PRINT_FLOW("dmov_exec_cmdptr(%d, %x)\n", id, cmdptr); + + cmd.dmov_cmd.cmdptr = cmdptr; + cmd.dmov_cmd.complete_func = dmov_exec_cmdptr_complete_func; + cmd.dmov_cmd.execute_func = NULL; + cmd.id = id; + init_completion(&cmd.complete); + + msm_dmov_enqueue_cmd(id, &cmd.dmov_cmd); + wait_for_completion(&cmd.complete); + + if (cmd.result != 0x80000002) { + PRINT_ERROR("dmov_exec_cmdptr(%d): ERROR, result: %x\n", id, cmd.result); + PRINT_ERROR("dmov_exec_cmdptr(%d): flush: %x %x %x %x\n", + id, cmd.err.flush[0], cmd.err.flush[1], cmd.err.flush[2], cmd.err.flush[3]); + return -EIO; + } + PRINT_FLOW("dmov_exec_cmdptr(%d, %x) done\n", id, cmdptr); + return 0; +} + + +static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id) +{ + unsigned int int_status, mask, id; + unsigned long irq_flags; + unsigned int ch_status; + unsigned int ch_result; + struct msm_dmov_cmd *cmd; + + spin_lock_irqsave(&msm_dmov_lock, irq_flags); + + int_status = readl(DMOV_ISR); /* read and clear interrupt */ + PRINT_FLOW("msm_datamover_irq_handler: DMOV_ISR %x\n", int_status); + + while (int_status) { + mask = int_status & -int_status; + id = fls(mask) - 1; + PRINT_FLOW("msm_datamover_irq_handler %08x %08x id %d\n", int_status, mask, id); + int_status &= ~mask; + ch_status = readl(DMOV_STATUS(id)); + if (!(ch_status & DMOV_STATUS_RSLT_VALID)) { + PRINT_FLOW("msm_datamover_irq_handler id %d, result not valid %x\n", id, ch_status); + continue; + } + do { + ch_result = readl(DMOV_RSLT(id)); + if (list_empty(&active_commands[id])) { + PRINT_ERROR("msm_datamover_irq_handler id %d, got result " + "with no active command, status %x, result %x\n", + id, ch_status, ch_result); + cmd = NULL; + } else + cmd = list_entry(active_commands[id].next, typeof(*cmd), list); + PRINT_FLOW("msm_datamover_irq_handler id %d, status %x, result %x\n", id, ch_status, ch_result); + if (ch_result & DMOV_RSLT_DONE) { + PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", + id, ch_status); + PRINT_IO("msm_datamover_irq_handler id %d, got result " + "for %p, result %x\n", id, cmd, ch_result); + if (cmd) { + list_del(&cmd->list); + dsb(); + cmd->complete_func(cmd, ch_result, NULL); + } + } + if (ch_result & DMOV_RSLT_FLUSH) { + struct msm_dmov_errdata errdata; + + errdata.flush[0] = readl(DMOV_FLUSH0(id)); + errdata.flush[1] = readl(DMOV_FLUSH1(id)); + errdata.flush[2] = readl(DMOV_FLUSH2(id)); + errdata.flush[3] = readl(DMOV_FLUSH3(id)); + errdata.flush[4] = readl(DMOV_FLUSH4(id)); + errdata.flush[5] = readl(DMOV_FLUSH5(id)); + PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); + PRINT_FLOW("msm_datamover_irq_handler id %d, flush, result %x, flush0 %x\n", id, ch_result, errdata.flush[0]); + if (cmd) { + list_del(&cmd->list); + dsb(); + cmd->complete_func(cmd, ch_result, &errdata); + } + } + if (ch_result & DMOV_RSLT_ERROR) { + struct msm_dmov_errdata errdata; + + errdata.flush[0] = readl(DMOV_FLUSH0(id)); + errdata.flush[1] = readl(DMOV_FLUSH1(id)); + errdata.flush[2] = readl(DMOV_FLUSH2(id)); + errdata.flush[3] = readl(DMOV_FLUSH3(id)); + errdata.flush[4] = readl(DMOV_FLUSH4(id)); + errdata.flush[5] = readl(DMOV_FLUSH5(id)); + + PRINT_ERROR("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); + PRINT_ERROR("msm_datamover_irq_handler id %d, error, result %x, flush0 %x\n", id, ch_result, errdata.flush[0]); + if (cmd) { + list_del(&cmd->list); + dsb(); + cmd->complete_func(cmd, ch_result, &errdata); + } + /* this does not seem to work, once we get an error */ + /* the datamover will no longer accept commands */ + writel(0, DMOV_FLUSH0(id)); + } + ch_status = readl(DMOV_STATUS(id)); + PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); + if ((ch_status & DMOV_STATUS_CMD_PTR_RDY) && !list_empty(&ready_commands[id])) { + cmd = list_entry(ready_commands[id].next, typeof(*cmd), list); + list_del(&cmd->list); + list_add_tail(&cmd->list, &active_commands[id]); + if (cmd->execute_func) + cmd->execute_func(cmd); + PRINT_FLOW("msm_datamover_irq_handler id %d, start command\n", id); + writel(cmd->cmdptr, DMOV_CMD_PTR(id)); + } + } while (ch_status & DMOV_STATUS_RSLT_VALID); + if (list_empty(&active_commands[id]) && list_empty(&ready_commands[id])) + channel_active &= ~(1U << id); + PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status); + } + + if (!channel_active) { + disable_irq_nosync(INT_ADM_AARM); + clk_disable(msm_dmov_clk); + } + + spin_unlock_irqrestore(&msm_dmov_lock, irq_flags); + return IRQ_HANDLED; +} + +static int __init msm_init_datamover(void) +{ + int i; + int ret; + struct clk *clk; + + for (i = 0; i < MSM_DMOV_CHANNEL_COUNT; i++) { + INIT_LIST_HEAD(&ready_commands[i]); + INIT_LIST_HEAD(&active_commands[i]); + writel(DMOV_CONFIG_IRQ_EN | DMOV_CONFIG_FORCE_TOP_PTR_RSLT | DMOV_CONFIG_FORCE_FLUSH_RSLT, DMOV_CONFIG(i)); + } + clk = clk_get(NULL, "adm_clk"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + msm_dmov_clk = clk; + ret = request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL); + if (ret) + return ret; + disable_irq(INT_ADM_AARM); + return 0; +} + +arch_initcall(msm_init_datamover); + diff --git a/arch/arm/mach-msm/gpiomux-8x50.c b/arch/arm/mach-msm/gpiomux-8x50.c new file mode 100644 index 00000000..f7a4ea59 --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-8x50.c @@ -0,0 +1,51 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include "gpiomux.h" + +#if defined(CONFIG_MMC_MSM) || defined(CONFIG_MMC_MSM_MODULE) + #define SDCC_DAT_0_3_CMD_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_UP\ + | GPIOMUX_FUNC_1 | GPIOMUX_DRV_8MA) + #define SDCC_CLK_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_NONE\ + | GPIOMUX_FUNC_1 | GPIOMUX_DRV_8MA) +#else + #define SDCC_DAT_0_3_CMD_ACTV_CFG 0 + #define SDCC_CLK_ACTV_CFG 0 +#endif + +#define SDC1_SUSPEND_CONFIG (GPIOMUX_VALID | GPIOMUX_PULL_DOWN\ + | GPIOMUX_FUNC_GPIO | GPIOMUX_DRV_2MA) + +struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = { + [86] = { /* UART3 RX */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_1 | GPIOMUX_VALID, + }, + [87] = { /* UART3 TX */ + .suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN | + GPIOMUX_FUNC_1 | GPIOMUX_VALID, + }, + /* SDC1 data[3:0] & CMD */ + [51 ... 55] = { + .active = SDCC_DAT_0_3_CMD_ACTV_CFG, + .suspended = SDC1_SUSPEND_CONFIG + }, + /* SDC1 CLK */ + [56] = { + .active = SDCC_CLK_ACTV_CFG, + .suspended = SDC1_SUSPEND_CONFIG + }, +}; diff --git a/arch/arm/mach-msm/gpiomux-8x60.c b/arch/arm/mach-msm/gpiomux-8x60.c new file mode 100644 index 00000000..7b380b31 --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-8x60.c @@ -0,0 +1,19 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include "gpiomux.h" + +struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {}; diff --git a/arch/arm/mach-msm/gpiomux-v1.c b/arch/arm/mach-msm/gpiomux-v1.c new file mode 100644 index 00000000..27de2abd --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-v1.c @@ -0,0 +1,33 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <linux/kernel.h> +#include "gpiomux.h" +#include "proc_comm.h" + +void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val) +{ + unsigned tlmm_config = (val & ~GPIOMUX_CTL_MASK) | + ((gpio & 0x3ff) << 4); + unsigned tlmm_disable = 0; + int rc; + + rc = msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, + &tlmm_config, &tlmm_disable); + if (rc) + pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n", + __func__, rc, tlmm_config, tlmm_disable); +} diff --git a/arch/arm/mach-msm/gpiomux-v1.h b/arch/arm/mach-msm/gpiomux-v1.h new file mode 100644 index 00000000..71d86feb --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-v1.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H +#define __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H + +#if defined(CONFIG_ARCH_MSM7X30) +#define GPIOMUX_NGPIOS 182 +#elif defined(CONFIG_ARCH_QSD8X50) +#define GPIOMUX_NGPIOS 165 +#else +#define GPIOMUX_NGPIOS 133 +#endif + +typedef u32 gpiomux_config_t; + +enum { + GPIOMUX_DRV_2MA = 0UL << 17, + GPIOMUX_DRV_4MA = 1UL << 17, + GPIOMUX_DRV_6MA = 2UL << 17, + GPIOMUX_DRV_8MA = 3UL << 17, + GPIOMUX_DRV_10MA = 4UL << 17, + GPIOMUX_DRV_12MA = 5UL << 17, + GPIOMUX_DRV_14MA = 6UL << 17, + GPIOMUX_DRV_16MA = 7UL << 17, +}; + +enum { + GPIOMUX_FUNC_GPIO = 0UL, + GPIOMUX_FUNC_1 = 1UL, + GPIOMUX_FUNC_2 = 2UL, + GPIOMUX_FUNC_3 = 3UL, + GPIOMUX_FUNC_4 = 4UL, + GPIOMUX_FUNC_5 = 5UL, + GPIOMUX_FUNC_6 = 6UL, + GPIOMUX_FUNC_7 = 7UL, + GPIOMUX_FUNC_8 = 8UL, + GPIOMUX_FUNC_9 = 9UL, + GPIOMUX_FUNC_A = 10UL, + GPIOMUX_FUNC_B = 11UL, + GPIOMUX_FUNC_C = 12UL, + GPIOMUX_FUNC_D = 13UL, + GPIOMUX_FUNC_E = 14UL, + GPIOMUX_FUNC_F = 15UL, +}; + +enum { + GPIOMUX_PULL_NONE = 0UL << 15, + GPIOMUX_PULL_DOWN = 1UL << 15, + GPIOMUX_PULL_KEEPER = 2UL << 15, + GPIOMUX_PULL_UP = 3UL << 15, +}; + +#endif diff --git a/arch/arm/mach-msm/gpiomux-v2.c b/arch/arm/mach-msm/gpiomux-v2.c new file mode 100644 index 00000000..273396d2 --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-v2.c @@ -0,0 +1,25 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <linux/io.h> +#include <mach/msm_iomap.h> +#include "gpiomux.h" + +void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val) +{ + writel(val & ~GPIOMUX_CTL_MASK, + MSM_TLMM_BASE + 0x1000 + (0x10 * gpio)); +} diff --git a/arch/arm/mach-msm/gpiomux-v2.h b/arch/arm/mach-msm/gpiomux-v2.h new file mode 100644 index 00000000..3bf10e7f --- /dev/null +++ b/arch/arm/mach-msm/gpiomux-v2.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H +#define __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H + +#define GPIOMUX_NGPIOS 173 + +typedef u16 gpiomux_config_t; + +enum { + GPIOMUX_DRV_2MA = 0UL << 6, + GPIOMUX_DRV_4MA = 1UL << 6, + GPIOMUX_DRV_6MA = 2UL << 6, + GPIOMUX_DRV_8MA = 3UL << 6, + GPIOMUX_DRV_10MA = 4UL << 6, + GPIOMUX_DRV_12MA = 5UL << 6, + GPIOMUX_DRV_14MA = 6UL << 6, + GPIOMUX_DRV_16MA = 7UL << 6, +}; + +enum { + GPIOMUX_FUNC_GPIO = 0UL << 2, + GPIOMUX_FUNC_1 = 1UL << 2, + GPIOMUX_FUNC_2 = 2UL << 2, + GPIOMUX_FUNC_3 = 3UL << 2, + GPIOMUX_FUNC_4 = 4UL << 2, + GPIOMUX_FUNC_5 = 5UL << 2, + GPIOMUX_FUNC_6 = 6UL << 2, + GPIOMUX_FUNC_7 = 7UL << 2, + GPIOMUX_FUNC_8 = 8UL << 2, + GPIOMUX_FUNC_9 = 9UL << 2, + GPIOMUX_FUNC_A = 10UL << 2, + GPIOMUX_FUNC_B = 11UL << 2, + GPIOMUX_FUNC_C = 12UL << 2, + GPIOMUX_FUNC_D = 13UL << 2, + GPIOMUX_FUNC_E = 14UL << 2, + GPIOMUX_FUNC_F = 15UL << 2, +}; + +enum { + GPIOMUX_PULL_NONE = 0UL, + GPIOMUX_PULL_DOWN = 1UL, + GPIOMUX_PULL_KEEPER = 2UL, + GPIOMUX_PULL_UP = 3UL, +}; + +#endif diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c new file mode 100644 index 00000000..53af21ab --- /dev/null +++ b/arch/arm/mach-msm/gpiomux.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#include <linux/module.h> +#include <linux/spinlock.h> +#include "gpiomux.h" + +static DEFINE_SPINLOCK(gpiomux_lock); + +int msm_gpiomux_write(unsigned gpio, + gpiomux_config_t active, + gpiomux_config_t suspended) +{ + struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio; + unsigned long irq_flags; + gpiomux_config_t setting; + + if (gpio >= GPIOMUX_NGPIOS) + return -EINVAL; + + spin_lock_irqsave(&gpiomux_lock, irq_flags); + + if (active & GPIOMUX_VALID) + cfg->active = active; + + if (suspended & GPIOMUX_VALID) + cfg->suspended = suspended; + + setting = cfg->ref ? active : suspended; + if (setting & GPIOMUX_VALID) + __msm_gpiomux_write(gpio, setting); + + spin_unlock_irqrestore(&gpiomux_lock, irq_flags); + return 0; +} +EXPORT_SYMBOL(msm_gpiomux_write); + +int msm_gpiomux_get(unsigned gpio) +{ + struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio; + unsigned long irq_flags; + + if (gpio >= GPIOMUX_NGPIOS) + return -EINVAL; + + spin_lock_irqsave(&gpiomux_lock, irq_flags); + if (cfg->ref++ == 0 && cfg->active & GPIOMUX_VALID) + __msm_gpiomux_write(gpio, cfg->active); + spin_unlock_irqrestore(&gpiomux_lock, irq_flags); + return 0; +} +EXPORT_SYMBOL(msm_gpiomux_get); + +int msm_gpiomux_put(unsigned gpio) +{ + struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio; + unsigned long irq_flags; + + if (gpio >= GPIOMUX_NGPIOS) + return -EINVAL; + + spin_lock_irqsave(&gpiomux_lock, irq_flags); + BUG_ON(cfg->ref == 0); + if (--cfg->ref == 0 && cfg->suspended & GPIOMUX_VALID) + __msm_gpiomux_write(gpio, cfg->suspended); + spin_unlock_irqrestore(&gpiomux_lock, irq_flags); + return 0; +} +EXPORT_SYMBOL(msm_gpiomux_put); + +static int __init gpiomux_init(void) +{ + unsigned n; + + for (n = 0; n < GPIOMUX_NGPIOS; ++n) { + msm_gpiomux_configs[n].ref = 0; + if (!(msm_gpiomux_configs[n].suspended & GPIOMUX_VALID)) + continue; + __msm_gpiomux_write(n, msm_gpiomux_configs[n].suspended); + } + return 0; +} +postcore_initcall(gpiomux_init); diff --git a/arch/arm/mach-msm/gpiomux.h b/arch/arm/mach-msm/gpiomux.h new file mode 100644 index 00000000..00459f6e --- /dev/null +++ b/arch/arm/mach-msm/gpiomux.h @@ -0,0 +1,99 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_H +#define __ARCH_ARM_MACH_MSM_GPIOMUX_H + +#include <linux/bitops.h> +#include <linux/errno.h> +#include <mach/msm_gpiomux.h> + +#if defined(CONFIG_MSM_V2_TLMM) +#include "gpiomux-v2.h" +#else +#include "gpiomux-v1.h" +#endif + +/** + * struct msm_gpiomux_config: gpiomux settings for one gpio line. + * + * A complete gpiomux config is the bitwise-or of a drive-strength, + * function, and pull. For functions other than GPIO, the OE + * is hard-wired according to the function. For GPIO mode, + * OE is controlled by gpiolib. + * + * Available settings differ by target; see the gpiomux header + * specific to your target arch for available configurations. + * + * @active: The configuration to be installed when the line is + * active, or its reference count is > 0. + * @suspended: The configuration to be installed when the line + * is suspended, or its reference count is 0. + * @ref: The reference count of the line. For internal use of + * the gpiomux framework only. + */ +struct msm_gpiomux_config { + gpiomux_config_t active; + gpiomux_config_t suspended; + unsigned ref; +}; + +/** + * @GPIOMUX_VALID: If set, the config field contains 'good data'. + * The absence of this bit will prevent the gpiomux + * system from applying the configuration under all + * circumstances. + */ +enum { + GPIOMUX_VALID = BIT(sizeof(gpiomux_config_t) * BITS_PER_BYTE - 1), + GPIOMUX_CTL_MASK = GPIOMUX_VALID, +}; + +#ifdef CONFIG_MSM_GPIOMUX + +/* Each architecture must provide its own instance of this table. + * To avoid having gpiomux manage any given gpio, one or both of + * the entries can avoid setting GPIOMUX_VALID - the absence + * of that flag will prevent the configuration from being applied + * during state transitions. + */ +extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS]; + +/* Install a new configuration to the gpio line. To avoid overwriting + * a configuration, leave the VALID bit out. + */ +int msm_gpiomux_write(unsigned gpio, + gpiomux_config_t active, + gpiomux_config_t suspended); + +/* Architecture-internal function for use by the framework only. + * This function can assume the following: + * - the gpio value has passed a bounds-check + * - the gpiomux spinlock has been obtained + * + * This function is not for public consumption. External users + * should use msm_gpiomux_write. + */ +void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val); +#else +static inline int msm_gpiomux_write(unsigned gpio, + gpiomux_config_t active, + gpiomux_config_t suspended) +{ + return -ENOSYS; +} +#endif +#endif diff --git a/arch/arm/mach-msm/headsmp.S b/arch/arm/mach-msm/headsmp.S new file mode 100644 index 00000000..bcd5af22 --- /dev/null +++ b/arch/arm/mach-msm/headsmp.S @@ -0,0 +1,41 @@ +/* + * linux/arch/arm/mach-realview/headsmp.S + * + * Copyright (c) 2003 ARM Limited + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/linkage.h> +#include <linux/init.h> + + __CPUINIT + +/* + * MSM specific entry point for secondary CPUs. This provides + * a "holding pen" into which all secondary cores are held until we're + * ready for them to initialise. + */ +ENTRY(msm_secondary_startup) + mrc p15, 0, r0, c0, c0, 5 + and r0, r0, #15 + adr r4, 1f + ldmia r4, {r5, r6} + sub r4, r4, r5 + add r6, r6, r4 +pen: ldr r7, [r6] + cmp r7, r0 + bne pen + + /* + * we've been released from the holding pen: secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup +ENDPROC(msm_secondary_startup) + + .align +1: .long . + .long pen_release diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c new file mode 100644 index 00000000..a446fc14 --- /dev/null +++ b/arch/arm/mach-msm/hotplug.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/smp.h> + +#include <asm/cacheflush.h> +#include <asm/smp_plat.h> + +extern volatile int pen_release; + +static inline void cpu_enter_lowpower(void) +{ + /* Just flush the cache. Changing the coherency is not yet + * available on msm. */ + flush_cache_all(); +} + +static inline void cpu_leave_lowpower(void) +{ +} + +static inline void platform_do_lowpower(unsigned int cpu) +{ + /* Just enter wfi for now. TODO: Properly shut off the cpu. */ + for (;;) { + /* + * here's the WFI + */ + asm("wfi" + : + : + : "memory", "cc"); + + if (pen_release == cpu_logical_map(cpu)) { + /* + * OK, proper wakeup, we're done + */ + break; + } + + /* + * getting here, means that we have come out of WFI without + * having been woken up - this shouldn't happen + * + * The trouble is, letting people know about this is not really + * possible, since we are currently running incoherently, and + * therefore cannot safely call printk() or anything else + */ + pr_debug("CPU%u: spurious wakeup call\n", cpu); + } +} + +int platform_cpu_kill(unsigned int cpu) +{ + return 1; +} + +/* + * platform-specific code to shutdown a CPU + * + * Called with IRQs disabled + */ +void platform_cpu_die(unsigned int cpu) +{ + /* + * we're ready for shutdown now, so do it + */ + cpu_enter_lowpower(); + platform_do_lowpower(cpu); + + /* + * bring this CPU back into the world of cache + * coherency, and then restore interrupts + */ + cpu_leave_lowpower(); +} + +int platform_cpu_disable(unsigned int cpu) +{ + /* + * we don't allow CPU 0 to be shutdown (it is still too special + * e.g. clock tick interrupts) + */ + return cpu == 0 ? -EPERM : 0; +} diff --git a/arch/arm/mach-msm/idle.c b/arch/arm/mach-msm/idle.c new file mode 100644 index 00000000..0c9e13c6 --- /dev/null +++ b/arch/arm/mach-msm/idle.c @@ -0,0 +1,49 @@ +/* arch/arm/mach-msm/idle.c + * + * Idle processing for MSM7K - work around bugs with SWFI. + * + * Copyright (c) 2007 QUALCOMM Incorporated. + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/init.h> +#include <asm/system.h> + +static void msm_idle(void) +{ +#ifdef CONFIG_MSM7X00A_IDLE + asm volatile ( + + "mrc p15, 0, r1, c1, c0, 0 /* read current CR */ \n\t" + "bic r0, r1, #(1 << 2) /* clear dcache bit */ \n\t" + "bic r0, r0, #(1 << 12) /* clear icache bit */ \n\t" + "mcr p15, 0, r0, c1, c0, 0 /* disable d/i cache */ \n\t" + + "mov r0, #0 /* prepare wfi value */ \n\t" + "mcr p15, 0, r0, c7, c10, 0 /* flush the cache */ \n\t" + "mcr p15, 0, r0, c7, c10, 4 /* memory barrier */ \n\t" + "mcr p15, 0, r0, c7, c0, 4 /* wait for interrupt */ \n\t" + + "mcr p15, 0, r1, c1, c0, 0 /* restore d/i cache */ \n\t" + + : : : "r0","r1" ); +#endif +} + +static int __init msm_idle_init(void) +{ + arm_pm_idle = msm_idle; + return 0; +} + +arch_initcall(msm_idle_init); diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h new file mode 100644 index 00000000..2ce8f1f2 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/board.h @@ -0,0 +1,50 @@ +/* arch/arm/mach-msm/include/mach/board.h + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_BOARD_H +#define __ASM_ARCH_MSM_BOARD_H + +#include <linux/types.h> +#include <mach/mmc.h> + +/* platform device data structures */ + +struct msm_acpu_clock_platform_data +{ + uint32_t acpu_switch_time_us; + uint32_t max_speed_delta_khz; + uint32_t vdd_switch_time_us; + unsigned long power_collapse_khz; + unsigned long wait_for_irq_khz; +}; + +struct clk_lookup; + +extern struct sys_timer msm_timer; + +/* common init routines for use by arch/arm/mach-msm/board-*.c */ + +void __init msm_add_devices(void); +void __init msm_map_common_io(void); +void __init msm_init_irq(void); +void __init msm_init_gpio(void); +void __init msm_clock_init(struct clk_lookup *clock_tbl, unsigned num_clocks); +void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *); +int __init msm_add_sdcc(unsigned int controller, + struct msm_mmc_platform_data *plat, + unsigned int stat_irq, unsigned long stat_irq_flags); + +#endif diff --git a/arch/arm/mach-msm/include/mach/clk.h b/arch/arm/mach-msm/include/mach/clk.h new file mode 100644 index 00000000..e8d38428 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/clk.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __MACH_CLK_H +#define __MACH_CLK_H + +/* Magic rate value for use with PM QOS to request the board's maximum + * supported AXI rate. PM QOS will only pass positive s32 rate values + * through to the clock driver, so INT_MAX is used. + */ +#define MSM_AXI_MAX_FREQ LONG_MAX + +enum clk_reset_action { + CLK_RESET_DEASSERT = 0, + CLK_RESET_ASSERT = 1 +}; + +struct clk; + +/* Rate is minimum clock rate in Hz */ +int clk_set_min_rate(struct clk *clk, unsigned long rate); + +/* Rate is maximum clock rate in Hz */ +int clk_set_max_rate(struct clk *clk, unsigned long rate); + +/* Assert/Deassert reset to a hardware block associated with a clock */ +int clk_reset(struct clk *clk, enum clk_reset_action action); + +/* Set clock-specific configuration parameters */ +int clk_set_flags(struct clk *clk, unsigned long flags); + +#endif diff --git a/arch/arm/mach-msm/include/mach/cpu.h b/arch/arm/mach-msm/include/mach/cpu.h new file mode 100644 index 00000000..a9481b08 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/cpu.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ARCH_ARM_MACH_MSM_CPU_H__ +#define __ARCH_ARM_MACH_MSM_CPU_H__ + +/* TODO: For now, only one CPU can be compiled at a time. */ + +#define cpu_is_msm7x01() 0 +#define cpu_is_msm7x30() 0 +#define cpu_is_qsd8x50() 0 +#define cpu_is_msm8x60() 0 +#define cpu_is_msm8960() 0 + +#ifdef CONFIG_ARCH_MSM7X00A +# undef cpu_is_msm7x01 +# define cpu_is_msm7x01() 1 +#endif + +#ifdef CONFIG_ARCH_MSM7X30 +# undef cpu_is_msm7x30 +# define cpu_is_msm7x30() 1 +#endif + +#ifdef CONFIG_ARCH_QSD8X50 +# undef cpu_is_qsd8x50 +# define cpu_is_qsd8x50() 1 +#endif + +#ifdef CONFIG_ARCH_MSM8X60 +# undef cpu_is_msm8x60 +# define cpu_is_msm8x60() 1 +#endif + +#ifdef CONFIG_ARCH_MSM8960 +# undef cpu_is_msm8960 +# define cpu_is_msm8960() 1 +#endif + +#endif diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S new file mode 100644 index 00000000..3ffd8668 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/debug-macro.S @@ -0,0 +1,66 @@ +/* + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <mach/hardware.h> +#include <mach/msm_iomap.h> + + .macro addruart, rp, rv, tmp +#ifdef MSM_DEBUG_UART_PHYS + ldr \rp, =MSM_DEBUG_UART_PHYS + ldr \rv, =MSM_DEBUG_UART_BASE +#endif + .endm + + .macro senduart, rd, rx +#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS + @ Write the 1 character to UARTDM_TF + str \rd, [\rx, #0x70] +#else + teq \rx, #0 + strne \rd, [\rx, #0x0C] +#endif + .endm + + .macro waituart, rd, rx +#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS + @ check for TX_EMT in UARTDM_SR + ldr \rd, [\rx, #0x08] + tst \rd, #0x08 + bne 1002f + @ wait for TXREADY in UARTDM_ISR +1001: ldr \rd, [\rx, #0x14] + tst \rd, #0x80 + beq 1001b +1002: + @ Clear TX_READY by writing to the UARTDM_CR register + mov \rd, #0x300 + str \rd, [\rx, #0x10] + @ Write 0x1 to NCF register + mov \rd, #0x1 + str \rd, [\rx, #0x40] + @ UARTDM reg. Read to induce delay + ldr \rd, [\rx, #0x08] +#else + @ wait for TX_READY +1001: ldr \rd, [\rx, #0x08] + tst \rd, #0x04 + beq 1001b +#endif + .endm + + .macro busyuart, rd, rx + .endm diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h new file mode 100644 index 00000000..05583f56 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/dma.h @@ -0,0 +1,177 @@ +/* linux/include/asm-arm/arch-msm/dma.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_DMA_H + +#include <linux/list.h> +#include <mach/msm_iomap.h> + +struct msm_dmov_errdata { + uint32_t flush[6]; +}; + +struct msm_dmov_cmd { + struct list_head list; + unsigned int cmdptr; + void (*complete_func)(struct msm_dmov_cmd *cmd, + unsigned int result, + struct msm_dmov_errdata *err); + void (*execute_func)(struct msm_dmov_cmd *cmd); + void *data; +}; + +#ifndef CONFIG_ARCH_MSM8X60 +void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd); +void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful); +int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr); +#else +static inline +void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) { } +static inline +void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful) { } +static inline +int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) { return -EIO; } +#endif + + +#define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2)) +#define DMOV_SD1(off, ch) (MSM_DMOV_BASE + 0x0400 + (off) + ((ch) << 2)) +#define DMOV_SD2(off, ch) (MSM_DMOV_BASE + 0x0800 + (off) + ((ch) << 2)) +#define DMOV_SD3(off, ch) (MSM_DMOV_BASE + 0x0C00 + (off) + ((ch) << 2)) + +#if defined(CONFIG_ARCH_MSM7X30) +#define DMOV_SD_AARM DMOV_SD2 +#else +#define DMOV_SD_AARM DMOV_SD3 +#endif + +#define DMOV_CMD_PTR(ch) DMOV_SD_AARM(0x000, ch) +#define DMOV_CMD_LIST (0 << 29) /* does not work */ +#define DMOV_CMD_PTR_LIST (1 << 29) /* works */ +#define DMOV_CMD_INPUT_CFG (2 << 29) /* untested */ +#define DMOV_CMD_OUTPUT_CFG (3 << 29) /* untested */ +#define DMOV_CMD_ADDR(addr) ((addr) >> 3) + +#define DMOV_RSLT(ch) DMOV_SD_AARM(0x040, ch) +#define DMOV_RSLT_VALID (1 << 31) /* 0 == host has empties result fifo */ +#define DMOV_RSLT_ERROR (1 << 3) +#define DMOV_RSLT_FLUSH (1 << 2) +#define DMOV_RSLT_DONE (1 << 1) /* top pointer done */ +#define DMOV_RSLT_USER (1 << 0) /* command with FR force result */ + +#define DMOV_FLUSH0(ch) DMOV_SD_AARM(0x080, ch) +#define DMOV_FLUSH1(ch) DMOV_SD_AARM(0x0C0, ch) +#define DMOV_FLUSH2(ch) DMOV_SD_AARM(0x100, ch) +#define DMOV_FLUSH3(ch) DMOV_SD_AARM(0x140, ch) +#define DMOV_FLUSH4(ch) DMOV_SD_AARM(0x180, ch) +#define DMOV_FLUSH5(ch) DMOV_SD_AARM(0x1C0, ch) + +#define DMOV_STATUS(ch) DMOV_SD_AARM(0x200, ch) +#define DMOV_STATUS_RSLT_COUNT(n) (((n) >> 29)) +#define DMOV_STATUS_CMD_COUNT(n) (((n) >> 27) & 3) +#define DMOV_STATUS_RSLT_VALID (1 << 1) +#define DMOV_STATUS_CMD_PTR_RDY (1 << 0) + +#define DMOV_ISR DMOV_SD_AARM(0x380, 0) + +#define DMOV_CONFIG(ch) DMOV_SD_AARM(0x300, ch) +#define DMOV_CONFIG_FORCE_TOP_PTR_RSLT (1 << 2) +#define DMOV_CONFIG_FORCE_FLUSH_RSLT (1 << 1) +#define DMOV_CONFIG_IRQ_EN (1 << 0) + +/* channel assignments */ + +#define DMOV_NAND_CHAN 7 +#define DMOV_NAND_CRCI_CMD 5 +#define DMOV_NAND_CRCI_DATA 4 + +#define DMOV_SDC1_CHAN 8 +#define DMOV_SDC1_CRCI 6 + +#define DMOV_SDC2_CHAN 8 +#define DMOV_SDC2_CRCI 7 + +#define DMOV_TSIF_CHAN 10 +#define DMOV_TSIF_CRCI 10 + +#define DMOV_USB_CHAN 11 + +/* no client rate control ifc (eg, ram) */ +#define DMOV_NONE_CRCI 0 + + +/* If the CMD_PTR register has CMD_PTR_LIST selected, the data mover + * is going to walk a list of 32bit pointers as described below. Each + * pointer points to a *array* of dmov_s, etc structs. The last pointer + * in the list is marked with CMD_PTR_LP. The last struct in each array + * is marked with CMD_LC (see below). + */ +#define CMD_PTR_ADDR(addr) ((addr) >> 3) +#define CMD_PTR_LP (1 << 31) /* last pointer */ +#define CMD_PTR_PT (3 << 29) /* ? */ + +/* Single Item Mode */ +typedef struct { + unsigned cmd; + unsigned src; + unsigned dst; + unsigned len; +} dmov_s; + +/* Scatter/Gather Mode */ +typedef struct { + unsigned cmd; + unsigned src_dscr; + unsigned dst_dscr; + unsigned _reserved; +} dmov_sg; + +/* Box mode */ +typedef struct { + uint32_t cmd; + uint32_t src_row_addr; + uint32_t dst_row_addr; + uint32_t src_dst_len; + uint32_t num_rows; + uint32_t row_offset; +} dmov_box; + +/* bits for the cmd field of the above structures */ + +#define CMD_LC (1 << 31) /* last command */ +#define CMD_FR (1 << 22) /* force result -- does not work? */ +#define CMD_OCU (1 << 21) /* other channel unblock */ +#define CMD_OCB (1 << 20) /* other channel block */ +#define CMD_TCB (1 << 19) /* ? */ +#define CMD_DAH (1 << 18) /* destination address hold -- does not work?*/ +#define CMD_SAH (1 << 17) /* source address hold -- does not work? */ + +#define CMD_MODE_SINGLE (0 << 0) /* dmov_s structure used */ +#define CMD_MODE_SG (1 << 0) /* untested */ +#define CMD_MODE_IND_SG (2 << 0) /* untested */ +#define CMD_MODE_BOX (3 << 0) /* untested */ + +#define CMD_DST_SWAP_BYTES (1 << 14) /* exchange each byte n with byte n+1 */ +#define CMD_DST_SWAP_SHORTS (1 << 15) /* exchange each short n with short n+1 */ +#define CMD_DST_SWAP_WORDS (1 << 16) /* exchange each word n with word n+1 */ + +#define CMD_SRC_SWAP_BYTES (1 << 11) /* exchange each byte n with byte n+1 */ +#define CMD_SRC_SWAP_SHORTS (1 << 12) /* exchange each short n with short n+1 */ +#define CMD_SRC_SWAP_WORDS (1 << 13) /* exchange each word n with word n+1 */ + +#define CMD_DST_CRCI(n) (((n) & 15) << 7) +#define CMD_SRC_CRCI(n) (((n) & 15) << 3) + +#endif diff --git a/arch/arm/mach-msm/include/mach/entry-macro.S b/arch/arm/mach-msm/include/mach/entry-macro.S new file mode 100644 index 00000000..f2ae9087 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/entry-macro.S @@ -0,0 +1,36 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#if !defined(CONFIG_ARM_GIC) +#include <mach/msm_iomap.h> + + .macro get_irqnr_preamble, base, tmp + @ enable imprecise aborts + cpsie a + mov \base, #MSM_VIC_BASE + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + @ 0xD0 has irq# or old irq# if the irq has been handled + @ 0xD4 has irq# or -1 if none pending *but* if you just + @ read 0xD4 you never get the first irq for some reason + ldr \irqnr, [\base, #0xD0] + ldr \irqnr, [\base, #0xD4] + cmp \irqnr, #0xffffffff + .endm +#endif diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h new file mode 100644 index 00000000..40a8c178 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/gpio.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/arm/mach-msm/include/mach/hardware.h b/arch/arm/mach-msm/include/mach/hardware.h new file mode 100644 index 00000000..2d126091 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/hardware.h @@ -0,0 +1,18 @@ +/* arch/arm/mach-msm/include/mach/hardware.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_HARDWARE_H + +#endif diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h new file mode 100644 index 00000000..5c7c955e --- /dev/null +++ b/arch/arm/mach-msm/include/mach/iommu.h @@ -0,0 +1,120 @@ +/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef MSM_IOMMU_H +#define MSM_IOMMU_H + +#include <linux/interrupt.h> +#include <linux/clk.h> + +/* Sharability attributes of MSM IOMMU mappings */ +#define MSM_IOMMU_ATTR_NON_SH 0x0 +#define MSM_IOMMU_ATTR_SH 0x4 + +/* Cacheability attributes of MSM IOMMU mappings */ +#define MSM_IOMMU_ATTR_NONCACHED 0x0 +#define MSM_IOMMU_ATTR_CACHED_WB_WA 0x1 +#define MSM_IOMMU_ATTR_CACHED_WB_NWA 0x2 +#define MSM_IOMMU_ATTR_CACHED_WT 0x3 + +/* Mask for the cache policy attribute */ +#define MSM_IOMMU_CP_MASK 0x03 + +/* Maximum number of Machine IDs that we are allowing to be mapped to the same + * context bank. The number of MIDs mapped to the same CB does not affect + * performance, but there is a practical limit on how many distinct MIDs may + * be present. These mappings are typically determined at design time and are + * not expected to change at run time. + */ +#define MAX_NUM_MIDS 32 + +/** + * struct msm_iommu_dev - a single IOMMU hardware instance + * name Human-readable name given to this IOMMU HW instance + * ncb Number of context banks present on this IOMMU HW instance + */ +struct msm_iommu_dev { + const char *name; + int ncb; +}; + +/** + * struct msm_iommu_ctx_dev - an IOMMU context bank instance + * name Human-readable name given to this context bank + * num Index of this context bank within the hardware + * mids List of Machine IDs that are to be mapped into this context + * bank, terminated by -1. The MID is a set of signals on the + * AXI bus that identifies the function associated with a specific + * memory request. (See ARM spec). + */ +struct msm_iommu_ctx_dev { + const char *name; + int num; + int mids[MAX_NUM_MIDS]; +}; + + +/** + * struct msm_iommu_drvdata - A single IOMMU hardware instance + * @base: IOMMU config port base address (VA) + * @ncb The number of contexts on this IOMMU + * @irq: Interrupt number + * @clk: The bus clock for this IOMMU hardware instance + * @pclk: The clock for the IOMMU bus interconnect + * + * A msm_iommu_drvdata holds the global driver data about a single piece + * of an IOMMU hardware instance. + */ +struct msm_iommu_drvdata { + void __iomem *base; + int irq; + int ncb; + struct clk *clk; + struct clk *pclk; +}; + +/** + * struct msm_iommu_ctx_drvdata - an IOMMU context bank instance + * @num: Hardware context number of this context + * @pdev: Platform device associated wit this HW instance + * @attached_elm: List element for domains to track which devices are + * attached to them + * + * A msm_iommu_ctx_drvdata holds the driver data for a single context bank + * within each IOMMU hardware instance + */ +struct msm_iommu_ctx_drvdata { + int num; + struct platform_device *pdev; + struct list_head attached_elm; +}; + +/* + * Look up an IOMMU context device by its context name. NULL if none found. + * Useful for testing and drivers that do not yet fully have IOMMU stuff in + * their platform devices. + */ +struct device *msm_iommu_get_ctx(const char *ctx_name); + +/* + * Interrupt handler for the IOMMU context fault interrupt. Hooking the + * interrupt is not supported in the API yet, but this will print an error + * message and dump useful IOMMU registers. + */ +irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id); + +#endif diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h new file mode 100644 index 00000000..fc160101 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h @@ -0,0 +1,1865 @@ +/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H +#define __ARCH_ARM_MACH_MSM_IOMMU_HW_8XXX_H + +#define CTX_SHIFT 12 + +#define GET_GLOBAL_REG(reg, base) (readl((base) + (reg))) +#define GET_CTX_REG(reg, base, ctx) \ + (readl((base) + (reg) + ((ctx) << CTX_SHIFT))) + +#define SET_GLOBAL_REG(reg, base, val) writel((val), ((base) + (reg))) + +#define SET_CTX_REG(reg, base, ctx, val) \ + writel((val), ((base) + (reg) + ((ctx) << CTX_SHIFT))) + +/* Wrappers for numbered registers */ +#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG(b, ((r) + (n << 2)), (v)) +#define GET_GLOBAL_REG_N(b, n, r) GET_GLOBAL_REG(b, ((r) + (n << 2))) + +/* Field wrappers */ +#define GET_GLOBAL_FIELD(b, r, F) GET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT) +#define GET_CONTEXT_FIELD(b, c, r, F) \ + GET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT) + +#define SET_GLOBAL_FIELD(b, r, F, v) \ + SET_FIELD(((b) + (r)), F##_MASK, F##_SHIFT, (v)) +#define SET_CONTEXT_FIELD(b, c, r, F, v) \ + SET_FIELD(((b) + (r) + ((c) << CTX_SHIFT)), F##_MASK, F##_SHIFT, (v)) + +#define GET_FIELD(addr, mask, shift) ((readl(addr) >> (shift)) & (mask)) + +#define SET_FIELD(addr, mask, shift, v) \ +do { \ + int t = readl(addr); \ + writel((t & ~((mask) << (shift))) + (((v) & (mask)) << (shift)), addr);\ +} while (0) + + +#define NUM_FL_PTE 4096 +#define NUM_SL_PTE 256 +#define NUM_TEX_CLASS 8 + +/* First-level page table bits */ +#define FL_BASE_MASK 0xFFFFFC00 +#define FL_TYPE_TABLE (1 << 0) +#define FL_TYPE_SECT (2 << 0) +#define FL_SUPERSECTION (1 << 18) +#define FL_AP_WRITE (1 << 10) +#define FL_AP_READ (1 << 11) +#define FL_SHARED (1 << 16) +#define FL_BUFFERABLE (1 << 2) +#define FL_CACHEABLE (1 << 3) +#define FL_TEX0 (1 << 12) +#define FL_OFFSET(va) (((va) & 0xFFF00000) >> 20) +#define FL_NG (1 << 17) + +/* Second-level page table bits */ +#define SL_BASE_MASK_LARGE 0xFFFF0000 +#define SL_BASE_MASK_SMALL 0xFFFFF000 +#define SL_TYPE_LARGE (1 << 0) +#define SL_TYPE_SMALL (2 << 0) +#define SL_AP0 (1 << 4) +#define SL_AP1 (2 << 4) +#define SL_SHARED (1 << 10) +#define SL_BUFFERABLE (1 << 2) +#define SL_CACHEABLE (1 << 3) +#define SL_TEX0 (1 << 6) +#define SL_OFFSET(va) (((va) & 0xFF000) >> 12) +#define SL_NG (1 << 11) + +/* Memory type and cache policy attributes */ +#define MT_SO 0 +#define MT_DEV 1 +#define MT_NORMAL 2 +#define CP_NONCACHED 0 +#define CP_WB_WA 1 +#define CP_WT 2 +#define CP_WB_NWA 3 + +/* Global register setters / getters */ +#define SET_M2VCBR_N(b, N, v) SET_GLOBAL_REG_N(M2VCBR_N, N, (b), (v)) +#define SET_CBACR_N(b, N, v) SET_GLOBAL_REG_N(CBACR_N, N, (b), (v)) +#define SET_TLBRSW(b, v) SET_GLOBAL_REG(TLBRSW, (b), (v)) +#define SET_TLBTR0(b, v) SET_GLOBAL_REG(TLBTR0, (b), (v)) +#define SET_TLBTR1(b, v) SET_GLOBAL_REG(TLBTR1, (b), (v)) +#define SET_TLBTR2(b, v) SET_GLOBAL_REG(TLBTR2, (b), (v)) +#define SET_TESTBUSCR(b, v) SET_GLOBAL_REG(TESTBUSCR, (b), (v)) +#define SET_GLOBAL_TLBIALL(b, v) SET_GLOBAL_REG(GLOBAL_TLBIALL, (b), (v)) +#define SET_TLBIVMID(b, v) SET_GLOBAL_REG(TLBIVMID, (b), (v)) +#define SET_CR(b, v) SET_GLOBAL_REG(CR, (b), (v)) +#define SET_EAR(b, v) SET_GLOBAL_REG(EAR, (b), (v)) +#define SET_ESR(b, v) SET_GLOBAL_REG(ESR, (b), (v)) +#define SET_ESRRESTORE(b, v) SET_GLOBAL_REG(ESRRESTORE, (b), (v)) +#define SET_ESYNR0(b, v) SET_GLOBAL_REG(ESYNR0, (b), (v)) +#define SET_ESYNR1(b, v) SET_GLOBAL_REG(ESYNR1, (b), (v)) +#define SET_RPU_ACR(b, v) SET_GLOBAL_REG(RPU_ACR, (b), (v)) + +#define GET_M2VCBR_N(b, N) GET_GLOBAL_REG_N(M2VCBR_N, N, (b)) +#define GET_CBACR_N(b, N) GET_GLOBAL_REG_N(CBACR_N, N, (b)) +#define GET_TLBTR0(b) GET_GLOBAL_REG(TLBTR0, (b)) +#define GET_TLBTR1(b) GET_GLOBAL_REG(TLBTR1, (b)) +#define GET_TLBTR2(b) GET_GLOBAL_REG(TLBTR2, (b)) +#define GET_TESTBUSCR(b) GET_GLOBAL_REG(TESTBUSCR, (b)) +#define GET_GLOBAL_TLBIALL(b) GET_GLOBAL_REG(GLOBAL_TLBIALL, (b)) +#define GET_TLBIVMID(b) GET_GLOBAL_REG(TLBIVMID, (b)) +#define GET_CR(b) GET_GLOBAL_REG(CR, (b)) +#define GET_EAR(b) GET_GLOBAL_REG(EAR, (b)) +#define GET_ESR(b) GET_GLOBAL_REG(ESR, (b)) +#define GET_ESRRESTORE(b) GET_GLOBAL_REG(ESRRESTORE, (b)) +#define GET_ESYNR0(b) GET_GLOBAL_REG(ESYNR0, (b)) +#define GET_ESYNR1(b) GET_GLOBAL_REG(ESYNR1, (b)) +#define GET_REV(b) GET_GLOBAL_REG(REV, (b)) +#define GET_IDR(b) GET_GLOBAL_REG(IDR, (b)) +#define GET_RPU_ACR(b) GET_GLOBAL_REG(RPU_ACR, (b)) + + +/* Context register setters/getters */ +#define SET_SCTLR(b, c, v) SET_CTX_REG(SCTLR, (b), (c), (v)) +#define SET_ACTLR(b, c, v) SET_CTX_REG(ACTLR, (b), (c), (v)) +#define SET_CONTEXTIDR(b, c, v) SET_CTX_REG(CONTEXTIDR, (b), (c), (v)) +#define SET_TTBR0(b, c, v) SET_CTX_REG(TTBR0, (b), (c), (v)) +#define SET_TTBR1(b, c, v) SET_CTX_REG(TTBR1, (b), (c), (v)) +#define SET_TTBCR(b, c, v) SET_CTX_REG(TTBCR, (b), (c), (v)) +#define SET_PAR(b, c, v) SET_CTX_REG(PAR, (b), (c), (v)) +#define SET_FSR(b, c, v) SET_CTX_REG(FSR, (b), (c), (v)) +#define SET_FSRRESTORE(b, c, v) SET_CTX_REG(FSRRESTORE, (b), (c), (v)) +#define SET_FAR(b, c, v) SET_CTX_REG(FAR, (b), (c), (v)) +#define SET_FSYNR0(b, c, v) SET_CTX_REG(FSYNR0, (b), (c), (v)) +#define SET_FSYNR1(b, c, v) SET_CTX_REG(FSYNR1, (b), (c), (v)) +#define SET_PRRR(b, c, v) SET_CTX_REG(PRRR, (b), (c), (v)) +#define SET_NMRR(b, c, v) SET_CTX_REG(NMRR, (b), (c), (v)) +#define SET_TLBLKCR(b, c, v) SET_CTX_REG(TLBLCKR, (b), (c), (v)) +#define SET_V2PSR(b, c, v) SET_CTX_REG(V2PSR, (b), (c), (v)) +#define SET_TLBFLPTER(b, c, v) SET_CTX_REG(TLBFLPTER, (b), (c), (v)) +#define SET_TLBSLPTER(b, c, v) SET_CTX_REG(TLBSLPTER, (b), (c), (v)) +#define SET_BFBCR(b, c, v) SET_CTX_REG(BFBCR, (b), (c), (v)) +#define SET_CTX_TLBIALL(b, c, v) SET_CTX_REG(CTX_TLBIALL, (b), (c), (v)) +#define SET_TLBIASID(b, c, v) SET_CTX_REG(TLBIASID, (b), (c), (v)) +#define SET_TLBIVA(b, c, v) SET_CTX_REG(TLBIVA, (b), (c), (v)) +#define SET_TLBIVAA(b, c, v) SET_CTX_REG(TLBIVAA, (b), (c), (v)) +#define SET_V2PPR(b, c, v) SET_CTX_REG(V2PPR, (b), (c), (v)) +#define SET_V2PPW(b, c, v) SET_CTX_REG(V2PPW, (b), (c), (v)) +#define SET_V2PUR(b, c, v) SET_CTX_REG(V2PUR, (b), (c), (v)) +#define SET_V2PUW(b, c, v) SET_CTX_REG(V2PUW, (b), (c), (v)) +#define SET_RESUME(b, c, v) SET_CTX_REG(RESUME, (b), (c), (v)) + +#define GET_SCTLR(b, c) GET_CTX_REG(SCTLR, (b), (c)) +#define GET_ACTLR(b, c) GET_CTX_REG(ACTLR, (b), (c)) +#define GET_CONTEXTIDR(b, c) GET_CTX_REG(CONTEXTIDR, (b), (c)) +#define GET_TTBR0(b, c) GET_CTX_REG(TTBR0, (b), (c)) +#define GET_TTBR1(b, c) GET_CTX_REG(TTBR1, (b), (c)) +#define GET_TTBCR(b, c) GET_CTX_REG(TTBCR, (b), (c)) +#define GET_PAR(b, c) GET_CTX_REG(PAR, (b), (c)) +#define GET_FSR(b, c) GET_CTX_REG(FSR, (b), (c)) +#define GET_FSRRESTORE(b, c) GET_CTX_REG(FSRRESTORE, (b), (c)) +#define GET_FAR(b, c) GET_CTX_REG(FAR, (b), (c)) +#define GET_FSYNR0(b, c) GET_CTX_REG(FSYNR0, (b), (c)) +#define GET_FSYNR1(b, c) GET_CTX_REG(FSYNR1, (b), (c)) +#define GET_PRRR(b, c) GET_CTX_REG(PRRR, (b), (c)) +#define GET_NMRR(b, c) GET_CTX_REG(NMRR, (b), (c)) +#define GET_TLBLCKR(b, c) GET_CTX_REG(TLBLCKR, (b), (c)) +#define GET_V2PSR(b, c) GET_CTX_REG(V2PSR, (b), (c)) +#define GET_TLBFLPTER(b, c) GET_CTX_REG(TLBFLPTER, (b), (c)) +#define GET_TLBSLPTER(b, c) GET_CTX_REG(TLBSLPTER, (b), (c)) +#define GET_BFBCR(b, c) GET_CTX_REG(BFBCR, (b), (c)) +#define GET_CTX_TLBIALL(b, c) GET_CTX_REG(CTX_TLBIALL, (b), (c)) +#define GET_TLBIASID(b, c) GET_CTX_REG(TLBIASID, (b), (c)) +#define GET_TLBIVA(b, c) GET_CTX_REG(TLBIVA, (b), (c)) +#define GET_TLBIVAA(b, c) GET_CTX_REG(TLBIVAA, (b), (c)) +#define GET_V2PPR(b, c) GET_CTX_REG(V2PPR, (b), (c)) +#define GET_V2PPW(b, c) GET_CTX_REG(V2PPW, (b), (c)) +#define GET_V2PUR(b, c) GET_CTX_REG(V2PUR, (b), (c)) +#define GET_V2PUW(b, c) GET_CTX_REG(V2PUW, (b), (c)) +#define GET_RESUME(b, c) GET_CTX_REG(RESUME, (b), (c)) + + +/* Global field setters / getters */ +/* Global Field Setters: */ +/* CBACR_N */ +#define SET_RWVMID(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID, v) +#define SET_RWE(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE, v) +#define SET_RWGE(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE, v) +#define SET_CBVMID(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID, v) +#define SET_IRPTNDX(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX, v) + + +/* M2VCBR_N */ +#define SET_VMID(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID, v) +#define SET_CBNDX(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX, v) +#define SET_BYPASSD(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD, v) +#define SET_BPRCOSH(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH, v) +#define SET_BPRCISH(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH, v) +#define SET_BPRCNSH(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH, v) +#define SET_BPSHCFG(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG, v) +#define SET_NSCFG(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG, v) +#define SET_BPMTCFG(b, n, v) SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG, v) +#define SET_BPMEMTYPE(b, n, v) \ + SET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE, v) + + +/* CR */ +#define SET_RPUE(b, v) SET_GLOBAL_FIELD(b, CR, RPUE, v) +#define SET_RPUERE(b, v) SET_GLOBAL_FIELD(b, CR, RPUERE, v) +#define SET_RPUEIE(b, v) SET_GLOBAL_FIELD(b, CR, RPUEIE, v) +#define SET_DCDEE(b, v) SET_GLOBAL_FIELD(b, CR, DCDEE, v) +#define SET_CLIENTPD(b, v) SET_GLOBAL_FIELD(b, CR, CLIENTPD, v) +#define SET_STALLD(b, v) SET_GLOBAL_FIELD(b, CR, STALLD, v) +#define SET_TLBLKCRWE(b, v) SET_GLOBAL_FIELD(b, CR, TLBLKCRWE, v) +#define SET_CR_TLBIALLCFG(b, v) SET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG, v) +#define SET_TLBIVMIDCFG(b, v) SET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG, v) +#define SET_CR_HUME(b, v) SET_GLOBAL_FIELD(b, CR, CR_HUME, v) + + +/* ESR */ +#define SET_CFG(b, v) SET_GLOBAL_FIELD(b, ESR, CFG, v) +#define SET_BYPASS(b, v) SET_GLOBAL_FIELD(b, ESR, BYPASS, v) +#define SET_ESR_MULTI(b, v) SET_GLOBAL_FIELD(b, ESR, ESR_MULTI, v) + + +/* ESYNR0 */ +#define SET_ESYNR0_AMID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID, v) +#define SET_ESYNR0_APID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID, v) +#define SET_ESYNR0_ABID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID, v) +#define SET_ESYNR0_AVMID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID, v) +#define SET_ESYNR0_ATID(b, v) SET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID, v) + + +/* ESYNR1 */ +#define SET_ESYNR1_AMEMTYPE(b, v) \ + SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE, v) +#define SET_ESYNR1_ASHARED(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED, v) +#define SET_ESYNR1_AINNERSHARED(b, v) \ + SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED, v) +#define SET_ESYNR1_APRIV(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV, v) +#define SET_ESYNR1_APROTNS(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS, v) +#define SET_ESYNR1_AINST(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST, v) +#define SET_ESYNR1_AWRITE(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE, v) +#define SET_ESYNR1_ABURST(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST, v) +#define SET_ESYNR1_ALEN(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN, v) +#define SET_ESYNR1_ASIZE(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE, v) +#define SET_ESYNR1_ALOCK(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK, v) +#define SET_ESYNR1_AOOO(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO, v) +#define SET_ESYNR1_AFULL(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL, v) +#define SET_ESYNR1_AC(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC, v) +#define SET_ESYNR1_DCD(b, v) SET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD, v) + + +/* TESTBUSCR */ +#define SET_TBE(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, TBE, v) +#define SET_SPDMBE(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE, v) +#define SET_WGSEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL, v) +#define SET_TBLSEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL, v) +#define SET_TBHSEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL, v) +#define SET_SPDM0SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL, v) +#define SET_SPDM1SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL, v) +#define SET_SPDM2SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL, v) +#define SET_SPDM3SEL(b, v) SET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL, v) + + +/* TLBIVMID */ +#define SET_TLBIVMID_VMID(b, v) SET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID, v) + + +/* TLBRSW */ +#define SET_TLBRSW_INDEX(b, v) SET_GLOBAL_FIELD(b, TLBRSW, TLBRSW_INDEX, v) +#define SET_TLBBFBS(b, v) SET_GLOBAL_FIELD(b, TLBRSW, TLBBFBS, v) + + +/* TLBTR0 */ +#define SET_PR(b, v) SET_GLOBAL_FIELD(b, TLBTR0, PR, v) +#define SET_PW(b, v) SET_GLOBAL_FIELD(b, TLBTR0, PW, v) +#define SET_UR(b, v) SET_GLOBAL_FIELD(b, TLBTR0, UR, v) +#define SET_UW(b, v) SET_GLOBAL_FIELD(b, TLBTR0, UW, v) +#define SET_XN(b, v) SET_GLOBAL_FIELD(b, TLBTR0, XN, v) +#define SET_NSDESC(b, v) SET_GLOBAL_FIELD(b, TLBTR0, NSDESC, v) +#define SET_ISH(b, v) SET_GLOBAL_FIELD(b, TLBTR0, ISH, v) +#define SET_SH(b, v) SET_GLOBAL_FIELD(b, TLBTR0, SH, v) +#define SET_MT(b, v) SET_GLOBAL_FIELD(b, TLBTR0, MT, v) +#define SET_DPSIZR(b, v) SET_GLOBAL_FIELD(b, TLBTR0, DPSIZR, v) +#define SET_DPSIZC(b, v) SET_GLOBAL_FIELD(b, TLBTR0, DPSIZC, v) + + +/* TLBTR1 */ +#define SET_TLBTR1_VMID(b, v) SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID, v) +#define SET_TLBTR1_PA(b, v) SET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA, v) + + +/* TLBTR2 */ +#define SET_TLBTR2_ASID(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID, v) +#define SET_TLBTR2_V(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V, v) +#define SET_TLBTR2_NSTID(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID, v) +#define SET_TLBTR2_NV(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV, v) +#define SET_TLBTR2_VA(b, v) SET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA, v) + + +/* Global Field Getters */ +/* CBACR_N */ +#define GET_RWVMID(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWVMID) +#define GET_RWE(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWE) +#define GET_RWGE(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), RWGE) +#define GET_CBVMID(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), CBVMID) +#define GET_IRPTNDX(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(CBACR_N), IRPTNDX) + + +/* M2VCBR_N */ +#define GET_VMID(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), VMID) +#define GET_CBNDX(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), CBNDX) +#define GET_BYPASSD(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BYPASSD) +#define GET_BPRCOSH(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCOSH) +#define GET_BPRCISH(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCISH) +#define GET_BPRCNSH(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPRCNSH) +#define GET_BPSHCFG(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPSHCFG) +#define GET_NSCFG(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), NSCFG) +#define GET_BPMTCFG(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMTCFG) +#define GET_BPMEMTYPE(b, n) GET_GLOBAL_FIELD(b, (n<<2)|(M2VCBR_N), BPMEMTYPE) + + +/* CR */ +#define GET_RPUE(b) GET_GLOBAL_FIELD(b, CR, RPUE) +#define GET_RPUERE(b) GET_GLOBAL_FIELD(b, CR, RPUERE) +#define GET_RPUEIE(b) GET_GLOBAL_FIELD(b, CR, RPUEIE) +#define GET_DCDEE(b) GET_GLOBAL_FIELD(b, CR, DCDEE) +#define GET_CLIENTPD(b) GET_GLOBAL_FIELD(b, CR, CLIENTPD) +#define GET_STALLD(b) GET_GLOBAL_FIELD(b, CR, STALLD) +#define GET_TLBLKCRWE(b) GET_GLOBAL_FIELD(b, CR, TLBLKCRWE) +#define GET_CR_TLBIALLCFG(b) GET_GLOBAL_FIELD(b, CR, CR_TLBIALLCFG) +#define GET_TLBIVMIDCFG(b) GET_GLOBAL_FIELD(b, CR, TLBIVMIDCFG) +#define GET_CR_HUME(b) GET_GLOBAL_FIELD(b, CR, CR_HUME) + + +/* ESR */ +#define GET_CFG(b) GET_GLOBAL_FIELD(b, ESR, CFG) +#define GET_BYPASS(b) GET_GLOBAL_FIELD(b, ESR, BYPASS) +#define GET_ESR_MULTI(b) GET_GLOBAL_FIELD(b, ESR, ESR_MULTI) + + +/* ESYNR0 */ +#define GET_ESYNR0_AMID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AMID) +#define GET_ESYNR0_APID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_APID) +#define GET_ESYNR0_ABID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ABID) +#define GET_ESYNR0_AVMID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_AVMID) +#define GET_ESYNR0_ATID(b) GET_GLOBAL_FIELD(b, ESYNR0, ESYNR0_ATID) + + +/* ESYNR1 */ +#define GET_ESYNR1_AMEMTYPE(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AMEMTYPE) +#define GET_ESYNR1_ASHARED(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASHARED) +#define GET_ESYNR1_AINNERSHARED(b) \ + GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINNERSHARED) +#define GET_ESYNR1_APRIV(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APRIV) +#define GET_ESYNR1_APROTNS(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_APROTNS) +#define GET_ESYNR1_AINST(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AINST) +#define GET_ESYNR1_AWRITE(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AWRITE) +#define GET_ESYNR1_ABURST(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ABURST) +#define GET_ESYNR1_ALEN(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALEN) +#define GET_ESYNR1_ASIZE(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ASIZE) +#define GET_ESYNR1_ALOCK(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_ALOCK) +#define GET_ESYNR1_AOOO(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AOOO) +#define GET_ESYNR1_AFULL(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AFULL) +#define GET_ESYNR1_AC(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_AC) +#define GET_ESYNR1_DCD(b) GET_GLOBAL_FIELD(b, ESYNR1, ESYNR1_DCD) + + +/* IDR */ +#define GET_NM2VCBMT(b) GET_GLOBAL_FIELD(b, IDR, NM2VCBMT) +#define GET_HTW(b) GET_GLOBAL_FIELD(b, IDR, HTW) +#define GET_HUM(b) GET_GLOBAL_FIELD(b, IDR, HUM) +#define GET_TLBSIZE(b) GET_GLOBAL_FIELD(b, IDR, TLBSIZE) +#define GET_NCB(b) GET_GLOBAL_FIELD(b, IDR, NCB) +#define GET_NIRPT(b) GET_GLOBAL_FIELD(b, IDR, NIRPT) + + +/* REV */ +#define GET_MAJOR(b) GET_GLOBAL_FIELD(b, REV, MAJOR) +#define GET_MINOR(b) GET_GLOBAL_FIELD(b, REV, MINOR) + + +/* TESTBUSCR */ +#define GET_TBE(b) GET_GLOBAL_FIELD(b, TESTBUSCR, TBE) +#define GET_SPDMBE(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDMBE) +#define GET_WGSEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, WGSEL) +#define GET_TBLSEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, TBLSEL) +#define GET_TBHSEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, TBHSEL) +#define GET_SPDM0SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM0SEL) +#define GET_SPDM1SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM1SEL) +#define GET_SPDM2SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM2SEL) +#define GET_SPDM3SEL(b) GET_GLOBAL_FIELD(b, TESTBUSCR, SPDM3SEL) + + +/* TLBIVMID */ +#define GET_TLBIVMID_VMID(b) GET_GLOBAL_FIELD(b, TLBIVMID, TLBIVMID_VMID) + + +/* TLBTR0 */ +#define GET_PR(b) GET_GLOBAL_FIELD(b, TLBTR0, PR) +#define GET_PW(b) GET_GLOBAL_FIELD(b, TLBTR0, PW) +#define GET_UR(b) GET_GLOBAL_FIELD(b, TLBTR0, UR) +#define GET_UW(b) GET_GLOBAL_FIELD(b, TLBTR0, UW) +#define GET_XN(b) GET_GLOBAL_FIELD(b, TLBTR0, XN) +#define GET_NSDESC(b) GET_GLOBAL_FIELD(b, TLBTR0, NSDESC) +#define GET_ISH(b) GET_GLOBAL_FIELD(b, TLBTR0, ISH) +#define GET_SH(b) GET_GLOBAL_FIELD(b, TLBTR0, SH) +#define GET_MT(b) GET_GLOBAL_FIELD(b, TLBTR0, MT) +#define GET_DPSIZR(b) GET_GLOBAL_FIELD(b, TLBTR0, DPSIZR) +#define GET_DPSIZC(b) GET_GLOBAL_FIELD(b, TLBTR0, DPSIZC) + + +/* TLBTR1 */ +#define GET_TLBTR1_VMID(b) GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_VMID) +#define GET_TLBTR1_PA(b) GET_GLOBAL_FIELD(b, TLBTR1, TLBTR1_PA) + + +/* TLBTR2 */ +#define GET_TLBTR2_ASID(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_ASID) +#define GET_TLBTR2_V(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_V) +#define GET_TLBTR2_NSTID(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NSTID) +#define GET_TLBTR2_NV(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_NV) +#define GET_TLBTR2_VA(b) GET_GLOBAL_FIELD(b, TLBTR2, TLBTR2_VA) + + +/* Context Register setters / getters */ +/* Context Register setters */ +/* ACTLR */ +#define SET_CFERE(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, CFERE, v) +#define SET_CFEIE(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, CFEIE, v) +#define SET_PTSHCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG, v) +#define SET_RCOSH(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, RCOSH, v) +#define SET_RCISH(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, RCISH, v) +#define SET_RCNSH(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, RCNSH, v) +#define SET_PRIVCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG, v) +#define SET_DNA(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, DNA, v) +#define SET_DNLV2PA(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA, v) +#define SET_TLBMCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG, v) +#define SET_CFCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, CFCFG, v) +#define SET_TIPCF(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, TIPCF, v) +#define SET_V2PCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG, v) +#define SET_HUME(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, HUME, v) +#define SET_PTMTCFG(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG, v) +#define SET_PTMEMTYPE(b, c, v) SET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE, v) + + +/* BFBCR */ +#define SET_BFBDFE(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE, v) +#define SET_BFBSFE(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE, v) +#define SET_SFVS(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, SFVS, v) +#define SET_FLVIC(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, FLVIC, v) +#define SET_SLVIC(b, c, v) SET_CONTEXT_FIELD(b, c, BFBCR, SLVIC, v) + + +/* CONTEXTIDR */ +#define SET_CONTEXTIDR_ASID(b, c, v) \ + SET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID, v) +#define SET_CONTEXTIDR_PROCID(b, c, v) \ + SET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID, v) + + +/* FSR */ +#define SET_TF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, TF, v) +#define SET_AFF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, AFF, v) +#define SET_APF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, APF, v) +#define SET_TLBMF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, TLBMF, v) +#define SET_HTWDEEF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, HTWDEEF, v) +#define SET_HTWSEEF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, HTWSEEF, v) +#define SET_MHF(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, MHF, v) +#define SET_SL(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, SL, v) +#define SET_SS(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, SS, v) +#define SET_MULTI(b, c, v) SET_CONTEXT_FIELD(b, c, FSR, MULTI, v) + + +/* FSYNR0 */ +#define SET_AMID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, AMID, v) +#define SET_APID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, APID, v) +#define SET_ABID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, ABID, v) +#define SET_ATID(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR0, ATID, v) + + +/* FSYNR1 */ +#define SET_AMEMTYPE(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE, v) +#define SET_ASHARED(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED, v) +#define SET_AINNERSHARED(b, c, v) \ + SET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED, v) +#define SET_APRIV(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, APRIV, v) +#define SET_APROTNS(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS, v) +#define SET_AINST(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AINST, v) +#define SET_AWRITE(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE, v) +#define SET_ABURST(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ABURST, v) +#define SET_ALEN(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ALEN, v) +#define SET_FSYNR1_ASIZE(b, c, v) \ + SET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE, v) +#define SET_ALOCK(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK, v) +#define SET_AFULL(b, c, v) SET_CONTEXT_FIELD(b, c, FSYNR1, AFULL, v) + + +/* NMRR */ +#define SET_ICPC0(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC0, v) +#define SET_ICPC1(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC1, v) +#define SET_ICPC2(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC2, v) +#define SET_ICPC3(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC3, v) +#define SET_ICPC4(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC4, v) +#define SET_ICPC5(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC5, v) +#define SET_ICPC6(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC6, v) +#define SET_ICPC7(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, ICPC7, v) +#define SET_OCPC0(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC0, v) +#define SET_OCPC1(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC1, v) +#define SET_OCPC2(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC2, v) +#define SET_OCPC3(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC3, v) +#define SET_OCPC4(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC4, v) +#define SET_OCPC5(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC5, v) +#define SET_OCPC6(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC6, v) +#define SET_OCPC7(b, c, v) SET_CONTEXT_FIELD(b, c, NMRR, OCPC7, v) + + +/* PAR */ +#define SET_FAULT(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT, v) + +#define SET_FAULT_TF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_TF, v) +#define SET_FAULT_AFF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF, v) +#define SET_FAULT_APF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_APF, v) +#define SET_FAULT_TLBMF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF, v) +#define SET_FAULT_HTWDEEF(b, c, v) \ + SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF, v) +#define SET_FAULT_HTWSEEF(b, c, v) \ + SET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF, v) +#define SET_FAULT_MHF(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF, v) +#define SET_FAULT_SL(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_SL, v) +#define SET_FAULT_SS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, FAULT_SS, v) + +#define SET_NOFAULT_SS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SS, v) +#define SET_NOFAULT_MT(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_MT, v) +#define SET_NOFAULT_SH(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_SH, v) +#define SET_NOFAULT_NS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NS, v) +#define SET_NOFAULT_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NOFAULT_NOS, v) +#define SET_NPFAULT_PA(b, c, v) SET_CONTEXT_FIELD(b, c, PAR, NPFAULT_PA, v) + + +/* PRRR */ +#define SET_MTC0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC0, v) +#define SET_MTC1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC1, v) +#define SET_MTC2(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC2, v) +#define SET_MTC3(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC3, v) +#define SET_MTC4(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC4, v) +#define SET_MTC5(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC5, v) +#define SET_MTC6(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC6, v) +#define SET_MTC7(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, MTC7, v) +#define SET_SHDSH0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHDSH0, v) +#define SET_SHDSH1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHDSH1, v) +#define SET_SHNMSH0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0, v) +#define SET_SHNMSH1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1, v) +#define SET_NOS0(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS0, v) +#define SET_NOS1(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS1, v) +#define SET_NOS2(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS2, v) +#define SET_NOS3(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS3, v) +#define SET_NOS4(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS4, v) +#define SET_NOS5(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS5, v) +#define SET_NOS6(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS6, v) +#define SET_NOS7(b, c, v) SET_CONTEXT_FIELD(b, c, PRRR, NOS7, v) + + +/* RESUME */ +#define SET_TNR(b, c, v) SET_CONTEXT_FIELD(b, c, RESUME, TNR, v) + + +/* SCTLR */ +#define SET_M(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, M, v) +#define SET_TRE(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, TRE, v) +#define SET_AFE(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, AFE, v) +#define SET_HAF(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, HAF, v) +#define SET_BE(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, BE, v) +#define SET_AFFD(b, c, v) SET_CONTEXT_FIELD(b, c, SCTLR, AFFD, v) + + +/* TLBLKCR */ +#define SET_LKE(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, LKE, v) +#define SET_TLBLKCR_TLBIALLCFG(b, c, v) \ + SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG, v) +#define SET_TLBIASIDCFG(b, c, v) \ + SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG, v) +#define SET_TLBIVAACFG(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG, v) +#define SET_FLOOR(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR, v) +#define SET_VICTIM(b, c, v) SET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM, v) + + +/* TTBCR */ +#define SET_N(b, c, v) SET_CONTEXT_FIELD(b, c, TTBCR, N, v) +#define SET_PD0(b, c, v) SET_CONTEXT_FIELD(b, c, TTBCR, PD0, v) +#define SET_PD1(b, c, v) SET_CONTEXT_FIELD(b, c, TTBCR, PD1, v) + + +/* TTBR0 */ +#define SET_TTBR0_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH, v) +#define SET_TTBR0_SH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH, v) +#define SET_TTBR0_ORGN(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN, v) +#define SET_TTBR0_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS, v) +#define SET_TTBR0_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL, v) +#define SET_TTBR0_PA(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA, v) + + +/* TTBR1 */ +#define SET_TTBR1_IRGNH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH, v) +#define SET_TTBR1_SH(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH, v) +#define SET_TTBR1_ORGN(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN, v) +#define SET_TTBR1_NOS(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS, v) +#define SET_TTBR1_IRGNL(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL, v) +#define SET_TTBR1_PA(b, c, v) SET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA, v) + + +/* V2PSR */ +#define SET_HIT(b, c, v) SET_CONTEXT_FIELD(b, c, V2PSR, HIT, v) +#define SET_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PSR, INDEX, v) + + +/* Context Register getters */ +/* ACTLR */ +#define GET_CFERE(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, CFERE) +#define GET_CFEIE(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, CFEIE) +#define GET_PTSHCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PTSHCFG) +#define GET_RCOSH(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, RCOSH) +#define GET_RCISH(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, RCISH) +#define GET_RCNSH(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, RCNSH) +#define GET_PRIVCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PRIVCFG) +#define GET_DNA(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, DNA) +#define GET_DNLV2PA(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, DNLV2PA) +#define GET_TLBMCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, TLBMCFG) +#define GET_CFCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, CFCFG) +#define GET_TIPCF(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, TIPCF) +#define GET_V2PCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, V2PCFG) +#define GET_HUME(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, HUME) +#define GET_PTMTCFG(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PTMTCFG) +#define GET_PTMEMTYPE(b, c) GET_CONTEXT_FIELD(b, c, ACTLR, PTMEMTYPE) + +/* BFBCR */ +#define GET_BFBDFE(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, BFBDFE) +#define GET_BFBSFE(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, BFBSFE) +#define GET_SFVS(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, SFVS) +#define GET_FLVIC(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, FLVIC) +#define GET_SLVIC(b, c) GET_CONTEXT_FIELD(b, c, BFBCR, SLVIC) + + +/* CONTEXTIDR */ +#define GET_CONTEXTIDR_ASID(b, c) \ + GET_CONTEXT_FIELD(b, c, CONTEXTIDR, CONTEXTIDR_ASID) +#define GET_CONTEXTIDR_PROCID(b, c) GET_CONTEXT_FIELD(b, c, CONTEXTIDR, PROCID) + + +/* FSR */ +#define GET_TF(b, c) GET_CONTEXT_FIELD(b, c, FSR, TF) +#define GET_AFF(b, c) GET_CONTEXT_FIELD(b, c, FSR, AFF) +#define GET_APF(b, c) GET_CONTEXT_FIELD(b, c, FSR, APF) +#define GET_TLBMF(b, c) GET_CONTEXT_FIELD(b, c, FSR, TLBMF) +#define GET_HTWDEEF(b, c) GET_CONTEXT_FIELD(b, c, FSR, HTWDEEF) +#define GET_HTWSEEF(b, c) GET_CONTEXT_FIELD(b, c, FSR, HTWSEEF) +#define GET_MHF(b, c) GET_CONTEXT_FIELD(b, c, FSR, MHF) +#define GET_SL(b, c) GET_CONTEXT_FIELD(b, c, FSR, SL) +#define GET_SS(b, c) GET_CONTEXT_FIELD(b, c, FSR, SS) +#define GET_MULTI(b, c) GET_CONTEXT_FIELD(b, c, FSR, MULTI) + + +/* FSYNR0 */ +#define GET_AMID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, AMID) +#define GET_APID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, APID) +#define GET_ABID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, ABID) +#define GET_ATID(b, c) GET_CONTEXT_FIELD(b, c, FSYNR0, ATID) + + +/* FSYNR1 */ +#define GET_AMEMTYPE(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AMEMTYPE) +#define GET_ASHARED(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ASHARED) +#define GET_AINNERSHARED(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AINNERSHARED) +#define GET_APRIV(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, APRIV) +#define GET_APROTNS(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, APROTNS) +#define GET_AINST(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AINST) +#define GET_AWRITE(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AWRITE) +#define GET_ABURST(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ABURST) +#define GET_ALEN(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ALEN) +#define GET_FSYNR1_ASIZE(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, FSYNR1_ASIZE) +#define GET_ALOCK(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, ALOCK) +#define GET_AFULL(b, c) GET_CONTEXT_FIELD(b, c, FSYNR1, AFULL) + + +/* NMRR */ +#define GET_ICPC0(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC0) +#define GET_ICPC1(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC1) +#define GET_ICPC2(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC2) +#define GET_ICPC3(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC3) +#define GET_ICPC4(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC4) +#define GET_ICPC5(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC5) +#define GET_ICPC6(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC6) +#define GET_ICPC7(b, c) GET_CONTEXT_FIELD(b, c, NMRR, ICPC7) +#define GET_OCPC0(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC0) +#define GET_OCPC1(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC1) +#define GET_OCPC2(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC2) +#define GET_OCPC3(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC3) +#define GET_OCPC4(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC4) +#define GET_OCPC5(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC5) +#define GET_OCPC6(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC6) +#define GET_OCPC7(b, c) GET_CONTEXT_FIELD(b, c, NMRR, OCPC7) +#define NMRR_ICP(nmrr, n) (((nmrr) & (3 << ((n) * 2))) >> ((n) * 2)) +#define NMRR_OCP(nmrr, n) (((nmrr) & (3 << ((n) * 2 + 16))) >> \ + ((n) * 2 + 16)) + +/* PAR */ +#define GET_FAULT(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT) + +#define GET_FAULT_TF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_TF) +#define GET_FAULT_AFF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_AFF) +#define GET_FAULT_APF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_APF) +#define GET_FAULT_TLBMF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_TLBMF) +#define GET_FAULT_HTWDEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWDEEF) +#define GET_FAULT_HTWSEEF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_HTWSEEF) +#define GET_FAULT_MHF(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_MHF) +#define GET_FAULT_SL(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_SL) +#define GET_FAULT_SS(b, c) GET_CONTEXT_FIELD(b, c, PAR, FAULT_SS) + +#define GET_NOFAULT_SS(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SS) +#define GET_NOFAULT_MT(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_MT) +#define GET_NOFAULT_SH(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_SH) +#define GET_NOFAULT_NS(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NS) +#define GET_NOFAULT_NOS(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NOFAULT_NOS) +#define GET_NPFAULT_PA(b, c) GET_CONTEXT_FIELD(b, c, PAR, PAR_NPFAULT_PA) + + +/* PRRR */ +#define GET_MTC0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC0) +#define GET_MTC1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC1) +#define GET_MTC2(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC2) +#define GET_MTC3(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC3) +#define GET_MTC4(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC4) +#define GET_MTC5(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC5) +#define GET_MTC6(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC6) +#define GET_MTC7(b, c) GET_CONTEXT_FIELD(b, c, PRRR, MTC7) +#define GET_SHDSH0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHDSH0) +#define GET_SHDSH1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHDSH1) +#define GET_SHNMSH0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH0) +#define GET_SHNMSH1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, SHNMSH1) +#define GET_NOS0(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS0) +#define GET_NOS1(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS1) +#define GET_NOS2(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS2) +#define GET_NOS3(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS3) +#define GET_NOS4(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS4) +#define GET_NOS5(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS5) +#define GET_NOS6(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS6) +#define GET_NOS7(b, c) GET_CONTEXT_FIELD(b, c, PRRR, NOS7) +#define PRRR_NOS(prrr, n) ((prrr) & (1 << ((n) + 24)) ? 1 : 0) +#define PRRR_MT(prrr, n) ((((prrr) & (3 << ((n) * 2))) >> ((n) * 2))) + + +/* RESUME */ +#define GET_TNR(b, c) GET_CONTEXT_FIELD(b, c, RESUME, TNR) + + +/* SCTLR */ +#define GET_M(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, M) +#define GET_TRE(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, TRE) +#define GET_AFE(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, AFE) +#define GET_HAF(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, HAF) +#define GET_BE(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, BE) +#define GET_AFFD(b, c) GET_CONTEXT_FIELD(b, c, SCTLR, AFFD) + + +/* TLBLKCR */ +#define GET_LKE(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, LKE) +#define GET_TLBLCKR_TLBIALLCFG(b, c) \ + GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBLCKR_TLBIALLCFG) +#define GET_TLBIASIDCFG(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIASIDCFG) +#define GET_TLBIVAACFG(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, TLBIVAACFG) +#define GET_FLOOR(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, FLOOR) +#define GET_VICTIM(b, c) GET_CONTEXT_FIELD(b, c, TLBLKCR, VICTIM) + + +/* TTBCR */ +#define GET_N(b, c) GET_CONTEXT_FIELD(b, c, TTBCR, N) +#define GET_PD0(b, c) GET_CONTEXT_FIELD(b, c, TTBCR, PD0) +#define GET_PD1(b, c) GET_CONTEXT_FIELD(b, c, TTBCR, PD1) + + +/* TTBR0 */ +#define GET_TTBR0_IRGNH(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNH) +#define GET_TTBR0_SH(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_SH) +#define GET_TTBR0_ORGN(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_ORGN) +#define GET_TTBR0_NOS(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_NOS) +#define GET_TTBR0_IRGNL(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_IRGNL) +#define GET_TTBR0_PA(b, c) GET_CONTEXT_FIELD(b, c, TTBR0, TTBR0_PA) + + +/* TTBR1 */ +#define GET_TTBR1_IRGNH(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNH) +#define GET_TTBR1_SH(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_SH) +#define GET_TTBR1_ORGN(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_ORGN) +#define GET_TTBR1_NOS(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_NOS) +#define GET_TTBR1_IRGNL(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_IRGNL) +#define GET_TTBR1_PA(b, c) GET_CONTEXT_FIELD(b, c, TTBR1, TTBR1_PA) + + +/* V2PSR */ +#define GET_HIT(b, c) GET_CONTEXT_FIELD(b, c, V2PSR, HIT) +#define GET_INDEX(b, c) GET_CONTEXT_FIELD(b, c, V2PSR, INDEX) + + +/* Global Registers */ +#define M2VCBR_N (0xFF000) +#define CBACR_N (0xFF800) +#define TLBRSW (0xFFE00) +#define TLBTR0 (0xFFE80) +#define TLBTR1 (0xFFE84) +#define TLBTR2 (0xFFE88) +#define TESTBUSCR (0xFFE8C) +#define GLOBAL_TLBIALL (0xFFF00) +#define TLBIVMID (0xFFF04) +#define CR (0xFFF80) +#define EAR (0xFFF84) +#define ESR (0xFFF88) +#define ESRRESTORE (0xFFF8C) +#define ESYNR0 (0xFFF90) +#define ESYNR1 (0xFFF94) +#define REV (0xFFFF4) +#define IDR (0xFFFF8) +#define RPU_ACR (0xFFFFC) + + +/* Context Bank Registers */ +#define SCTLR (0x000) +#define ACTLR (0x004) +#define CONTEXTIDR (0x008) +#define TTBR0 (0x010) +#define TTBR1 (0x014) +#define TTBCR (0x018) +#define PAR (0x01C) +#define FSR (0x020) +#define FSRRESTORE (0x024) +#define FAR (0x028) +#define FSYNR0 (0x02C) +#define FSYNR1 (0x030) +#define PRRR (0x034) +#define NMRR (0x038) +#define TLBLCKR (0x03C) +#define V2PSR (0x040) +#define TLBFLPTER (0x044) +#define TLBSLPTER (0x048) +#define BFBCR (0x04C) +#define CTX_TLBIALL (0x800) +#define TLBIASID (0x804) +#define TLBIVA (0x808) +#define TLBIVAA (0x80C) +#define V2PPR (0x810) +#define V2PPW (0x814) +#define V2PUR (0x818) +#define V2PUW (0x81C) +#define RESUME (0x820) + + +/* Global Register Fields */ +/* CBACRn */ +#define RWVMID (RWVMID_MASK << RWVMID_SHIFT) +#define RWE (RWE_MASK << RWE_SHIFT) +#define RWGE (RWGE_MASK << RWGE_SHIFT) +#define CBVMID (CBVMID_MASK << CBVMID_SHIFT) +#define IRPTNDX (IRPTNDX_MASK << IRPTNDX_SHIFT) + + +/* CR */ +#define RPUE (RPUE_MASK << RPUE_SHIFT) +#define RPUERE (RPUERE_MASK << RPUERE_SHIFT) +#define RPUEIE (RPUEIE_MASK << RPUEIE_SHIFT) +#define DCDEE (DCDEE_MASK << DCDEE_SHIFT) +#define CLIENTPD (CLIENTPD_MASK << CLIENTPD_SHIFT) +#define STALLD (STALLD_MASK << STALLD_SHIFT) +#define TLBLKCRWE (TLBLKCRWE_MASK << TLBLKCRWE_SHIFT) +#define CR_TLBIALLCFG (CR_TLBIALLCFG_MASK << CR_TLBIALLCFG_SHIFT) +#define TLBIVMIDCFG (TLBIVMIDCFG_MASK << TLBIVMIDCFG_SHIFT) +#define CR_HUME (CR_HUME_MASK << CR_HUME_SHIFT) + + +/* ESR */ +#define CFG (CFG_MASK << CFG_SHIFT) +#define BYPASS (BYPASS_MASK << BYPASS_SHIFT) +#define ESR_MULTI (ESR_MULTI_MASK << ESR_MULTI_SHIFT) + + +/* ESYNR0 */ +#define ESYNR0_AMID (ESYNR0_AMID_MASK << ESYNR0_AMID_SHIFT) +#define ESYNR0_APID (ESYNR0_APID_MASK << ESYNR0_APID_SHIFT) +#define ESYNR0_ABID (ESYNR0_ABID_MASK << ESYNR0_ABID_SHIFT) +#define ESYNR0_AVMID (ESYNR0_AVMID_MASK << ESYNR0_AVMID_SHIFT) +#define ESYNR0_ATID (ESYNR0_ATID_MASK << ESYNR0_ATID_SHIFT) + + +/* ESYNR1 */ +#define ESYNR1_AMEMTYPE (ESYNR1_AMEMTYPE_MASK << ESYNR1_AMEMTYPE_SHIFT) +#define ESYNR1_ASHARED (ESYNR1_ASHARED_MASK << ESYNR1_ASHARED_SHIFT) +#define ESYNR1_AINNERSHARED (ESYNR1_AINNERSHARED_MASK<< \ + ESYNR1_AINNERSHARED_SHIFT) +#define ESYNR1_APRIV (ESYNR1_APRIV_MASK << ESYNR1_APRIV_SHIFT) +#define ESYNR1_APROTNS (ESYNR1_APROTNS_MASK << ESYNR1_APROTNS_SHIFT) +#define ESYNR1_AINST (ESYNR1_AINST_MASK << ESYNR1_AINST_SHIFT) +#define ESYNR1_AWRITE (ESYNR1_AWRITE_MASK << ESYNR1_AWRITE_SHIFT) +#define ESYNR1_ABURST (ESYNR1_ABURST_MASK << ESYNR1_ABURST_SHIFT) +#define ESYNR1_ALEN (ESYNR1_ALEN_MASK << ESYNR1_ALEN_SHIFT) +#define ESYNR1_ASIZE (ESYNR1_ASIZE_MASK << ESYNR1_ASIZE_SHIFT) +#define ESYNR1_ALOCK (ESYNR1_ALOCK_MASK << ESYNR1_ALOCK_SHIFT) +#define ESYNR1_AOOO (ESYNR1_AOOO_MASK << ESYNR1_AOOO_SHIFT) +#define ESYNR1_AFULL (ESYNR1_AFULL_MASK << ESYNR1_AFULL_SHIFT) +#define ESYNR1_AC (ESYNR1_AC_MASK << ESYNR1_AC_SHIFT) +#define ESYNR1_DCD (ESYNR1_DCD_MASK << ESYNR1_DCD_SHIFT) + + +/* IDR */ +#define NM2VCBMT (NM2VCBMT_MASK << NM2VCBMT_SHIFT) +#define HTW (HTW_MASK << HTW_SHIFT) +#define HUM (HUM_MASK << HUM_SHIFT) +#define TLBSIZE (TLBSIZE_MASK << TLBSIZE_SHIFT) +#define NCB (NCB_MASK << NCB_SHIFT) +#define NIRPT (NIRPT_MASK << NIRPT_SHIFT) + + +/* M2VCBRn */ +#define VMID (VMID_MASK << VMID_SHIFT) +#define CBNDX (CBNDX_MASK << CBNDX_SHIFT) +#define BYPASSD (BYPASSD_MASK << BYPASSD_SHIFT) +#define BPRCOSH (BPRCOSH_MASK << BPRCOSH_SHIFT) +#define BPRCISH (BPRCISH_MASK << BPRCISH_SHIFT) +#define BPRCNSH (BPRCNSH_MASK << BPRCNSH_SHIFT) +#define BPSHCFG (BPSHCFG_MASK << BPSHCFG_SHIFT) +#define NSCFG (NSCFG_MASK << NSCFG_SHIFT) +#define BPMTCFG (BPMTCFG_MASK << BPMTCFG_SHIFT) +#define BPMEMTYPE (BPMEMTYPE_MASK << BPMEMTYPE_SHIFT) + + +/* REV */ +#define IDR_MINOR (MINOR_MASK << MINOR_SHIFT) +#define IDR_MAJOR (MAJOR_MASK << MAJOR_SHIFT) + + +/* TESTBUSCR */ +#define TBE (TBE_MASK << TBE_SHIFT) +#define SPDMBE (SPDMBE_MASK << SPDMBE_SHIFT) +#define WGSEL (WGSEL_MASK << WGSEL_SHIFT) +#define TBLSEL (TBLSEL_MASK << TBLSEL_SHIFT) +#define TBHSEL (TBHSEL_MASK << TBHSEL_SHIFT) +#define SPDM0SEL (SPDM0SEL_MASK << SPDM0SEL_SHIFT) +#define SPDM1SEL (SPDM1SEL_MASK << SPDM1SEL_SHIFT) +#define SPDM2SEL (SPDM2SEL_MASK << SPDM2SEL_SHIFT) +#define SPDM3SEL (SPDM3SEL_MASK << SPDM3SEL_SHIFT) + + +/* TLBIVMID */ +#define TLBIVMID_VMID (TLBIVMID_VMID_MASK << TLBIVMID_VMID_SHIFT) + + +/* TLBRSW */ +#define TLBRSW_INDEX (TLBRSW_INDEX_MASK << TLBRSW_INDEX_SHIFT) +#define TLBBFBS (TLBBFBS_MASK << TLBBFBS_SHIFT) + + +/* TLBTR0 */ +#define PR (PR_MASK << PR_SHIFT) +#define PW (PW_MASK << PW_SHIFT) +#define UR (UR_MASK << UR_SHIFT) +#define UW (UW_MASK << UW_SHIFT) +#define XN (XN_MASK << XN_SHIFT) +#define NSDESC (NSDESC_MASK << NSDESC_SHIFT) +#define ISH (ISH_MASK << ISH_SHIFT) +#define SH (SH_MASK << SH_SHIFT) +#define MT (MT_MASK << MT_SHIFT) +#define DPSIZR (DPSIZR_MASK << DPSIZR_SHIFT) +#define DPSIZC (DPSIZC_MASK << DPSIZC_SHIFT) + + +/* TLBTR1 */ +#define TLBTR1_VMID (TLBTR1_VMID_MASK << TLBTR1_VMID_SHIFT) +#define TLBTR1_PA (TLBTR1_PA_MASK << TLBTR1_PA_SHIFT) + + +/* TLBTR2 */ +#define TLBTR2_ASID (TLBTR2_ASID_MASK << TLBTR2_ASID_SHIFT) +#define TLBTR2_V (TLBTR2_V_MASK << TLBTR2_V_SHIFT) +#define TLBTR2_NSTID (TLBTR2_NSTID_MASK << TLBTR2_NSTID_SHIFT) +#define TLBTR2_NV (TLBTR2_NV_MASK << TLBTR2_NV_SHIFT) +#define TLBTR2_VA (TLBTR2_VA_MASK << TLBTR2_VA_SHIFT) + + +/* Context Register Fields */ +/* ACTLR */ +#define CFERE (CFERE_MASK << CFERE_SHIFT) +#define CFEIE (CFEIE_MASK << CFEIE_SHIFT) +#define PTSHCFG (PTSHCFG_MASK << PTSHCFG_SHIFT) +#define RCOSH (RCOSH_MASK << RCOSH_SHIFT) +#define RCISH (RCISH_MASK << RCISH_SHIFT) +#define RCNSH (RCNSH_MASK << RCNSH_SHIFT) +#define PRIVCFG (PRIVCFG_MASK << PRIVCFG_SHIFT) +#define DNA (DNA_MASK << DNA_SHIFT) +#define DNLV2PA (DNLV2PA_MASK << DNLV2PA_SHIFT) +#define TLBMCFG (TLBMCFG_MASK << TLBMCFG_SHIFT) +#define CFCFG (CFCFG_MASK << CFCFG_SHIFT) +#define TIPCF (TIPCF_MASK << TIPCF_SHIFT) +#define V2PCFG (V2PCFG_MASK << V2PCFG_SHIFT) +#define HUME (HUME_MASK << HUME_SHIFT) +#define PTMTCFG (PTMTCFG_MASK << PTMTCFG_SHIFT) +#define PTMEMTYPE (PTMEMTYPE_MASK << PTMEMTYPE_SHIFT) + + +/* BFBCR */ +#define BFBDFE (BFBDFE_MASK << BFBDFE_SHIFT) +#define BFBSFE (BFBSFE_MASK << BFBSFE_SHIFT) +#define SFVS (SFVS_MASK << SFVS_SHIFT) +#define FLVIC (FLVIC_MASK << FLVIC_SHIFT) +#define SLVIC (SLVIC_MASK << SLVIC_SHIFT) + + +/* CONTEXTIDR */ +#define CONTEXTIDR_ASID (CONTEXTIDR_ASID_MASK << CONTEXTIDR_ASID_SHIFT) +#define PROCID (PROCID_MASK << PROCID_SHIFT) + + +/* FSR */ +#define TF (TF_MASK << TF_SHIFT) +#define AFF (AFF_MASK << AFF_SHIFT) +#define APF (APF_MASK << APF_SHIFT) +#define TLBMF (TLBMF_MASK << TLBMF_SHIFT) +#define HTWDEEF (HTWDEEF_MASK << HTWDEEF_SHIFT) +#define HTWSEEF (HTWSEEF_MASK << HTWSEEF_SHIFT) +#define MHF (MHF_MASK << MHF_SHIFT) +#define SL (SL_MASK << SL_SHIFT) +#define SS (SS_MASK << SS_SHIFT) +#define MULTI (MULTI_MASK << MULTI_SHIFT) + + +/* FSYNR0 */ +#define AMID (AMID_MASK << AMID_SHIFT) +#define APID (APID_MASK << APID_SHIFT) +#define ABID (ABID_MASK << ABID_SHIFT) +#define ATID (ATID_MASK << ATID_SHIFT) + + +/* FSYNR1 */ +#define AMEMTYPE (AMEMTYPE_MASK << AMEMTYPE_SHIFT) +#define ASHARED (ASHARED_MASK << ASHARED_SHIFT) +#define AINNERSHARED (AINNERSHARED_MASK << AINNERSHARED_SHIFT) +#define APRIV (APRIV_MASK << APRIV_SHIFT) +#define APROTNS (APROTNS_MASK << APROTNS_SHIFT) +#define AINST (AINST_MASK << AINST_SHIFT) +#define AWRITE (AWRITE_MASK << AWRITE_SHIFT) +#define ABURST (ABURST_MASK << ABURST_SHIFT) +#define ALEN (ALEN_MASK << ALEN_SHIFT) +#define FSYNR1_ASIZE (FSYNR1_ASIZE_MASK << FSYNR1_ASIZE_SHIFT) +#define ALOCK (ALOCK_MASK << ALOCK_SHIFT) +#define AFULL (AFULL_MASK << AFULL_SHIFT) + + +/* NMRR */ +#define ICPC0 (ICPC0_MASK << ICPC0_SHIFT) +#define ICPC1 (ICPC1_MASK << ICPC1_SHIFT) +#define ICPC2 (ICPC2_MASK << ICPC2_SHIFT) +#define ICPC3 (ICPC3_MASK << ICPC3_SHIFT) +#define ICPC4 (ICPC4_MASK << ICPC4_SHIFT) +#define ICPC5 (ICPC5_MASK << ICPC5_SHIFT) +#define ICPC6 (ICPC6_MASK << ICPC6_SHIFT) +#define ICPC7 (ICPC7_MASK << ICPC7_SHIFT) +#define OCPC0 (OCPC0_MASK << OCPC0_SHIFT) +#define OCPC1 (OCPC1_MASK << OCPC1_SHIFT) +#define OCPC2 (OCPC2_MASK << OCPC2_SHIFT) +#define OCPC3 (OCPC3_MASK << OCPC3_SHIFT) +#define OCPC4 (OCPC4_MASK << OCPC4_SHIFT) +#define OCPC5 (OCPC5_MASK << OCPC5_SHIFT) +#define OCPC6 (OCPC6_MASK << OCPC6_SHIFT) +#define OCPC7 (OCPC7_MASK << OCPC7_SHIFT) + + +/* PAR */ +#define FAULT (FAULT_MASK << FAULT_SHIFT) +/* If a fault is present, these are the +same as the fault fields in the FAR */ +#define FAULT_TF (FAULT_TF_MASK << FAULT_TF_SHIFT) +#define FAULT_AFF (FAULT_AFF_MASK << FAULT_AFF_SHIFT) +#define FAULT_APF (FAULT_APF_MASK << FAULT_APF_SHIFT) +#define FAULT_TLBMF (FAULT_TLBMF_MASK << FAULT_TLBMF_SHIFT) +#define FAULT_HTWDEEF (FAULT_HTWDEEF_MASK << FAULT_HTWDEEF_SHIFT) +#define FAULT_HTWSEEF (FAULT_HTWSEEF_MASK << FAULT_HTWSEEF_SHIFT) +#define FAULT_MHF (FAULT_MHF_MASK << FAULT_MHF_SHIFT) +#define FAULT_SL (FAULT_SL_MASK << FAULT_SL_SHIFT) +#define FAULT_SS (FAULT_SS_MASK << FAULT_SS_SHIFT) + +/* If NO fault is present, the following fields are in effect */ +/* (FAULT remains as before) */ +#define PAR_NOFAULT_SS (PAR_NOFAULT_SS_MASK << PAR_NOFAULT_SS_SHIFT) +#define PAR_NOFAULT_MT (PAR_NOFAULT_MT_MASK << PAR_NOFAULT_MT_SHIFT) +#define PAR_NOFAULT_SH (PAR_NOFAULT_SH_MASK << PAR_NOFAULT_SH_SHIFT) +#define PAR_NOFAULT_NS (PAR_NOFAULT_NS_MASK << PAR_NOFAULT_NS_SHIFT) +#define PAR_NOFAULT_NOS (PAR_NOFAULT_NOS_MASK << PAR_NOFAULT_NOS_SHIFT) +#define PAR_NPFAULT_PA (PAR_NPFAULT_PA_MASK << PAR_NPFAULT_PA_SHIFT) + + +/* PRRR */ +#define MTC0 (MTC0_MASK << MTC0_SHIFT) +#define MTC1 (MTC1_MASK << MTC1_SHIFT) +#define MTC2 (MTC2_MASK << MTC2_SHIFT) +#define MTC3 (MTC3_MASK << MTC3_SHIFT) +#define MTC4 (MTC4_MASK << MTC4_SHIFT) +#define MTC5 (MTC5_MASK << MTC5_SHIFT) +#define MTC6 (MTC6_MASK << MTC6_SHIFT) +#define MTC7 (MTC7_MASK << MTC7_SHIFT) +#define SHDSH0 (SHDSH0_MASK << SHDSH0_SHIFT) +#define SHDSH1 (SHDSH1_MASK << SHDSH1_SHIFT) +#define SHNMSH0 (SHNMSH0_MASK << SHNMSH0_SHIFT) +#define SHNMSH1 (SHNMSH1_MASK << SHNMSH1_SHIFT) +#define NOS0 (NOS0_MASK << NOS0_SHIFT) +#define NOS1 (NOS1_MASK << NOS1_SHIFT) +#define NOS2 (NOS2_MASK << NOS2_SHIFT) +#define NOS3 (NOS3_MASK << NOS3_SHIFT) +#define NOS4 (NOS4_MASK << NOS4_SHIFT) +#define NOS5 (NOS5_MASK << NOS5_SHIFT) +#define NOS6 (NOS6_MASK << NOS6_SHIFT) +#define NOS7 (NOS7_MASK << NOS7_SHIFT) + + +/* RESUME */ +#define TNR (TNR_MASK << TNR_SHIFT) + + +/* SCTLR */ +#define M (M_MASK << M_SHIFT) +#define TRE (TRE_MASK << TRE_SHIFT) +#define AFE (AFE_MASK << AFE_SHIFT) +#define HAF (HAF_MASK << HAF_SHIFT) +#define BE (BE_MASK << BE_SHIFT) +#define AFFD (AFFD_MASK << AFFD_SHIFT) + + +/* TLBIASID */ +#define TLBIASID_ASID (TLBIASID_ASID_MASK << TLBIASID_ASID_SHIFT) + + +/* TLBIVA */ +#define TLBIVA_ASID (TLBIVA_ASID_MASK << TLBIVA_ASID_SHIFT) +#define TLBIVA_VA (TLBIVA_VA_MASK << TLBIVA_VA_SHIFT) + + +/* TLBIVAA */ +#define TLBIVAA_VA (TLBIVAA_VA_MASK << TLBIVAA_VA_SHIFT) + + +/* TLBLCKR */ +#define LKE (LKE_MASK << LKE_SHIFT) +#define TLBLCKR_TLBIALLCFG (TLBLCKR_TLBIALLCFG_MASK<<TLBLCKR_TLBIALLCFG_SHIFT) +#define TLBIASIDCFG (TLBIASIDCFG_MASK << TLBIASIDCFG_SHIFT) +#define TLBIVAACFG (TLBIVAACFG_MASK << TLBIVAACFG_SHIFT) +#define FLOOR (FLOOR_MASK << FLOOR_SHIFT) +#define VICTIM (VICTIM_MASK << VICTIM_SHIFT) + + +/* TTBCR */ +#define N (N_MASK << N_SHIFT) +#define PD0 (PD0_MASK << PD0_SHIFT) +#define PD1 (PD1_MASK << PD1_SHIFT) + + +/* TTBR0 */ +#define TTBR0_IRGNH (TTBR0_IRGNH_MASK << TTBR0_IRGNH_SHIFT) +#define TTBR0_SH (TTBR0_SH_MASK << TTBR0_SH_SHIFT) +#define TTBR0_ORGN (TTBR0_ORGN_MASK << TTBR0_ORGN_SHIFT) +#define TTBR0_NOS (TTBR0_NOS_MASK << TTBR0_NOS_SHIFT) +#define TTBR0_IRGNL (TTBR0_IRGNL_MASK << TTBR0_IRGNL_SHIFT) +#define TTBR0_PA (TTBR0_PA_MASK << TTBR0_PA_SHIFT) + + +/* TTBR1 */ +#define TTBR1_IRGNH (TTBR1_IRGNH_MASK << TTBR1_IRGNH_SHIFT) +#define TTBR1_SH (TTBR1_SH_MASK << TTBR1_SH_SHIFT) +#define TTBR1_ORGN (TTBR1_ORGN_MASK << TTBR1_ORGN_SHIFT) +#define TTBR1_NOS (TTBR1_NOS_MASK << TTBR1_NOS_SHIFT) +#define TTBR1_IRGNL (TTBR1_IRGNL_MASK << TTBR1_IRGNL_SHIFT) +#define TTBR1_PA (TTBR1_PA_MASK << TTBR1_PA_SHIFT) + + +/* V2PSR */ +#define HIT (HIT_MASK << HIT_SHIFT) +#define INDEX (INDEX_MASK << INDEX_SHIFT) + + +/* V2Pxx */ +#define V2Pxx_INDEX (V2Pxx_INDEX_MASK << V2Pxx_INDEX_SHIFT) +#define V2Pxx_VA (V2Pxx_VA_MASK << V2Pxx_VA_SHIFT) + + +/* Global Register Masks */ +/* CBACRn */ +#define RWVMID_MASK 0x1F +#define RWE_MASK 0x01 +#define RWGE_MASK 0x01 +#define CBVMID_MASK 0x1F +#define IRPTNDX_MASK 0xFF + + +/* CR */ +#define RPUE_MASK 0x01 +#define RPUERE_MASK 0x01 +#define RPUEIE_MASK 0x01 +#define DCDEE_MASK 0x01 +#define CLIENTPD_MASK 0x01 +#define STALLD_MASK 0x01 +#define TLBLKCRWE_MASK 0x01 +#define CR_TLBIALLCFG_MASK 0x01 +#define TLBIVMIDCFG_MASK 0x01 +#define CR_HUME_MASK 0x01 + + +/* ESR */ +#define CFG_MASK 0x01 +#define BYPASS_MASK 0x01 +#define ESR_MULTI_MASK 0x01 + + +/* ESYNR0 */ +#define ESYNR0_AMID_MASK 0xFF +#define ESYNR0_APID_MASK 0x1F +#define ESYNR0_ABID_MASK 0x07 +#define ESYNR0_AVMID_MASK 0x1F +#define ESYNR0_ATID_MASK 0xFF + + +/* ESYNR1 */ +#define ESYNR1_AMEMTYPE_MASK 0x07 +#define ESYNR1_ASHARED_MASK 0x01 +#define ESYNR1_AINNERSHARED_MASK 0x01 +#define ESYNR1_APRIV_MASK 0x01 +#define ESYNR1_APROTNS_MASK 0x01 +#define ESYNR1_AINST_MASK 0x01 +#define ESYNR1_AWRITE_MASK 0x01 +#define ESYNR1_ABURST_MASK 0x01 +#define ESYNR1_ALEN_MASK 0x0F +#define ESYNR1_ASIZE_MASK 0x01 +#define ESYNR1_ALOCK_MASK 0x03 +#define ESYNR1_AOOO_MASK 0x01 +#define ESYNR1_AFULL_MASK 0x01 +#define ESYNR1_AC_MASK 0x01 +#define ESYNR1_DCD_MASK 0x01 + + +/* IDR */ +#define NM2VCBMT_MASK 0x1FF +#define HTW_MASK 0x01 +#define HUM_MASK 0x01 +#define TLBSIZE_MASK 0x0F +#define NCB_MASK 0xFF +#define NIRPT_MASK 0xFF + + +/* M2VCBRn */ +#define VMID_MASK 0x1F +#define CBNDX_MASK 0xFF +#define BYPASSD_MASK 0x01 +#define BPRCOSH_MASK 0x01 +#define BPRCISH_MASK 0x01 +#define BPRCNSH_MASK 0x01 +#define BPSHCFG_MASK 0x03 +#define NSCFG_MASK 0x03 +#define BPMTCFG_MASK 0x01 +#define BPMEMTYPE_MASK 0x07 + + +/* REV */ +#define MINOR_MASK 0x0F +#define MAJOR_MASK 0x0F + + +/* TESTBUSCR */ +#define TBE_MASK 0x01 +#define SPDMBE_MASK 0x01 +#define WGSEL_MASK 0x03 +#define TBLSEL_MASK 0x03 +#define TBHSEL_MASK 0x03 +#define SPDM0SEL_MASK 0x0F +#define SPDM1SEL_MASK 0x0F +#define SPDM2SEL_MASK 0x0F +#define SPDM3SEL_MASK 0x0F + + +/* TLBIMID */ +#define TLBIVMID_VMID_MASK 0x1F + + +/* TLBRSW */ +#define TLBRSW_INDEX_MASK 0xFF +#define TLBBFBS_MASK 0x03 + + +/* TLBTR0 */ +#define PR_MASK 0x01 +#define PW_MASK 0x01 +#define UR_MASK 0x01 +#define UW_MASK 0x01 +#define XN_MASK 0x01 +#define NSDESC_MASK 0x01 +#define ISH_MASK 0x01 +#define SH_MASK 0x01 +#define MT_MASK 0x07 +#define DPSIZR_MASK 0x07 +#define DPSIZC_MASK 0x07 + + +/* TLBTR1 */ +#define TLBTR1_VMID_MASK 0x1F +#define TLBTR1_PA_MASK 0x000FFFFF + + +/* TLBTR2 */ +#define TLBTR2_ASID_MASK 0xFF +#define TLBTR2_V_MASK 0x01 +#define TLBTR2_NSTID_MASK 0x01 +#define TLBTR2_NV_MASK 0x01 +#define TLBTR2_VA_MASK 0x000FFFFF + + +/* Global Register Shifts */ +/* CBACRn */ +#define RWVMID_SHIFT 0 +#define RWE_SHIFT 8 +#define RWGE_SHIFT 9 +#define CBVMID_SHIFT 16 +#define IRPTNDX_SHIFT 24 + + +/* CR */ +#define RPUE_SHIFT 0 +#define RPUERE_SHIFT 1 +#define RPUEIE_SHIFT 2 +#define DCDEE_SHIFT 3 +#define CLIENTPD_SHIFT 4 +#define STALLD_SHIFT 5 +#define TLBLKCRWE_SHIFT 6 +#define CR_TLBIALLCFG_SHIFT 7 +#define TLBIVMIDCFG_SHIFT 8 +#define CR_HUME_SHIFT 9 + + +/* ESR */ +#define CFG_SHIFT 0 +#define BYPASS_SHIFT 1 +#define ESR_MULTI_SHIFT 31 + + +/* ESYNR0 */ +#define ESYNR0_AMID_SHIFT 0 +#define ESYNR0_APID_SHIFT 8 +#define ESYNR0_ABID_SHIFT 13 +#define ESYNR0_AVMID_SHIFT 16 +#define ESYNR0_ATID_SHIFT 24 + + +/* ESYNR1 */ +#define ESYNR1_AMEMTYPE_SHIFT 0 +#define ESYNR1_ASHARED_SHIFT 3 +#define ESYNR1_AINNERSHARED_SHIFT 4 +#define ESYNR1_APRIV_SHIFT 5 +#define ESYNR1_APROTNS_SHIFT 6 +#define ESYNR1_AINST_SHIFT 7 +#define ESYNR1_AWRITE_SHIFT 8 +#define ESYNR1_ABURST_SHIFT 10 +#define ESYNR1_ALEN_SHIFT 12 +#define ESYNR1_ASIZE_SHIFT 16 +#define ESYNR1_ALOCK_SHIFT 20 +#define ESYNR1_AOOO_SHIFT 22 +#define ESYNR1_AFULL_SHIFT 24 +#define ESYNR1_AC_SHIFT 30 +#define ESYNR1_DCD_SHIFT 31 + + +/* IDR */ +#define NM2VCBMT_SHIFT 0 +#define HTW_SHIFT 9 +#define HUM_SHIFT 10 +#define TLBSIZE_SHIFT 12 +#define NCB_SHIFT 16 +#define NIRPT_SHIFT 24 + + +/* M2VCBRn */ +#define VMID_SHIFT 0 +#define CBNDX_SHIFT 8 +#define BYPASSD_SHIFT 16 +#define BPRCOSH_SHIFT 17 +#define BPRCISH_SHIFT 18 +#define BPRCNSH_SHIFT 19 +#define BPSHCFG_SHIFT 20 +#define NSCFG_SHIFT 22 +#define BPMTCFG_SHIFT 24 +#define BPMEMTYPE_SHIFT 25 + + +/* REV */ +#define MINOR_SHIFT 0 +#define MAJOR_SHIFT 4 + + +/* TESTBUSCR */ +#define TBE_SHIFT 0 +#define SPDMBE_SHIFT 1 +#define WGSEL_SHIFT 8 +#define TBLSEL_SHIFT 12 +#define TBHSEL_SHIFT 14 +#define SPDM0SEL_SHIFT 16 +#define SPDM1SEL_SHIFT 20 +#define SPDM2SEL_SHIFT 24 +#define SPDM3SEL_SHIFT 28 + + +/* TLBIMID */ +#define TLBIVMID_VMID_SHIFT 0 + + +/* TLBRSW */ +#define TLBRSW_INDEX_SHIFT 0 +#define TLBBFBS_SHIFT 8 + + +/* TLBTR0 */ +#define PR_SHIFT 0 +#define PW_SHIFT 1 +#define UR_SHIFT 2 +#define UW_SHIFT 3 +#define XN_SHIFT 4 +#define NSDESC_SHIFT 6 +#define ISH_SHIFT 7 +#define SH_SHIFT 8 +#define MT_SHIFT 9 +#define DPSIZR_SHIFT 16 +#define DPSIZC_SHIFT 20 + + +/* TLBTR1 */ +#define TLBTR1_VMID_SHIFT 0 +#define TLBTR1_PA_SHIFT 12 + + +/* TLBTR2 */ +#define TLBTR2_ASID_SHIFT 0 +#define TLBTR2_V_SHIFT 8 +#define TLBTR2_NSTID_SHIFT 9 +#define TLBTR2_NV_SHIFT 10 +#define TLBTR2_VA_SHIFT 12 + + +/* Context Register Masks */ +/* ACTLR */ +#define CFERE_MASK 0x01 +#define CFEIE_MASK 0x01 +#define PTSHCFG_MASK 0x03 +#define RCOSH_MASK 0x01 +#define RCISH_MASK 0x01 +#define RCNSH_MASK 0x01 +#define PRIVCFG_MASK 0x03 +#define DNA_MASK 0x01 +#define DNLV2PA_MASK 0x01 +#define TLBMCFG_MASK 0x03 +#define CFCFG_MASK 0x01 +#define TIPCF_MASK 0x01 +#define V2PCFG_MASK 0x03 +#define HUME_MASK 0x01 +#define PTMTCFG_MASK 0x01 +#define PTMEMTYPE_MASK 0x07 + + +/* BFBCR */ +#define BFBDFE_MASK 0x01 +#define BFBSFE_MASK 0x01 +#define SFVS_MASK 0x01 +#define FLVIC_MASK 0x0F +#define SLVIC_MASK 0x0F + + +/* CONTEXTIDR */ +#define CONTEXTIDR_ASID_MASK 0xFF +#define PROCID_MASK 0x00FFFFFF + + +/* FSR */ +#define TF_MASK 0x01 +#define AFF_MASK 0x01 +#define APF_MASK 0x01 +#define TLBMF_MASK 0x01 +#define HTWDEEF_MASK 0x01 +#define HTWSEEF_MASK 0x01 +#define MHF_MASK 0x01 +#define SL_MASK 0x01 +#define SS_MASK 0x01 +#define MULTI_MASK 0x01 + + +/* FSYNR0 */ +#define AMID_MASK 0xFF +#define APID_MASK 0x1F +#define ABID_MASK 0x07 +#define ATID_MASK 0xFF + + +/* FSYNR1 */ +#define AMEMTYPE_MASK 0x07 +#define ASHARED_MASK 0x01 +#define AINNERSHARED_MASK 0x01 +#define APRIV_MASK 0x01 +#define APROTNS_MASK 0x01 +#define AINST_MASK 0x01 +#define AWRITE_MASK 0x01 +#define ABURST_MASK 0x01 +#define ALEN_MASK 0x0F +#define FSYNR1_ASIZE_MASK 0x07 +#define ALOCK_MASK 0x03 +#define AFULL_MASK 0x01 + + +/* NMRR */ +#define ICPC0_MASK 0x03 +#define ICPC1_MASK 0x03 +#define ICPC2_MASK 0x03 +#define ICPC3_MASK 0x03 +#define ICPC4_MASK 0x03 +#define ICPC5_MASK 0x03 +#define ICPC6_MASK 0x03 +#define ICPC7_MASK 0x03 +#define OCPC0_MASK 0x03 +#define OCPC1_MASK 0x03 +#define OCPC2_MASK 0x03 +#define OCPC3_MASK 0x03 +#define OCPC4_MASK 0x03 +#define OCPC5_MASK 0x03 +#define OCPC6_MASK 0x03 +#define OCPC7_MASK 0x03 + + +/* PAR */ +#define FAULT_MASK 0x01 +/* If a fault is present, these are the +same as the fault fields in the FAR */ +#define FAULT_TF_MASK 0x01 +#define FAULT_AFF_MASK 0x01 +#define FAULT_APF_MASK 0x01 +#define FAULT_TLBMF_MASK 0x01 +#define FAULT_HTWDEEF_MASK 0x01 +#define FAULT_HTWSEEF_MASK 0x01 +#define FAULT_MHF_MASK 0x01 +#define FAULT_SL_MASK 0x01 +#define FAULT_SS_MASK 0x01 + +/* If NO fault is present, the following + * fields are in effect + * (FAULT remains as before) */ +#define PAR_NOFAULT_SS_MASK 0x01 +#define PAR_NOFAULT_MT_MASK 0x07 +#define PAR_NOFAULT_SH_MASK 0x01 +#define PAR_NOFAULT_NS_MASK 0x01 +#define PAR_NOFAULT_NOS_MASK 0x01 +#define PAR_NPFAULT_PA_MASK 0x000FFFFF + + +/* PRRR */ +#define MTC0_MASK 0x03 +#define MTC1_MASK 0x03 +#define MTC2_MASK 0x03 +#define MTC3_MASK 0x03 +#define MTC4_MASK 0x03 +#define MTC5_MASK 0x03 +#define MTC6_MASK 0x03 +#define MTC7_MASK 0x03 +#define SHDSH0_MASK 0x01 +#define SHDSH1_MASK 0x01 +#define SHNMSH0_MASK 0x01 +#define SHNMSH1_MASK 0x01 +#define NOS0_MASK 0x01 +#define NOS1_MASK 0x01 +#define NOS2_MASK 0x01 +#define NOS3_MASK 0x01 +#define NOS4_MASK 0x01 +#define NOS5_MASK 0x01 +#define NOS6_MASK 0x01 +#define NOS7_MASK 0x01 + + +/* RESUME */ +#define TNR_MASK 0x01 + + +/* SCTLR */ +#define M_MASK 0x01 +#define TRE_MASK 0x01 +#define AFE_MASK 0x01 +#define HAF_MASK 0x01 +#define BE_MASK 0x01 +#define AFFD_MASK 0x01 + + +/* TLBIASID */ +#define TLBIASID_ASID_MASK 0xFF + + +/* TLBIVA */ +#define TLBIVA_ASID_MASK 0xFF +#define TLBIVA_VA_MASK 0x000FFFFF + + +/* TLBIVAA */ +#define TLBIVAA_VA_MASK 0x000FFFFF + + +/* TLBLCKR */ +#define LKE_MASK 0x01 +#define TLBLCKR_TLBIALLCFG_MASK 0x01 +#define TLBIASIDCFG_MASK 0x01 +#define TLBIVAACFG_MASK 0x01 +#define FLOOR_MASK 0xFF +#define VICTIM_MASK 0xFF + + +/* TTBCR */ +#define N_MASK 0x07 +#define PD0_MASK 0x01 +#define PD1_MASK 0x01 + + +/* TTBR0 */ +#define TTBR0_IRGNH_MASK 0x01 +#define TTBR0_SH_MASK 0x01 +#define TTBR0_ORGN_MASK 0x03 +#define TTBR0_NOS_MASK 0x01 +#define TTBR0_IRGNL_MASK 0x01 +#define TTBR0_PA_MASK 0x0003FFFF + + +/* TTBR1 */ +#define TTBR1_IRGNH_MASK 0x01 +#define TTBR1_SH_MASK 0x01 +#define TTBR1_ORGN_MASK 0x03 +#define TTBR1_NOS_MASK 0x01 +#define TTBR1_IRGNL_MASK 0x01 +#define TTBR1_PA_MASK 0x0003FFFF + + +/* V2PSR */ +#define HIT_MASK 0x01 +#define INDEX_MASK 0xFF + + +/* V2Pxx */ +#define V2Pxx_INDEX_MASK 0xFF +#define V2Pxx_VA_MASK 0x000FFFFF + + +/* Context Register Shifts */ +/* ACTLR */ +#define CFERE_SHIFT 0 +#define CFEIE_SHIFT 1 +#define PTSHCFG_SHIFT 2 +#define RCOSH_SHIFT 4 +#define RCISH_SHIFT 5 +#define RCNSH_SHIFT 6 +#define PRIVCFG_SHIFT 8 +#define DNA_SHIFT 10 +#define DNLV2PA_SHIFT 11 +#define TLBMCFG_SHIFT 12 +#define CFCFG_SHIFT 14 +#define TIPCF_SHIFT 15 +#define V2PCFG_SHIFT 16 +#define HUME_SHIFT 18 +#define PTMTCFG_SHIFT 20 +#define PTMEMTYPE_SHIFT 21 + + +/* BFBCR */ +#define BFBDFE_SHIFT 0 +#define BFBSFE_SHIFT 1 +#define SFVS_SHIFT 2 +#define FLVIC_SHIFT 4 +#define SLVIC_SHIFT 8 + + +/* CONTEXTIDR */ +#define CONTEXTIDR_ASID_SHIFT 0 +#define PROCID_SHIFT 8 + + +/* FSR */ +#define TF_SHIFT 1 +#define AFF_SHIFT 2 +#define APF_SHIFT 3 +#define TLBMF_SHIFT 4 +#define HTWDEEF_SHIFT 5 +#define HTWSEEF_SHIFT 6 +#define MHF_SHIFT 7 +#define SL_SHIFT 16 +#define SS_SHIFT 30 +#define MULTI_SHIFT 31 + + +/* FSYNR0 */ +#define AMID_SHIFT 0 +#define APID_SHIFT 8 +#define ABID_SHIFT 13 +#define ATID_SHIFT 24 + + +/* FSYNR1 */ +#define AMEMTYPE_SHIFT 0 +#define ASHARED_SHIFT 3 +#define AINNERSHARED_SHIFT 4 +#define APRIV_SHIFT 5 +#define APROTNS_SHIFT 6 +#define AINST_SHIFT 7 +#define AWRITE_SHIFT 8 +#define ABURST_SHIFT 10 +#define ALEN_SHIFT 12 +#define FSYNR1_ASIZE_SHIFT 16 +#define ALOCK_SHIFT 20 +#define AFULL_SHIFT 24 + + +/* NMRR */ +#define ICPC0_SHIFT 0 +#define ICPC1_SHIFT 2 +#define ICPC2_SHIFT 4 +#define ICPC3_SHIFT 6 +#define ICPC4_SHIFT 8 +#define ICPC5_SHIFT 10 +#define ICPC6_SHIFT 12 +#define ICPC7_SHIFT 14 +#define OCPC0_SHIFT 16 +#define OCPC1_SHIFT 18 +#define OCPC2_SHIFT 20 +#define OCPC3_SHIFT 22 +#define OCPC4_SHIFT 24 +#define OCPC5_SHIFT 26 +#define OCPC6_SHIFT 28 +#define OCPC7_SHIFT 30 + + +/* PAR */ +#define FAULT_SHIFT 0 +/* If a fault is present, these are the +same as the fault fields in the FAR */ +#define FAULT_TF_SHIFT 1 +#define FAULT_AFF_SHIFT 2 +#define FAULT_APF_SHIFT 3 +#define FAULT_TLBMF_SHIFT 4 +#define FAULT_HTWDEEF_SHIFT 5 +#define FAULT_HTWSEEF_SHIFT 6 +#define FAULT_MHF_SHIFT 7 +#define FAULT_SL_SHIFT 16 +#define FAULT_SS_SHIFT 30 + +/* If NO fault is present, the following + * fields are in effect + * (FAULT remains as before) */ +#define PAR_NOFAULT_SS_SHIFT 1 +#define PAR_NOFAULT_MT_SHIFT 4 +#define PAR_NOFAULT_SH_SHIFT 7 +#define PAR_NOFAULT_NS_SHIFT 9 +#define PAR_NOFAULT_NOS_SHIFT 10 +#define PAR_NPFAULT_PA_SHIFT 12 + + +/* PRRR */ +#define MTC0_SHIFT 0 +#define MTC1_SHIFT 2 +#define MTC2_SHIFT 4 +#define MTC3_SHIFT 6 +#define MTC4_SHIFT 8 +#define MTC5_SHIFT 10 +#define MTC6_SHIFT 12 +#define MTC7_SHIFT 14 +#define SHDSH0_SHIFT 16 +#define SHDSH1_SHIFT 17 +#define SHNMSH0_SHIFT 18 +#define SHNMSH1_SHIFT 19 +#define NOS0_SHIFT 24 +#define NOS1_SHIFT 25 +#define NOS2_SHIFT 26 +#define NOS3_SHIFT 27 +#define NOS4_SHIFT 28 +#define NOS5_SHIFT 29 +#define NOS6_SHIFT 30 +#define NOS7_SHIFT 31 + + +/* RESUME */ +#define TNR_SHIFT 0 + + +/* SCTLR */ +#define M_SHIFT 0 +#define TRE_SHIFT 1 +#define AFE_SHIFT 2 +#define HAF_SHIFT 3 +#define BE_SHIFT 4 +#define AFFD_SHIFT 5 + + +/* TLBIASID */ +#define TLBIASID_ASID_SHIFT 0 + + +/* TLBIVA */ +#define TLBIVA_ASID_SHIFT 0 +#define TLBIVA_VA_SHIFT 12 + + +/* TLBIVAA */ +#define TLBIVAA_VA_SHIFT 12 + + +/* TLBLCKR */ +#define LKE_SHIFT 0 +#define TLBLCKR_TLBIALLCFG_SHIFT 1 +#define TLBIASIDCFG_SHIFT 2 +#define TLBIVAACFG_SHIFT 3 +#define FLOOR_SHIFT 8 +#define VICTIM_SHIFT 8 + + +/* TTBCR */ +#define N_SHIFT 3 +#define PD0_SHIFT 4 +#define PD1_SHIFT 5 + + +/* TTBR0 */ +#define TTBR0_IRGNH_SHIFT 0 +#define TTBR0_SH_SHIFT 1 +#define TTBR0_ORGN_SHIFT 3 +#define TTBR0_NOS_SHIFT 5 +#define TTBR0_IRGNL_SHIFT 6 +#define TTBR0_PA_SHIFT 14 + + +/* TTBR1 */ +#define TTBR1_IRGNH_SHIFT 0 +#define TTBR1_SH_SHIFT 1 +#define TTBR1_ORGN_SHIFT 3 +#define TTBR1_NOS_SHIFT 5 +#define TTBR1_IRGNL_SHIFT 6 +#define TTBR1_PA_SHIFT 14 + + +/* V2PSR */ +#define HIT_SHIFT 0 +#define INDEX_SHIFT 8 + + +/* V2Pxx */ +#define V2Pxx_INDEX_SHIFT 0 +#define V2Pxx_VA_SHIFT 12 + +#endif diff --git a/arch/arm/mach-msm/include/mach/irqs-7x00.h b/arch/arm/mach-msm/include/mach/irqs-7x00.h new file mode 100644 index 00000000..f1fe7061 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/irqs-7x00.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + */ + +#ifndef __ASM_ARCH_MSM_IRQS_7X00_H +#define __ASM_ARCH_MSM_IRQS_7X00_H + +/* MSM ARM11 Interrupt Numbers */ +/* See 80-VE113-1 A, pp219-221 */ + +#define INT_A9_M2A_0 0 +#define INT_A9_M2A_1 1 +#define INT_A9_M2A_2 2 +#define INT_A9_M2A_3 3 +#define INT_A9_M2A_4 4 +#define INT_A9_M2A_5 5 +#define INT_A9_M2A_6 6 +#define INT_GP_TIMER_EXP 7 +#define INT_DEBUG_TIMER_EXP 8 +#define INT_UART1 9 +#define INT_UART2 10 +#define INT_UART3 11 +#define INT_UART1_RX 12 +#define INT_UART2_RX 13 +#define INT_UART3_RX 14 +#define INT_USB_OTG 15 +#define INT_MDDI_PRI 16 +#define INT_MDDI_EXT 17 +#define INT_MDDI_CLIENT 18 +#define INT_MDP 19 +#define INT_GRAPHICS 20 +#define INT_ADM_AARM 21 +#define INT_ADSP_A11 22 +#define INT_ADSP_A9_A11 23 +#define INT_SDC1_0 24 +#define INT_SDC1_1 25 +#define INT_SDC2_0 26 +#define INT_SDC2_1 27 +#define INT_KEYSENSE 28 +#define INT_TCHSCRN_SSBI 29 +#define INT_TCHSCRN1 30 +#define INT_TCHSCRN2 31 + +#define INT_GPIO_GROUP1 (32 + 0) +#define INT_GPIO_GROUP2 (32 + 1) +#define INT_PWB_I2C (32 + 2) +#define INT_SOFTRESET (32 + 3) +#define INT_NAND_WR_ER_DONE (32 + 4) +#define INT_NAND_OP_DONE (32 + 5) +#define INT_PBUS_ARM11 (32 + 6) +#define INT_AXI_MPU_SMI (32 + 7) +#define INT_AXI_MPU_EBI1 (32 + 8) +#define INT_AD_HSSD (32 + 9) +#define INT_ARM11_PMU (32 + 10) +#define INT_ARM11_DMA (32 + 11) +#define INT_TSIF_IRQ (32 + 12) +#define INT_UART1DM_IRQ (32 + 13) +#define INT_UART1DM_RX (32 + 14) +#define INT_USB_HS (32 + 15) +#define INT_SDC3_0 (32 + 16) +#define INT_SDC3_1 (32 + 17) +#define INT_SDC4_0 (32 + 18) +#define INT_SDC4_1 (32 + 19) +#define INT_UART2DM_RX (32 + 20) +#define INT_UART2DM_IRQ (32 + 21) + +/* 22-31 are reserved */ + +#define NR_MSM_IRQS 64 +#define NR_GPIO_IRQS 122 +#define NR_BOARD_IRQS 64 + +#endif diff --git a/arch/arm/mach-msm/include/mach/irqs-7x30.h b/arch/arm/mach-msm/include/mach/irqs-7x30.h new file mode 100644 index 00000000..1f159026 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/irqs-7x30.h @@ -0,0 +1,153 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ASM_ARCH_MSM_IRQS_7X30_H +#define __ASM_ARCH_MSM_IRQS_7X30_H + +/* MSM ACPU Interrupt Numbers */ + +#define INT_DEBUG_TIMER_EXP 0 +#define INT_GPT0_TIMER_EXP 1 +#define INT_GPT1_TIMER_EXP 2 +#define INT_WDT0_ACCSCSSBARK 3 +#define INT_WDT1_ACCSCSSBARK 4 +#define INT_AVS_SVIC 5 +#define INT_AVS_SVIC_SW_DONE 6 +#define INT_SC_DBG_RX_FULL 7 +#define INT_SC_DBG_TX_EMPTY 8 +#define INT_ARM11_PM 9 +#define INT_AVS_REQ_DOWN 10 +#define INT_AVS_REQ_UP 11 +#define INT_SC_ACG 12 +/* SCSS_VICFIQSTS0[13:15] are RESERVED */ +#define INT_L2_SVICCPUIRPTREQ 16 +#define INT_L2_SVICDMANSIRPTREQ 17 +#define INT_L2_SVICDMASIRPTREQ 18 +#define INT_L2_SVICSLVIRPTREQ 19 +#define INT_AD5A_MPROC_APPS_0 20 +#define INT_AD5A_MPROC_APPS_1 21 +#define INT_A9_M2A_0 22 +#define INT_A9_M2A_1 23 +#define INT_A9_M2A_2 24 +#define INT_A9_M2A_3 25 +#define INT_A9_M2A_4 26 +#define INT_A9_M2A_5 27 +#define INT_A9_M2A_6 28 +#define INT_A9_M2A_7 29 +#define INT_A9_M2A_8 30 +#define INT_A9_M2A_9 31 + +#define INT_AXI_EBI1_SC (32 + 0) +#define INT_IMEM_ERR (32 + 1) +#define INT_AXI_EBI0_SC (32 + 2) +#define INT_PBUS_SC_IRQC (32 + 3) +#define INT_PERPH_BUS_BPM (32 + 4) +#define INT_CC_TEMP_SENSE (32 + 5) +#define INT_UXMC_EBI0 (32 + 6) +#define INT_UXMC_EBI1 (32 + 7) +#define INT_EBI2_OP_DONE (32 + 8) +#define INT_EBI2_WR_ER_DONE (32 + 9) +#define INT_TCSR_SPSS_CE (32 + 10) +#define INT_EMDH (32 + 11) +#define INT_PMDH (32 + 12) +#define INT_MDC (32 + 13) +#define INT_MIDI_TO_SUPSS (32 + 14) +#define INT_LPA_2 (32 + 15) +#define INT_GPIO_GROUP1_SECURE (32 + 16) +#define INT_GPIO_GROUP2_SECURE (32 + 17) +#define INT_GPIO_GROUP1 (32 + 18) +#define INT_GPIO_GROUP2 (32 + 19) +#define INT_MPRPH_SOFTRESET (32 + 20) +#define INT_PWB_I2C (32 + 21) +#define INT_PWB_I2C_2 (32 + 22) +#define INT_TSSC_SAMPLE (32 + 23) +#define INT_TSSC_PENUP (32 + 24) +#define INT_TCHSCRN_SSBI (32 + 25) +#define INT_FM_RDS (32 + 26) +#define INT_KEYSENSE (32 + 27) +#define INT_USB_OTG_HS (32 + 28) +#define INT_USB_OTG_HS2 (32 + 29) +#define INT_USB_OTG_HS3 (32 + 30) +#define INT_CSI (32 + 31) + +#define INT_SPI_OUTPUT (64 + 0) +#define INT_SPI_INPUT (64 + 1) +#define INT_SPI_ERROR (64 + 2) +#define INT_UART1 (64 + 3) +#define INT_UART1_RX (64 + 4) +#define INT_UART2 (64 + 5) +#define INT_UART2_RX (64 + 6) +#define INT_UART3 (64 + 7) +#define INT_UART3_RX (64 + 8) +#define INT_UART1DM_IRQ (64 + 9) +#define INT_UART1DM_RX (64 + 10) +#define INT_UART2DM_IRQ (64 + 11) +#define INT_UART2DM_RX (64 + 12) +#define INT_TSIF (64 + 13) +#define INT_ADM_SC1 (64 + 14) +#define INT_ADM_SC2 (64 + 15) +#define INT_MDP (64 + 16) +#define INT_VPE (64 + 17) +#define INT_GRP_2D (64 + 18) +#define INT_GRP_3D (64 + 19) +#define INT_ROTATOR (64 + 20) +#define INT_MFC720 (64 + 21) +#define INT_JPEG (64 + 22) +#define INT_VFE (64 + 23) +#define INT_TV_ENC (64 + 24) +#define INT_PMIC_SSBI (64 + 25) +#define INT_MPM_1 (64 + 26) +#define INT_TCSR_SPSS_SAMPLE (64 + 27) +#define INT_TCSR_SPSS_PENUP (64 + 28) +#define INT_MPM_2 (64 + 29) +#define INT_SDC1_0 (64 + 30) +#define INT_SDC1_1 (64 + 31) + +#define INT_SDC3_0 (96 + 0) +#define INT_SDC3_1 (96 + 1) +#define INT_SDC2_0 (96 + 2) +#define INT_SDC2_1 (96 + 3) +#define INT_SDC4_0 (96 + 4) +#define INT_SDC4_1 (96 + 5) +#define INT_PWB_QUP_IN (96 + 6) +#define INT_PWB_QUP_OUT (96 + 7) +#define INT_PWB_QUP_ERR (96 + 8) +#define INT_SCSS_WDT0_BITE (96 + 9) +/* SCSS_VICFIQSTS3[10:31] are RESERVED */ + +/* Retrofit universal macro names */ +#define INT_ADM_AARM INT_ADM_SC2 +#define INT_USB_HS INT_USB_OTG_HS +#define INT_USB_OTG INT_USB_OTG_HS +#define INT_TCHSCRN1 INT_TSSC_SAMPLE +#define INT_TCHSCRN2 INT_TSSC_PENUP +#define INT_GP_TIMER_EXP INT_GPT0_TIMER_EXP +#define INT_ADSP_A11 INT_AD5A_MPROC_APPS_0 +#define INT_ADSP_A9_A11 INT_AD5A_MPROC_APPS_1 +#define INT_MDDI_EXT INT_EMDH +#define INT_MDDI_PRI INT_PMDH +#define INT_MDDI_CLIENT INT_MDC +#define INT_NAND_WR_ER_DONE INT_EBI2_WR_ER_DONE +#define INT_NAND_OP_DONE INT_EBI2_OP_DONE + +#define NR_MSM_IRQS 128 +#define NR_GPIO_IRQS 182 +#define PMIC8058_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS) +#define NR_PMIC8058_GPIO_IRQS 40 +#define NR_PMIC8058_MPP_IRQS 12 +#define NR_PMIC8058_MISC_IRQS 8 +#define NR_PMIC8058_IRQS (NR_PMIC8058_GPIO_IRQS +\ + NR_PMIC8058_MPP_IRQS +\ + NR_PMIC8058_MISC_IRQS) +#define NR_BOARD_IRQS NR_PMIC8058_IRQS + +#endif /* __ASM_ARCH_MSM_IRQS_7X30_H */ diff --git a/arch/arm/mach-msm/include/mach/irqs-8960.h b/arch/arm/mach-msm/include/mach/irqs-8960.h new file mode 100644 index 00000000..81ab2a67 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/irqs-8960.h @@ -0,0 +1,277 @@ +/* Copyright (c) 2011 Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ASM_ARCH_MSM_IRQS_8960_H +#define __ASM_ARCH_MSM_IRQS_8960_H + +/* MSM ACPU Interrupt Numbers */ + +/* 0-15: STI/SGI (software triggered/generated interrupts) + 16-31: PPI (private peripheral interrupts) + 32+: SPI (shared peripheral interrupts) */ + +#define GIC_PPI_START 16 +#define GIC_SPI_START 32 + +#define INT_VGIC (GIC_PPI_START + 0) +#define INT_DEBUG_TIMER_EXP (GIC_PPI_START + 1) +#define INT_GP_TIMER_EXP (GIC_PPI_START + 2) +#define INT_GP_TIMER2_EXP (GIC_PPI_START + 3) +#define WDT0_ACCSCSSNBARK_INT (GIC_PPI_START + 4) +#define WDT1_ACCSCSSNBARK_INT (GIC_PPI_START + 5) +#define AVS_SVICINT (GIC_PPI_START + 6) +#define AVS_SVICINTSWDONE (GIC_PPI_START + 7) +#define CPU_DBGCPUXCOMMRXFULL (GIC_PPI_START + 8) +#define CPU_DBGCPUXCOMMTXEMPTY (GIC_PPI_START + 9) +#define CPU_SICCPUXPERFMONIRPTREQ (GIC_PPI_START + 10) +#define SC_AVSCPUXDOWN (GIC_PPI_START + 11) +#define SC_AVSCPUXUP (GIC_PPI_START + 12) +#define SC_SICCPUXACGIRPTREQ (GIC_PPI_START + 13) +#define SC_SICCPUXEXTFAULTIRPTREQ (GIC_PPI_START + 14) +/* PPI 15 is unused */ + +#define SC_SICMPUIRPTREQ (GIC_SPI_START + 0) +#define SC_SICL2IRPTREQ (GIC_SPI_START + 1) +#define SC_SICL2PERFMONIRPTREQ (GIC_SPI_START + 2) +#define SC_SICAGCIRPTREQ (GIC_SPI_START + 3) +#define TLMM_APCC_DIR_CONN_IRQ_0 (GIC_SPI_START + 4) +#define TLMM_APCC_DIR_CONN_IRQ_1 (GIC_SPI_START + 5) +#define TLMM_APCC_DIR_CONN_IRQ_2 (GIC_SPI_START + 6) +#define TLMM_APCC_DIR_CONN_IRQ_3 (GIC_SPI_START + 7) +#define TLMM_APCC_DIR_CONN_IRQ_4 (GIC_SPI_START + 8) +#define TLMM_APCC_DIR_CONN_IRQ_5 (GIC_SPI_START + 9) +#define TLMM_APCC_DIR_CONN_IRQ_6 (GIC_SPI_START + 10) +#define TLMM_APCC_DIR_CONN_IRQ_7 (GIC_SPI_START + 11) +#define TLMM_APCC_DIR_CONN_IRQ_8 (GIC_SPI_START + 12) +#define TLMM_APCC_DIR_CONN_IRQ_9 (GIC_SPI_START + 13) +#define PM8921_SEC_IRQ_103 (GIC_SPI_START + 14) +#define PM8018_SEC_IRQ_106 (GIC_SPI_START + 15) +#define TLMM_APCC_SUMMARY_IRQ (GIC_SPI_START + 16) +#define SPDM_RT_1_IRQ (GIC_SPI_START + 17) +#define SPDM_DIAG_IRQ (GIC_SPI_START + 18) +#define RPM_APCC_CPU0_GP_HIGH_IRQ (GIC_SPI_START + 19) +#define RPM_APCC_CPU0_GP_MEDIUM_IRQ (GIC_SPI_START + 20) +#define RPM_APCC_CPU0_GP_LOW_IRQ (GIC_SPI_START + 21) +#define RPM_APCC_CPU0_WAKE_UP_IRQ (GIC_SPI_START + 22) +#define RPM_APCC_CPU1_GP_HIGH_IRQ (GIC_SPI_START + 23) +#define RPM_APCC_CPU1_GP_MEDIUM_IRQ (GIC_SPI_START + 24) +#define RPM_APCC_CPU1_GP_LOW_IRQ (GIC_SPI_START + 25) +#define RPM_APCC_CPU1_WAKE_UP_IRQ (GIC_SPI_START + 26) +#define SSBI2_2_SC_CPU0_SECURE_IRQ (GIC_SPI_START + 27) +#define SSBI2_2_SC_CPU0_NON_SECURE_IRQ (GIC_SPI_START + 28) +#define SSBI2_1_SC_CPU0_SECURE_IRQ (GIC_SPI_START + 29) +#define SSBI2_1_SC_CPU0_NON_SECURE_IRQ (GIC_SPI_START + 30) +#define MSMC_SC_SEC_CE_IRQ (GIC_SPI_START + 31) +#define MSMC_SC_PRI_CE_IRQ (GIC_SPI_START + 32) +#define SLIMBUS0_CORE_EE1_IRQ (GIC_SPI_START + 33) +#define SLIMBUS0_BAM_EE1_IRQ (GIC_SPI_START + 34) +#define Q6FW_WDOG_EXPIRED_IRQ (GIC_SPI_START + 35) +#define Q6SW_WDOG_EXPIRED_IRQ (GIC_SPI_START + 36) +#define MSS_TO_APPS_IRQ_0 (GIC_SPI_START + 37) +#define MSS_TO_APPS_IRQ_1 (GIC_SPI_START + 38) +#define MSS_TO_APPS_IRQ_2 (GIC_SPI_START + 39) +#define MSS_TO_APPS_IRQ_3 (GIC_SPI_START + 40) +#define MSS_TO_APPS_IRQ_4 (GIC_SPI_START + 41) +#define MSS_TO_APPS_IRQ_5 (GIC_SPI_START + 42) +#define MSS_TO_APPS_IRQ_6 (GIC_SPI_START + 43) +#define MSS_TO_APPS_IRQ_7 (GIC_SPI_START + 44) +#define MSS_TO_APPS_IRQ_8 (GIC_SPI_START + 45) +#define MSS_TO_APPS_IRQ_9 (GIC_SPI_START + 46) +#define VPE_IRQ (GIC_SPI_START + 47) +#define VFE_IRQ (GIC_SPI_START + 48) +#define VCODEC_IRQ (GIC_SPI_START + 49) +#define TV_ENC_IRQ (GIC_SPI_START + 50) +#define SMMU_VPE_CB_SC_SECURE_IRQ (GIC_SPI_START + 51) +#define SMMU_VPE_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 52) +#define SMMU_VFE_CB_SC_SECURE_IRQ (GIC_SPI_START + 53) +#define SMMU_VFE_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 54) +#define SMMU_VCODEC_B_CB_SC_SECURE_IRQ (GIC_SPI_START + 55) +#define SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 56) +#define SMMU_VCODEC_A_CB_SC_SECURE_IRQ (GIC_SPI_START + 57) +#define SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 58) +#define SMMU_ROT_CB_SC_SECURE_IRQ (GIC_SPI_START + 59) +#define SMMU_ROT_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 60) +#define SMMU_MDP1_CB_SC_SECURE_IRQ (GIC_SPI_START + 61) +#define SMMU_MDP1_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 62) +#define SMMU_MDP0_CB_SC_SECURE_IRQ (GIC_SPI_START + 63) +#define SMMU_MDP0_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 64) +#define SMMU_JPEGD_CB_SC_SECURE_IRQ (GIC_SPI_START + 65) +#define SMMU_JPEGD_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 66) +#define SMMU_IJPEG_CB_SC_SECURE_IRQ (GIC_SPI_START + 67) +#define SMMU_IJPEG_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 68) +#define SMMU_GFX3D_CB_SC_SECURE_IRQ (GIC_SPI_START + 69) +#define SMMU_GFX3D_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 70) +#define SMMU_GFX2D0_CB_SC_SECURE_IRQ (GIC_SPI_START + 71) +#define SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 72) +#define ROT_IRQ (GIC_SPI_START + 73) +#define MMSS_FABRIC_IRQ (GIC_SPI_START + 74) +#define MDP_IRQ (GIC_SPI_START + 75) +#define JPEGD_IRQ (GIC_SPI_START + 76) +#define JPEG_IRQ (GIC_SPI_START + 77) +#define MMSS_IMEM_IRQ (GIC_SPI_START + 78) +#define HDMI_IRQ (GIC_SPI_START + 79) +#define GFX3D_IRQ (GIC_SPI_START + 80) +#define GFX2D0_IRQ (GIC_SPI_START + 81) +#define DSI1_IRQ (GIC_SPI_START + 82) +#define CSI_1_IRQ (GIC_SPI_START + 83) +#define CSI_0_IRQ (GIC_SPI_START + 84) +#define LPASS_SCSS_AUDIO_IF_OUT0_IRQ (GIC_SPI_START + 85) +#define LPASS_SCSS_MIDI_IRQ (GIC_SPI_START + 86) +#define LPASS_Q6SS_WDOG_EXPIRED (GIC_SPI_START + 87) +#define LPASS_SCSS_GP_LOW_IRQ (GIC_SPI_START + 88) +#define LPASS_SCSS_GP_MEDIUM_IRQ (GIC_SPI_START + 89) +#define LPASS_SCSS_GP_HIGH_IRQ (GIC_SPI_START + 90) +#define TOP_IMEM_IRQ (GIC_SPI_START + 91) +#define FABRIC_SYS_IRQ (GIC_SPI_START + 92) +#define FABRIC_APPS_IRQ (GIC_SPI_START + 93) +#define USB1_HS_BAM_IRQ (GIC_SPI_START + 94) +#define SDC4_BAM_IRQ (GIC_SPI_START + 95) +#define SDC3_BAM_IRQ (GIC_SPI_START + 96) +#define SDC2_BAM_IRQ (GIC_SPI_START + 97) +#define SDC1_BAM_IRQ (GIC_SPI_START + 98) +#define FABRIC_SPS_IRQ (GIC_SPI_START + 99) +#define USB1_HS_IRQ (GIC_SPI_START + 100) +#define SDC4_IRQ_0 (GIC_SPI_START + 101) +#define SDC3_IRQ_0 (GIC_SPI_START + 102) +#define SDC2_IRQ_0 (GIC_SPI_START + 103) +#define SDC1_IRQ_0 (GIC_SPI_START + 104) +#define SPS_BAM_DMA_IRQ (GIC_SPI_START + 105) +#define SPS_SEC_VIOL_IRQ (GIC_SPI_START + 106) +#define SPS_MTI_0 (GIC_SPI_START + 107) +#define SPS_MTI_1 (GIC_SPI_START + 108) +#define SPS_MTI_2 (GIC_SPI_START + 109) +#define SPS_MTI_3 (GIC_SPI_START + 110) +#define SPS_MTI_4 (GIC_SPI_START + 111) +#define SPS_MTI_5 (GIC_SPI_START + 112) +#define SPS_MTI_6 (GIC_SPI_START + 113) +#define SPS_MTI_7 (GIC_SPI_START + 114) +#define SPS_MTI_8 (GIC_SPI_START + 115) +#define SPS_MTI_9 (GIC_SPI_START + 116) +#define SPS_MTI_10 (GIC_SPI_START + 117) +#define SPS_MTI_11 (GIC_SPI_START + 118) +#define SPS_MTI_12 (GIC_SPI_START + 119) +#define SPS_MTI_13 (GIC_SPI_START + 120) +#define SPS_MTI_14 (GIC_SPI_START + 121) +#define SPS_MTI_15 (GIC_SPI_START + 122) +#define SPS_MTI_16 (GIC_SPI_START + 123) +#define SPS_MTI_17 (GIC_SPI_START + 124) +#define SPS_MTI_18 (GIC_SPI_START + 125) +#define SPS_MTI_19 (GIC_SPI_START + 126) +#define SPS_MTI_20 (GIC_SPI_START + 127) +#define SPS_MTI_21 (GIC_SPI_START + 128) +#define SPS_MTI_22 (GIC_SPI_START + 129) +#define SPS_MTI_23 (GIC_SPI_START + 130) +#define SPS_MTI_24 (GIC_SPI_START + 131) +#define SPS_MTI_25 (GIC_SPI_START + 132) +#define SPS_MTI_26 (GIC_SPI_START + 133) +#define SPS_MTI_27 (GIC_SPI_START + 134) +#define SPS_MTI_28 (GIC_SPI_START + 135) +#define SPS_MTI_29 (GIC_SPI_START + 136) +#define SPS_MTI_30 (GIC_SPI_START + 137) +#define SPS_MTI_31 (GIC_SPI_START + 138) +#define CSIPHY_4LN_IRQ (GIC_SPI_START + 139) +#define CSIPHY_2LN_IRQ (GIC_SPI_START + 140) +#define USB2_IRQ (GIC_SPI_START + 141) +#define USB1_IRQ (GIC_SPI_START + 142) +#define TSSC_SSBI_IRQ (GIC_SPI_START + 143) +#define TSSC_SAMPLE_IRQ (GIC_SPI_START + 144) +#define TSSC_PENUP_IRQ (GIC_SPI_START + 145) +#define GSBI1_UARTDM_IRQ (GIC_SPI_START + 146) +#define GSBI1_QUP_IRQ (GIC_SPI_START + 147) +#define GSBI2_UARTDM_IRQ (GIC_SPI_START + 148) +#define GSBI2_QUP_IRQ (GIC_SPI_START + 149) +#define GSBI3_UARTDM_IRQ (GIC_SPI_START + 150) +#define GSBI3_QUP_IRQ (GIC_SPI_START + 151) +#define GSBI4_UARTDM_IRQ (GIC_SPI_START + 152) +#define GSBI4_QUP_IRQ (GIC_SPI_START + 153) +#define GSBI5_UARTDM_IRQ (GIC_SPI_START + 154) +#define GSBI5_QUP_IRQ (GIC_SPI_START + 155) +#define GSBI6_UARTDM_IRQ (GIC_SPI_START + 156) +#define GSBI6_QUP_IRQ (GIC_SPI_START + 157) +#define GSBI7_UARTDM_IRQ (GIC_SPI_START + 158) +#define GSBI7_QUP_IRQ (GIC_SPI_START + 159) +#define GSBI8_UARTDM_IRQ (GIC_SPI_START + 160) +#define GSBI8_QUP_IRQ (GIC_SPI_START + 161) +#define TSIF_TSPP_IRQ (GIC_SPI_START + 162) +#define TSIF_BAM_IRQ (GIC_SPI_START + 163) +#define TSIF2_IRQ (GIC_SPI_START + 164) +#define TSIF1_IRQ (GIC_SPI_START + 165) +#define DSI2_IRQ (GIC_SPI_START + 166) +#define ISPIF_IRQ (GIC_SPI_START + 167) +#define MSMC_SC_SEC_TMR_IRQ (GIC_SPI_START + 168) +#define MSMC_SC_SEC_WDOG_BARK_IRQ (GIC_SPI_START + 169) +#define INT_ADM0_SCSS_0_IRQ (GIC_SPI_START + 170) +#define INT_ADM0_SCSS_1_IRQ (GIC_SPI_START + 171) +#define INT_ADM0_SCSS_2_IRQ (GIC_SPI_START + 172) +#define INT_ADM0_SCSS_3_IRQ (GIC_SPI_START + 173) +#define CC_SCSS_WDT1CPU1BITEEXPIRED (GIC_SPI_START + 174) +#define CC_SCSS_WDT1CPU0BITEEXPIRED (GIC_SPI_START + 175) +#define CC_SCSS_WDT0CPU1BITEEXPIRED (GIC_SPI_START + 176) +#define CC_SCSS_WDT0CPU0BITEEXPIRED (GIC_SPI_START + 177) +#define TSENS_UPPER_LOWER_INT (GIC_SPI_START + 178) +#define SSBI2_2_SC_CPU1_SECURE_INT (GIC_SPI_START + 179) +#define SSBI2_2_SC_CPU1_NON_SECURE_INT (GIC_SPI_START + 180) +#define SSBI2_1_SC_CPU1_SECURE_INT (GIC_SPI_START + 181) +#define SSBI2_1_SC_CPU1_NON_SECURE_INT (GIC_SPI_START + 182) +#define XPU_SUMMARY_IRQ (GIC_SPI_START + 183) +#define BUS_EXCEPTION_SUMMARY_IRQ (GIC_SPI_START + 184) +#define HSDDRX_EBI1CH0_IRQ (GIC_SPI_START + 185) +#define HSDDRX_EBI1CH1_IRQ (GIC_SPI_START + 186) +#define SDC5_BAM_IRQ (GIC_SPI_START + 187) +#define SDC5_IRQ_0 (GIC_SPI_START + 188) +#define GSBI9_UARTDM_IRQ (GIC_SPI_START + 189) +#define GSBI9_QUP_IRQ (GIC_SPI_START + 190) +#define GSBI10_UARTDM_IRQ (GIC_SPI_START + 191) +#define GSBI10_QUP_IRQ (GIC_SPI_START + 192) +#define GSBI11_UARTDM_IRQ (GIC_SPI_START + 193) +#define GSBI11_QUP_IRQ (GIC_SPI_START + 194) +#define GSBI12_UARTDM_IRQ (GIC_SPI_START + 195) +#define GSBI12_QUP_IRQ (GIC_SPI_START + 196) +#define RIVA_APSS_LTECOEX_IRQ (GIC_SPI_START + 197) +#define RIVA_APSS_SPARE_IRQ (GIC_SPI_START + 198) +#define RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ (GIC_SPI_START + 199) +#define RIVA_ASS_RESET_DONE_IRQ (GIC_SPI_START + 200) +#define RIVA_APSS_ASIC_IRQ (GIC_SPI_START + 201) +#define RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ (GIC_SPI_START + 202) +#define RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ (GIC_SPI_START + 203) +#define RIVA_APPS_WLAM_SMSM_IRQ (GIC_SPI_START + 204) +#define RIVA_APPS_LOG_CTRL_IRQ (GIC_SPI_START + 205) +#define RIVA_APPS_FM_CTRL_IRQ (GIC_SPI_START + 206) +#define RIVA_APPS_HCI_IRQ (GIC_SPI_START + 207) +#define RIVA_APPS_WLAN_CTRL_IRQ (GIC_SPI_START + 208) +#define A2_BAM_IRQ (GIC_SPI_START + 209) +#define SMMU_GFX2D1_CB_SC_SECURE_IRQ (GIC_SPI_START + 210) +#define SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 211) +#define GFX2D1_IRQ (GIC_SPI_START + 212) +#define PPSS_WDOG_TIMER_IRQ (GIC_SPI_START + 213) +#define SPS_SLIMBUS_CORE_EE0_IRQ (GIC_SPI_START + 214) +#define SPS_SLIMBUS_BAM_EE0_IRQ (GIC_SPI_START + 215) +#define QDSS_ETB_IRQ (GIC_SPI_START + 216) +#define QDSS_CTI2KPSS_CPU1_IRQ (GIC_SPI_START + 217) +#define QDSS_CTI2KPSS_CPU0_IRQ (GIC_SPI_START + 218) +#define TLMM_APCC_DIR_CONN_IRQ_16 (GIC_SPI_START + 219) +#define TLMM_APCC_DIR_CONN_IRQ_17 (GIC_SPI_START + 220) +#define TLMM_APCC_DIR_CONN_IRQ_18 (GIC_SPI_START + 221) +#define TLMM_APCC_DIR_CONN_IRQ_19 (GIC_SPI_START + 222) +#define TLMM_APCC_DIR_CONN_IRQ_20 (GIC_SPI_START + 223) +#define TLMM_APCC_DIR_CONN_IRQ_21 (GIC_SPI_START + 224) +#define PM8921_SEC_IRQ_104 (GIC_SPI_START + 225) +#define PM8018_SEC_IRQ_107 (GIC_SPI_START + 226) + +/* For now, use the maximum number of interrupts until a pending GIC issue + * is sorted out */ +#define NR_MSM_IRQS 1020 +#define NR_BOARD_IRQS 0 +#define NR_GPIO_IRQS 0 + +#endif + diff --git a/arch/arm/mach-msm/include/mach/irqs-8x50.h b/arch/arm/mach-msm/include/mach/irqs-8x50.h new file mode 100644 index 00000000..26adbe0e --- /dev/null +++ b/arch/arm/mach-msm/include/mach/irqs-8x50.h @@ -0,0 +1,88 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ASM_ARCH_MSM_IRQS_8XXX_H +#define __ASM_ARCH_MSM_IRQS_8XXX_H + +/* MSM ACPU Interrupt Numbers */ + +#define INT_A9_M2A_0 0 +#define INT_A9_M2A_1 1 +#define INT_A9_M2A_2 2 +#define INT_A9_M2A_3 3 +#define INT_A9_M2A_4 4 +#define INT_A9_M2A_5 5 +#define INT_A9_M2A_6 6 +#define INT_GP_TIMER_EXP 7 +#define INT_DEBUG_TIMER_EXP 8 +#define INT_SIRC_0 9 +#define INT_SDC3_0 10 +#define INT_SDC3_1 11 +#define INT_SDC4_0 12 +#define INT_SDC4_1 13 +#define INT_AD6_EXT_VFR 14 +#define INT_USB_OTG 15 +#define INT_MDDI_PRI 16 +#define INT_MDDI_EXT 17 +#define INT_MDDI_CLIENT 18 +#define INT_MDP 19 +#define INT_GRAPHICS 20 +#define INT_ADM_AARM 21 +#define INT_ADSP_A11 22 +#define INT_ADSP_A9_A11 23 +#define INT_SDC1_0 24 +#define INT_SDC1_1 25 +#define INT_SDC2_0 26 +#define INT_SDC2_1 27 +#define INT_KEYSENSE 28 +#define INT_TCHSCRN_SSBI 29 +#define INT_TCHSCRN1 30 +#define INT_TCHSCRN2 31 + +#define INT_TCSR_MPRPH_SC1 (32 + 0) +#define INT_USB_FS2 (32 + 1) +#define INT_PWB_I2C (32 + 2) +#define INT_SOFTRESET (32 + 3) +#define INT_NAND_WR_ER_DONE (32 + 4) +#define INT_NAND_OP_DONE (32 + 5) +#define INT_TCSR_MPRPH_SC2 (32 + 6) +#define INT_OP_PEN (32 + 7) +#define INT_AD_HSSD (32 + 8) +#define INT_ARM11_PM (32 + 9) +#define INT_SDMA_NON_SECURE (32 + 10) +#define INT_TSIF_IRQ (32 + 11) +#define INT_UART1DM_IRQ (32 + 12) +#define INT_UART1DM_RX (32 + 13) +#define INT_SDMA_SECURE (32 + 14) +#define INT_SI2S_SLAVE (32 + 15) +#define INT_SC_I2CPU (32 + 16) +#define INT_SC_DBG_RDTRFULL (32 + 17) +#define INT_SC_DBG_WDTRFULL (32 + 18) +#define INT_SCPLL_CTL_DONE (32 + 19) +#define INT_UART2DM_IRQ (32 + 20) +#define INT_UART2DM_RX (32 + 21) +#define INT_VDC_MEC (32 + 22) +#define INT_VDC_DB (32 + 23) +#define INT_VDC_AXI (32 + 24) +#define INT_VFE (32 + 25) +#define INT_USB_HS (32 + 26) +#define INT_AUDIO_OUT0 (32 + 27) +#define INT_AUDIO_OUT1 (32 + 28) +#define INT_CRYPTO (32 + 29) +#define INT_AD6M_IDLE (32 + 30) +#define INT_SIRC_1 (32 + 31) + +#define NR_GPIO_IRQS 165 +#define NR_MSM_IRQS 64 +#define NR_BOARD_IRQS 64 + +#endif diff --git a/arch/arm/mach-msm/include/mach/irqs-8x60.h b/arch/arm/mach-msm/include/mach/irqs-8x60.h new file mode 100644 index 00000000..f65841c7 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/irqs-8x60.h @@ -0,0 +1,258 @@ +/* Copyright (c) 2010 Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_IRQS_8X60_H +#define __ASM_ARCH_MSM_IRQS_8X60_H + +/* MSM ACPU Interrupt Numbers */ + +/* 0-15: STI/SGI (software triggered/generated interrupts) + * 16-31: PPI (private peripheral interrupts) + * 32+: SPI (shared peripheral interrupts) + */ + +#define GIC_PPI_START 16 +#define GIC_SPI_START 32 + +#define INT_DEBUG_TIMER_EXP (GIC_PPI_START + 0) +#define INT_GP_TIMER_EXP (GIC_PPI_START + 1) +#define INT_GP_TIMER2_EXP (GIC_PPI_START + 2) +#define WDT0_ACCSCSSNBARK_INT (GIC_PPI_START + 3) +#define WDT1_ACCSCSSNBARK_INT (GIC_PPI_START + 4) +#define AVS_SVICINT (GIC_PPI_START + 5) +#define AVS_SVICINTSWDONE (GIC_PPI_START + 6) +#define CPU_DBGCPUXCOMMRXFULL (GIC_PPI_START + 7) +#define CPU_DBGCPUXCOMMTXEMPTY (GIC_PPI_START + 8) +#define CPU_SICCPUXPERFMONIRPTREQ (GIC_PPI_START + 9) +#define SC_AVSCPUXDOWN (GIC_PPI_START + 10) +#define SC_AVSCPUXUP (GIC_PPI_START + 11) +#define SC_SICCPUXACGIRPTREQ (GIC_PPI_START + 12) +/* PPI 13 to 15 are unused */ + + +#define SC_SICMPUIRPTREQ (GIC_SPI_START + 0) +#define SC_SICL2IRPTREQ (GIC_SPI_START + 1) +#define SC_SICL2ACGIRPTREQ (GIC_SPI_START + 2) +#define NC (GIC_SPI_START + 3) +#define TLMM_SCSS_DIR_CONN_IRQ_0 (GIC_SPI_START + 4) +#define TLMM_SCSS_DIR_CONN_IRQ_1 (GIC_SPI_START + 5) +#define TLMM_SCSS_DIR_CONN_IRQ_2 (GIC_SPI_START + 6) +#define TLMM_SCSS_DIR_CONN_IRQ_3 (GIC_SPI_START + 7) +#define TLMM_SCSS_DIR_CONN_IRQ_4 (GIC_SPI_START + 8) +#define TLMM_SCSS_DIR_CONN_IRQ_5 (GIC_SPI_START + 9) +#define TLMM_SCSS_DIR_CONN_IRQ_6 (GIC_SPI_START + 10) +#define TLMM_SCSS_DIR_CONN_IRQ_7 (GIC_SPI_START + 11) +#define TLMM_SCSS_DIR_CONN_IRQ_8 (GIC_SPI_START + 12) +#define TLMM_SCSS_DIR_CONN_IRQ_9 (GIC_SPI_START + 13) +#define PM8058_SEC_IRQ_N (GIC_SPI_START + 14) +#define PM8901_SEC_IRQ_N (GIC_SPI_START + 15) +#define TLMM_SCSS_SUMMARY_IRQ (GIC_SPI_START + 16) +#define SPDM_RT_1_IRQ (GIC_SPI_START + 17) +#define SPDM_DIAG_IRQ (GIC_SPI_START + 18) +#define RPM_SCSS_CPU0_GP_HIGH_IRQ (GIC_SPI_START + 19) +#define RPM_SCSS_CPU0_GP_MEDIUM_IRQ (GIC_SPI_START + 20) +#define RPM_SCSS_CPU0_GP_LOW_IRQ (GIC_SPI_START + 21) +#define RPM_SCSS_CPU0_WAKE_UP_IRQ (GIC_SPI_START + 22) +#define RPM_SCSS_CPU1_GP_HIGH_IRQ (GIC_SPI_START + 23) +#define RPM_SCSS_CPU1_GP_MEDIUM_IRQ (GIC_SPI_START + 24) +#define RPM_SCSS_CPU1_GP_LOW_IRQ (GIC_SPI_START + 25) +#define RPM_SCSS_CPU1_WAKE_UP_IRQ (GIC_SPI_START + 26) +#define SSBI2_2_SC_CPU0_SECURE_INT (GIC_SPI_START + 27) +#define SSBI2_2_SC_CPU0_NON_SECURE_INT (GIC_SPI_START + 28) +#define SSBI2_1_SC_CPU0_SECURE_INT (GIC_SPI_START + 29) +#define SSBI2_1_SC_CPU0_NON_SECURE_INT (GIC_SPI_START + 30) +#define MSMC_SC_SEC_CE_IRQ (GIC_SPI_START + 31) +#define MSMC_SC_PRI_CE_IRQ (GIC_SPI_START + 32) +#define MARM_FIQ (GIC_SPI_START + 33) +#define MARM_IRQ (GIC_SPI_START + 34) +#define MARM_L2CC_IRQ (GIC_SPI_START + 35) +#define MARM_WDOG_EXPIRED (GIC_SPI_START + 36) +#define MARM_SCSS_GP_IRQ_0 (GIC_SPI_START + 37) +#define MARM_SCSS_GP_IRQ_1 (GIC_SPI_START + 38) +#define MARM_SCSS_GP_IRQ_2 (GIC_SPI_START + 39) +#define MARM_SCSS_GP_IRQ_3 (GIC_SPI_START + 40) +#define MARM_SCSS_GP_IRQ_4 (GIC_SPI_START + 41) +#define MARM_SCSS_GP_IRQ_5 (GIC_SPI_START + 42) +#define MARM_SCSS_GP_IRQ_6 (GIC_SPI_START + 43) +#define MARM_SCSS_GP_IRQ_7 (GIC_SPI_START + 44) +#define MARM_SCSS_GP_IRQ_8 (GIC_SPI_START + 45) +#define MARM_SCSS_GP_IRQ_9 (GIC_SPI_START + 46) +#define VPE_IRQ (GIC_SPI_START + 47) +#define VFE_IRQ (GIC_SPI_START + 48) +#define VCODEC_IRQ (GIC_SPI_START + 49) +#define TV_ENC_IRQ (GIC_SPI_START + 50) +#define SMMU_VPE_CB_SC_SECURE_IRQ (GIC_SPI_START + 51) +#define SMMU_VPE_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 52) +#define SMMU_VFE_CB_SC_SECURE_IRQ (GIC_SPI_START + 53) +#define SMMU_VFE_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 54) +#define SMMU_VCODEC_B_CB_SC_SECURE_IRQ (GIC_SPI_START + 55) +#define SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 56) +#define SMMU_VCODEC_A_CB_SC_SECURE_IRQ (GIC_SPI_START + 57) +#define SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 58) +#define SMMU_ROT_CB_SC_SECURE_IRQ (GIC_SPI_START + 59) +#define SMMU_ROT_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 60) +#define SMMU_MDP1_CB_SC_SECURE_IRQ (GIC_SPI_START + 61) +#define SMMU_MDP1_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 62) +#define SMMU_MDP0_CB_SC_SECURE_IRQ (GIC_SPI_START + 63) +#define SMMU_MDP0_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 64) +#define SMMU_JPEGD_CB_SC_SECURE_IRQ (GIC_SPI_START + 65) +#define SMMU_JPEGD_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 66) +#define SMMU_IJPEG_CB_SC_SECURE_IRQ (GIC_SPI_START + 67) +#define SMMU_IJPEG_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 68) +#define SMMU_GFX3D_CB_SC_SECURE_IRQ (GIC_SPI_START + 69) +#define SMMU_GFX3D_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 70) +#define SMMU_GFX2D0_CB_SC_SECURE_IRQ (GIC_SPI_START + 71) +#define SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 72) +#define ROT_IRQ (GIC_SPI_START + 73) +#define MMSS_FABRIC_IRQ (GIC_SPI_START + 74) +#define MDP_IRQ (GIC_SPI_START + 75) +#define JPEGD_IRQ (GIC_SPI_START + 76) +#define JPEG_IRQ (GIC_SPI_START + 77) +#define MMSS_IMEM_IRQ (GIC_SPI_START + 78) +#define HDMI_IRQ (GIC_SPI_START + 79) +#define GFX3D_IRQ (GIC_SPI_START + 80) +#define GFX2D0_IRQ (GIC_SPI_START + 81) +#define DSI_IRQ (GIC_SPI_START + 82) +#define CSI_1_IRQ (GIC_SPI_START + 83) +#define CSI_0_IRQ (GIC_SPI_START + 84) +#define LPASS_SCSS_AUDIO_IF_OUT0_IRQ (GIC_SPI_START + 85) +#define LPASS_SCSS_MIDI_IRQ (GIC_SPI_START + 86) +#define LPASS_Q6SS_WDOG_EXPIRED (GIC_SPI_START + 87) +#define LPASS_SCSS_GP_LOW_IRQ (GIC_SPI_START + 88) +#define LPASS_SCSS_GP_MEDIUM_IRQ (GIC_SPI_START + 89) +#define LPASS_SCSS_GP_HIGH_IRQ (GIC_SPI_START + 90) +#define TOP_IMEM_IRQ (GIC_SPI_START + 91) +#define FABRIC_SYS_IRQ (GIC_SPI_START + 92) +#define FABRIC_APPS_IRQ (GIC_SPI_START + 93) +#define USB1_HS_BAM_IRQ (GIC_SPI_START + 94) +#define SDC4_BAM_IRQ (GIC_SPI_START + 95) +#define SDC3_BAM_IRQ (GIC_SPI_START + 96) +#define SDC2_BAM_IRQ (GIC_SPI_START + 97) +#define SDC1_BAM_IRQ (GIC_SPI_START + 98) +#define FABRIC_SPS_IRQ (GIC_SPI_START + 99) +#define USB1_HS_IRQ (GIC_SPI_START + 100) +#define SDC4_IRQ_0 (GIC_SPI_START + 101) +#define SDC3_IRQ_0 (GIC_SPI_START + 102) +#define SDC2_IRQ_0 (GIC_SPI_START + 103) +#define SDC1_IRQ_0 (GIC_SPI_START + 104) +#define SPS_BAM_DMA_IRQ (GIC_SPI_START + 105) +#define SPS_SEC_VIOL_IRQ (GIC_SPI_START + 106) +#define SPS_MTI_0 (GIC_SPI_START + 107) +#define SPS_MTI_1 (GIC_SPI_START + 108) +#define SPS_MTI_2 (GIC_SPI_START + 109) +#define SPS_MTI_3 (GIC_SPI_START + 110) +#define SPS_MTI_4 (GIC_SPI_START + 111) +#define SPS_MTI_5 (GIC_SPI_START + 112) +#define SPS_MTI_6 (GIC_SPI_START + 113) +#define SPS_MTI_7 (GIC_SPI_START + 114) +#define SPS_MTI_8 (GIC_SPI_START + 115) +#define SPS_MTI_9 (GIC_SPI_START + 116) +#define SPS_MTI_10 (GIC_SPI_START + 117) +#define SPS_MTI_11 (GIC_SPI_START + 118) +#define SPS_MTI_12 (GIC_SPI_START + 119) +#define SPS_MTI_13 (GIC_SPI_START + 120) +#define SPS_MTI_14 (GIC_SPI_START + 121) +#define SPS_MTI_15 (GIC_SPI_START + 122) +#define SPS_MTI_16 (GIC_SPI_START + 123) +#define SPS_MTI_17 (GIC_SPI_START + 124) +#define SPS_MTI_18 (GIC_SPI_START + 125) +#define SPS_MTI_19 (GIC_SPI_START + 126) +#define SPS_MTI_20 (GIC_SPI_START + 127) +#define SPS_MTI_21 (GIC_SPI_START + 128) +#define SPS_MTI_22 (GIC_SPI_START + 129) +#define SPS_MTI_23 (GIC_SPI_START + 130) +#define SPS_MTI_24 (GIC_SPI_START + 131) +#define SPS_MTI_25 (GIC_SPI_START + 132) +#define SPS_MTI_26 (GIC_SPI_START + 133) +#define SPS_MTI_27 (GIC_SPI_START + 134) +#define SPS_MTI_28 (GIC_SPI_START + 135) +#define SPS_MTI_29 (GIC_SPI_START + 136) +#define SPS_MTI_30 (GIC_SPI_START + 137) +#define SPS_MTI_31 (GIC_SPI_START + 138) +#define UXMC_EBI2_WR_ER_DONE_IRQ (GIC_SPI_START + 139) +#define UXMC_EBI2_OP_DONE_IRQ (GIC_SPI_START + 140) +#define USB2_IRQ (GIC_SPI_START + 141) +#define USB1_IRQ (GIC_SPI_START + 142) +#define TSSC_SSBI_IRQ (GIC_SPI_START + 143) +#define TSSC_SAMPLE_IRQ (GIC_SPI_START + 144) +#define TSSC_PENUP_IRQ (GIC_SPI_START + 145) +#define INT_UART1DM_IRQ (GIC_SPI_START + 146) +#define GSBI1_QUP_IRQ (GIC_SPI_START + 147) +#define INT_UART2DM_IRQ (GIC_SPI_START + 148) +#define GSBI2_QUP_IRQ (GIC_SPI_START + 149) +#define INT_UART3DM_IRQ (GIC_SPI_START + 150) +#define GSBI3_QUP_IRQ (GIC_SPI_START + 151) +#define INT_UART4DM_IRQ (GIC_SPI_START + 152) +#define GSBI4_QUP_IRQ (GIC_SPI_START + 153) +#define INT_UART5DM_IRQ (GIC_SPI_START + 154) +#define GSBI5_QUP_IRQ (GIC_SPI_START + 155) +#define INT_UART6DM_IRQ (GIC_SPI_START + 156) +#define GSBI6_QUP_IRQ (GIC_SPI_START + 157) +#define INT_UART7DM_IRQ (GIC_SPI_START + 158) +#define GSBI7_QUP_IRQ (GIC_SPI_START + 159) +#define INT_UART8DM_IRQ (GIC_SPI_START + 160) +#define GSBI8_QUP_IRQ (GIC_SPI_START + 161) +#define TSIF_TSPP_IRQ (GIC_SPI_START + 162) +#define TSIF_BAM_IRQ (GIC_SPI_START + 163) +#define TSIF2_IRQ (GIC_SPI_START + 164) +#define TSIF1_IRQ (GIC_SPI_START + 165) +#define INT_ADM1_MASTER (GIC_SPI_START + 166) +#define INT_ADM1_AARM (GIC_SPI_START + 167) +#define INT_ADM1_SD2 (GIC_SPI_START + 168) +#define INT_ADM1_SD3 (GIC_SPI_START + 169) +#define INT_ADM0_MASTER (GIC_SPI_START + 170) +#define INT_ADM0_AARM (GIC_SPI_START + 171) +#define INT_ADM0_SD2 (GIC_SPI_START + 172) +#define INT_ADM0_SD3 (GIC_SPI_START + 173) +#define CC_SCSS_WDT1CPU1BITEEXPIRED (GIC_SPI_START + 174) +#define CC_SCSS_WDT1CPU0BITEEXPIRED (GIC_SPI_START + 175) +#define CC_SCSS_WDT0CPU1BITEEXPIRED (GIC_SPI_START + 176) +#define CC_SCSS_WDT0CPU0BITEEXPIRED (GIC_SPI_START + 177) +#define TSENS_UPPER_LOWER_INT (GIC_SPI_START + 178) +#define SSBI2_2_SC_CPU1_SECURE_INT (GIC_SPI_START + 179) +#define SSBI2_2_SC_CPU1_NON_SECURE_INT (GIC_SPI_START + 180) +#define SSBI2_1_SC_CPU1_SECURE_INT (GIC_SPI_START + 181) +#define SSBI2_1_SC_CPU1_NON_SECURE_INT (GIC_SPI_START + 182) +#define XPU_SUMMARY_IRQ (GIC_SPI_START + 183) +#define BUS_EXCEPTION_SUMMARY_IRQ (GIC_SPI_START + 184) +#define HSDDRX_SMICH0_IRQ (GIC_SPI_START + 185) +#define HSDDRX_EBI1_IRQ (GIC_SPI_START + 186) +#define SDC5_BAM_IRQ (GIC_SPI_START + 187) +#define SDC5_IRQ_0 (GIC_SPI_START + 188) +#define INT_UART9DM_IRQ (GIC_SPI_START + 189) +#define GSBI9_QUP_IRQ (GIC_SPI_START + 190) +#define INT_UART10DM_IRQ (GIC_SPI_START + 191) +#define GSBI10_QUP_IRQ (GIC_SPI_START + 192) +#define INT_UART11DM_IRQ (GIC_SPI_START + 193) +#define GSBI11_QUP_IRQ (GIC_SPI_START + 194) +#define INT_UART12DM_IRQ (GIC_SPI_START + 195) +#define GSBI12_QUP_IRQ (GIC_SPI_START + 196) + +/*SPI 197 to 209 arent used in 8x60*/ +#define SMMU_GFX2D1_CB_SC_SECURE_IRQ (GIC_SPI_START + 210) +#define SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 211) + +/*SPI 212 to 216 arent used in 8x60*/ +#define SMPSS_SPARE_1 (GIC_SPI_START + 217) +#define SMPSS_SPARE_2 (GIC_SPI_START + 218) +#define SMPSS_SPARE_3 (GIC_SPI_START + 219) +#define SMPSS_SPARE_4 (GIC_SPI_START + 220) +#define SMPSS_SPARE_5 (GIC_SPI_START + 221) +#define SMPSS_SPARE_6 (GIC_SPI_START + 222) +#define SMPSS_SPARE_7 (GIC_SPI_START + 223) + +#define NR_GPIO_IRQS 173 +#define NR_MSM_IRQS 256 +#define NR_BOARD_IRQS 0 + +#endif diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h new file mode 100644 index 00000000..3cd78b16 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/irqs.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_IRQS_H +#define __ASM_ARCH_MSM_IRQS_H + +#define MSM_IRQ_BIT(irq) (1 << ((irq) & 31)) + +#if defined(CONFIG_ARCH_MSM7X30) +#include "irqs-7x30.h" +#elif defined(CONFIG_ARCH_QSD8X50) +#include "irqs-8x50.h" +#include "sirc.h" +#elif defined(CONFIG_ARCH_MSM8X60) +#include "irqs-8x60.h" +#elif defined(CONFIG_ARCH_MSM8960) +/* TODO: Make these not generic. */ +#include "irqs-8960.h" +#elif defined(CONFIG_ARCH_MSM_ARM11) +#include "irqs-7x00.h" +#else +#error "Unknown architecture specification" +#endif + +#define NR_IRQS (NR_MSM_IRQS + NR_GPIO_IRQS + NR_BOARD_IRQS) +#define MSM_GPIO_TO_INT(n) (NR_MSM_IRQS + (n)) +#define MSM_INT_TO_REG(base, irq) (base + irq / 32) + +#endif diff --git a/arch/arm/mach-msm/include/mach/mmc.h b/arch/arm/mach-msm/include/mach/mmc.h new file mode 100644 index 00000000..ffcd9e3a --- /dev/null +++ b/arch/arm/mach-msm/include/mach/mmc.h @@ -0,0 +1,30 @@ +/* + * arch/arm/include/asm/mach/mmc.h + */ +#ifndef ASMARM_MACH_MMC_H +#define ASMARM_MACH_MMC_H + +#include <linux/mmc/host.h> +#include <linux/mmc/card.h> +#include <linux/mmc/sdio_func.h> + +struct msm_mmc_gpio { + unsigned no; + const char *name; +}; + +struct msm_mmc_gpio_data { + struct msm_mmc_gpio *gpio; + u8 size; +}; + +struct msm_mmc_platform_data { + unsigned int ocr_mask; /* available voltages */ + u32 (*translate_vdd)(struct device *, unsigned int); + unsigned int (*status)(struct device *); + int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id); + struct msm_mmc_gpio_data *gpio_data; + void (*init_card)(struct mmc_card *card); +}; + +#endif diff --git a/arch/arm/mach-msm/include/mach/msm_fb.h b/arch/arm/mach-msm/include/mach/msm_fb.h new file mode 100644 index 00000000..1f4fc81b --- /dev/null +++ b/arch/arm/mach-msm/include/mach/msm_fb.h @@ -0,0 +1,147 @@ +/* arch/arm/mach-msm/include/mach/msm_fb.h + * + * Internal shared definitions for various MSM framebuffer parts. + * + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _MSM_FB_H_ +#define _MSM_FB_H_ + +#include <linux/device.h> + +struct mddi_info; + +struct msm_fb_data { + int xres; /* x resolution in pixels */ + int yres; /* y resolution in pixels */ + int width; /* disply width in mm */ + int height; /* display height in mm */ + unsigned output_format; +}; + +struct msmfb_callback { + void (*func)(struct msmfb_callback *); +}; + +enum { + MSM_MDDI_PMDH_INTERFACE, + MSM_MDDI_EMDH_INTERFACE, + MSM_EBI2_INTERFACE, +}; + +#define MSMFB_CAP_PARTIAL_UPDATES (1 << 0) + +struct msm_panel_data { + /* turns off the fb memory */ + int (*suspend)(struct msm_panel_data *); + /* turns on the fb memory */ + int (*resume)(struct msm_panel_data *); + /* turns off the panel */ + int (*blank)(struct msm_panel_data *); + /* turns on the panel */ + int (*unblank)(struct msm_panel_data *); + void (*wait_vsync)(struct msm_panel_data *); + void (*request_vsync)(struct msm_panel_data *, struct msmfb_callback *); + void (*clear_vsync)(struct msm_panel_data *); + /* from the enum above */ + unsigned interface_type; + /* data to be passed to the fb driver */ + struct msm_fb_data *fb_data; + + /* capabilities supported by the panel */ + uint32_t caps; +}; + +struct msm_mddi_client_data { + void (*suspend)(struct msm_mddi_client_data *); + void (*resume)(struct msm_mddi_client_data *); + void (*activate_link)(struct msm_mddi_client_data *); + void (*remote_write)(struct msm_mddi_client_data *, uint32_t val, + uint32_t reg); + uint32_t (*remote_read)(struct msm_mddi_client_data *, uint32_t reg); + void (*auto_hibernate)(struct msm_mddi_client_data *, int); + /* custom data that needs to be passed from the board file to a + * particular client */ + void *private_client_data; + struct resource *fb_resource; + /* from the list above */ + unsigned interface_type; +}; + +struct msm_mddi_platform_data { + unsigned int clk_rate; + void (*power_client)(struct msm_mddi_client_data *, int on); + + /* fixup the mfr name, product id */ + void (*fixup)(uint16_t *mfr_name, uint16_t *product_id); + + struct resource *fb_resource; /*optional*/ + /* number of clients in the list that follows */ + int num_clients; + /* array of client information of clients */ + struct { + unsigned product_id; /* mfr id in top 16 bits, product id + * in lower 16 bits + */ + char *name; /* the device name will be the platform + * device name registered for the client, + * it should match the name of the associated + * driver + */ + unsigned id; /* id for mddi client device node, will also + * be used as device id of panel devices, if + * the client device will have multiple panels + * space must be left here for them + */ + void *client_data; /* required private client data */ + unsigned int clk_rate; /* optional: if the client requires a + * different mddi clk rate + */ + } client_platform_data[]; +}; + +struct mdp_blit_req; +struct fb_info; +struct mdp_device { + struct device dev; + void (*dma)(struct mdp_device *mpd, uint32_t addr, + uint32_t stride, uint32_t w, uint32_t h, uint32_t x, + uint32_t y, struct msmfb_callback *callback, int interface); + void (*dma_wait)(struct mdp_device *mdp); + int (*blit)(struct mdp_device *mdp, struct fb_info *fb, + struct mdp_blit_req *req); + void (*set_grp_disp)(struct mdp_device *mdp, uint32_t disp_id); +}; + +struct class_interface; +int register_mdp_client(struct class_interface *class_intf); + +/**** private client data structs go below this line ***/ + +struct msm_mddi_bridge_platform_data { + /* from board file */ + int (*init)(struct msm_mddi_bridge_platform_data *, + struct msm_mddi_client_data *); + int (*uninit)(struct msm_mddi_bridge_platform_data *, + struct msm_mddi_client_data *); + /* passed to panel for use by the fb driver */ + int (*blank)(struct msm_mddi_bridge_platform_data *, + struct msm_mddi_client_data *); + int (*unblank)(struct msm_mddi_bridge_platform_data *, + struct msm_mddi_client_data *); + struct msm_fb_data fb_data; +}; + + + +#endif diff --git a/arch/arm/mach-msm/include/mach/msm_gpiomux.h b/arch/arm/mach-msm/include/mach/msm_gpiomux.h new file mode 100644 index 00000000..0c7d3936 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/msm_gpiomux.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _LINUX_MSM_GPIOMUX_H +#define _LINUX_MSM_GPIOMUX_H + +#ifdef CONFIG_MSM_GPIOMUX + +/* Increment a gpio's reference count, possibly activating the line. */ +int __must_check msm_gpiomux_get(unsigned gpio); + +/* Decrement a gpio's reference count, possibly suspending the line. */ +int msm_gpiomux_put(unsigned gpio); + +#else + +static inline int __must_check msm_gpiomux_get(unsigned gpio) +{ + return -ENOSYS; +} + +static inline int msm_gpiomux_put(unsigned gpio) +{ + return -ENOSYS; +} + +#endif + +#endif /* _LINUX_MSM_GPIOMUX_H */ diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h new file mode 100644 index 00000000..6c4046c2 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h @@ -0,0 +1,115 @@ +/* arch/arm/mach-msm/include/mach/msm_iomap.h + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * The MSM peripherals are spread all over across 768MB of physical + * space, which makes just having a simple IO_ADDRESS macro to slide + * them into the right virtual location rough. Instead, we will + * provide a master phys->virt mapping for peripherals here. + * + */ + +#ifndef __ASM_ARCH_MSM_IOMAP_7X00_H +#define __ASM_ARCH_MSM_IOMAP_7X00_H + +#include <asm/sizes.h> + +/* Physical base address and size of peripherals. + * Ordered by the virtual base addresses they will be mapped at. + * + * MSM_VIC_BASE must be an value that can be loaded via a "mov" + * instruction, otherwise entry-macro.S will not compile. + * + * If you add or remove entries here, you'll want to edit the + * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your + * changes. + * + */ + +#define MSM_VIC_BASE IOMEM(0xE0000000) +#define MSM_VIC_PHYS 0xC0000000 +#define MSM_VIC_SIZE SZ_4K + +#define MSM7X00_CSR_PHYS 0xC0100000 +#define MSM7X00_CSR_SIZE SZ_4K + +#define MSM_DMOV_BASE IOMEM(0xE0002000) +#define MSM_DMOV_PHYS 0xA9700000 +#define MSM_DMOV_SIZE SZ_4K + +#define MSM7X00_GPIO1_PHYS 0xA9200000 +#define MSM7X00_GPIO1_SIZE SZ_4K + +#define MSM7X00_GPIO2_PHYS 0xA9300000 +#define MSM7X00_GPIO2_SIZE SZ_4K + +#define MSM_CLK_CTL_BASE IOMEM(0xE0005000) +#define MSM_CLK_CTL_PHYS 0xA8600000 +#define MSM_CLK_CTL_SIZE SZ_4K + +#define MSM_SHARED_RAM_BASE IOMEM(0xE0100000) +#define MSM_SHARED_RAM_PHYS 0x01F00000 +#define MSM_SHARED_RAM_SIZE SZ_1M + +#define MSM_UART1_PHYS 0xA9A00000 +#define MSM_UART1_SIZE SZ_4K + +#define MSM_UART2_PHYS 0xA9B00000 +#define MSM_UART2_SIZE SZ_4K + +#define MSM_UART3_PHYS 0xA9C00000 +#define MSM_UART3_SIZE SZ_4K + +#define MSM_SDC1_PHYS 0xA0400000 +#define MSM_SDC1_SIZE SZ_4K + +#define MSM_SDC2_PHYS 0xA0500000 +#define MSM_SDC2_SIZE SZ_4K + +#define MSM_SDC3_PHYS 0xA0600000 +#define MSM_SDC3_SIZE SZ_4K + +#define MSM_SDC4_PHYS 0xA0700000 +#define MSM_SDC4_SIZE SZ_4K + +#define MSM_I2C_PHYS 0xA9900000 +#define MSM_I2C_SIZE SZ_4K + +#define MSM_HSUSB_PHYS 0xA0800000 +#define MSM_HSUSB_SIZE SZ_4K + +#define MSM_PMDH_PHYS 0xAA600000 +#define MSM_PMDH_SIZE SZ_4K + +#define MSM_EMDH_PHYS 0xAA700000 +#define MSM_EMDH_SIZE SZ_4K + +#define MSM_MDP_PHYS 0xAA200000 +#define MSM_MDP_SIZE 0x000F0000 + +#define MSM_MDC_PHYS 0xAA500000 +#define MSM_MDC_SIZE SZ_1M + +#define MSM_AD5_PHYS 0xAC000000 +#define MSM_AD5_SIZE (SZ_1M*13) + +#ifndef __ASSEMBLY__ + +extern void __iomem *__msm_ioremap_caller(unsigned long phys_addr, size_t size, + unsigned int mtype, void *caller); + +#endif + +#endif diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h new file mode 100644 index 00000000..f944fe65 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2008-2011 Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * The MSM peripherals are spread all over across 768MB of physical + * space, which makes just having a simple IO_ADDRESS macro to slide + * them into the right virtual location rough. Instead, we will + * provide a master phys->virt mapping for peripherals here. + * + */ + +#ifndef __ASM_ARCH_MSM_IOMAP_7X30_H +#define __ASM_ARCH_MSM_IOMAP_7X30_H + +/* Physical base address and size of peripherals. + * Ordered by the virtual base addresses they will be mapped at. + * + * MSM_VIC_BASE must be an value that can be loaded via a "mov" + * instruction, otherwise entry-macro.S will not compile. + * + * If you add or remove entries here, you'll want to edit the + * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your + * changes. + * + */ + +#define MSM_VIC_BASE IOMEM(0xE0000000) +#define MSM_VIC_PHYS 0xC0080000 +#define MSM_VIC_SIZE SZ_4K + +#define MSM7X30_CSR_PHYS 0xC0100000 +#define MSM7X30_CSR_SIZE SZ_4K + +#define MSM_DMOV_BASE IOMEM(0xE0002000) +#define MSM_DMOV_PHYS 0xAC400000 +#define MSM_DMOV_SIZE SZ_4K + +#define MSM7X30_GPIO1_PHYS 0xAC001000 +#define MSM7X30_GPIO1_SIZE SZ_4K + +#define MSM7X30_GPIO2_PHYS 0xAC101000 +#define MSM7X30_GPIO2_SIZE SZ_4K + +#define MSM_CLK_CTL_BASE IOMEM(0xE0005000) +#define MSM_CLK_CTL_PHYS 0xAB800000 +#define MSM_CLK_CTL_SIZE SZ_4K + +#define MSM_CLK_CTL_SH2_BASE IOMEM(0xE0006000) +#define MSM_CLK_CTL_SH2_PHYS 0xABA01000 +#define MSM_CLK_CTL_SH2_SIZE SZ_4K + +#define MSM_ACC_BASE IOMEM(0xE0007000) +#define MSM_ACC_PHYS 0xC0101000 +#define MSM_ACC_SIZE SZ_4K + +#define MSM_SAW_BASE IOMEM(0xE0008000) +#define MSM_SAW_PHYS 0xC0102000 +#define MSM_SAW_SIZE SZ_4K + +#define MSM_GCC_BASE IOMEM(0xE0009000) +#define MSM_GCC_PHYS 0xC0182000 +#define MSM_GCC_SIZE SZ_4K + +#define MSM_TCSR_BASE IOMEM(0xE000A000) +#define MSM_TCSR_PHYS 0xAB600000 +#define MSM_TCSR_SIZE SZ_4K + +#define MSM_SHARED_RAM_BASE IOMEM(0xE0100000) +#define MSM_SHARED_RAM_PHYS 0x00100000 +#define MSM_SHARED_RAM_SIZE SZ_1M + +#define MSM_UART1_PHYS 0xACA00000 +#define MSM_UART1_SIZE SZ_4K + +#define MSM_UART2_PHYS 0xACB00000 +#define MSM_UART2_SIZE SZ_4K + +#define MSM_UART3_PHYS 0xACC00000 +#define MSM_UART3_SIZE SZ_4K + +#define MSM_MDC_BASE IOMEM(0xE0200000) +#define MSM_MDC_PHYS 0xAA500000 +#define MSM_MDC_SIZE SZ_1M + +#define MSM_AD5_BASE IOMEM(0xE0300000) +#define MSM_AD5_PHYS 0xA7000000 +#define MSM_AD5_SIZE (SZ_1M*13) + +#define MSM_HSUSB_PHYS 0xA3600000 +#define MSM_HSUSB_SIZE SZ_1K + +#ifndef __ASSEMBLY__ +extern void msm_map_msm7x30_io(void); +#endif + +#endif diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h new file mode 100644 index 00000000..a1752c02 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * The MSM peripherals are spread all over across 768MB of physical + * space, which makes just having a simple IO_ADDRESS macro to slide + * them into the right virtual location rough. Instead, we will + * provide a master phys->virt mapping for peripherals here. + * + */ + +#ifndef __ASM_ARCH_MSM_IOMAP_8960_H +#define __ASM_ARCH_MSM_IOMAP_8960_H + +/* Physical base address and size of peripherals. + * Ordered by the virtual base addresses they will be mapped at. + * + * If you add or remove entries here, you'll want to edit the + * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your + * changes. + * + */ + + +#define MSM8960_QGIC_DIST_PHYS 0x02000000 +#define MSM8960_QGIC_DIST_SIZE SZ_4K + +#define MSM8960_QGIC_CPU_PHYS 0x02002000 +#define MSM8960_QGIC_CPU_SIZE SZ_4K + +#define MSM8960_TMR_PHYS 0x0200A000 +#define MSM8960_TMR_SIZE SZ_4K + +#define MSM8960_TMR0_PHYS 0x0208A000 +#define MSM8960_TMR0_SIZE SZ_4K + +#ifdef CONFIG_DEBUG_MSM8960_UART +#define MSM_DEBUG_UART_BASE 0xE1040000 +#define MSM_DEBUG_UART_PHYS 0x16440000 +#endif + +#ifndef __ASSEMBLY__ +extern void msm_map_msm8960_io(void); +#endif + +#endif diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h new file mode 100644 index 00000000..da77cc1d --- /dev/null +++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2008-2011 Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * The MSM peripherals are spread all over across 768MB of physical + * space, which makes just having a simple IO_ADDRESS macro to slide + * them into the right virtual location rough. Instead, we will + * provide a master phys->virt mapping for peripherals here. + * + */ + +#ifndef __ASM_ARCH_MSM_IOMAP_8X50_H +#define __ASM_ARCH_MSM_IOMAP_8X50_H + +/* Physical base address and size of peripherals. + * Ordered by the virtual base addresses they will be mapped at. + * + * MSM_VIC_BASE must be an value that can be loaded via a "mov" + * instruction, otherwise entry-macro.S will not compile. + * + * If you add or remove entries here, you'll want to edit the + * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your + * changes. + * + */ + +#define MSM_VIC_BASE IOMEM(0xE0000000) +#define MSM_VIC_PHYS 0xAC000000 +#define MSM_VIC_SIZE SZ_4K + +#define QSD8X50_CSR_PHYS 0xAC100000 +#define QSD8X50_CSR_SIZE SZ_4K + +#define MSM_DMOV_BASE IOMEM(0xE0002000) +#define MSM_DMOV_PHYS 0xA9700000 +#define MSM_DMOV_SIZE SZ_4K + +#define QSD8X50_GPIO1_PHYS 0xA9000000 +#define QSD8X50_GPIO1_SIZE SZ_4K + +#define QSD8X50_GPIO2_PHYS 0xA9100000 +#define QSD8X50_GPIO2_SIZE SZ_4K + +#define MSM_CLK_CTL_BASE IOMEM(0xE0005000) +#define MSM_CLK_CTL_PHYS 0xA8600000 +#define MSM_CLK_CTL_SIZE SZ_4K + +#define MSM_SIRC_BASE IOMEM(0xE1006000) +#define MSM_SIRC_PHYS 0xAC200000 +#define MSM_SIRC_SIZE SZ_4K + +#define MSM_SCPLL_BASE IOMEM(0xE1007000) +#define MSM_SCPLL_PHYS 0xA8800000 +#define MSM_SCPLL_SIZE SZ_4K + +#ifdef CONFIG_MSM_SOC_REV_A +#define MSM_SMI_BASE 0xE0000000 +#else +#define MSM_SMI_BASE 0x00000000 +#endif + +#define MSM_SHARED_RAM_BASE IOMEM(0xE0100000) +#define MSM_SHARED_RAM_PHYS (MSM_SMI_BASE + 0x00100000) +#define MSM_SHARED_RAM_SIZE SZ_1M + +#define MSM_UART1_PHYS 0xA9A00000 +#define MSM_UART1_SIZE SZ_4K + +#define MSM_UART2_PHYS 0xA9B00000 +#define MSM_UART2_SIZE SZ_4K + +#define MSM_UART3_PHYS 0xA9C00000 +#define MSM_UART3_SIZE SZ_4K + +#define MSM_MDC_BASE IOMEM(0xE0200000) +#define MSM_MDC_PHYS 0xAA500000 +#define MSM_MDC_SIZE SZ_1M + +#define MSM_AD5_BASE IOMEM(0xE0300000) +#define MSM_AD5_PHYS 0xAC000000 +#define MSM_AD5_SIZE (SZ_1M*13) + + +#define MSM_I2C_SIZE SZ_4K +#define MSM_I2C_PHYS 0xA9900000 + +#define MSM_HSUSB_PHYS 0xA0800000 +#define MSM_HSUSB_SIZE SZ_1K + +#define MSM_NAND_PHYS 0xA0A00000 + + +#define MSM_TSIF_PHYS (0xa0100000) +#define MSM_TSIF_SIZE (0x200) + +#define MSM_TSSC_PHYS 0xAA300000 + +#define MSM_UART1DM_PHYS 0xA0200000 +#define MSM_UART2DM_PHYS 0xA0900000 + + +#define MSM_SDC1_PHYS 0xA0300000 +#define MSM_SDC1_SIZE SZ_4K + +#define MSM_SDC2_PHYS 0xA0400000 +#define MSM_SDC2_SIZE SZ_4K + +#define MSM_SDC3_PHYS 0xA0500000 +#define MSM_SDC3_SIZE SZ_4K + +#define MSM_SDC4_PHYS 0xA0600000 +#define MSM_SDC4_SIZE SZ_4K + +#ifndef __ASSEMBLY__ +extern void msm_map_qsd8x50_io(void); +#endif + +#endif diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h new file mode 100644 index 00000000..5aed57dc --- /dev/null +++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * The MSM peripherals are spread all over across 768MB of physical + * space, which makes just having a simple IO_ADDRESS macro to slide + * them into the right virtual location rough. Instead, we will + * provide a master phys->virt mapping for peripherals here. + * + */ + +#ifndef __ASM_ARCH_MSM_IOMAP_8X60_H +#define __ASM_ARCH_MSM_IOMAP_8X60_H + +/* Physical base address and size of peripherals. + * Ordered by the virtual base addresses they will be mapped at. + * + * MSM_VIC_BASE must be an value that can be loaded via a "mov" + * instruction, otherwise entry-macro.S will not compile. + * + * If you add or remove entries here, you'll want to edit the + * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your + * changes. + * + */ + +#define MSM8X60_QGIC_DIST_PHYS 0x02080000 +#define MSM8X60_QGIC_DIST_SIZE SZ_4K + +#define MSM8X60_QGIC_CPU_PHYS 0x02081000 +#define MSM8X60_QGIC_CPU_SIZE SZ_4K + +#define MSM_ACC_BASE IOMEM(0xF0002000) +#define MSM_ACC_PHYS 0x02001000 +#define MSM_ACC_SIZE SZ_4K + +#define MSM_GCC_BASE IOMEM(0xF0003000) +#define MSM_GCC_PHYS 0x02082000 +#define MSM_GCC_SIZE SZ_4K + +#define MSM_TLMM_BASE IOMEM(0xF0004000) +#define MSM_TLMM_PHYS 0x00800000 +#define MSM_TLMM_SIZE SZ_16K + +#define MSM_SHARED_RAM_BASE IOMEM(0xF0100000) +#define MSM_SHARED_RAM_SIZE SZ_1M + +#define MSM8X60_TMR_PHYS 0x02000000 +#define MSM8X60_TMR_SIZE SZ_4K + +#define MSM8X60_TMR0_PHYS 0x02040000 +#define MSM8X60_TMR0_SIZE SZ_4K + +#ifdef CONFIG_DEBUG_MSM8660_UART +#define MSM_DEBUG_UART_BASE 0xE1040000 +#define MSM_DEBUG_UART_PHYS 0x19C40000 +#endif + +#ifndef __ASSEMBLY__ +extern void msm_map_msm8x60_io(void); +#endif + +#endif diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h new file mode 100644 index 00000000..00afdfb8 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/msm_iomap.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * The MSM peripherals are spread all over across 768MB of physical + * space, which makes just having a simple IO_ADDRESS macro to slide + * them into the right virtual location rough. Instead, we will + * provide a master phys->virt mapping for peripherals here. + * + */ + +#ifndef __ASM_ARCH_MSM_IOMAP_H +#define __ASM_ARCH_MSM_IOMAP_H + +#include <asm/sizes.h> + +/* Physical base address and size of peripherals. + * Ordered by the virtual base addresses they will be mapped at. + * + * MSM_VIC_BASE must be an value that can be loaded via a "mov" + * instruction, otherwise entry-macro.S will not compile. + * + * If you add or remove entries here, you'll want to edit the + * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your + * changes. + * + */ + +#if defined(CONFIG_ARCH_MSM7X30) +#include "msm_iomap-7x30.h" +#elif defined(CONFIG_ARCH_QSD8X50) +#include "msm_iomap-8x50.h" +#elif defined(CONFIG_ARCH_MSM8X60) +#include "msm_iomap-8x60.h" +#else +#include "msm_iomap-7x00.h" +#endif + +#include "msm_iomap-8960.h" + +#define MSM_DEBUG_UART_SIZE SZ_4K +#if defined(CONFIG_DEBUG_MSM_UART1) +#define MSM_DEBUG_UART_BASE 0xE1000000 +#define MSM_DEBUG_UART_PHYS MSM_UART1_PHYS +#elif defined(CONFIG_DEBUG_MSM_UART2) +#define MSM_DEBUG_UART_BASE 0xE1000000 +#define MSM_DEBUG_UART_PHYS MSM_UART2_PHYS +#elif defined(CONFIG_DEBUG_MSM_UART3) +#define MSM_DEBUG_UART_BASE 0xE1000000 +#define MSM_DEBUG_UART_PHYS MSM_UART3_PHYS +#endif + +/* Virtual addresses shared across all MSM targets. */ +#define MSM_CSR_BASE IOMEM(0xE0001000) +#define MSM_QGIC_DIST_BASE IOMEM(0xF0000000) +#define MSM_QGIC_CPU_BASE IOMEM(0xF0001000) +#define MSM_TMR_BASE IOMEM(0xF0200000) +#define MSM_TMR0_BASE IOMEM(0xF0201000) +#define MSM_GPIO1_BASE IOMEM(0xE0003000) +#define MSM_GPIO2_BASE IOMEM(0xE0004000) + +#endif diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h new file mode 100644 index 00000000..029463ec --- /dev/null +++ b/arch/arm/mach-msm/include/mach/msm_smd.h @@ -0,0 +1,109 @@ +/* linux/include/asm-arm/arch-msm/msm_smd.h + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_SMD_H +#define __ASM_ARCH_MSM_SMD_H + +typedef struct smd_channel smd_channel_t; + +extern int (*msm_check_for_modem_crash)(void); + +/* warning: notify() may be called before open returns */ +int smd_open(const char *name, smd_channel_t **ch, void *priv, + void (*notify)(void *priv, unsigned event)); + +#define SMD_EVENT_DATA 1 +#define SMD_EVENT_OPEN 2 +#define SMD_EVENT_CLOSE 3 + +int smd_close(smd_channel_t *ch); + +/* passing a null pointer for data reads and discards */ +int smd_read(smd_channel_t *ch, void *data, int len); + +/* Write to stream channels may do a partial write and return +** the length actually written. +** Write to packet channels will never do a partial write -- +** it will return the requested length written or an error. +*/ +int smd_write(smd_channel_t *ch, const void *data, int len); +int smd_write_atomic(smd_channel_t *ch, const void *data, int len); + +int smd_write_avail(smd_channel_t *ch); +int smd_read_avail(smd_channel_t *ch); + +/* Returns the total size of the current packet being read. +** Returns 0 if no packets available or a stream channel. +*/ +int smd_cur_packet_size(smd_channel_t *ch); + +/* used for tty unthrottling and the like -- causes the notify() +** callback to be called from the same lock context as is used +** when it is called from channel updates +*/ +void smd_kick(smd_channel_t *ch); + + +#if 0 +/* these are interruptable waits which will block you until the specified +** number of bytes are readable or writable. +*/ +int smd_wait_until_readable(smd_channel_t *ch, int bytes); +int smd_wait_until_writable(smd_channel_t *ch, int bytes); +#endif + +typedef enum { + SMD_PORT_DS = 0, + SMD_PORT_DIAG, + SMD_PORT_RPC_CALL, + SMD_PORT_RPC_REPLY, + SMD_PORT_BT, + SMD_PORT_CONTROL, + SMD_PORT_MEMCPY_SPARE1, + SMD_PORT_DATA1, + SMD_PORT_DATA2, + SMD_PORT_DATA3, + SMD_PORT_DATA4, + SMD_PORT_DATA5, + SMD_PORT_DATA6, + SMD_PORT_DATA7, + SMD_PORT_DATA8, + SMD_PORT_DATA9, + SMD_PORT_DATA10, + SMD_PORT_DATA11, + SMD_PORT_DATA12, + SMD_PORT_DATA13, + SMD_PORT_DATA14, + SMD_PORT_DATA15, + SMD_PORT_DATA16, + SMD_PORT_DATA17, + SMD_PORT_DATA18, + SMD_PORT_DATA19, + SMD_PORT_DATA20, + SMD_PORT_GPS_NMEA, + SMD_PORT_BRIDGE_1, + SMD_PORT_BRIDGE_2, + SMD_PORT_BRIDGE_3, + SMD_PORT_BRIDGE_4, + SMD_PORT_BRIDGE_5, + SMD_PORT_LOOPBACK, + SMD_PORT_CS_APPS_MODEM, + SMD_PORT_CS_APPS_DSP, + SMD_PORT_CS_MODEM_DSP, + SMD_NUM_PORTS, +} smd_port_id_type; + +#endif diff --git a/arch/arm/mach-msm/include/mach/sirc.h b/arch/arm/mach-msm/include/mach/sirc.h new file mode 100644 index 00000000..ef55868a --- /dev/null +++ b/arch/arm/mach-msm/include/mach/sirc.h @@ -0,0 +1,98 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __ASM_ARCH_MSM_SIRC_H +#define __ASM_ARCH_MSM_SIRC_H + +struct sirc_regs_t { + void *int_enable; + void *int_enable_clear; + void *int_enable_set; + void *int_type; + void *int_polarity; + void *int_clear; +}; + +struct sirc_cascade_regs { + void *int_status; + unsigned int cascade_irq; +}; + +void msm_init_sirc(void); +void msm_sirc_enter_sleep(void); +void msm_sirc_exit_sleep(void); + +#if defined(CONFIG_ARCH_MSM_SCORPION) + +#include <mach/msm_iomap.h> + +/* + * Secondary interrupt controller interrupts + */ + +#define FIRST_SIRC_IRQ (NR_MSM_IRQS + NR_GPIO_IRQS) + +#define INT_UART1 (FIRST_SIRC_IRQ + 0) +#define INT_UART2 (FIRST_SIRC_IRQ + 1) +#define INT_UART3 (FIRST_SIRC_IRQ + 2) +#define INT_UART1_RX (FIRST_SIRC_IRQ + 3) +#define INT_UART2_RX (FIRST_SIRC_IRQ + 4) +#define INT_UART3_RX (FIRST_SIRC_IRQ + 5) +#define INT_SPI_INPUT (FIRST_SIRC_IRQ + 6) +#define INT_SPI_OUTPUT (FIRST_SIRC_IRQ + 7) +#define INT_SPI_ERROR (FIRST_SIRC_IRQ + 8) +#define INT_GPIO_GROUP1 (FIRST_SIRC_IRQ + 9) +#define INT_GPIO_GROUP2 (FIRST_SIRC_IRQ + 10) +#define INT_GPIO_GROUP1_SECURE (FIRST_SIRC_IRQ + 11) +#define INT_GPIO_GROUP2_SECURE (FIRST_SIRC_IRQ + 12) +#define INT_AVS_SVIC (FIRST_SIRC_IRQ + 13) +#define INT_AVS_REQ_UP (FIRST_SIRC_IRQ + 14) +#define INT_AVS_REQ_DOWN (FIRST_SIRC_IRQ + 15) +#define INT_PBUS_ERR (FIRST_SIRC_IRQ + 16) +#define INT_AXI_ERR (FIRST_SIRC_IRQ + 17) +#define INT_SMI_ERR (FIRST_SIRC_IRQ + 18) +#define INT_EBI1_ERR (FIRST_SIRC_IRQ + 19) +#define INT_IMEM_ERR (FIRST_SIRC_IRQ + 20) +#define INT_TEMP_SENSOR (FIRST_SIRC_IRQ + 21) +#define INT_TV_ENC (FIRST_SIRC_IRQ + 22) +#define INT_GRP2D (FIRST_SIRC_IRQ + 23) +#define INT_GSBI_QUP (FIRST_SIRC_IRQ + 24) +#define INT_SC_ACG (FIRST_SIRC_IRQ + 25) +#define INT_WDT0 (FIRST_SIRC_IRQ + 26) +#define INT_WDT1 (FIRST_SIRC_IRQ + 27) + +#if defined(CONFIG_MSM_SOC_REV_A) +#define NR_SIRC_IRQS 28 +#define SIRC_MASK 0x0FFFFFFF +#else +#define NR_SIRC_IRQS 23 +#define SIRC_MASK 0x007FFFFF +#endif + +#define LAST_SIRC_IRQ (FIRST_SIRC_IRQ + NR_SIRC_IRQS - 1) + +#define SPSS_SIRC_INT_SELECT (MSM_SIRC_BASE + 0x00) +#define SPSS_SIRC_INT_ENABLE (MSM_SIRC_BASE + 0x04) +#define SPSS_SIRC_INT_ENABLE_CLEAR (MSM_SIRC_BASE + 0x08) +#define SPSS_SIRC_INT_ENABLE_SET (MSM_SIRC_BASE + 0x0C) +#define SPSS_SIRC_INT_TYPE (MSM_SIRC_BASE + 0x10) +#define SPSS_SIRC_INT_POLARITY (MSM_SIRC_BASE + 0x14) +#define SPSS_SIRC_SECURITY (MSM_SIRC_BASE + 0x18) +#define SPSS_SIRC_IRQ_STATUS (MSM_SIRC_BASE + 0x1C) +#define SPSS_SIRC_IRQ1_STATUS (MSM_SIRC_BASE + 0x20) +#define SPSS_SIRC_RAW_STATUS (MSM_SIRC_BASE + 0x24) +#define SPSS_SIRC_INT_CLEAR (MSM_SIRC_BASE + 0x28) +#define SPSS_SIRC_SOFT_INT (MSM_SIRC_BASE + 0x2C) + +#endif + +#endif diff --git a/arch/arm/mach-msm/include/mach/system.h b/arch/arm/mach-msm/include/mach/system.h new file mode 100644 index 00000000..f5fb2ec8 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/system.h @@ -0,0 +1,19 @@ +/* arch/arm/mach-msm/include/mach/system.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* low level hardware reset hook -- for example, hitting the + * PSHOLD line on the PMIC to hard reset the system + */ +extern void (*msm_hw_reset_hook)(void); diff --git a/arch/arm/mach-msm/include/mach/timex.h b/arch/arm/mach-msm/include/mach/timex.h new file mode 100644 index 00000000..a62e6b21 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/timex.h @@ -0,0 +1,21 @@ +/* arch/arm/mach-msm/include/mach/timex.h + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_TIMEX_H +#define __ASM_ARCH_MSM_TIMEX_H + +#define CLOCK_TICK_RATE 1000000 + +#endif diff --git a/arch/arm/mach-msm/include/mach/uncompress.h b/arch/arm/mach-msm/include/mach/uncompress.h new file mode 100644 index 00000000..c14011fe --- /dev/null +++ b/arch/arm/mach-msm/include/mach/uncompress.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ASM_ARCH_MSM_UNCOMPRESS_H +#define __ASM_ARCH_MSM_UNCOMPRESS_H + +#include <asm/barrier.h> +#include <asm/processor.h> +#include <mach/msm_iomap.h> + +#define UART_CSR (*(volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x08)) +#define UART_TF (*(volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x0c)) + +#define UART_DM_SR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x08))) +#define UART_DM_CR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x10))) +#define UART_DM_ISR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x14))) +#define UART_DM_NCHAR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x40))) +#define UART_DM_TF (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x70))) + +static void putc(int c) +{ +#if defined(MSM_DEBUG_UART_PHYS) +#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS + /* + * Wait for TX_READY to be set; but skip it if we have a + * TX underrun. + */ + if (UART_DM_SR & 0x08) + while (!(UART_DM_ISR & 0x80)) + cpu_relax(); + + UART_DM_CR = 0x300; + UART_DM_NCHAR = 0x1; + UART_DM_TF = c; +#else + while (!(UART_CSR & 0x04)) + cpu_relax(); + UART_TF = c; +#endif +#endif +} + +static inline void flush(void) +{ +} + +static inline void arch_decomp_setup(void) +{ +} + +static inline void arch_decomp_wdog(void) +{ +} + +#endif diff --git a/arch/arm/mach-msm/include/mach/vreg.h b/arch/arm/mach-msm/include/mach/vreg.h new file mode 100644 index 00000000..6626e786 --- /dev/null +++ b/arch/arm/mach-msm/include/mach/vreg.h @@ -0,0 +1,29 @@ +/* linux/include/asm-arm/arch-msm/vreg.h + * + * Copyright (C) 2008 Google, Inc. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __ARCH_ARM_MACH_MSM_VREG_H +#define __ARCH_ARM_MACH_MSM_VREG_H + +struct vreg; + +struct vreg *vreg_get(struct device *dev, const char *id); +void vreg_put(struct vreg *vreg); + +int vreg_enable(struct vreg *vreg); +int vreg_disable(struct vreg *vreg); +int vreg_set_level(struct vreg *vreg, unsigned mv); + +#endif diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c new file mode 100644 index 00000000..a1e7b116 --- /dev/null +++ b/arch/arm/mach-msm/io.c @@ -0,0 +1,188 @@ +/* arch/arm/mach-msm/io.c + * + * MSM7K, QSD io support + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/export.h> + +#include <mach/hardware.h> +#include <asm/page.h> +#include <mach/msm_iomap.h> +#include <asm/mach/map.h> + +#include <mach/board.h> + +#define MSM_CHIP_DEVICE(name, chip) { \ + .virtual = (unsigned long) MSM_##name##_BASE, \ + .pfn = __phys_to_pfn(chip##_##name##_PHYS), \ + .length = chip##_##name##_SIZE, \ + .type = MT_DEVICE_NONSHARED, \ + } + +#define MSM_DEVICE(name) MSM_CHIP_DEVICE(name, MSM) + +#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X27) \ + || defined(CONFIG_ARCH_MSM7X25) +static struct map_desc msm_io_desc[] __initdata = { + MSM_DEVICE(VIC), + MSM_CHIP_DEVICE(CSR, MSM7X00), + MSM_DEVICE(DMOV), + MSM_CHIP_DEVICE(GPIO1, MSM7X00), + MSM_CHIP_DEVICE(GPIO2, MSM7X00), + MSM_DEVICE(CLK_CTL), +#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \ + defined(CONFIG_DEBUG_MSM_UART3) + MSM_DEVICE(DEBUG_UART), +#endif +#ifdef CONFIG_ARCH_MSM7X30 + MSM_DEVICE(GCC), +#endif + { + .virtual = (unsigned long) MSM_SHARED_RAM_BASE, + .pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS), + .length = MSM_SHARED_RAM_SIZE, + .type = MT_DEVICE, + }, +}; + +void __init msm_map_common_io(void) +{ + /* Make sure the peripheral register window is closed, since + * we will use PTE flags (TEX[1]=1,B=0,C=1) to determine which + * pages are peripheral interface or not. + */ + asm("mcr p15, 0, %0, c15, c2, 4" : : "r" (0)); + iotable_init(msm_io_desc, ARRAY_SIZE(msm_io_desc)); +} +#endif + +#ifdef CONFIG_ARCH_QSD8X50 +static struct map_desc qsd8x50_io_desc[] __initdata = { + MSM_DEVICE(VIC), + MSM_CHIP_DEVICE(CSR, QSD8X50), + MSM_DEVICE(DMOV), + MSM_CHIP_DEVICE(GPIO1, QSD8X50), + MSM_CHIP_DEVICE(GPIO2, QSD8X50), + MSM_DEVICE(CLK_CTL), + MSM_DEVICE(SIRC), + MSM_DEVICE(SCPLL), + MSM_DEVICE(AD5), + MSM_DEVICE(MDC), +#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \ + defined(CONFIG_DEBUG_MSM_UART3) + MSM_DEVICE(DEBUG_UART), +#endif + { + .virtual = (unsigned long) MSM_SHARED_RAM_BASE, + .pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS), + .length = MSM_SHARED_RAM_SIZE, + .type = MT_DEVICE, + }, +}; + +void __init msm_map_qsd8x50_io(void) +{ + iotable_init(qsd8x50_io_desc, ARRAY_SIZE(qsd8x50_io_desc)); +} +#endif /* CONFIG_ARCH_QSD8X50 */ + +#ifdef CONFIG_ARCH_MSM8X60 +static struct map_desc msm8x60_io_desc[] __initdata = { + MSM_CHIP_DEVICE(QGIC_DIST, MSM8X60), + MSM_CHIP_DEVICE(QGIC_CPU, MSM8X60), + MSM_CHIP_DEVICE(TMR, MSM8X60), + MSM_CHIP_DEVICE(TMR0, MSM8X60), + MSM_DEVICE(ACC), + MSM_DEVICE(GCC), +#ifdef CONFIG_DEBUG_MSM8660_UART + MSM_DEVICE(DEBUG_UART), +#endif +}; + +void __init msm_map_msm8x60_io(void) +{ + iotable_init(msm8x60_io_desc, ARRAY_SIZE(msm8x60_io_desc)); +} +#endif /* CONFIG_ARCH_MSM8X60 */ + +#ifdef CONFIG_ARCH_MSM8960 +static struct map_desc msm8960_io_desc[] __initdata = { + MSM_CHIP_DEVICE(QGIC_DIST, MSM8960), + MSM_CHIP_DEVICE(QGIC_CPU, MSM8960), + MSM_CHIP_DEVICE(TMR, MSM8960), + MSM_CHIP_DEVICE(TMR0, MSM8960), +#ifdef CONFIG_DEBUG_MSM8960_UART + MSM_DEVICE(DEBUG_UART), +#endif +}; + +void __init msm_map_msm8960_io(void) +{ + iotable_init(msm8960_io_desc, ARRAY_SIZE(msm8960_io_desc)); +} +#endif /* CONFIG_ARCH_MSM8960 */ + +#ifdef CONFIG_ARCH_MSM7X30 +static struct map_desc msm7x30_io_desc[] __initdata = { + MSM_DEVICE(VIC), + MSM_CHIP_DEVICE(CSR, MSM7X30), + MSM_DEVICE(DMOV), + MSM_CHIP_DEVICE(GPIO1, MSM7X30), + MSM_CHIP_DEVICE(GPIO2, MSM7X30), + MSM_DEVICE(CLK_CTL), + MSM_DEVICE(CLK_CTL_SH2), + MSM_DEVICE(AD5), + MSM_DEVICE(MDC), + MSM_DEVICE(ACC), + MSM_DEVICE(SAW), + MSM_DEVICE(GCC), + MSM_DEVICE(TCSR), +#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \ + defined(CONFIG_DEBUG_MSM_UART3) + MSM_DEVICE(DEBUG_UART), +#endif + { + .virtual = (unsigned long) MSM_SHARED_RAM_BASE, + .pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS), + .length = MSM_SHARED_RAM_SIZE, + .type = MT_DEVICE, + }, +}; + +void __init msm_map_msm7x30_io(void) +{ + iotable_init(msm7x30_io_desc, ARRAY_SIZE(msm7x30_io_desc)); +} +#endif /* CONFIG_ARCH_MSM7X30 */ + +void __iomem *__msm_ioremap_caller(unsigned long phys_addr, size_t size, + unsigned int mtype, void *caller) +{ + if (mtype == MT_DEVICE) { + /* The peripherals in the 88000000 - D0000000 range + * are only accessible by type MT_DEVICE_NONSHARED. + * Adjust mtype as necessary to make this "just work." + */ + if ((phys_addr >= 0x88000000) && (phys_addr < 0xD0000000)) + mtype = MT_DEVICE_NONSHARED; + } + + return __arm_ioremap_caller(phys_addr, size, mtype, caller); +} diff --git a/arch/arm/mach-msm/irq-vic.c b/arch/arm/mach-msm/irq-vic.c new file mode 100644 index 00000000..1b54f807 --- /dev/null +++ b/arch/arm/mach-msm/irq-vic.c @@ -0,0 +1,363 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ptrace.h> +#include <linux/timer.h> +#include <linux/irq.h> +#include <linux/io.h> + +#include <asm/cacheflush.h> + +#include <mach/hardware.h> + +#include <mach/msm_iomap.h> + +#include "smd_private.h" + +enum { + IRQ_DEBUG_SLEEP_INT_TRIGGER = 1U << 0, + IRQ_DEBUG_SLEEP_INT = 1U << 1, + IRQ_DEBUG_SLEEP_ABORT = 1U << 2, + IRQ_DEBUG_SLEEP = 1U << 3, + IRQ_DEBUG_SLEEP_REQUEST = 1U << 4, +}; +static int msm_irq_debug_mask; +module_param_named(debug_mask, msm_irq_debug_mask, int, + S_IRUGO | S_IWUSR | S_IWGRP); + +#define VIC_REG(off) (MSM_VIC_BASE + (off)) +#define VIC_INT_TO_REG_ADDR(base, irq) (base + (irq / 32) * 4) +#define VIC_INT_TO_REG_INDEX(irq) ((irq >> 5) & 3) + +#define VIC_INT_SELECT0 VIC_REG(0x0000) /* 1: FIQ, 0: IRQ */ +#define VIC_INT_SELECT1 VIC_REG(0x0004) /* 1: FIQ, 0: IRQ */ +#define VIC_INT_SELECT2 VIC_REG(0x0008) /* 1: FIQ, 0: IRQ */ +#define VIC_INT_SELECT3 VIC_REG(0x000C) /* 1: FIQ, 0: IRQ */ +#define VIC_INT_EN0 VIC_REG(0x0010) +#define VIC_INT_EN1 VIC_REG(0x0014) +#define VIC_INT_EN2 VIC_REG(0x0018) +#define VIC_INT_EN3 VIC_REG(0x001C) +#define VIC_INT_ENCLEAR0 VIC_REG(0x0020) +#define VIC_INT_ENCLEAR1 VIC_REG(0x0024) +#define VIC_INT_ENCLEAR2 VIC_REG(0x0028) +#define VIC_INT_ENCLEAR3 VIC_REG(0x002C) +#define VIC_INT_ENSET0 VIC_REG(0x0030) +#define VIC_INT_ENSET1 VIC_REG(0x0034) +#define VIC_INT_ENSET2 VIC_REG(0x0038) +#define VIC_INT_ENSET3 VIC_REG(0x003C) +#define VIC_INT_TYPE0 VIC_REG(0x0040) /* 1: EDGE, 0: LEVEL */ +#define VIC_INT_TYPE1 VIC_REG(0x0044) /* 1: EDGE, 0: LEVEL */ +#define VIC_INT_TYPE2 VIC_REG(0x0048) /* 1: EDGE, 0: LEVEL */ +#define VIC_INT_TYPE3 VIC_REG(0x004C) /* 1: EDGE, 0: LEVEL */ +#define VIC_INT_POLARITY0 VIC_REG(0x0050) /* 1: NEG, 0: POS */ +#define VIC_INT_POLARITY1 VIC_REG(0x0054) /* 1: NEG, 0: POS */ +#define VIC_INT_POLARITY2 VIC_REG(0x0058) /* 1: NEG, 0: POS */ +#define VIC_INT_POLARITY3 VIC_REG(0x005C) /* 1: NEG, 0: POS */ +#define VIC_NO_PEND_VAL VIC_REG(0x0060) + +#if defined(CONFIG_ARCH_MSM_SCORPION) +#define VIC_NO_PEND_VAL_FIQ VIC_REG(0x0064) +#define VIC_INT_MASTEREN VIC_REG(0x0068) /* 1: IRQ, 2: FIQ */ +#define VIC_CONFIG VIC_REG(0x006C) /* 1: USE SC VIC */ +#else +#define VIC_INT_MASTEREN VIC_REG(0x0064) /* 1: IRQ, 2: FIQ */ +#define VIC_PROTECTION VIC_REG(0x006C) /* 1: ENABLE */ +#define VIC_CONFIG VIC_REG(0x0068) /* 1: USE ARM1136 VIC */ +#endif + +#define VIC_IRQ_STATUS0 VIC_REG(0x0080) +#define VIC_IRQ_STATUS1 VIC_REG(0x0084) +#define VIC_IRQ_STATUS2 VIC_REG(0x0088) +#define VIC_IRQ_STATUS3 VIC_REG(0x008C) +#define VIC_FIQ_STATUS0 VIC_REG(0x0090) +#define VIC_FIQ_STATUS1 VIC_REG(0x0094) +#define VIC_FIQ_STATUS2 VIC_REG(0x0098) +#define VIC_FIQ_STATUS3 VIC_REG(0x009C) +#define VIC_RAW_STATUS0 VIC_REG(0x00A0) +#define VIC_RAW_STATUS1 VIC_REG(0x00A4) +#define VIC_RAW_STATUS2 VIC_REG(0x00A8) +#define VIC_RAW_STATUS3 VIC_REG(0x00AC) +#define VIC_INT_CLEAR0 VIC_REG(0x00B0) +#define VIC_INT_CLEAR1 VIC_REG(0x00B4) +#define VIC_INT_CLEAR2 VIC_REG(0x00B8) +#define VIC_INT_CLEAR3 VIC_REG(0x00BC) +#define VIC_SOFTINT0 VIC_REG(0x00C0) +#define VIC_SOFTINT1 VIC_REG(0x00C4) +#define VIC_SOFTINT2 VIC_REG(0x00C8) +#define VIC_SOFTINT3 VIC_REG(0x00CC) +#define VIC_IRQ_VEC_RD VIC_REG(0x00D0) /* pending int # */ +#define VIC_IRQ_VEC_PEND_RD VIC_REG(0x00D4) /* pending vector addr */ +#define VIC_IRQ_VEC_WR VIC_REG(0x00D8) + +#if defined(CONFIG_ARCH_MSM_SCORPION) +#define VIC_FIQ_VEC_RD VIC_REG(0x00DC) +#define VIC_FIQ_VEC_PEND_RD VIC_REG(0x00E0) +#define VIC_FIQ_VEC_WR VIC_REG(0x00E4) +#define VIC_IRQ_IN_SERVICE VIC_REG(0x00E8) +#define VIC_IRQ_IN_STACK VIC_REG(0x00EC) +#define VIC_FIQ_IN_SERVICE VIC_REG(0x00F0) +#define VIC_FIQ_IN_STACK VIC_REG(0x00F4) +#define VIC_TEST_BUS_SEL VIC_REG(0x00F8) +#define VIC_IRQ_CTRL_CONFIG VIC_REG(0x00FC) +#else +#define VIC_IRQ_IN_SERVICE VIC_REG(0x00E0) +#define VIC_IRQ_IN_STACK VIC_REG(0x00E4) +#define VIC_TEST_BUS_SEL VIC_REG(0x00E8) +#endif + +#define VIC_VECTPRIORITY(n) VIC_REG(0x0200+((n) * 4)) +#define VIC_VECTADDR(n) VIC_REG(0x0400+((n) * 4)) + +#if defined(CONFIG_ARCH_MSM7X30) +#define VIC_NUM_REGS 4 +#else +#define VIC_NUM_REGS 2 +#endif + +#if VIC_NUM_REGS == 2 +#define DPRINT_REGS(base_reg, format, ...) \ + printk(KERN_INFO format " %x %x\n", ##__VA_ARGS__, \ + readl(base_reg ## 0), readl(base_reg ## 1)) +#define DPRINT_ARRAY(array, format, ...) \ + printk(KERN_INFO format " %x %x\n", ##__VA_ARGS__, \ + array[0], array[1]) +#elif VIC_NUM_REGS == 4 +#define DPRINT_REGS(base_reg, format, ...) \ + printk(KERN_INFO format " %x %x %x %x\n", ##__VA_ARGS__, \ + readl(base_reg ## 0), readl(base_reg ## 1), \ + readl(base_reg ## 2), readl(base_reg ## 3)) +#define DPRINT_ARRAY(array, format, ...) \ + printk(KERN_INFO format " %x %x %x %x\n", ##__VA_ARGS__, \ + array[0], array[1], \ + array[2], array[3]) +#else +#error "VIC_NUM_REGS set to illegal value" +#endif + +static uint32_t msm_irq_smsm_wake_enable[2]; +static struct { + uint32_t int_en[2]; + uint32_t int_type; + uint32_t int_polarity; + uint32_t int_select; +} msm_irq_shadow_reg[VIC_NUM_REGS]; +static uint32_t msm_irq_idle_disable[VIC_NUM_REGS]; + +#define SMSM_FAKE_IRQ (0xff) +static uint8_t msm_irq_to_smsm[NR_IRQS] = { + [INT_MDDI_EXT] = 1, + [INT_MDDI_PRI] = 2, + [INT_MDDI_CLIENT] = 3, + [INT_USB_OTG] = 4, + + [INT_PWB_I2C] = 5, + [INT_SDC1_0] = 6, + [INT_SDC1_1] = 7, + [INT_SDC2_0] = 8, + + [INT_SDC2_1] = 9, + [INT_ADSP_A9_A11] = 10, + [INT_UART1] = 11, + [INT_UART2] = 12, + + [INT_UART3] = 13, + [INT_UART1_RX] = 14, + [INT_UART2_RX] = 15, + [INT_UART3_RX] = 16, + + [INT_UART1DM_IRQ] = 17, + [INT_UART1DM_RX] = 18, + [INT_KEYSENSE] = 19, +#if !defined(CONFIG_ARCH_MSM7X30) + [INT_AD_HSSD] = 20, +#endif + + [INT_NAND_WR_ER_DONE] = 21, + [INT_NAND_OP_DONE] = 22, + [INT_TCHSCRN1] = 23, + [INT_TCHSCRN2] = 24, + + [INT_TCHSCRN_SSBI] = 25, + [INT_USB_HS] = 26, + [INT_UART2DM_RX] = 27, + [INT_UART2DM_IRQ] = 28, + + [INT_SDC4_1] = 29, + [INT_SDC4_0] = 30, + [INT_SDC3_1] = 31, + [INT_SDC3_0] = 32, + + /* fake wakeup interrupts */ + [INT_GPIO_GROUP1] = SMSM_FAKE_IRQ, + [INT_GPIO_GROUP2] = SMSM_FAKE_IRQ, + [INT_A9_M2A_0] = SMSM_FAKE_IRQ, + [INT_A9_M2A_1] = SMSM_FAKE_IRQ, + [INT_A9_M2A_5] = SMSM_FAKE_IRQ, + [INT_GP_TIMER_EXP] = SMSM_FAKE_IRQ, + [INT_DEBUG_TIMER_EXP] = SMSM_FAKE_IRQ, + [INT_ADSP_A11] = SMSM_FAKE_IRQ, +#ifdef CONFIG_ARCH_QSD8X50 + [INT_SIRC_0] = SMSM_FAKE_IRQ, + [INT_SIRC_1] = SMSM_FAKE_IRQ, +#endif +}; + +static inline void msm_irq_write_all_regs(void __iomem *base, unsigned int val) +{ + int i; + + for (i = 0; i < VIC_NUM_REGS; i++) + writel(val, base + (i * 4)); +} + +static void msm_irq_ack(struct irq_data *d) +{ + void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_CLEAR0, d->irq); + writel(1 << (d->irq & 31), reg); +} + +static void msm_irq_mask(struct irq_data *d) +{ + void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENCLEAR0, d->irq); + unsigned index = VIC_INT_TO_REG_INDEX(d->irq); + uint32_t mask = 1UL << (d->irq & 31); + int smsm_irq = msm_irq_to_smsm[d->irq]; + + msm_irq_shadow_reg[index].int_en[0] &= ~mask; + writel(mask, reg); + if (smsm_irq == 0) + msm_irq_idle_disable[index] &= ~mask; + else { + mask = 1UL << (smsm_irq - 1); + msm_irq_smsm_wake_enable[0] &= ~mask; + } +} + +static void msm_irq_unmask(struct irq_data *d) +{ + void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENSET0, d->irq); + unsigned index = VIC_INT_TO_REG_INDEX(d->irq); + uint32_t mask = 1UL << (d->irq & 31); + int smsm_irq = msm_irq_to_smsm[d->irq]; + + msm_irq_shadow_reg[index].int_en[0] |= mask; + writel(mask, reg); + + if (smsm_irq == 0) + msm_irq_idle_disable[index] |= mask; + else { + mask = 1UL << (smsm_irq - 1); + msm_irq_smsm_wake_enable[0] |= mask; + } +} + +static int msm_irq_set_wake(struct irq_data *d, unsigned int on) +{ + unsigned index = VIC_INT_TO_REG_INDEX(d->irq); + uint32_t mask = 1UL << (d->irq & 31); + int smsm_irq = msm_irq_to_smsm[d->irq]; + + if (smsm_irq == 0) { + printk(KERN_ERR "msm_irq_set_wake: bad wakeup irq %d\n", d->irq); + return -EINVAL; + } + if (on) + msm_irq_shadow_reg[index].int_en[1] |= mask; + else + msm_irq_shadow_reg[index].int_en[1] &= ~mask; + + if (smsm_irq == SMSM_FAKE_IRQ) + return 0; + + mask = 1UL << (smsm_irq - 1); + if (on) + msm_irq_smsm_wake_enable[1] |= mask; + else + msm_irq_smsm_wake_enable[1] &= ~mask; + return 0; +} + +static int msm_irq_set_type(struct irq_data *d, unsigned int flow_type) +{ + void __iomem *treg = VIC_INT_TO_REG_ADDR(VIC_INT_TYPE0, d->irq); + void __iomem *preg = VIC_INT_TO_REG_ADDR(VIC_INT_POLARITY0, d->irq); + unsigned index = VIC_INT_TO_REG_INDEX(d->irq); + int b = 1 << (d->irq & 31); + uint32_t polarity; + uint32_t type; + + polarity = msm_irq_shadow_reg[index].int_polarity; + if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW)) + polarity |= b; + if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH)) + polarity &= ~b; + writel(polarity, preg); + msm_irq_shadow_reg[index].int_polarity = polarity; + + type = msm_irq_shadow_reg[index].int_type; + if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { + type |= b; + __irq_set_handler_locked(d->irq, handle_edge_irq); + } + if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) { + type &= ~b; + __irq_set_handler_locked(d->irq, handle_level_irq); + } + writel(type, treg); + msm_irq_shadow_reg[index].int_type = type; + return 0; +} + +static struct irq_chip msm_irq_chip = { + .name = "msm", + .irq_disable = msm_irq_mask, + .irq_ack = msm_irq_ack, + .irq_mask = msm_irq_mask, + .irq_unmask = msm_irq_unmask, + .irq_set_wake = msm_irq_set_wake, + .irq_set_type = msm_irq_set_type, +}; + +void __init msm_init_irq(void) +{ + unsigned n; + + /* select level interrupts */ + msm_irq_write_all_regs(VIC_INT_TYPE0, 0); + + /* select highlevel interrupts */ + msm_irq_write_all_regs(VIC_INT_POLARITY0, 0); + + /* select IRQ for all INTs */ + msm_irq_write_all_regs(VIC_INT_SELECT0, 0); + + /* disable all INTs */ + msm_irq_write_all_regs(VIC_INT_EN0, 0); + + /* don't use vic */ + writel(0, VIC_CONFIG); + + /* enable interrupt controller */ + writel(3, VIC_INT_MASTEREN); + + for (n = 0; n < NR_MSM_IRQS; n++) { + irq_set_chip_and_handler(n, &msm_irq_chip, handle_level_irq); + set_irq_flags(n, IRQF_VALID); + } +} diff --git a/arch/arm/mach-msm/irq.c b/arch/arm/mach-msm/irq.c new file mode 100644 index 00000000..ea514be3 --- /dev/null +++ b/arch/arm/mach-msm/irq.c @@ -0,0 +1,151 @@ +/* linux/arch/arm/mach-msm/irq.c + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ptrace.h> +#include <linux/timer.h> +#include <linux/irq.h> +#include <linux/io.h> + +#include <mach/hardware.h> + +#include <mach/msm_iomap.h> + +#define VIC_REG(off) (MSM_VIC_BASE + (off)) + +#define VIC_INT_SELECT0 VIC_REG(0x0000) /* 1: FIQ, 0: IRQ */ +#define VIC_INT_SELECT1 VIC_REG(0x0004) /* 1: FIQ, 0: IRQ */ +#define VIC_INT_EN0 VIC_REG(0x0010) +#define VIC_INT_EN1 VIC_REG(0x0014) +#define VIC_INT_ENCLEAR0 VIC_REG(0x0020) +#define VIC_INT_ENCLEAR1 VIC_REG(0x0024) +#define VIC_INT_ENSET0 VIC_REG(0x0030) +#define VIC_INT_ENSET1 VIC_REG(0x0034) +#define VIC_INT_TYPE0 VIC_REG(0x0040) /* 1: EDGE, 0: LEVEL */ +#define VIC_INT_TYPE1 VIC_REG(0x0044) /* 1: EDGE, 0: LEVEL */ +#define VIC_INT_POLARITY0 VIC_REG(0x0050) /* 1: NEG, 0: POS */ +#define VIC_INT_POLARITY1 VIC_REG(0x0054) /* 1: NEG, 0: POS */ +#define VIC_NO_PEND_VAL VIC_REG(0x0060) +#define VIC_INT_MASTEREN VIC_REG(0x0064) /* 1: IRQ, 2: FIQ */ +#define VIC_PROTECTION VIC_REG(0x006C) /* 1: ENABLE */ +#define VIC_CONFIG VIC_REG(0x0068) /* 1: USE ARM1136 VIC */ +#define VIC_IRQ_STATUS0 VIC_REG(0x0080) +#define VIC_IRQ_STATUS1 VIC_REG(0x0084) +#define VIC_FIQ_STATUS0 VIC_REG(0x0090) +#define VIC_FIQ_STATUS1 VIC_REG(0x0094) +#define VIC_RAW_STATUS0 VIC_REG(0x00A0) +#define VIC_RAW_STATUS1 VIC_REG(0x00A4) +#define VIC_INT_CLEAR0 VIC_REG(0x00B0) +#define VIC_INT_CLEAR1 VIC_REG(0x00B4) +#define VIC_SOFTINT0 VIC_REG(0x00C0) +#define VIC_SOFTINT1 VIC_REG(0x00C4) +#define VIC_IRQ_VEC_RD VIC_REG(0x00D0) /* pending int # */ +#define VIC_IRQ_VEC_PEND_RD VIC_REG(0x00D4) /* pending vector addr */ +#define VIC_IRQ_VEC_WR VIC_REG(0x00D8) +#define VIC_IRQ_IN_SERVICE VIC_REG(0x00E0) +#define VIC_IRQ_IN_STACK VIC_REG(0x00E4) +#define VIC_TEST_BUS_SEL VIC_REG(0x00E8) + +#define VIC_VECTPRIORITY(n) VIC_REG(0x0200+((n) * 4)) +#define VIC_VECTADDR(n) VIC_REG(0x0400+((n) * 4)) + +static void msm_irq_ack(struct irq_data *d) +{ + void __iomem *reg = VIC_INT_CLEAR0 + ((d->irq & 32) ? 4 : 0); + writel(1 << (d->irq & 31), reg); +} + +static void msm_irq_mask(struct irq_data *d) +{ + void __iomem *reg = VIC_INT_ENCLEAR0 + ((d->irq & 32) ? 4 : 0); + writel(1 << (d->irq & 31), reg); +} + +static void msm_irq_unmask(struct irq_data *d) +{ + void __iomem *reg = VIC_INT_ENSET0 + ((d->irq & 32) ? 4 : 0); + writel(1 << (d->irq & 31), reg); +} + +static int msm_irq_set_wake(struct irq_data *d, unsigned int on) +{ + return -EINVAL; +} + +static int msm_irq_set_type(struct irq_data *d, unsigned int flow_type) +{ + void __iomem *treg = VIC_INT_TYPE0 + ((d->irq & 32) ? 4 : 0); + void __iomem *preg = VIC_INT_POLARITY0 + ((d->irq & 32) ? 4 : 0); + int b = 1 << (d->irq & 31); + + if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW)) + writel(readl(preg) | b, preg); + if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH)) + writel(readl(preg) & (~b), preg); + + if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { + writel(readl(treg) | b, treg); + __irq_set_handler_locked(d->irq, handle_edge_irq); + } + if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) { + writel(readl(treg) & (~b), treg); + __irq_set_handler_locked(d->irq, handle_level_irq); + } + return 0; +} + +static struct irq_chip msm_irq_chip = { + .name = "msm", + .irq_ack = msm_irq_ack, + .irq_mask = msm_irq_mask, + .irq_unmask = msm_irq_unmask, + .irq_set_wake = msm_irq_set_wake, + .irq_set_type = msm_irq_set_type, +}; + +void __init msm_init_irq(void) +{ + unsigned n; + + /* select level interrupts */ + writel(0, VIC_INT_TYPE0); + writel(0, VIC_INT_TYPE1); + + /* select highlevel interrupts */ + writel(0, VIC_INT_POLARITY0); + writel(0, VIC_INT_POLARITY1); + + /* select IRQ for all INTs */ + writel(0, VIC_INT_SELECT0); + writel(0, VIC_INT_SELECT1); + + /* disable all INTs */ + writel(0, VIC_INT_EN0); + writel(0, VIC_INT_EN1); + + /* don't use 1136 vic */ + writel(0, VIC_CONFIG); + + /* enable interrupt controller */ + writel(1, VIC_INT_MASTEREN); + + for (n = 0; n < NR_MSM_IRQS; n++) { + irq_set_chip_and_handler(n, &msm_irq_chip, handle_level_irq); + set_irq_flags(n, IRQF_VALID); + } +} diff --git a/arch/arm/mach-msm/last_radio_log.c b/arch/arm/mach-msm/last_radio_log.c new file mode 100644 index 00000000..1e243f46 --- /dev/null +++ b/arch/arm/mach-msm/last_radio_log.c @@ -0,0 +1,83 @@ +/* arch/arm/mach-msm/last_radio_log.c + * + * Extract the log from a modem crash though SMEM + * + * Copyright (C) 2007 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/proc_fs.h> +#include <linux/uaccess.h> + +#include "smd_private.h" + +static void *radio_log_base; +static size_t radio_log_size; + +extern void *smem_item(unsigned id, unsigned *size); + +static ssize_t last_radio_log_read(struct file *file, char __user *buf, + size_t len, loff_t *offset) +{ + loff_t pos = *offset; + ssize_t count; + + if (pos >= radio_log_size) + return 0; + + count = min(len, (size_t)(radio_log_size - pos)); + if (copy_to_user(buf, radio_log_base + pos, count)) { + pr_err("%s: copy to user failed\n", __func__); + return -EFAULT; + } + + *offset += count; + return count; +} + +static struct file_operations last_radio_log_fops = { + .read = last_radio_log_read, + .llseek = default_llseek, +}; + +void msm_init_last_radio_log(struct module *owner) +{ + struct proc_dir_entry *entry; + + if (last_radio_log_fops.owner) { + pr_err("%s: already claimed\n", __func__); + return; + } + + radio_log_base = smem_item(SMEM_CLKREGIM_BSP, &radio_log_size); + if (!radio_log_base) { + pr_err("%s: could not retrieve SMEM_CLKREGIM_BSP\n", __func__); + return; + } + + entry = create_proc_entry("last_radio_log", S_IFREG | S_IRUGO, NULL); + if (!entry) { + pr_err("%s: could not create proc entry for radio log\n", + __func__); + return; + } + + pr_err("%s: last radio log is %d bytes long\n", __func__, + radio_log_size); + last_radio_log_fops.owner = owner; + entry->proc_fops = &last_radio_log_fops; + entry->size = radio_log_size; +} +EXPORT_SYMBOL(msm_init_last_radio_log); diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c new file mode 100644 index 00000000..db0117ec --- /dev/null +++ b/arch/arm/mach-msm/platsmp.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/jiffies.h> +#include <linux/smp.h> +#include <linux/io.h> + +#include <asm/hardware/gic.h> +#include <asm/cacheflush.h> +#include <asm/cputype.h> +#include <asm/mach-types.h> +#include <asm/smp_plat.h> + +#include <mach/msm_iomap.h> + +#include "scm-boot.h" + +#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0 +#define SCSS_CPU1CORE_RESET 0xD80 +#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64 + +/* Mask for edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */ +#define GIC_PPI_EDGE_MASK 0xFFFFD7FF + +extern void msm_secondary_startup(void); +/* + * control for which core is the next to come out of the secondary + * boot "holding pen". + */ +volatile int pen_release = -1; + +static DEFINE_SPINLOCK(boot_lock); + +static inline int get_core_count(void) +{ + /* 1 + the PART[1:0] field of MIDR */ + return ((read_cpuid_id() >> 4) & 3) + 1; +} + +void __cpuinit platform_secondary_init(unsigned int cpu) +{ + /* Configure edge-triggered PPIs */ + writel(GIC_PPI_EDGE_MASK, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4); + + /* + * if any interrupts are already enabled for the primary + * core (e.g. timer irq), then they will not have been enabled + * for us: do so + */ + gic_secondary_init(0); + + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + pen_release = -1; + smp_wmb(); + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +static __cpuinit void prepare_cold_cpu(unsigned int cpu) +{ + int ret; + ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup), + SCM_FLAG_COLDBOOT_CPU1); + if (ret == 0) { + void __iomem *sc1_base_ptr; + sc1_base_ptr = ioremap_nocache(0x00902000, SZ_4K*2); + if (sc1_base_ptr) { + writel(0, sc1_base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL); + writel(0, sc1_base_ptr + SCSS_CPU1CORE_RESET); + writel(3, sc1_base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP); + iounmap(sc1_base_ptr); + } + } else + printk(KERN_DEBUG "Failed to set secondary core boot " + "address\n"); +} + +int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + static int cold_boot_done; + + /* Only need to bring cpu out of reset this way once */ + if (cold_boot_done == false) { + prepare_cold_cpu(cpu); + cold_boot_done = true; + } + + /* + * set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * The secondary processor is waiting to be released from + * the holding pen - release it, then wait for it to flag + * that it has been released by resetting pen_release. + * + * Note that "pen_release" is the hardware CPU ID, whereas + * "cpu" is Linux's internal ID. + */ + pen_release = cpu_logical_map(cpu); + __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); + outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); + + /* + * Send the secondary CPU a soft interrupt, thereby causing + * the boot monitor to read the system wide flags register, + * and branch to the address found there. + */ + gic_raise_softirq(cpumask_of(cpu), 1); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + smp_rmb(); + if (pen_release == -1) + break; + + udelay(10); + } + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return pen_release != -1 ? -ENOSYS : 0; +} + +/* + * Initialise the CPU possible map early - this describes the CPUs + * which may be present or become present in the system. The msm8x60 + * does not support the ARM SCU, so just set the possible cpu mask to + * NR_CPUS. + */ +void __init smp_init_cpus(void) +{ + unsigned int i, ncores = get_core_count(); + + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; + } + + for (i = 0; i < ncores; i++) + set_cpu_possible(i, true); + + set_smp_cross_call(gic_raise_softirq); +} + +void __init platform_smp_prepare_cpus(unsigned int max_cpus) +{ +} diff --git a/arch/arm/mach-msm/proc_comm.c b/arch/arm/mach-msm/proc_comm.c new file mode 100644 index 00000000..9980dc73 --- /dev/null +++ b/arch/arm/mach-msm/proc_comm.c @@ -0,0 +1,130 @@ +/* arch/arm/mach-msm/proc_comm.c + * + * Copyright (C) 2007-2008 Google, Inc. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/spinlock.h> +#include <mach/msm_iomap.h> +#include <mach/system.h> + +#include "proc_comm.h" + +static inline void msm_a2m_int(uint32_t irq) +{ +#if defined(CONFIG_ARCH_MSM7X30) + writel(1 << irq, MSM_GCC_BASE + 0x8); +#else + writel(1, MSM_CSR_BASE + 0x400 + (irq * 4)); +#endif +} + +static inline void notify_other_proc_comm(void) +{ + msm_a2m_int(6); +} + +#define APP_COMMAND 0x00 +#define APP_STATUS 0x04 +#define APP_DATA1 0x08 +#define APP_DATA2 0x0C + +#define MDM_COMMAND 0x10 +#define MDM_STATUS 0x14 +#define MDM_DATA1 0x18 +#define MDM_DATA2 0x1C + +static DEFINE_SPINLOCK(proc_comm_lock); + +/* The higher level SMD support will install this to + * provide a way to check for and handle modem restart. + */ +int (*msm_check_for_modem_crash)(void); + +/* Poll for a state change, checking for possible + * modem crashes along the way (so we don't wait + * forever while the ARM9 is blowing up). + * + * Return an error in the event of a modem crash and + * restart so the msm_proc_comm() routine can restart + * the operation from the beginning. + */ +static int proc_comm_wait_for(void __iomem *addr, unsigned value) +{ + for (;;) { + if (readl(addr) == value) + return 0; + + if (msm_check_for_modem_crash) + if (msm_check_for_modem_crash()) + return -EAGAIN; + } +} + +int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2) +{ + void __iomem *base = MSM_SHARED_RAM_BASE; + unsigned long flags; + int ret; + + spin_lock_irqsave(&proc_comm_lock, flags); + + for (;;) { + if (proc_comm_wait_for(base + MDM_STATUS, PCOM_READY)) + continue; + + writel(cmd, base + APP_COMMAND); + writel(data1 ? *data1 : 0, base + APP_DATA1); + writel(data2 ? *data2 : 0, base + APP_DATA2); + + notify_other_proc_comm(); + + if (proc_comm_wait_for(base + APP_COMMAND, PCOM_CMD_DONE)) + continue; + + if (readl(base + APP_STATUS) != PCOM_CMD_FAIL) { + if (data1) + *data1 = readl(base + APP_DATA1); + if (data2) + *data2 = readl(base + APP_DATA2); + ret = 0; + } else { + ret = -EIO; + } + break; + } + + writel(PCOM_CMD_IDLE, base + APP_COMMAND); + + spin_unlock_irqrestore(&proc_comm_lock, flags); + + return ret; +} + +/* + * We need to wait for the ARM9 to at least partially boot + * up before we can continue. Since the ARM9 does resource + * allocation, if we dont' wait we could end up crashing or in + * and unknown state. This function should be called early to + * wait on the ARM9. + */ +void __devinit proc_comm_boot_wait(void) +{ + void __iomem *base = MSM_SHARED_RAM_BASE; + + proc_comm_wait_for(base + MDM_STATUS, PCOM_READY); + +} diff --git a/arch/arm/mach-msm/proc_comm.h b/arch/arm/mach-msm/proc_comm.h new file mode 100644 index 00000000..12da4cac --- /dev/null +++ b/arch/arm/mach-msm/proc_comm.h @@ -0,0 +1,258 @@ +/* arch/arm/mach-msm/proc_comm.h + * + * Copyright (c) 2007 QUALCOMM Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _ARCH_ARM_MACH_MSM_PROC_COMM_H_ +#define _ARCH_ARM_MACH_MSM_PROC_COMM_H_ + +#include <linux/init.h> + +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_WRITE_BYTES_4_7, + PCOM_CONFIG_DISP, + PCOM_GET_FTM_BOOT_COUNT, + PCOM_RPC_GPIO_TLMM_CONFIG_EX, + PCOM_PM_MPP_CONFIG, + PCOM_GPIO_IN, + PCOM_GPIO_OUT, + PCOM_RESET_MODEM, + PCOM_RESET_CHIP_IMM, + PCOM_PM_VID_EN, + PCOM_VREG_PULLDOWN, + PCOM_GET_MODEM_VERSION, + PCOM_CLK_REGIME_SEC_RESET, + PCOM_CLK_REGIME_SEC_RESET_ASSERT, + PCOM_CLK_REGIME_SEC_RESET_DEASSERT, + PCOM_CLK_REGIME_SEC_PLL_REQUEST_WRP, + PCOM_CLK_REGIME_SEC_ENABLE, + PCOM_CLK_REGIME_SEC_DISABLE, + PCOM_CLK_REGIME_SEC_IS_ON, + PCOM_CLK_REGIME_SEC_SEL_CLK_INV, + PCOM_CLK_REGIME_SEC_SEL_CLK_SRC, + PCOM_CLK_REGIME_SEC_SEL_CLK_DIV, + PCOM_CLK_REGIME_SEC_ICODEC_CLK_ENABLE, + PCOM_CLK_REGIME_SEC_ICODEC_CLK_DISABLE, + PCOM_CLK_REGIME_SEC_SEL_SPEED, + PCOM_CLK_REGIME_SEC_CONFIG_GP_CLK_WRP, + PCOM_CLK_REGIME_SEC_CONFIG_MDH_CLK_WRP, + PCOM_CLK_REGIME_SEC_USB_XTAL_ON, + PCOM_CLK_REGIME_SEC_USB_XTAL_OFF, + PCOM_CLK_REGIME_SEC_SET_QDSP_DME_MODE, + PCOM_CLK_REGIME_SEC_SWITCH_ADSP_CLK, + PCOM_CLK_REGIME_SEC_GET_MAX_ADSP_CLK_KHZ, + PCOM_CLK_REGIME_SEC_GET_I2C_CLK_KHZ, + PCOM_CLK_REGIME_SEC_MSM_GET_CLK_FREQ_KHZ, + PCOM_CLK_REGIME_SEC_SEL_VFE_SRC, + PCOM_CLK_REGIME_SEC_MSM_SEL_CAMCLK, + PCOM_CLK_REGIME_SEC_MSM_SEL_LCDCLK, + PCOM_CLK_REGIME_SEC_VFE_RAIL_OFF, + PCOM_CLK_REGIME_SEC_VFE_RAIL_ON, + PCOM_CLK_REGIME_SEC_GRP_RAIL_OFF, + PCOM_CLK_REGIME_SEC_GRP_RAIL_ON, + PCOM_CLK_REGIME_SEC_VDC_RAIL_OFF, + PCOM_CLK_REGIME_SEC_VDC_RAIL_ON, + PCOM_CLK_REGIME_SEC_LCD_CTRL, + PCOM_CLK_REGIME_SEC_REGISTER_FOR_CPU_RESOURCE, + PCOM_CLK_REGIME_SEC_DEREGISTER_FOR_CPU_RESOURCE, + PCOM_CLK_REGIME_SEC_RESOURCE_REQUEST_WRP, + PCOM_CLK_REGIME_MSM_SEC_SEL_CLK_OWNER, + PCOM_CLK_REGIME_SEC_DEVMAN_REQUEST_WRP, + PCOM_GPIO_CONFIG, + PCOM_GPIO_CONFIGURE_GROUP, + PCOM_GPIO_TLMM_SET_PORT, + PCOM_GPIO_TLMM_CONFIG_EX, + PCOM_SET_FTM_BOOT_COUNT, + PCOM_RESERVED0, + PCOM_RESERVED1, + PCOM_CUSTOMER_CMD1, + PCOM_CUSTOMER_CMD2, + PCOM_CUSTOMER_CMD3, + PCOM_CLK_REGIME_ENTER_APPSBL_CHG_MODE, + PCOM_CLK_REGIME_EXIT_APPSBL_CHG_MODE, + PCOM_CLK_REGIME_SEC_RAIL_DISABLE, + PCOM_CLK_REGIME_SEC_RAIL_ENABLE, + PCOM_CLK_REGIME_SEC_RAIL_CONTROL, + PCOM_SET_SW_WATCHDOG_STATE, + PCOM_PM_MPP_CONFIG_DIGITAL_INPUT, + PCOM_PM_MPP_CONFIG_I_SINK, + PCOM_RESERVED_101, + PCOM_MSM_HSUSB_PHY_RESET, + PCOM_GET_BATT_MV_LEVEL, + PCOM_CHG_USB_IS_PC_CONNECTED, + PCOM_CHG_USB_IS_CHARGER_CONNECTED, + PCOM_CHG_USB_IS_DISCONNECTED, + PCOM_CHG_USB_IS_AVAILABLE, + PCOM_CLK_REGIME_SEC_MSM_SEL_FREQ, + PCOM_CLK_REGIME_SEC_SET_PCLK_AXI_POLICY, + PCOM_CLKCTL_RPC_RESET_ASSERT, + PCOM_CLKCTL_RPC_RESET_DEASSERT, + PCOM_CLKCTL_RPC_RAIL_ON, + PCOM_CLKCTL_RPC_RAIL_OFF, + PCOM_CLKCTL_RPC_RAIL_ENABLE, + PCOM_CLKCTL_RPC_RAIL_DISABLE, + PCOM_CLKCTL_RPC_RAIL_CONTROL, + PCOM_CLKCTL_RPC_MIN_MSMC1, + PCOM_NUM_CMDS, +}; + +enum { + PCOM_INVALID_STATUS = 0x0, + PCOM_READY, + PCOM_CMD_RUNNING, + PCOM_CMD_SUCCESS, + PCOM_CMD_FAIL, + PCOM_CMD_FAIL_FALSE_RETURNED, + PCOM_CMD_FAIL_CMD_OUT_OF_BOUNDS_SERVER, + PCOM_CMD_FAIL_CMD_OUT_OF_BOUNDS_CLIENT, + PCOM_CMD_FAIL_CMD_UNREGISTERED, + PCOM_CMD_FAIL_CMD_LOCKED, + PCOM_CMD_FAIL_SERVER_NOT_YET_READY, + PCOM_CMD_FAIL_BAD_DESTINATION, + PCOM_CMD_FAIL_SERVER_RESET, + PCOM_CMD_FAIL_SMSM_NOT_INIT, + PCOM_CMD_FAIL_PROC_COMM_BUSY, + PCOM_CMD_FAIL_PROC_COMM_NOT_INIT, + +}; + +/* List of VREGs that support the Pull Down Resistor setting. */ +enum vreg_pdown_id { + PM_VREG_PDOWN_MSMA_ID, + PM_VREG_PDOWN_MSMP_ID, + PM_VREG_PDOWN_MSME1_ID, /* Not supported in Panoramix */ + PM_VREG_PDOWN_MSMC1_ID, /* Not supported in PM6620 */ + PM_VREG_PDOWN_MSMC2_ID, /* Supported in PM7500 only */ + PM_VREG_PDOWN_GP3_ID, /* Supported in PM7500 only */ + PM_VREG_PDOWN_MSME2_ID, /* Supported in PM7500 and Panoramix only */ + PM_VREG_PDOWN_GP4_ID, /* Supported in PM7500 only */ + PM_VREG_PDOWN_GP1_ID, /* Supported in PM7500 only */ + PM_VREG_PDOWN_TCXO_ID, + PM_VREG_PDOWN_PA_ID, + PM_VREG_PDOWN_RFTX_ID, + PM_VREG_PDOWN_RFRX1_ID, + PM_VREG_PDOWN_RFRX2_ID, + PM_VREG_PDOWN_SYNT_ID, + PM_VREG_PDOWN_WLAN_ID, + PM_VREG_PDOWN_USB_ID, + PM_VREG_PDOWN_MMC_ID, + PM_VREG_PDOWN_RUIM_ID, + PM_VREG_PDOWN_MSMC0_ID, /* Supported in PM6610 only */ + PM_VREG_PDOWN_GP2_ID, /* Supported in PM7500 only */ + PM_VREG_PDOWN_GP5_ID, /* Supported in PM7500 only */ + PM_VREG_PDOWN_GP6_ID, /* Supported in PM7500 only */ + PM_VREG_PDOWN_RF_ID, + PM_VREG_PDOWN_RF_VCO_ID, + PM_VREG_PDOWN_MPLL_ID, + PM_VREG_PDOWN_S2_ID, + PM_VREG_PDOWN_S3_ID, + PM_VREG_PDOWN_RFUBM_ID, + + /* new for HAN */ + PM_VREG_PDOWN_RF1_ID, + PM_VREG_PDOWN_RF2_ID, + PM_VREG_PDOWN_RFA_ID, + PM_VREG_PDOWN_CDC2_ID, + PM_VREG_PDOWN_RFTX2_ID, + PM_VREG_PDOWN_USIM_ID, + PM_VREG_PDOWN_USB2P6_ID, + PM_VREG_PDOWN_USB3P3_ID, + PM_VREG_PDOWN_INVALID_ID, + + /* backward compatible enums only */ + PM_VREG_PDOWN_CAM_ID = PM_VREG_PDOWN_GP1_ID, + PM_VREG_PDOWN_MDDI_ID = PM_VREG_PDOWN_GP2_ID, + PM_VREG_PDOWN_RUIM2_ID = PM_VREG_PDOWN_GP3_ID, + PM_VREG_PDOWN_AUX_ID = PM_VREG_PDOWN_GP4_ID, + PM_VREG_PDOWN_AUX2_ID = PM_VREG_PDOWN_GP5_ID, + PM_VREG_PDOWN_BT_ID = PM_VREG_PDOWN_GP6_ID, + + PM_VREG_PDOWN_MSME_ID = PM_VREG_PDOWN_MSME1_ID, + PM_VREG_PDOWN_MSMC_ID = PM_VREG_PDOWN_MSMC1_ID, + PM_VREG_PDOWN_RFA1_ID = PM_VREG_PDOWN_RFRX2_ID, + PM_VREG_PDOWN_RFA2_ID = PM_VREG_PDOWN_RFTX2_ID, + PM_VREG_PDOWN_XO_ID = PM_VREG_PDOWN_TCXO_ID +}; + +enum { + PCOM_CLKRGM_APPS_RESET_USB_PHY = 34, + PCOM_CLKRGM_APPS_RESET_USBH = 37, +}; + +/* gpio info for PCOM_RPC_GPIO_TLMM_CONFIG_EX */ + +#define GPIO_ENABLE 0 +#define GPIO_DISABLE 1 + +#define GPIO_INPUT 0 +#define GPIO_OUTPUT 1 + +#define GPIO_NO_PULL 0 +#define GPIO_PULL_DOWN 1 +#define GPIO_KEEPER 2 +#define GPIO_PULL_UP 3 + +#define GPIO_2MA 0 +#define GPIO_4MA 1 +#define GPIO_6MA 2 +#define GPIO_8MA 3 +#define GPIO_10MA 4 +#define GPIO_12MA 5 +#define GPIO_14MA 6 +#define GPIO_16MA 7 + +#define PCOM_GPIO_CFG(gpio, func, dir, pull, drvstr) \ + ((((gpio) & 0x3FF) << 4) | \ + ((func) & 0xf) | \ + (((dir) & 0x1) << 14) | \ + (((pull) & 0x3) << 15) | \ + (((drvstr) & 0xF) << 17)) + +int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2); +void __init proc_comm_boot_wait(void); + +#endif diff --git a/arch/arm/mach-msm/scm-boot.c b/arch/arm/mach-msm/scm-boot.c new file mode 100644 index 00000000..45cee3e4 --- /dev/null +++ b/arch/arm/mach-msm/scm-boot.c @@ -0,0 +1,39 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/module.h> +#include <linux/slab.h> + +#include "scm.h" +#include "scm-boot.h" + +/* + * Set the cold/warm boot address for one of the CPU cores. + */ +int scm_set_boot_addr(phys_addr_t addr, int flags) +{ + struct { + unsigned int flags; + phys_addr_t addr; + } cmd; + + cmd.addr = addr; + cmd.flags = flags; + return scm_call(SCM_SVC_BOOT, SCM_BOOT_ADDR, + &cmd, sizeof(cmd), NULL, 0); +} +EXPORT_SYMBOL(scm_set_boot_addr); diff --git a/arch/arm/mach-msm/scm-boot.h b/arch/arm/mach-msm/scm-boot.h new file mode 100644 index 00000000..7be32ff5 --- /dev/null +++ b/arch/arm/mach-msm/scm-boot.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __MACH_SCM_BOOT_H +#define __MACH_SCM_BOOT_H + +#define SCM_BOOT_ADDR 0x1 +#define SCM_FLAG_COLDBOOT_CPU1 0x1 +#define SCM_FLAG_WARMBOOT_CPU1 0x2 +#define SCM_FLAG_WARMBOOT_CPU0 0x4 + +int scm_set_boot_addr(phys_addr_t addr, int flags); + +#endif diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c new file mode 100644 index 00000000..bafabb50 --- /dev/null +++ b/arch/arm/mach-msm/scm.c @@ -0,0 +1,296 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/errno.h> +#include <linux/err.h> + +#include <asm/cacheflush.h> + +#include "scm.h" + +/* Cache line size for msm8x60 */ +#define CACHELINESIZE 32 + +#define SCM_ENOMEM -5 +#define SCM_EOPNOTSUPP -4 +#define SCM_EINVAL_ADDR -3 +#define SCM_EINVAL_ARG -2 +#define SCM_ERROR -1 +#define SCM_INTERRUPTED 1 + +static DEFINE_MUTEX(scm_lock); + +/** + * struct scm_command - one SCM command buffer + * @len: total available memory for command and response + * @buf_offset: start of command buffer + * @resp_hdr_offset: start of response buffer + * @id: command to be executed + * @buf: buffer returned from scm_get_command_buffer() + * + * An SCM command is laid out in memory as follows: + * + * ------------------- <--- struct scm_command + * | command header | + * ------------------- <--- scm_get_command_buffer() + * | command buffer | + * ------------------- <--- struct scm_response and + * | response header | scm_command_to_response() + * ------------------- <--- scm_get_response_buffer() + * | response buffer | + * ------------------- + * + * There can be arbitrary padding between the headers and buffers so + * you should always use the appropriate scm_get_*_buffer() routines + * to access the buffers in a safe manner. + */ +struct scm_command { + u32 len; + u32 buf_offset; + u32 resp_hdr_offset; + u32 id; + u32 buf[0]; +}; + +/** + * struct scm_response - one SCM response buffer + * @len: total available memory for response + * @buf_offset: start of response data relative to start of scm_response + * @is_complete: indicates if the command has finished processing + */ +struct scm_response { + u32 len; + u32 buf_offset; + u32 is_complete; +}; + +/** + * alloc_scm_command() - Allocate an SCM command + * @cmd_size: size of the command buffer + * @resp_size: size of the response buffer + * + * Allocate an SCM command, including enough room for the command + * and response headers as well as the command and response buffers. + * + * Returns a valid &scm_command on success or %NULL if the allocation fails. + */ +static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size) +{ + struct scm_command *cmd; + size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size + + resp_size; + + cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL); + if (cmd) { + cmd->len = len; + cmd->buf_offset = offsetof(struct scm_command, buf); + cmd->resp_hdr_offset = cmd->buf_offset + cmd_size; + } + return cmd; +} + +/** + * free_scm_command() - Free an SCM command + * @cmd: command to free + * + * Free an SCM command. + */ +static inline void free_scm_command(struct scm_command *cmd) +{ + kfree(cmd); +} + +/** + * scm_command_to_response() - Get a pointer to a scm_response + * @cmd: command + * + * Returns a pointer to a response for a command. + */ +static inline struct scm_response *scm_command_to_response( + const struct scm_command *cmd) +{ + return (void *)cmd + cmd->resp_hdr_offset; +} + +/** + * scm_get_command_buffer() - Get a pointer to a command buffer + * @cmd: command + * + * Returns a pointer to the command buffer of a command. + */ +static inline void *scm_get_command_buffer(const struct scm_command *cmd) +{ + return (void *)cmd->buf; +} + +/** + * scm_get_response_buffer() - Get a pointer to a response buffer + * @rsp: response + * + * Returns a pointer to a response buffer of a response. + */ +static inline void *scm_get_response_buffer(const struct scm_response *rsp) +{ + return (void *)rsp + rsp->buf_offset; +} + +static int scm_remap_error(int err) +{ + switch (err) { + case SCM_ERROR: + return -EIO; + case SCM_EINVAL_ADDR: + case SCM_EINVAL_ARG: + return -EINVAL; + case SCM_EOPNOTSUPP: + return -EOPNOTSUPP; + case SCM_ENOMEM: + return -ENOMEM; + } + return -EINVAL; +} + +static u32 smc(u32 cmd_addr) +{ + int context_id; + register u32 r0 asm("r0") = 1; + register u32 r1 asm("r1") = (u32)&context_id; + register u32 r2 asm("r2") = cmd_addr; + do { + asm volatile( + __asmeq("%0", "r0") + __asmeq("%1", "r0") + __asmeq("%2", "r1") + __asmeq("%3", "r2") +#ifdef REQUIRES_SEC + ".arch_extension sec\n" +#endif + "smc #0 @ switch to secure world\n" + : "=r" (r0) + : "r" (r0), "r" (r1), "r" (r2) + : "r3"); + } while (r0 == SCM_INTERRUPTED); + + return r0; +} + +static int __scm_call(const struct scm_command *cmd) +{ + int ret; + u32 cmd_addr = virt_to_phys(cmd); + + /* + * Flush the entire cache here so callers don't have to remember + * to flush the cache when passing physical addresses to the secure + * side in the buffer. + */ + flush_cache_all(); + ret = smc(cmd_addr); + if (ret < 0) + ret = scm_remap_error(ret); + + return ret; +} + +/** + * scm_call() - Send an SCM command + * @svc_id: service identifier + * @cmd_id: command identifier + * @cmd_buf: command buffer + * @cmd_len: length of the command buffer + * @resp_buf: response buffer + * @resp_len: length of the response buffer + * + * Sends a command to the SCM and waits for the command to finish processing. + */ +int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, + void *resp_buf, size_t resp_len) +{ + int ret; + struct scm_command *cmd; + struct scm_response *rsp; + + cmd = alloc_scm_command(cmd_len, resp_len); + if (!cmd) + return -ENOMEM; + + cmd->id = (svc_id << 10) | cmd_id; + if (cmd_buf) + memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len); + + mutex_lock(&scm_lock); + ret = __scm_call(cmd); + mutex_unlock(&scm_lock); + if (ret) + goto out; + + rsp = scm_command_to_response(cmd); + do { + u32 start = (u32)rsp; + u32 end = (u32)scm_get_response_buffer(rsp) + resp_len; + start &= ~(CACHELINESIZE - 1); + while (start < end) { + asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start) + : "memory"); + start += CACHELINESIZE; + } + } while (!rsp->is_complete); + + if (resp_buf) + memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len); +out: + free_scm_command(cmd); + return ret; +} +EXPORT_SYMBOL(scm_call); + +u32 scm_get_version(void) +{ + int context_id; + static u32 version = -1; + register u32 r0 asm("r0"); + register u32 r1 asm("r1"); + + if (version != -1) + return version; + + mutex_lock(&scm_lock); + + r0 = 0x1 << 8; + r1 = (u32)&context_id; + do { + asm volatile( + __asmeq("%0", "r0") + __asmeq("%1", "r1") + __asmeq("%2", "r0") + __asmeq("%3", "r1") + "smc #0 @ switch to secure world\n" + : "=r" (r0), "=r" (r1) + : "r" (r0), "r" (r1) + : "r2", "r3"); + } while (r0 == SCM_INTERRUPTED); + + version = r1; + mutex_unlock(&scm_lock); + + return version; +} +EXPORT_SYMBOL(scm_get_version); diff --git a/arch/arm/mach-msm/scm.h b/arch/arm/mach-msm/scm.h new file mode 100644 index 00000000..00b31ea5 --- /dev/null +++ b/arch/arm/mach-msm/scm.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef __MACH_SCM_H +#define __MACH_SCM_H + +#define SCM_SVC_BOOT 0x1 +#define SCM_SVC_PIL 0x2 + +extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, + void *resp_buf, size_t resp_len); + +#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF)) + +extern u32 scm_get_version(void); + +#endif diff --git a/arch/arm/mach-msm/sirc.c b/arch/arm/mach-msm/sirc.c new file mode 100644 index 00000000..689e78c9 --- /dev/null +++ b/arch/arm/mach-msm/sirc.c @@ -0,0 +1,172 @@ +/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + */ + +#include <linux/io.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <asm/irq.h> + +static unsigned int int_enable; +static unsigned int wake_enable; + +static struct sirc_regs_t sirc_regs = { + .int_enable = SPSS_SIRC_INT_ENABLE, + .int_enable_clear = SPSS_SIRC_INT_ENABLE_CLEAR, + .int_enable_set = SPSS_SIRC_INT_ENABLE_SET, + .int_type = SPSS_SIRC_INT_TYPE, + .int_polarity = SPSS_SIRC_INT_POLARITY, + .int_clear = SPSS_SIRC_INT_CLEAR, +}; + +static struct sirc_cascade_regs sirc_reg_table[] = { + { + .int_status = SPSS_SIRC_IRQ_STATUS, + .cascade_irq = INT_SIRC_0, + } +}; + +/* Mask off the given interrupt. Keep the int_enable mask in sync with + the enable reg, so it can be restored after power collapse. */ +static void sirc_irq_mask(struct irq_data *d) +{ + unsigned int mask; + + mask = 1 << (d->irq - FIRST_SIRC_IRQ); + writel(mask, sirc_regs.int_enable_clear); + int_enable &= ~mask; + return; +} + +/* Unmask the given interrupt. Keep the int_enable mask in sync with + the enable reg, so it can be restored after power collapse. */ +static void sirc_irq_unmask(struct irq_data *d) +{ + unsigned int mask; + + mask = 1 << (d->irq - FIRST_SIRC_IRQ); + writel(mask, sirc_regs.int_enable_set); + int_enable |= mask; + return; +} + +static void sirc_irq_ack(struct irq_data *d) +{ + unsigned int mask; + + mask = 1 << (d->irq - FIRST_SIRC_IRQ); + writel(mask, sirc_regs.int_clear); + return; +} + +static int sirc_irq_set_wake(struct irq_data *d, unsigned int on) +{ + unsigned int mask; + + /* Used to set the interrupt enable mask during power collapse. */ + mask = 1 << (d->irq - FIRST_SIRC_IRQ); + if (on) + wake_enable |= mask; + else + wake_enable &= ~mask; + + return 0; +} + +static int sirc_irq_set_type(struct irq_data *d, unsigned int flow_type) +{ + unsigned int mask; + unsigned int val; + + mask = 1 << (d->irq - FIRST_SIRC_IRQ); + val = readl(sirc_regs.int_polarity); + + if (flow_type & (IRQF_TRIGGER_LOW | IRQF_TRIGGER_FALLING)) + val |= mask; + else + val &= ~mask; + + writel(val, sirc_regs.int_polarity); + + val = readl(sirc_regs.int_type); + if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) { + val |= mask; + __irq_set_handler_locked(d->irq, handle_edge_irq); + } else { + val &= ~mask; + __irq_set_handler_locked(d->irq, handle_level_irq); + } + + writel(val, sirc_regs.int_type); + + return 0; +} + +/* Finds the pending interrupt on the passed cascade irq and redrives it */ +static void sirc_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + unsigned int reg = 0; + unsigned int sirq; + unsigned int status; + + while ((reg < ARRAY_SIZE(sirc_reg_table)) && + (sirc_reg_table[reg].cascade_irq != irq)) + reg++; + + status = readl(sirc_reg_table[reg].int_status); + status &= SIRC_MASK; + if (status == 0) + return; + + for (sirq = 0; + (sirq < NR_SIRC_IRQS) && ((status & (1U << sirq)) == 0); + sirq++) + ; + generic_handle_irq(sirq+FIRST_SIRC_IRQ); + + desc->irq_data.chip->irq_ack(&desc->irq_data); +} + +static struct irq_chip sirc_irq_chip = { + .name = "sirc", + .irq_ack = sirc_irq_ack, + .irq_mask = sirc_irq_mask, + .irq_unmask = sirc_irq_unmask, + .irq_set_wake = sirc_irq_set_wake, + .irq_set_type = sirc_irq_set_type, +}; + +void __init msm_init_sirc(void) +{ + int i; + + int_enable = 0; + wake_enable = 0; + + for (i = FIRST_SIRC_IRQ; i < LAST_SIRC_IRQ; i++) { + irq_set_chip_and_handler(i, &sirc_irq_chip, handle_edge_irq); + set_irq_flags(i, IRQF_VALID); + } + + for (i = 0; i < ARRAY_SIZE(sirc_reg_table); i++) { + irq_set_chained_handler(sirc_reg_table[i].cascade_irq, + sirc_irq_handler); + irq_set_irq_wake(sirc_reg_table[i].cascade_irq, 1); + } + return; +} + diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c new file mode 100644 index 00000000..657be732 --- /dev/null +++ b/arch/arm/mach-msm/smd.c @@ -0,0 +1,1041 @@ +/* arch/arm/mach-msm/smd.c + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/cdev.h> +#include <linux/device.h> +#include <linux/wait.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/list.h> +#include <linux/slab.h> +#include <linux/debugfs.h> +#include <linux/delay.h> + +#include <mach/msm_smd.h> +#include <mach/system.h> + +#include "smd_private.h" +#include "proc_comm.h" + +#if defined(CONFIG_ARCH_QSD8X50) +#define CONFIG_QDSP6 1 +#endif + +void (*msm_hw_reset_hook)(void); + +#define MODULE_NAME "msm_smd" + +enum { + MSM_SMD_DEBUG = 1U << 0, + MSM_SMSM_DEBUG = 1U << 0, +}; + +static int msm_smd_debug_mask; + +struct shared_info { + int ready; + unsigned state; +}; + +static unsigned dummy_state[SMSM_STATE_COUNT]; + +static struct shared_info smd_info = { + .state = (unsigned) &dummy_state, +}; + +module_param_named(debug_mask, msm_smd_debug_mask, + int, S_IRUGO | S_IWUSR | S_IWGRP); + +static unsigned last_heap_free = 0xffffffff; + +static inline void notify_other_smsm(void) +{ + msm_a2m_int(5); +#ifdef CONFIG_QDSP6 + msm_a2m_int(8); +#endif +} + +static inline void notify_modem_smd(void) +{ + msm_a2m_int(0); +} + +static inline void notify_dsp_smd(void) +{ + msm_a2m_int(8); +} + +static void smd_diag(void) +{ + char *x; + + x = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG); + if (x != 0) { + x[SZ_DIAG_ERR_MSG - 1] = 0; + pr_debug("DIAG '%s'\n", x); + } +} + +/* call when SMSM_RESET flag is set in the A9's smsm_state */ +static void handle_modem_crash(void) +{ + pr_err("ARM9 has CRASHED\n"); + smd_diag(); + + /* hard reboot if possible */ + if (msm_hw_reset_hook) + msm_hw_reset_hook(); + + /* in this case the modem or watchdog should reboot us */ + for (;;) + ; +} + +uint32_t raw_smsm_get_state(enum smsm_state_item item) +{ + return readl(smd_info.state + item * 4); +} + +static int check_for_modem_crash(void) +{ + if (raw_smsm_get_state(SMSM_STATE_MODEM) & SMSM_RESET) { + handle_modem_crash(); + return -1; + } + return 0; +} + +/* the spinlock is used to synchronize between the + * irq handler and code that mutates the channel + * list or fiddles with channel state + */ +DEFINE_SPINLOCK(smd_lock); +DEFINE_SPINLOCK(smem_lock); + +/* the mutex is used during open() and close() + * operations to avoid races while creating or + * destroying smd_channel structures + */ +static DEFINE_MUTEX(smd_creation_mutex); + +static int smd_initialized; + +LIST_HEAD(smd_ch_closed_list); +LIST_HEAD(smd_ch_list_modem); +LIST_HEAD(smd_ch_list_dsp); + +static unsigned char smd_ch_allocated[64]; +static struct work_struct probe_work; + +/* how many bytes are available for reading */ +static int smd_stream_read_avail(struct smd_channel *ch) +{ + return (ch->recv->head - ch->recv->tail) & ch->fifo_mask; +} + +/* how many bytes we are free to write */ +static int smd_stream_write_avail(struct smd_channel *ch) +{ + return ch->fifo_mask - + ((ch->send->head - ch->send->tail) & ch->fifo_mask); +} + +static int smd_packet_read_avail(struct smd_channel *ch) +{ + if (ch->current_packet) { + int n = smd_stream_read_avail(ch); + if (n > ch->current_packet) + n = ch->current_packet; + return n; + } else { + return 0; + } +} + +static int smd_packet_write_avail(struct smd_channel *ch) +{ + int n = smd_stream_write_avail(ch); + return n > SMD_HEADER_SIZE ? n - SMD_HEADER_SIZE : 0; +} + +static int ch_is_open(struct smd_channel *ch) +{ + return (ch->recv->state == SMD_SS_OPENED) && + (ch->send->state == SMD_SS_OPENED); +} + +/* provide a pointer and length to readable data in the fifo */ +static unsigned ch_read_buffer(struct smd_channel *ch, void **ptr) +{ + unsigned head = ch->recv->head; + unsigned tail = ch->recv->tail; + *ptr = (void *) (ch->recv_data + tail); + + if (tail <= head) + return head - tail; + else + return ch->fifo_size - tail; +} + +/* advance the fifo read pointer after data from ch_read_buffer is consumed */ +static void ch_read_done(struct smd_channel *ch, unsigned count) +{ + BUG_ON(count > smd_stream_read_avail(ch)); + ch->recv->tail = (ch->recv->tail + count) & ch->fifo_mask; + ch->send->fTAIL = 1; +} + +/* basic read interface to ch_read_{buffer,done} used + * by smd_*_read() and update_packet_state() + * will read-and-discard if the _data pointer is null + */ +static int ch_read(struct smd_channel *ch, void *_data, int len) +{ + void *ptr; + unsigned n; + unsigned char *data = _data; + int orig_len = len; + + while (len > 0) { + n = ch_read_buffer(ch, &ptr); + if (n == 0) + break; + + if (n > len) + n = len; + if (_data) + memcpy(data, ptr, n); + + data += n; + len -= n; + ch_read_done(ch, n); + } + + return orig_len - len; +} + +static void update_stream_state(struct smd_channel *ch) +{ + /* streams have no special state requiring updating */ +} + +static void update_packet_state(struct smd_channel *ch) +{ + unsigned hdr[5]; + int r; + + /* can't do anything if we're in the middle of a packet */ + if (ch->current_packet != 0) + return; + + /* don't bother unless we can get the full header */ + if (smd_stream_read_avail(ch) < SMD_HEADER_SIZE) + return; + + r = ch_read(ch, hdr, SMD_HEADER_SIZE); + BUG_ON(r != SMD_HEADER_SIZE); + + ch->current_packet = hdr[0]; +} + +/* provide a pointer and length to next free space in the fifo */ +static unsigned ch_write_buffer(struct smd_channel *ch, void **ptr) +{ + unsigned head = ch->send->head; + unsigned tail = ch->send->tail; + *ptr = (void *) (ch->send_data + head); + + if (head < tail) { + return tail - head - 1; + } else { + if (tail == 0) + return ch->fifo_size - head - 1; + else + return ch->fifo_size - head; + } +} + +/* advace the fifo write pointer after freespace + * from ch_write_buffer is filled + */ +static void ch_write_done(struct smd_channel *ch, unsigned count) +{ + BUG_ON(count > smd_stream_write_avail(ch)); + ch->send->head = (ch->send->head + count) & ch->fifo_mask; + ch->send->fHEAD = 1; +} + +static void ch_set_state(struct smd_channel *ch, unsigned n) +{ + if (n == SMD_SS_OPENED) { + ch->send->fDSR = 1; + ch->send->fCTS = 1; + ch->send->fCD = 1; + } else { + ch->send->fDSR = 0; + ch->send->fCTS = 0; + ch->send->fCD = 0; + } + ch->send->state = n; + ch->send->fSTATE = 1; + ch->notify_other_cpu(); +} + +static void do_smd_probe(void) +{ + struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE; + if (shared->heap_info.free_offset != last_heap_free) { + last_heap_free = shared->heap_info.free_offset; + schedule_work(&probe_work); + } +} + +static void smd_state_change(struct smd_channel *ch, + unsigned last, unsigned next) +{ + ch->last_state = next; + + pr_debug("ch %d %d -> %d\n", ch->n, last, next); + + switch (next) { + case SMD_SS_OPENING: + ch->recv->tail = 0; + case SMD_SS_OPENED: + if (ch->send->state != SMD_SS_OPENED) + ch_set_state(ch, SMD_SS_OPENED); + ch->notify(ch->priv, SMD_EVENT_OPEN); + break; + case SMD_SS_FLUSHING: + case SMD_SS_RESET: + /* we should force them to close? */ + default: + ch->notify(ch->priv, SMD_EVENT_CLOSE); + } +} + +static void handle_smd_irq(struct list_head *list, void (*notify)(void)) +{ + unsigned long flags; + struct smd_channel *ch; + int do_notify = 0; + unsigned ch_flags; + unsigned tmp; + + spin_lock_irqsave(&smd_lock, flags); + list_for_each_entry(ch, list, ch_list) { + ch_flags = 0; + if (ch_is_open(ch)) { + if (ch->recv->fHEAD) { + ch->recv->fHEAD = 0; + ch_flags |= 1; + do_notify |= 1; + } + if (ch->recv->fTAIL) { + ch->recv->fTAIL = 0; + ch_flags |= 2; + do_notify |= 1; + } + if (ch->recv->fSTATE) { + ch->recv->fSTATE = 0; + ch_flags |= 4; + do_notify |= 1; + } + } + tmp = ch->recv->state; + if (tmp != ch->last_state) + smd_state_change(ch, ch->last_state, tmp); + if (ch_flags) { + ch->update_state(ch); + ch->notify(ch->priv, SMD_EVENT_DATA); + } + } + if (do_notify) + notify(); + spin_unlock_irqrestore(&smd_lock, flags); + do_smd_probe(); +} + +static irqreturn_t smd_modem_irq_handler(int irq, void *data) +{ + handle_smd_irq(&smd_ch_list_modem, notify_modem_smd); + return IRQ_HANDLED; +} + +#if defined(CONFIG_QDSP6) +static irqreturn_t smd_dsp_irq_handler(int irq, void *data) +{ + handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd); + return IRQ_HANDLED; +} +#endif + +static void smd_fake_irq_handler(unsigned long arg) +{ + handle_smd_irq(&smd_ch_list_modem, notify_modem_smd); + handle_smd_irq(&smd_ch_list_dsp, notify_dsp_smd); +} + +static DECLARE_TASKLET(smd_fake_irq_tasklet, smd_fake_irq_handler, 0); + +static inline int smd_need_int(struct smd_channel *ch) +{ + if (ch_is_open(ch)) { + if (ch->recv->fHEAD || ch->recv->fTAIL || ch->recv->fSTATE) + return 1; + if (ch->recv->state != ch->last_state) + return 1; + } + return 0; +} + +void smd_sleep_exit(void) +{ + unsigned long flags; + struct smd_channel *ch; + int need_int = 0; + + spin_lock_irqsave(&smd_lock, flags); + list_for_each_entry(ch, &smd_ch_list_modem, ch_list) { + if (smd_need_int(ch)) { + need_int = 1; + break; + } + } + list_for_each_entry(ch, &smd_ch_list_dsp, ch_list) { + if (smd_need_int(ch)) { + need_int = 1; + break; + } + } + spin_unlock_irqrestore(&smd_lock, flags); + do_smd_probe(); + + if (need_int) { + if (msm_smd_debug_mask & MSM_SMD_DEBUG) + pr_info("smd_sleep_exit need interrupt\n"); + tasklet_schedule(&smd_fake_irq_tasklet); + } +} + + +void smd_kick(smd_channel_t *ch) +{ + unsigned long flags; + unsigned tmp; + + spin_lock_irqsave(&smd_lock, flags); + ch->update_state(ch); + tmp = ch->recv->state; + if (tmp != ch->last_state) { + ch->last_state = tmp; + if (tmp == SMD_SS_OPENED) + ch->notify(ch->priv, SMD_EVENT_OPEN); + else + ch->notify(ch->priv, SMD_EVENT_CLOSE); + } + ch->notify(ch->priv, SMD_EVENT_DATA); + ch->notify_other_cpu(); + spin_unlock_irqrestore(&smd_lock, flags); +} + +static int smd_is_packet(int chn, unsigned type) +{ + type &= SMD_KIND_MASK; + if (type == SMD_KIND_PACKET) + return 1; + if (type == SMD_KIND_STREAM) + return 0; + + /* older AMSS reports SMD_KIND_UNKNOWN always */ + if ((chn > 4) || (chn == 1)) + return 1; + else + return 0; +} + +static int smd_stream_write(smd_channel_t *ch, const void *_data, int len) +{ + void *ptr; + const unsigned char *buf = _data; + unsigned xfer; + int orig_len = len; + + if (len < 0) + return -EINVAL; + + while ((xfer = ch_write_buffer(ch, &ptr)) != 0) { + if (!ch_is_open(ch)) + break; + if (xfer > len) + xfer = len; + memcpy(ptr, buf, xfer); + ch_write_done(ch, xfer); + len -= xfer; + buf += xfer; + if (len == 0) + break; + } + + ch->notify_other_cpu(); + + return orig_len - len; +} + +static int smd_packet_write(smd_channel_t *ch, const void *_data, int len) +{ + unsigned hdr[5]; + + if (len < 0) + return -EINVAL; + + if (smd_stream_write_avail(ch) < (len + SMD_HEADER_SIZE)) + return -ENOMEM; + + hdr[0] = len; + hdr[1] = hdr[2] = hdr[3] = hdr[4] = 0; + + smd_stream_write(ch, hdr, sizeof(hdr)); + smd_stream_write(ch, _data, len); + + return len; +} + +static int smd_stream_read(smd_channel_t *ch, void *data, int len) +{ + int r; + + if (len < 0) + return -EINVAL; + + r = ch_read(ch, data, len); + if (r > 0) + ch->notify_other_cpu(); + + return r; +} + +static int smd_packet_read(smd_channel_t *ch, void *data, int len) +{ + unsigned long flags; + int r; + + if (len < 0) + return -EINVAL; + + if (len > ch->current_packet) + len = ch->current_packet; + + r = ch_read(ch, data, len); + if (r > 0) + ch->notify_other_cpu(); + + spin_lock_irqsave(&smd_lock, flags); + ch->current_packet -= r; + update_packet_state(ch); + spin_unlock_irqrestore(&smd_lock, flags); + + return r; +} + +static int smd_alloc_channel(const char *name, uint32_t cid, uint32_t type) +{ + struct smd_channel *ch; + + ch = kzalloc(sizeof(struct smd_channel), GFP_KERNEL); + if (ch == 0) { + pr_err("smd_alloc_channel() out of memory\n"); + return -1; + } + ch->n = cid; + + if (_smd_alloc_channel(ch)) { + kfree(ch); + return -1; + } + + ch->fifo_mask = ch->fifo_size - 1; + ch->type = type; + + if ((type & SMD_TYPE_MASK) == SMD_TYPE_APPS_MODEM) + ch->notify_other_cpu = notify_modem_smd; + else + ch->notify_other_cpu = notify_dsp_smd; + + if (smd_is_packet(cid, type)) { + ch->read = smd_packet_read; + ch->write = smd_packet_write; + ch->read_avail = smd_packet_read_avail; + ch->write_avail = smd_packet_write_avail; + ch->update_state = update_packet_state; + } else { + ch->read = smd_stream_read; + ch->write = smd_stream_write; + ch->read_avail = smd_stream_read_avail; + ch->write_avail = smd_stream_write_avail; + ch->update_state = update_stream_state; + } + + if ((type & 0xff) == 0) + memcpy(ch->name, "SMD_", 4); + else + memcpy(ch->name, "DSP_", 4); + memcpy(ch->name + 4, name, 20); + ch->name[23] = 0; + ch->pdev.name = ch->name; + ch->pdev.id = -1; + + pr_debug("smd_alloc_channel() cid=%02d size=%05d '%s'\n", + ch->n, ch->fifo_size, ch->name); + + mutex_lock(&smd_creation_mutex); + list_add(&ch->ch_list, &smd_ch_closed_list); + mutex_unlock(&smd_creation_mutex); + + platform_device_register(&ch->pdev); + return 0; +} + +static void smd_channel_probe_worker(struct work_struct *work) +{ + struct smd_alloc_elm *shared; + unsigned ctype; + unsigned type; + unsigned n; + + shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64); + if (!shared) { + pr_err("cannot find allocation table\n"); + return; + } + for (n = 0; n < 64; n++) { + if (smd_ch_allocated[n]) + continue; + if (!shared[n].ref_count) + continue; + if (!shared[n].name[0]) + continue; + ctype = shared[n].ctype; + type = ctype & SMD_TYPE_MASK; + + /* DAL channels are stream but neither the modem, + * nor the DSP correctly indicate this. Fixup manually. + */ + if (!memcmp(shared[n].name, "DAL", 3)) + ctype = (ctype & (~SMD_KIND_MASK)) | SMD_KIND_STREAM; + + type = shared[n].ctype & SMD_TYPE_MASK; + if ((type == SMD_TYPE_APPS_MODEM) || + (type == SMD_TYPE_APPS_DSP)) + if (!smd_alloc_channel(shared[n].name, shared[n].cid, ctype)) + smd_ch_allocated[n] = 1; + } +} + +static void do_nothing_notify(void *priv, unsigned flags) +{ +} + +struct smd_channel *smd_get_channel(const char *name) +{ + struct smd_channel *ch; + + mutex_lock(&smd_creation_mutex); + list_for_each_entry(ch, &smd_ch_closed_list, ch_list) { + if (!strcmp(name, ch->name)) { + list_del(&ch->ch_list); + mutex_unlock(&smd_creation_mutex); + return ch; + } + } + mutex_unlock(&smd_creation_mutex); + + return NULL; +} + +int smd_open(const char *name, smd_channel_t **_ch, + void *priv, void (*notify)(void *, unsigned)) +{ + struct smd_channel *ch; + unsigned long flags; + + if (smd_initialized == 0) { + pr_info("smd_open() before smd_init()\n"); + return -ENODEV; + } + + ch = smd_get_channel(name); + if (!ch) + return -ENODEV; + + if (notify == 0) + notify = do_nothing_notify; + + ch->notify = notify; + ch->current_packet = 0; + ch->last_state = SMD_SS_CLOSED; + ch->priv = priv; + + *_ch = ch; + + spin_lock_irqsave(&smd_lock, flags); + + if ((ch->type & SMD_TYPE_MASK) == SMD_TYPE_APPS_MODEM) + list_add(&ch->ch_list, &smd_ch_list_modem); + else + list_add(&ch->ch_list, &smd_ch_list_dsp); + + /* If the remote side is CLOSING, we need to get it to + * move to OPENING (which we'll do by moving from CLOSED to + * OPENING) and then get it to move from OPENING to + * OPENED (by doing the same state change ourselves). + * + * Otherwise, it should be OPENING and we can move directly + * to OPENED so that it will follow. + */ + if (ch->recv->state == SMD_SS_CLOSING) { + ch->send->head = 0; + ch_set_state(ch, SMD_SS_OPENING); + } else { + ch_set_state(ch, SMD_SS_OPENED); + } + spin_unlock_irqrestore(&smd_lock, flags); + smd_kick(ch); + + return 0; +} + +int smd_close(smd_channel_t *ch) +{ + unsigned long flags; + + if (ch == 0) + return -1; + + spin_lock_irqsave(&smd_lock, flags); + ch->notify = do_nothing_notify; + list_del(&ch->ch_list); + ch_set_state(ch, SMD_SS_CLOSED); + spin_unlock_irqrestore(&smd_lock, flags); + + mutex_lock(&smd_creation_mutex); + list_add(&ch->ch_list, &smd_ch_closed_list); + mutex_unlock(&smd_creation_mutex); + + return 0; +} + +int smd_read(smd_channel_t *ch, void *data, int len) +{ + return ch->read(ch, data, len); +} + +int smd_write(smd_channel_t *ch, const void *data, int len) +{ + return ch->write(ch, data, len); +} + +int smd_write_atomic(smd_channel_t *ch, const void *data, int len) +{ + unsigned long flags; + int res; + spin_lock_irqsave(&smd_lock, flags); + res = ch->write(ch, data, len); + spin_unlock_irqrestore(&smd_lock, flags); + return res; +} + +int smd_read_avail(smd_channel_t *ch) +{ + return ch->read_avail(ch); +} + +int smd_write_avail(smd_channel_t *ch) +{ + return ch->write_avail(ch); +} + +int smd_wait_until_readable(smd_channel_t *ch, int bytes) +{ + return -1; +} + +int smd_wait_until_writable(smd_channel_t *ch, int bytes) +{ + return -1; +} + +int smd_cur_packet_size(smd_channel_t *ch) +{ + return ch->current_packet; +} + + +/* ------------------------------------------------------------------------- */ + +void *smem_alloc(unsigned id, unsigned size) +{ + return smem_find(id, size); +} + +void *smem_item(unsigned id, unsigned *size) +{ + struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE; + struct smem_heap_entry *toc = shared->heap_toc; + + if (id >= SMEM_NUM_ITEMS) + return 0; + + if (toc[id].allocated) { + *size = toc[id].size; + return (void *) (MSM_SHARED_RAM_BASE + toc[id].offset); + } else { + *size = 0; + } + + return 0; +} + +void *smem_find(unsigned id, unsigned size_in) +{ + unsigned size; + void *ptr; + + ptr = smem_item(id, &size); + if (!ptr) + return 0; + + size_in = ALIGN(size_in, 8); + if (size_in != size) { + pr_err("smem_find(%d, %d): wrong size %d\n", + id, size_in, size); + return 0; + } + + return ptr; +} + +static irqreturn_t smsm_irq_handler(int irq, void *data) +{ + unsigned long flags; + unsigned apps, modm; + + spin_lock_irqsave(&smem_lock, flags); + + apps = raw_smsm_get_state(SMSM_STATE_APPS); + modm = raw_smsm_get_state(SMSM_STATE_MODEM); + + if (msm_smd_debug_mask & MSM_SMSM_DEBUG) + pr_info("<SM %08x %08x>\n", apps, modm); + if (modm & SMSM_RESET) + handle_modem_crash(); + + do_smd_probe(); + + spin_unlock_irqrestore(&smem_lock, flags); + return IRQ_HANDLED; +} + +int smsm_change_state(enum smsm_state_item item, + uint32_t clear_mask, uint32_t set_mask) +{ + unsigned long addr = smd_info.state + item * 4; + unsigned long flags; + unsigned state; + + if (!smd_info.ready) + return -EIO; + + spin_lock_irqsave(&smem_lock, flags); + + if (raw_smsm_get_state(SMSM_STATE_MODEM) & SMSM_RESET) + handle_modem_crash(); + + state = (readl(addr) & ~clear_mask) | set_mask; + writel(state, addr); + + if (msm_smd_debug_mask & MSM_SMSM_DEBUG) + pr_info("smsm_change_state %d %x\n", item, state); + notify_other_smsm(); + + spin_unlock_irqrestore(&smem_lock, flags); + + return 0; +} + +uint32_t smsm_get_state(enum smsm_state_item item) +{ + unsigned long flags; + uint32_t rv; + + spin_lock_irqsave(&smem_lock, flags); + + rv = readl(smd_info.state + item * 4); + + if (item == SMSM_STATE_MODEM && (rv & SMSM_RESET)) + handle_modem_crash(); + + spin_unlock_irqrestore(&smem_lock, flags); + + return rv; +} + +#ifdef CONFIG_ARCH_MSM_SCORPION + +int smsm_set_sleep_duration(uint32_t delay) +{ + struct msm_dem_slave_data *ptr; + + ptr = smem_find(SMEM_APPS_DEM_SLAVE_DATA, sizeof(*ptr)); + if (ptr == NULL) { + pr_err("smsm_set_sleep_duration <SM NO APPS_DEM_SLAVE_DATA>\n"); + return -EIO; + } + if (msm_smd_debug_mask & MSM_SMSM_DEBUG) + pr_info("smsm_set_sleep_duration %d -> %d\n", + ptr->sleep_time, delay); + ptr->sleep_time = delay; + return 0; +} + +#else + +int smsm_set_sleep_duration(uint32_t delay) +{ + uint32_t *ptr; + + ptr = smem_find(SMEM_SMSM_SLEEP_DELAY, sizeof(*ptr)); + if (ptr == NULL) { + pr_err("smsm_set_sleep_duration <SM NO SLEEP_DELAY>\n"); + return -EIO; + } + if (msm_smd_debug_mask & MSM_SMSM_DEBUG) + pr_info("smsm_set_sleep_duration %d -> %d\n", + *ptr, delay); + *ptr = delay; + return 0; +} + +#endif + +int smd_core_init(void) +{ + int r; + + /* wait for essential items to be initialized */ + for (;;) { + unsigned size; + void *state; + state = smem_item(SMEM_SMSM_SHARED_STATE, &size); + if (size == SMSM_V1_SIZE || size == SMSM_V2_SIZE) { + smd_info.state = (unsigned)state; + break; + } + } + + smd_info.ready = 1; + + r = request_irq(INT_A9_M2A_0, smd_modem_irq_handler, + IRQF_TRIGGER_RISING, "smd_dev", 0); + if (r < 0) + return r; + r = enable_irq_wake(INT_A9_M2A_0); + if (r < 0) + pr_err("smd_core_init: enable_irq_wake failed for A9_M2A_0\n"); + + r = request_irq(INT_A9_M2A_5, smsm_irq_handler, + IRQF_TRIGGER_RISING, "smsm_dev", 0); + if (r < 0) { + free_irq(INT_A9_M2A_0, 0); + return r; + } + r = enable_irq_wake(INT_A9_M2A_5); + if (r < 0) + pr_err("smd_core_init: enable_irq_wake failed for A9_M2A_5\n"); + +#if defined(CONFIG_QDSP6) + r = request_irq(INT_ADSP_A11, smd_dsp_irq_handler, + IRQF_TRIGGER_RISING, "smd_dsp", 0); + if (r < 0) { + free_irq(INT_A9_M2A_0, 0); + free_irq(INT_A9_M2A_5, 0); + return r; + } +#endif + + /* check for any SMD channels that may already exist */ + do_smd_probe(); + + /* indicate that we're up and running */ + smsm_change_state(SMSM_STATE_APPS, + ~0, SMSM_INIT | SMSM_SMDINIT | SMSM_RPCINIT | SMSM_RUN); +#ifdef CONFIG_ARCH_MSM_SCORPION + smsm_change_state(SMSM_STATE_APPS_DEM, ~0, 0); +#endif + + return 0; +} + +static int __devinit msm_smd_probe(struct platform_device *pdev) +{ + /* + * If we haven't waited for the ARM9 to boot up till now, + * then we need to wait here. Otherwise this should just + * return immediately. + */ + proc_comm_boot_wait(); + + INIT_WORK(&probe_work, smd_channel_probe_worker); + + if (smd_core_init()) { + pr_err("smd_core_init() failed\n"); + return -1; + } + + do_smd_probe(); + + msm_check_for_modem_crash = check_for_modem_crash; + + msm_init_last_radio_log(THIS_MODULE); + + smd_initialized = 1; + + return 0; +} + +static struct platform_driver msm_smd_driver = { + .probe = msm_smd_probe, + .driver = { + .name = MODULE_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init msm_smd_init(void) +{ + return platform_driver_register(&msm_smd_driver); +} + +module_init(msm_smd_init); + +MODULE_DESCRIPTION("MSM Shared Memory Core"); +MODULE_AUTHOR("Brian Swetland <swetland@google.com>"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c new file mode 100644 index 00000000..c56df9e9 --- /dev/null +++ b/arch/arm/mach-msm/smd_debug.c @@ -0,0 +1,312 @@ +/* arch/arm/mach-msm/smd_debug.c + * + * Copyright (C) 2007 Google, Inc. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/debugfs.h> +#include <linux/list.h> + +#include <mach/msm_iomap.h> + +#include "smd_private.h" + +#if defined(CONFIG_DEBUG_FS) + +static char *chstate(unsigned n) +{ + switch (n) { + case SMD_SS_CLOSED: + return "CLOSED"; + case SMD_SS_OPENING: + return "OPENING"; + case SMD_SS_OPENED: + return "OPENED"; + case SMD_SS_FLUSHING: + return "FLUSHING"; + case SMD_SS_CLOSING: + return "CLOSING"; + case SMD_SS_RESET: + return "RESET"; + case SMD_SS_RESET_OPENING: + return "ROPENING"; + default: + return "UNKNOWN"; + } +} + + +static int dump_ch(char *buf, int max, struct smd_channel *ch) +{ + volatile struct smd_half_channel *s = ch->send; + volatile struct smd_half_channel *r = ch->recv; + + return scnprintf( + buf, max, + "ch%02d:" + " %8s(%05d/%05d) %c%c%c%c%c%c%c <->" + " %8s(%05d/%05d) %c%c%c%c%c%c%c '%s'\n", ch->n, + chstate(s->state), s->tail, s->head, + s->fDSR ? 'D' : 'd', + s->fCTS ? 'C' : 'c', + s->fCD ? 'C' : 'c', + s->fRI ? 'I' : 'i', + s->fHEAD ? 'W' : 'w', + s->fTAIL ? 'R' : 'r', + s->fSTATE ? 'S' : 's', + chstate(r->state), r->tail, r->head, + r->fDSR ? 'D' : 'd', + r->fCTS ? 'R' : 'r', + r->fCD ? 'C' : 'c', + r->fRI ? 'I' : 'i', + r->fHEAD ? 'W' : 'w', + r->fTAIL ? 'R' : 'r', + r->fSTATE ? 'S' : 's', + ch->name + ); +} + +static int debug_read_stat(char *buf, int max) +{ + char *msg; + int i = 0; + + msg = smem_find(ID_DIAG_ERR_MSG, SZ_DIAG_ERR_MSG); + + if (raw_smsm_get_state(SMSM_STATE_MODEM) & SMSM_RESET) + i += scnprintf(buf + i, max - i, + "smsm: ARM9 HAS CRASHED\n"); + + i += scnprintf(buf + i, max - i, "smsm: a9: %08x a11: %08x\n", + raw_smsm_get_state(SMSM_STATE_MODEM), + raw_smsm_get_state(SMSM_STATE_APPS)); +#ifdef CONFIG_ARCH_MSM_SCORPION + i += scnprintf(buf + i, max - i, "smsm dem: apps: %08x modem: %08x " + "qdsp6: %08x power: %08x time: %08x\n", + raw_smsm_get_state(SMSM_STATE_APPS_DEM), + raw_smsm_get_state(SMSM_STATE_MODEM_DEM), + raw_smsm_get_state(SMSM_STATE_QDSP6_DEM), + raw_smsm_get_state(SMSM_STATE_POWER_MASTER_DEM), + raw_smsm_get_state(SMSM_STATE_TIME_MASTER_DEM)); +#endif + if (msg) { + msg[SZ_DIAG_ERR_MSG - 1] = 0; + i += scnprintf(buf + i, max - i, "diag: '%s'\n", msg); + } + return i; +} + +static int debug_read_mem(char *buf, int max) +{ + unsigned n; + struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE; + struct smem_heap_entry *toc = shared->heap_toc; + int i = 0; + + i += scnprintf(buf + i, max - i, + "heap: init=%d free=%d remain=%d\n", + shared->heap_info.initialized, + shared->heap_info.free_offset, + shared->heap_info.heap_remaining); + + for (n = 0; n < SMEM_NUM_ITEMS; n++) { + if (toc[n].allocated == 0) + continue; + i += scnprintf(buf + i, max - i, + "%04d: offset %08x size %08x\n", + n, toc[n].offset, toc[n].size); + } + return i; +} + +static int debug_read_ch(char *buf, int max) +{ + struct smd_channel *ch; + unsigned long flags; + int i = 0; + + spin_lock_irqsave(&smd_lock, flags); + list_for_each_entry(ch, &smd_ch_list_dsp, ch_list) + i += dump_ch(buf + i, max - i, ch); + list_for_each_entry(ch, &smd_ch_list_modem, ch_list) + i += dump_ch(buf + i, max - i, ch); + list_for_each_entry(ch, &smd_ch_closed_list, ch_list) + i += dump_ch(buf + i, max - i, ch); + spin_unlock_irqrestore(&smd_lock, flags); + + return i; +} + +static int debug_read_version(char *buf, int max) +{ + struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE; + unsigned version = shared->version[VERSION_MODEM]; + return sprintf(buf, "%d.%d\n", version >> 16, version & 0xffff); +} + +static int debug_read_build_id(char *buf, int max) +{ + unsigned size; + void *data; + + data = smem_item(SMEM_HW_SW_BUILD_ID, &size); + if (!data) + return 0; + + if (size >= max) + size = max; + memcpy(buf, data, size); + + return size; +} + +static int debug_read_alloc_tbl(char *buf, int max) +{ + struct smd_alloc_elm *shared; + int n, i = 0; + + shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64); + + for (n = 0; n < 64; n++) { + if (shared[n].ref_count == 0) + continue; + i += scnprintf(buf + i, max - i, + "%03d: %-20s cid=%02d type=%03d " + "kind=%02d ref_count=%d\n", + n, shared[n].name, shared[n].cid, + shared[n].ctype & 0xff, + (shared[n].ctype >> 8) & 0xf, + shared[n].ref_count); + } + + return i; +} + +#define DEBUG_BUFMAX 4096 +static char debug_buffer[DEBUG_BUFMAX]; + +static ssize_t debug_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int (*fill)(char *buf, int max) = file->private_data; + int bsize = fill(debug_buffer, DEBUG_BUFMAX); + return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize); +} + +static const struct file_operations debug_ops = { + .read = debug_read, + .open = simple_open, + .llseek = default_llseek, +}; + +static void debug_create(const char *name, umode_t mode, + struct dentry *dent, + int (*fill)(char *buf, int max)) +{ + debugfs_create_file(name, mode, dent, fill, &debug_ops); +} + +static int smd_debugfs_init(void) +{ + struct dentry *dent; + + dent = debugfs_create_dir("smd", 0); + if (IS_ERR(dent)) + return 1; + + debug_create("ch", 0444, dent, debug_read_ch); + debug_create("stat", 0444, dent, debug_read_stat); + debug_create("mem", 0444, dent, debug_read_mem); + debug_create("version", 0444, dent, debug_read_version); + debug_create("tbl", 0444, dent, debug_read_alloc_tbl); + debug_create("build", 0444, dent, debug_read_build_id); + + return 0; +} + +late_initcall(smd_debugfs_init); +#endif + + +#define MAX_NUM_SLEEP_CLIENTS 64 +#define MAX_SLEEP_NAME_LEN 8 + +#define NUM_GPIO_INT_REGISTERS 6 +#define GPIO_SMEM_NUM_GROUPS 2 +#define GPIO_SMEM_MAX_PC_INTERRUPTS 8 + +struct tramp_gpio_save { + unsigned int enable; + unsigned int detect; + unsigned int polarity; +}; + +struct tramp_gpio_smem { + uint16_t num_fired[GPIO_SMEM_NUM_GROUPS]; + uint16_t fired[GPIO_SMEM_NUM_GROUPS][GPIO_SMEM_MAX_PC_INTERRUPTS]; + uint32_t enabled[NUM_GPIO_INT_REGISTERS]; + uint32_t detection[NUM_GPIO_INT_REGISTERS]; + uint32_t polarity[NUM_GPIO_INT_REGISTERS]; +}; + + +void smsm_print_sleep_info(void) +{ + unsigned long flags; + uint32_t *ptr; +#ifndef CONFIG_ARCH_MSM_SCORPION + struct tramp_gpio_smem *gpio; + struct smsm_interrupt_info *int_info; +#endif + + + spin_lock_irqsave(&smem_lock, flags); + + ptr = smem_alloc(SMEM_SMSM_SLEEP_DELAY, sizeof(*ptr)); + if (ptr) + pr_info("SMEM_SMSM_SLEEP_DELAY: %x\n", *ptr); + + ptr = smem_alloc(SMEM_SMSM_LIMIT_SLEEP, sizeof(*ptr)); + if (ptr) + pr_info("SMEM_SMSM_LIMIT_SLEEP: %x\n", *ptr); + + ptr = smem_alloc(SMEM_SLEEP_POWER_COLLAPSE_DISABLED, sizeof(*ptr)); + if (ptr) + pr_info("SMEM_SLEEP_POWER_COLLAPSE_DISABLED: %x\n", *ptr); + +#ifndef CONFIG_ARCH_MSM_SCORPION + int_info = smem_alloc(SMEM_SMSM_INT_INFO, sizeof(*int_info)); + if (int_info) + pr_info("SMEM_SMSM_INT_INFO %x %x %x\n", + int_info->interrupt_mask, + int_info->pending_interrupts, + int_info->wakeup_reason); + + gpio = smem_alloc(SMEM_GPIO_INT, sizeof(*gpio)); + if (gpio) { + int i; + for (i = 0; i < NUM_GPIO_INT_REGISTERS; i++) + pr_info("SMEM_GPIO_INT: %d: e %x d %x p %x\n", + i, gpio->enabled[i], gpio->detection[i], + gpio->polarity[i]); + + for (i = 0; i < GPIO_SMEM_NUM_GROUPS; i++) + pr_info("SMEM_GPIO_INT: %d: f %d: %d %d...\n", + i, gpio->num_fired[i], gpio->fired[i][0], + gpio->fired[i][1]); + } +#else +#endif + spin_unlock_irqrestore(&smem_lock, flags); +} + diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h new file mode 100644 index 00000000..727bfe68 --- /dev/null +++ b/arch/arm/mach-msm/smd_private.h @@ -0,0 +1,403 @@ +/* arch/arm/mach-msm/smd_private.h + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2007 QUALCOMM Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef _ARCH_ARM_MACH_MSM_MSM_SMD_PRIVATE_H_ +#define _ARCH_ARM_MACH_MSM_MSM_SMD_PRIVATE_H_ + +#include <linux/platform_device.h> +#include <linux/spinlock.h> +#include <linux/list.h> +#include <linux/io.h> + +#include <mach/msm_iomap.h> + +struct smem_heap_info { + unsigned initialized; + unsigned free_offset; + unsigned heap_remaining; + unsigned reserved; +}; + +struct smem_heap_entry { + unsigned allocated; + unsigned offset; + unsigned size; + unsigned reserved; +}; + +struct smem_proc_comm { + unsigned command; + unsigned status; + unsigned data1; + unsigned data2; +}; + +#define PC_APPS 0 +#define PC_MODEM 1 + +#define VERSION_SMD 0 +#define VERSION_QDSP6 4 +#define VERSION_APPS_SBL 6 +#define VERSION_MODEM_SBL 7 +#define VERSION_APPS 8 +#define VERSION_MODEM 9 + +struct smem_shared { + struct smem_proc_comm proc_comm[4]; + unsigned version[32]; + struct smem_heap_info heap_info; + struct smem_heap_entry heap_toc[512]; +}; + +#define SMSM_V1_SIZE (sizeof(unsigned) * 8) +#define SMSM_V2_SIZE (sizeof(unsigned) * 4) + +#ifdef CONFIG_MSM_SMD_PKG3 +struct smsm_interrupt_info { + uint32_t interrupt_mask; + uint32_t pending_interrupts; + uint32_t wakeup_reason; +}; +#else +#define DEM_MAX_PORT_NAME_LEN (20) +struct msm_dem_slave_data { + uint32_t sleep_time; + uint32_t interrupt_mask; + uint32_t resources_used; + uint32_t reserved1; + + uint32_t wakeup_reason; + uint32_t pending_interrupts; + uint32_t rpc_prog; + uint32_t rpc_proc; + char smd_port_name[DEM_MAX_PORT_NAME_LEN]; + uint32_t reserved2; +}; +#endif + +#define SZ_DIAG_ERR_MSG 0xC8 +#define ID_DIAG_ERR_MSG SMEM_DIAG_ERR_MESSAGE +#define ID_SMD_CHANNELS SMEM_SMD_BASE_ID +#define ID_SHARED_STATE SMEM_SMSM_SHARED_STATE +#define ID_CH_ALLOC_TBL SMEM_CHANNEL_ALLOC_TBL + +#define SMSM_INIT 0x00000001 +#define SMSM_SMDINIT 0x00000008 +#define SMSM_RPCINIT 0x00000020 +#define SMSM_RESET 0x00000040 +#define SMSM_RSA 0x00000080 +#define SMSM_RUN 0x00000100 +#define SMSM_PWRC 0x00000200 +#define SMSM_TIMEWAIT 0x00000400 +#define SMSM_TIMEINIT 0x00000800 +#define SMSM_PWRC_EARLY_EXIT 0x00001000 +#define SMSM_WFPI 0x00002000 +#define SMSM_SLEEP 0x00004000 +#define SMSM_SLEEPEXIT 0x00008000 +#define SMSM_APPS_REBOOT 0x00020000 +#define SMSM_SYSTEM_POWER_DOWN 0x00040000 +#define SMSM_SYSTEM_REBOOT 0x00080000 +#define SMSM_SYSTEM_DOWNLOAD 0x00100000 +#define SMSM_PWRC_SUSPEND 0x00200000 +#define SMSM_APPS_SHUTDOWN 0x00400000 +#define SMSM_SMD_LOOPBACK 0x00800000 +#define SMSM_RUN_QUIET 0x01000000 +#define SMSM_MODEM_WAIT 0x02000000 +#define SMSM_MODEM_BREAK 0x04000000 +#define SMSM_MODEM_CONTINUE 0x08000000 +#define SMSM_UNKNOWN 0x80000000 + +#define SMSM_WKUP_REASON_RPC 0x00000001 +#define SMSM_WKUP_REASON_INT 0x00000002 +#define SMSM_WKUP_REASON_GPIO 0x00000004 +#define SMSM_WKUP_REASON_TIMER 0x00000008 +#define SMSM_WKUP_REASON_ALARM 0x00000010 +#define SMSM_WKUP_REASON_RESET 0x00000020 + +#ifdef CONFIG_ARCH_MSM7X00A +enum smsm_state_item { + SMSM_STATE_APPS = 1, + SMSM_STATE_MODEM = 3, + SMSM_STATE_COUNT, +}; +#else +enum smsm_state_item { + SMSM_STATE_APPS, + SMSM_STATE_MODEM, + SMSM_STATE_HEXAGON, + SMSM_STATE_APPS_DEM, + SMSM_STATE_MODEM_DEM, + SMSM_STATE_QDSP6_DEM, + SMSM_STATE_POWER_MASTER_DEM, + SMSM_STATE_TIME_MASTER_DEM, + SMSM_STATE_COUNT, +}; +#endif + +void *smem_alloc(unsigned id, unsigned size); +int smsm_change_state(enum smsm_state_item item, uint32_t clear_mask, uint32_t set_mask); +uint32_t smsm_get_state(enum smsm_state_item item); +int smsm_set_sleep_duration(uint32_t delay); +void smsm_print_sleep_info(void); + +#define SMEM_NUM_SMD_CHANNELS 64 + +typedef enum { + /* fixed items */ + SMEM_PROC_COMM = 0, + SMEM_HEAP_INFO, + SMEM_ALLOCATION_TABLE, + SMEM_VERSION_INFO, + SMEM_HW_RESET_DETECT, + SMEM_AARM_WARM_BOOT, + SMEM_DIAG_ERR_MESSAGE, + SMEM_SPINLOCK_ARRAY, + SMEM_MEMORY_BARRIER_LOCATION, + + /* dynamic items */ + SMEM_AARM_PARTITION_TABLE, + SMEM_AARM_BAD_BLOCK_TABLE, + SMEM_RESERVE_BAD_BLOCKS, + SMEM_WM_UUID, + SMEM_CHANNEL_ALLOC_TBL, + SMEM_SMD_BASE_ID, + SMEM_SMEM_LOG_IDX = SMEM_SMD_BASE_ID + SMEM_NUM_SMD_CHANNELS, + SMEM_SMEM_LOG_EVENTS, + SMEM_SMEM_STATIC_LOG_IDX, + SMEM_SMEM_STATIC_LOG_EVENTS, + SMEM_SMEM_SLOW_CLOCK_SYNC, + SMEM_SMEM_SLOW_CLOCK_VALUE, + SMEM_BIO_LED_BUF, + SMEM_SMSM_SHARED_STATE, + SMEM_SMSM_INT_INFO, + SMEM_SMSM_SLEEP_DELAY, + SMEM_SMSM_LIMIT_SLEEP, + SMEM_SLEEP_POWER_COLLAPSE_DISABLED, + SMEM_KEYPAD_KEYS_PRESSED, + SMEM_KEYPAD_STATE_UPDATED, + SMEM_KEYPAD_STATE_IDX, + SMEM_GPIO_INT, + SMEM_MDDI_LCD_IDX, + SMEM_MDDI_HOST_DRIVER_STATE, + SMEM_MDDI_LCD_DISP_STATE, + SMEM_LCD_CUR_PANEL, + SMEM_MARM_BOOT_SEGMENT_INFO, + SMEM_AARM_BOOT_SEGMENT_INFO, + SMEM_SLEEP_STATIC, + SMEM_SCORPION_FREQUENCY, + SMEM_SMD_PROFILES, + SMEM_TSSC_BUSY, + SMEM_HS_SUSPEND_FILTER_INFO, + SMEM_BATT_INFO, + SMEM_APPS_BOOT_MODE, + SMEM_VERSION_FIRST, + SMEM_VERSION_LAST = SMEM_VERSION_FIRST + 24, + SMEM_OSS_RRCASN1_BUF1, + SMEM_OSS_RRCASN1_BUF2, + SMEM_ID_VENDOR0, + SMEM_ID_VENDOR1, + SMEM_ID_VENDOR2, + SMEM_HW_SW_BUILD_ID, + SMEM_SMD_BLOCK_PORT_BASE_ID, + SMEM_SMD_BLOCK_PORT_PROC0_HEAP = SMEM_SMD_BLOCK_PORT_BASE_ID + SMEM_NUM_SMD_CHANNELS, + SMEM_SMD_BLOCK_PORT_PROC1_HEAP = SMEM_SMD_BLOCK_PORT_PROC0_HEAP + SMEM_NUM_SMD_CHANNELS, + SMEM_I2C_MUTEX = SMEM_SMD_BLOCK_PORT_PROC1_HEAP + SMEM_NUM_SMD_CHANNELS, + SMEM_SCLK_CONVERSION, + SMEM_SMD_SMSM_INTR_MUX, + SMEM_SMSM_CPU_INTR_MASK, + SMEM_APPS_DEM_SLAVE_DATA, + SMEM_QDSP6_DEM_SLAVE_DATA, + SMEM_CLKREGIM_BSP, + SMEM_CLKREGIM_SOURCES, + SMEM_SMD_FIFO_BASE_ID, + SMEM_USABLE_RAM_PARTITION_TABLE = SMEM_SMD_FIFO_BASE_ID + SMEM_NUM_SMD_CHANNELS, + SMEM_POWER_ON_STATUS_INFO, + SMEM_DAL_AREA, + SMEM_SMEM_LOG_POWER_IDX, + SMEM_SMEM_LOG_POWER_WRAP, + SMEM_SMEM_LOG_POWER_EVENTS, + SMEM_ERR_CRASH_LOG, + SMEM_ERR_F3_TRACE_LOG, + SMEM_NUM_ITEMS, +} smem_mem_type; + + +#define SMD_SS_CLOSED 0x00000000 +#define SMD_SS_OPENING 0x00000001 +#define SMD_SS_OPENED 0x00000002 +#define SMD_SS_FLUSHING 0x00000003 +#define SMD_SS_CLOSING 0x00000004 +#define SMD_SS_RESET 0x00000005 +#define SMD_SS_RESET_OPENING 0x00000006 + +#define SMD_BUF_SIZE 8192 +#define SMD_CHANNELS 64 + +#define SMD_HEADER_SIZE 20 + +struct smd_alloc_elm { + char name[20]; + uint32_t cid; + uint32_t ctype; + uint32_t ref_count; +}; + +struct smd_half_channel { + unsigned state; + unsigned char fDSR; + unsigned char fCTS; + unsigned char fCD; + unsigned char fRI; + unsigned char fHEAD; + unsigned char fTAIL; + unsigned char fSTATE; + unsigned char fUNUSED; + unsigned tail; + unsigned head; +} __attribute__(( aligned(4), packed )); + +/* Only used on SMD package v3 on msm7201a */ +struct smd_shared_v1 { + struct smd_half_channel ch0; + unsigned char data0[SMD_BUF_SIZE]; + struct smd_half_channel ch1; + unsigned char data1[SMD_BUF_SIZE]; +}; + +/* Used on SMD package v4 */ +struct smd_shared_v2 { + struct smd_half_channel ch0; + struct smd_half_channel ch1; +}; + +struct smd_channel { + volatile struct smd_half_channel *send; + volatile struct smd_half_channel *recv; + unsigned char *send_data; + unsigned char *recv_data; + + unsigned fifo_mask; + unsigned fifo_size; + unsigned current_packet; + unsigned n; + + struct list_head ch_list; + + void *priv; + void (*notify)(void *priv, unsigned flags); + + int (*read)(struct smd_channel *ch, void *data, int len); + int (*write)(struct smd_channel *ch, const void *data, int len); + int (*read_avail)(struct smd_channel *ch); + int (*write_avail)(struct smd_channel *ch); + + void (*update_state)(struct smd_channel *ch); + unsigned last_state; + void (*notify_other_cpu)(void); + unsigned type; + + char name[32]; + struct platform_device pdev; +}; + +#define SMD_TYPE_MASK 0x0FF +#define SMD_TYPE_APPS_MODEM 0x000 +#define SMD_TYPE_APPS_DSP 0x001 +#define SMD_TYPE_MODEM_DSP 0x002 + +#define SMD_KIND_MASK 0xF00 +#define SMD_KIND_UNKNOWN 0x000 +#define SMD_KIND_STREAM 0x100 +#define SMD_KIND_PACKET 0x200 + +extern struct list_head smd_ch_closed_list; +extern struct list_head smd_ch_list_modem; +extern struct list_head smd_ch_list_dsp; + +extern spinlock_t smd_lock; +extern spinlock_t smem_lock; + +void *smem_find(unsigned id, unsigned size); +void *smem_item(unsigned id, unsigned *size); +uint32_t raw_smsm_get_state(enum smsm_state_item item); + +extern void msm_init_last_radio_log(struct module *); + +#ifdef CONFIG_MSM_SMD_PKG3 +/* + * This allocator assumes an SMD Package v3 which only exists on + * MSM7x00 SoC's. + */ +static inline int _smd_alloc_channel(struct smd_channel *ch) +{ + struct smd_shared_v1 *shared1; + + shared1 = smem_alloc(ID_SMD_CHANNELS + ch->n, sizeof(*shared1)); + if (!shared1) { + pr_err("smd_alloc_channel() cid %d does not exist\n", ch->n); + return -1; + } + ch->send = &shared1->ch0; + ch->recv = &shared1->ch1; + ch->send_data = shared1->data0; + ch->recv_data = shared1->data1; + ch->fifo_size = SMD_BUF_SIZE; + return 0; +} +#else +/* + * This allocator assumes an SMD Package v4, the most common + * and the default. + */ +static inline int _smd_alloc_channel(struct smd_channel *ch) +{ + struct smd_shared_v2 *shared2; + void *buffer; + unsigned buffer_sz; + + shared2 = smem_alloc(SMEM_SMD_BASE_ID + ch->n, sizeof(*shared2)); + buffer = smem_item(SMEM_SMD_FIFO_BASE_ID + ch->n, &buffer_sz); + + if (!buffer) + return -1; + + /* buffer must be a power-of-two size */ + if (buffer_sz & (buffer_sz - 1)) + return -1; + + buffer_sz /= 2; + ch->send = &shared2->ch0; + ch->recv = &shared2->ch1; + ch->send_data = buffer; + ch->recv_data = buffer + buffer_sz; + ch->fifo_size = buffer_sz; + return 0; +} +#endif /* CONFIG_MSM_SMD_PKG3 */ + +#if defined(CONFIG_ARCH_MSM7X30) +static inline void msm_a2m_int(uint32_t irq) +{ + writel(1 << irq, MSM_GCC_BASE + 0x8); +} +#else +static inline void msm_a2m_int(uint32_t irq) +{ + writel(1, MSM_CSR_BASE + 0x400 + (irq * 4)); +} +#endif /* CONFIG_ARCH_MSM7X30 */ + + +#endif diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c new file mode 100644 index 00000000..81280825 --- /dev/null +++ b/arch/arm/mach-msm/timer.c @@ -0,0 +1,247 @@ +/* + * + * Copyright (C) 2007 Google, Inc. + * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/io.h> + +#include <asm/mach/time.h> +#include <asm/hardware/gic.h> +#include <asm/localtimer.h> +#include <asm/sched_clock.h> + +#include <mach/msm_iomap.h> +#include <mach/cpu.h> +#include <mach/board.h> + +#define TIMER_MATCH_VAL 0x0000 +#define TIMER_COUNT_VAL 0x0004 +#define TIMER_ENABLE 0x0008 +#define TIMER_ENABLE_CLR_ON_MATCH_EN BIT(1) +#define TIMER_ENABLE_EN BIT(0) +#define TIMER_CLEAR 0x000C +#define DGT_CLK_CTL 0x0034 +#define DGT_CLK_CTL_DIV_4 0x3 + +#define GPT_HZ 32768 + +#define MSM_DGT_SHIFT 5 + +static void __iomem *event_base; + +static irqreturn_t msm_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = *(struct clock_event_device **)dev_id; + /* Stop the timer tick */ + if (evt->mode == CLOCK_EVT_MODE_ONESHOT) { + u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); + ctrl &= ~TIMER_ENABLE_EN; + writel_relaxed(ctrl, event_base + TIMER_ENABLE); + } + evt->event_handler(evt); + return IRQ_HANDLED; +} + +static int msm_timer_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE); + + writel_relaxed(0, event_base + TIMER_CLEAR); + writel_relaxed(cycles, event_base + TIMER_MATCH_VAL); + writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE); + return 0; +} + +static void msm_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + u32 ctrl; + + ctrl = readl_relaxed(event_base + TIMER_ENABLE); + ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN); + + switch (mode) { + case CLOCK_EVT_MODE_RESUME: + case CLOCK_EVT_MODE_PERIODIC: + break; + case CLOCK_EVT_MODE_ONESHOT: + /* Timer is enabled in set_next_event */ + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + break; + } + writel_relaxed(ctrl, event_base + TIMER_ENABLE); +} + +static struct clock_event_device msm_clockevent = { + .name = "gp_timer", + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 200, + .set_next_event = msm_timer_set_next_event, + .set_mode = msm_timer_set_mode, +}; + +static union { + struct clock_event_device *evt; + struct clock_event_device __percpu **percpu_evt; +} msm_evt; + +static void __iomem *source_base; + +static notrace cycle_t msm_read_timer_count(struct clocksource *cs) +{ + return readl_relaxed(source_base + TIMER_COUNT_VAL); +} + +static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs) +{ + /* + * Shift timer count down by a constant due to unreliable lower bits + * on some targets. + */ + return msm_read_timer_count(cs) >> MSM_DGT_SHIFT; +} + +static struct clocksource msm_clocksource = { + .name = "dg_timer", + .rating = 300, + .read = msm_read_timer_count, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +#ifdef CONFIG_LOCAL_TIMERS +static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt) +{ + /* Use existing clock_event for cpu 0 */ + if (!smp_processor_id()) + return 0; + + writel_relaxed(0, event_base + TIMER_ENABLE); + writel_relaxed(0, event_base + TIMER_CLEAR); + writel_relaxed(~0, event_base + TIMER_MATCH_VAL); + evt->irq = msm_clockevent.irq; + evt->name = "local_timer"; + evt->features = msm_clockevent.features; + evt->rating = msm_clockevent.rating; + evt->set_mode = msm_timer_set_mode; + evt->set_next_event = msm_timer_set_next_event; + evt->shift = msm_clockevent.shift; + evt->mult = div_sc(GPT_HZ, NSEC_PER_SEC, evt->shift); + evt->max_delta_ns = clockevent_delta2ns(0xf0000000, evt); + evt->min_delta_ns = clockevent_delta2ns(4, evt); + + *__this_cpu_ptr(msm_evt.percpu_evt) = evt; + clockevents_register_device(evt); + enable_percpu_irq(evt->irq, 0); + return 0; +} + +static void msm_local_timer_stop(struct clock_event_device *evt) +{ + evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); + disable_percpu_irq(evt->irq); +} + +static struct local_timer_ops msm_local_timer_ops __cpuinitdata = { + .setup = msm_local_timer_setup, + .stop = msm_local_timer_stop, +}; +#endif /* CONFIG_LOCAL_TIMERS */ + +static notrace u32 msm_sched_clock_read(void) +{ + return msm_clocksource.read(&msm_clocksource); +} + +static void __init msm_timer_init(void) +{ + struct clock_event_device *ce = &msm_clockevent; + struct clocksource *cs = &msm_clocksource; + int res; + u32 dgt_hz; + + if (cpu_is_msm7x01()) { + event_base = MSM_CSR_BASE; + source_base = MSM_CSR_BASE + 0x10; + dgt_hz = 19200000 >> MSM_DGT_SHIFT; /* 600 KHz */ + cs->read = msm_read_timer_count_shift; + cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)); + } else if (cpu_is_msm7x30()) { + event_base = MSM_CSR_BASE + 0x04; + source_base = MSM_CSR_BASE + 0x24; + dgt_hz = 24576000 / 4; + } else if (cpu_is_qsd8x50()) { + event_base = MSM_CSR_BASE; + source_base = MSM_CSR_BASE + 0x10; + dgt_hz = 19200000 / 4; + } else if (cpu_is_msm8x60() || cpu_is_msm8960()) { + event_base = MSM_TMR_BASE + 0x04; + /* Use CPU0's timer as the global clock source. */ + source_base = MSM_TMR0_BASE + 0x24; + dgt_hz = 27000000 / 4; + writel_relaxed(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL); + } else + BUG(); + + writel_relaxed(0, event_base + TIMER_ENABLE); + writel_relaxed(0, event_base + TIMER_CLEAR); + writel_relaxed(~0, event_base + TIMER_MATCH_VAL); + ce->cpumask = cpumask_of(0); + + ce->irq = INT_GP_TIMER_EXP; + clockevents_config_and_register(ce, GPT_HZ, 4, 0xffffffff); + if (cpu_is_msm8x60() || cpu_is_msm8960()) { + msm_evt.percpu_evt = alloc_percpu(struct clock_event_device *); + if (!msm_evt.percpu_evt) { + pr_err("memory allocation failed for %s\n", ce->name); + goto err; + } + *__this_cpu_ptr(msm_evt.percpu_evt) = ce; + res = request_percpu_irq(ce->irq, msm_timer_interrupt, + ce->name, msm_evt.percpu_evt); + if (!res) { + enable_percpu_irq(ce->irq, 0); +#ifdef CONFIG_LOCAL_TIMERS + local_timer_register(&msm_local_timer_ops); +#endif + } + } else { + msm_evt.evt = ce; + res = request_irq(ce->irq, msm_timer_interrupt, + IRQF_TIMER | IRQF_NOBALANCING | + IRQF_TRIGGER_RISING, ce->name, &msm_evt.evt); + } + + if (res) + pr_err("request_irq failed for %s\n", ce->name); +err: + writel_relaxed(TIMER_ENABLE_EN, source_base + TIMER_ENABLE); + res = clocksource_register_hz(cs, dgt_hz); + if (res) + pr_err("clocksource_register failed\n"); + setup_sched_clock(msm_sched_clock_read, + cpu_is_msm7x01() ? 32 - MSM_DGT_SHIFT : 32, dgt_hz); +} + +struct sys_timer msm_timer = { + .init = msm_timer_init +}; diff --git a/arch/arm/mach-msm/vreg.c b/arch/arm/mach-msm/vreg.c new file mode 100644 index 00000000..bd66ed04 --- /dev/null +++ b/arch/arm/mach-msm/vreg.c @@ -0,0 +1,220 @@ +/* arch/arm/mach-msm/vreg.c + * + * Copyright (C) 2008 Google, Inc. + * Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * Author: Brian Swetland <swetland@google.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/init.h> +#include <linux/debugfs.h> +#include <linux/module.h> +#include <linux/string.h> +#include <mach/vreg.h> + +#include "proc_comm.h" + +struct vreg { + const char *name; + unsigned id; + int status; + unsigned refcnt; +}; + +#define VREG(_name, _id, _status, _refcnt) \ + { .name = _name, .id = _id, .status = _status, .refcnt = _refcnt } + +static struct vreg vregs[] = { + VREG("msma", 0, 0, 0), + VREG("msmp", 1, 0, 0), + VREG("msme1", 2, 0, 0), + VREG("msmc1", 3, 0, 0), + VREG("msmc2", 4, 0, 0), + VREG("gp3", 5, 0, 0), + VREG("msme2", 6, 0, 0), + VREG("gp4", 7, 0, 0), + VREG("gp1", 8, 0, 0), + VREG("tcxo", 9, 0, 0), + VREG("pa", 10, 0, 0), + VREG("rftx", 11, 0, 0), + VREG("rfrx1", 12, 0, 0), + VREG("rfrx2", 13, 0, 0), + VREG("synt", 14, 0, 0), + VREG("wlan", 15, 0, 0), + VREG("usb", 16, 0, 0), + VREG("boost", 17, 0, 0), + VREG("mmc", 18, 0, 0), + VREG("ruim", 19, 0, 0), + VREG("msmc0", 20, 0, 0), + VREG("gp2", 21, 0, 0), + VREG("gp5", 22, 0, 0), + VREG("gp6", 23, 0, 0), + VREG("rf", 24, 0, 0), + VREG("rf_vco", 26, 0, 0), + VREG("mpll", 27, 0, 0), + VREG("s2", 28, 0, 0), + VREG("s3", 29, 0, 0), + VREG("rfubm", 30, 0, 0), + VREG("ncp", 31, 0, 0), + VREG("gp7", 32, 0, 0), + VREG("gp8", 33, 0, 0), + VREG("gp9", 34, 0, 0), + VREG("gp10", 35, 0, 0), + VREG("gp11", 36, 0, 0), + VREG("gp12", 37, 0, 0), + VREG("gp13", 38, 0, 0), + VREG("gp14", 39, 0, 0), + VREG("gp15", 40, 0, 0), + VREG("gp16", 41, 0, 0), + VREG("gp17", 42, 0, 0), + VREG("s4", 43, 0, 0), + VREG("usb2", 44, 0, 0), + VREG("wlan2", 45, 0, 0), + VREG("xo_out", 46, 0, 0), + VREG("lvsw0", 47, 0, 0), + VREG("lvsw1", 48, 0, 0), +}; + +struct vreg *vreg_get(struct device *dev, const char *id) +{ + int n; + for (n = 0; n < ARRAY_SIZE(vregs); n++) { + if (!strcmp(vregs[n].name, id)) + return vregs + n; + } + return ERR_PTR(-ENOENT); +} + +void vreg_put(struct vreg *vreg) +{ +} + +int vreg_enable(struct vreg *vreg) +{ + unsigned id = vreg->id; + unsigned enable = 1; + + if (vreg->refcnt == 0) + vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable); + + if ((vreg->refcnt < UINT_MAX) && (!vreg->status)) + vreg->refcnt++; + + return vreg->status; +} + +int vreg_disable(struct vreg *vreg) +{ + unsigned id = vreg->id; + unsigned enable = 0; + + if (!vreg->refcnt) + return 0; + + if (vreg->refcnt == 1) + vreg->status = msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable); + + if (!vreg->status) + vreg->refcnt--; + + return vreg->status; +} + +int vreg_set_level(struct vreg *vreg, unsigned mv) +{ + unsigned id = vreg->id; + + vreg->status = msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv); + return vreg->status; +} + +#if defined(CONFIG_DEBUG_FS) + +static int vreg_debug_set(void *data, u64 val) +{ + struct vreg *vreg = data; + switch (val) { + case 0: + vreg_disable(vreg); + break; + case 1: + vreg_enable(vreg); + break; + default: + vreg_set_level(vreg, val); + break; + } + return 0; +} + +static int vreg_debug_get(void *data, u64 *val) +{ + struct vreg *vreg = data; + + if (!vreg->status) + *val = 0; + else + *val = 1; + + return 0; +} + +static int vreg_debug_count_set(void *data, u64 val) +{ + struct vreg *vreg = data; + if (val > UINT_MAX) + val = UINT_MAX; + vreg->refcnt = val; + return 0; +} + +static int vreg_debug_count_get(void *data, u64 *val) +{ + struct vreg *vreg = data; + + *val = vreg->refcnt; + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n"); +DEFINE_SIMPLE_ATTRIBUTE(vreg_count_fops, vreg_debug_count_get, + vreg_debug_count_set, "%llu\n"); + +static int __init vreg_debug_init(void) +{ + struct dentry *dent; + int n; + char name[32]; + const char *refcnt_name = "_refcnt"; + + dent = debugfs_create_dir("vreg", 0); + if (IS_ERR(dent)) + return 0; + + for (n = 0; n < ARRAY_SIZE(vregs); n++) { + (void) debugfs_create_file(vregs[n].name, 0644, + dent, vregs + n, &vreg_fops); + + strlcpy(name, vregs[n].name, sizeof(name)); + strlcat(name, refcnt_name, sizeof(name)); + (void) debugfs_create_file(name, 0644, + dent, vregs + n, &vreg_count_fops); + } + + return 0; +} + +device_initcall(vreg_debug_init); +#endif |