summaryrefslogtreecommitdiff
path: root/arch/arm/mach-msm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-msm')
-rw-r--r--arch/arm/mach-msm/Kconfig17
-rw-r--r--arch/arm/mach-msm/Makefile7
-rw-r--r--arch/arm/mach-msm/board-halibut.c38
-rw-r--r--arch/arm/mach-msm/clock-7x01a.c126
-rw-r--r--arch/arm/mach-msm/clock.c218
-rw-r--r--arch/arm/mach-msm/clock.h48
-rw-r--r--arch/arm/mach-msm/common.c116
-rw-r--r--arch/arm/mach-msm/devices.c267
-rw-r--r--arch/arm/mach-msm/devices.h36
-rw-r--r--arch/arm/mach-msm/dma.c72
-rw-r--r--arch/arm/mach-msm/include/mach/board.h1
-rw-r--r--arch/arm/mach-msm/include/mach/debug-macro.S8
-rw-r--r--arch/arm/mach-msm/include/mach/dma.h24
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap.h69
-rw-r--r--arch/arm/mach-msm/include/mach/vreg.h29
-rw-r--r--arch/arm/mach-msm/io.c12
-rw-r--r--arch/arm/mach-msm/irq.c10
-rw-r--r--arch/arm/mach-msm/proc_comm.c110
-rw-r--r--arch/arm/mach-msm/proc_comm.h165
-rw-r--r--arch/arm/mach-msm/timer.c2
-rw-r--r--arch/arm/mach-msm/vreg.c143
21 files changed, 1289 insertions, 229 deletions
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 3553babbbf05..d140abca690a 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1,18 +1,13 @@
-if ARCH_MSM7X00A
+if ARCH_MSM
-comment "MSM7X00A Board Type"
- depends on ARCH_MSM7X00A
+comment "MSM Board Type"
+ depends on ARCH_MSM
config MACH_HALIBUT
- depends on ARCH_MSM7X00A
+ depends on ARCH_MSM
default y
- bool "Halibut Board (QCT SURF7200A)"
+ bool "Halibut Board (QCT SURF7201A)"
help
- Support for the Qualcomm SURF7200A eval board.
-
-config MSM7X00A_IDLE
- depends on ARCH_MSM7X00A
- default y
- bool "Idle Support for MSM7X00A"
+ Support for the Qualcomm SURF7201A eval board.
endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d12f23655850..1aa47001aa3b 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,7 +1,8 @@
obj-y += io.o idle.o irq.o timer.o dma.o
-
-# Common code for board init
-obj-y += common.o
+obj-y += devices.o
+obj-y += proc_comm.o
+obj-y += vreg.o
+obj-y += clock.o clock-7x01a.o
obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index a24259133e07..c2a96e3965a6 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -33,6 +33,8 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
+#include "devices.h"
+
static struct resource smc91x_resources[] = {
[0] = {
.start = 0x9C004300,
@@ -53,31 +55,12 @@ static struct platform_device smc91x_device = {
.resource = smc91x_resources,
};
-static void mddi0_panel_power(int on)
-{
-}
-
-static struct msm_mddi_platform_data msm_mddi0_pdata = {
- .panel_power = mddi0_panel_power,
- .has_vsync_irq = 0,
-};
-
-static struct platform_device msm_mddi0_device = {
- .name = "msm_mddi",
- .id = 0,
- .dev = {
- .platform_data = &msm_mddi0_pdata
- },
-};
-
-static struct platform_device msm_serial0_device = {
- .name = "msm_serial",
- .id = 0,
-};
-
static struct platform_device *devices[] __initdata = {
- &msm_serial0_device,
- &msm_mddi0_device,
+ &msm_device_uart3,
+ &msm_device_smd,
+ &msm_device_nand,
+ &msm_device_hsusb,
+ &msm_device_i2c,
&smc91x_device,
};
@@ -91,20 +74,15 @@ static void __init halibut_init_irq(void)
static void __init halibut_init(void)
{
platform_add_devices(devices, ARRAY_SIZE(devices));
- msm_add_devices();
}
static void __init halibut_map_io(void)
{
msm_map_common_io();
+ msm_clock_init();
}
MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
-
-/* UART for LL DEBUG */
- .phys_io = MSM_UART1_PHYS,
- .io_pg_offst = ((MSM_UART1_BASE) >> 18) & 0xfffc,
-
.boot_params = 0x10000100,
.map_io = halibut_map_io,
.init_irq = halibut_init_irq,
diff --git a/arch/arm/mach-msm/clock-7x01a.c b/arch/arm/mach-msm/clock-7x01a.c
new file mode 100644
index 000000000000..62230a3428ee
--- /dev/null
+++ b/arch/arm/mach-msm/clock-7x01a.c
@@ -0,0 +1,126 @@
+/* arch/arm/mach-msm/clock-7x01a.c
+ *
+ * Clock tables for MSM7X01A
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include "clock.h"
+#include "devices.h"
+
+/* clock IDs used by the modem processor */
+
+#define ACPU_CLK 0 /* Applications processor clock */
+#define ADM_CLK 1 /* Applications data mover clock */
+#define ADSP_CLK 2 /* ADSP clock */
+#define EBI1_CLK 3 /* External bus interface 1 clock */
+#define EBI2_CLK 4 /* External bus interface 2 clock */
+#define ECODEC_CLK 5 /* External CODEC clock */
+#define EMDH_CLK 6 /* External MDDI host clock */
+#define GP_CLK 7 /* General purpose clock */
+#define GRP_CLK 8 /* Graphics clock */
+#define I2C_CLK 9 /* I2C clock */
+#define ICODEC_RX_CLK 10 /* Internal CODEX RX clock */
+#define ICODEC_TX_CLK 11 /* Internal CODEX TX clock */
+#define IMEM_CLK 12 /* Internal graphics memory clock */
+#define MDC_CLK 13 /* MDDI client clock */
+#define MDP_CLK 14 /* Mobile display processor clock */
+#define PBUS_CLK 15 /* Peripheral bus clock */
+#define PCM_CLK 16 /* PCM clock */
+#define PMDH_CLK 17 /* Primary MDDI host clock */
+#define SDAC_CLK 18 /* Stereo DAC clock */
+#define SDC1_CLK 19 /* Secure Digital Card clocks */
+#define SDC1_PCLK 20
+#define SDC2_CLK 21
+#define SDC2_PCLK 22
+#define SDC3_CLK 23
+#define SDC3_PCLK 24
+#define SDC4_CLK 25
+#define SDC4_PCLK 26
+#define TSIF_CLK 27 /* Transport Stream Interface clocks */
+#define TSIF_REF_CLK 28
+#define TV_DAC_CLK 29 /* TV clocks */
+#define TV_ENC_CLK 30
+#define UART1_CLK 31 /* UART clocks */
+#define UART2_CLK 32
+#define UART3_CLK 33
+#define UART1DM_CLK 34
+#define UART2DM_CLK 35
+#define USB_HS_CLK 36 /* High speed USB core clock */
+#define USB_HS_PCLK 37 /* High speed USB pbus clock */
+#define USB_OTG_CLK 38 /* Full speed USB clock */
+#define VDC_CLK 39 /* Video controller clock */
+#define VFE_CLK 40 /* Camera / Video Front End clock */
+#define VFE_MDC_CLK 41 /* VFE MDDI client clock */
+
+#define NR_CLKS 42
+
+#define CLOCK(clk_name, clk_id, clk_dev, clk_flags) { \
+ .name = clk_name, \
+ .id = clk_id, \
+ .flags = clk_flags, \
+ .dev = clk_dev, \
+ }
+
+#define OFF CLKFLAG_AUTO_OFF
+#define MINMAX CLKFLAG_USE_MIN_MAX_TO_SET
+
+struct clk msm_clocks[] = {
+ CLOCK("adm_clk", ADM_CLK, NULL, 0),
+ CLOCK("adsp_clk", ADSP_CLK, NULL, 0),
+ CLOCK("ebi1_clk", EBI1_CLK, NULL, 0),
+ CLOCK("ebi2_clk", EBI2_CLK, NULL, 0),
+ CLOCK("ecodec_clk", ECODEC_CLK, NULL, 0),
+ CLOCK("emdh_clk", EMDH_CLK, NULL, OFF),
+ CLOCK("gp_clk", GP_CLK, NULL, 0),
+ CLOCK("grp_clk", GRP_CLK, NULL, OFF),
+ CLOCK("i2c_clk", I2C_CLK, &msm_device_i2c.dev, 0),
+ CLOCK("icodec_rx_clk", ICODEC_RX_CLK, NULL, 0),
+ CLOCK("icodec_tx_clk", ICODEC_TX_CLK, NULL, 0),
+ CLOCK("imem_clk", IMEM_CLK, NULL, OFF),
+ CLOCK("mdc_clk", MDC_CLK, NULL, 0),
+ CLOCK("mdp_clk", MDP_CLK, NULL, OFF),
+ CLOCK("pbus_clk", PBUS_CLK, NULL, 0),
+ CLOCK("pcm_clk", PCM_CLK, NULL, 0),
+ CLOCK("pmdh_clk", PMDH_CLK, NULL, OFF | MINMAX),
+ CLOCK("sdac_clk", SDAC_CLK, NULL, OFF),
+ CLOCK("sdc_clk", SDC1_CLK, &msm_device_sdc1.dev, OFF),
+ CLOCK("sdc_pclk", SDC1_PCLK, &msm_device_sdc1.dev, OFF),
+ CLOCK("sdc_clk", SDC2_CLK, &msm_device_sdc2.dev, OFF),
+ CLOCK("sdc_pclk", SDC2_PCLK, &msm_device_sdc2.dev, OFF),
+ CLOCK("sdc_clk", SDC3_CLK, &msm_device_sdc3.dev, OFF),
+ CLOCK("sdc_pclk", SDC3_PCLK, &msm_device_sdc3.dev, OFF),
+ CLOCK("sdc_clk", SDC4_CLK, &msm_device_sdc4.dev, OFF),
+ CLOCK("sdc_pclk", SDC4_PCLK, &msm_device_sdc4.dev, OFF),
+ CLOCK("tsif_clk", TSIF_CLK, NULL, 0),
+ CLOCK("tsif_ref_clk", TSIF_REF_CLK, NULL, 0),
+ CLOCK("tv_dac_clk", TV_DAC_CLK, NULL, 0),
+ CLOCK("tv_enc_clk", TV_ENC_CLK, NULL, 0),
+ CLOCK("uart_clk", UART1_CLK, &msm_device_uart1.dev, OFF),
+ CLOCK("uart_clk", UART2_CLK, &msm_device_uart2.dev, 0),
+ CLOCK("uart_clk", UART3_CLK, &msm_device_uart3.dev, OFF),
+ CLOCK("uart1dm_clk", UART1DM_CLK, NULL, OFF),
+ CLOCK("uart2dm_clk", UART2DM_CLK, NULL, 0),
+ CLOCK("usb_hs_clk", USB_HS_CLK, &msm_device_hsusb.dev, OFF),
+ CLOCK("usb_hs_pclk", USB_HS_PCLK, &msm_device_hsusb.dev, OFF),
+ CLOCK("usb_otg_clk", USB_OTG_CLK, NULL, 0),
+ CLOCK("vdc_clk", VDC_CLK, NULL, OFF | MINMAX),
+ CLOCK("vfe_clk", VFE_CLK, NULL, OFF),
+ CLOCK("vfe_mdc_clk", VFE_MDC_CLK, NULL, OFF),
+};
+
+unsigned msm_num_clocks = ARRAY_SIZE(msm_clocks);
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
new file mode 100644
index 000000000000..3b1ce36f1032
--- /dev/null
+++ b/arch/arm/mach-msm/clock.c
@@ -0,0 +1,218 @@
+/* arch/arm/mach-msm/clock.c
+ *
+ * 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.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+
+#include "clock.h"
+#include "proc_comm.h"
+
+static DEFINE_MUTEX(clocks_mutex);
+static DEFINE_SPINLOCK(clocks_lock);
+static LIST_HEAD(clocks);
+
+/*
+ * glue for the proc_comm interface
+ */
+static inline int pc_clk_enable(unsigned id)
+{
+ return msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL);
+}
+
+static inline void pc_clk_disable(unsigned id)
+{
+ msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL);
+}
+
+static inline int pc_clk_set_rate(unsigned id, unsigned rate)
+{
+ return msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate);
+}
+
+static inline int pc_clk_set_min_rate(unsigned id, unsigned rate)
+{
+ return msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate);
+}
+
+static inline int pc_clk_set_max_rate(unsigned id, unsigned rate)
+{
+ return msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &rate);
+}
+
+static inline int pc_clk_set_flags(unsigned id, unsigned flags)
+{
+ return msm_proc_comm(PCOM_CLKCTL_RPC_SET_FLAGS, &id, &flags);
+}
+
+static inline unsigned pc_clk_get_rate(unsigned id)
+{
+ if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL))
+ return 0;
+ else
+ return id;
+}
+
+static inline unsigned pc_clk_is_enabled(unsigned id)
+{
+ if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL))
+ return 0;
+ else
+ return id;
+}
+
+static inline int pc_pll_request(unsigned id, unsigned on)
+{
+ on = !!on;
+ return msm_proc_comm(PCOM_CLKCTL_RPC_PLL_REQUEST, &id, &on);
+}
+
+/*
+ * Standard clock functions defined in include/linux/clk.h
+ */
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ struct clk *clk;
+
+ mutex_lock(&clocks_mutex);
+
+ list_for_each_entry(clk, &clocks, list)
+ if (!strcmp(id, clk->name) && clk->dev == dev)
+ goto found_it;
+
+ list_for_each_entry(clk, &clocks, list)
+ if (!strcmp(id, clk->name) && clk->dev == NULL)
+ goto found_it;
+
+ clk = ERR_PTR(-ENOENT);
+found_it:
+ mutex_unlock(&clocks_mutex);
+ return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&clocks_lock, flags);
+ clk->count++;
+ if (clk->count == 1)
+ pc_clk_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)
+ pc_clk_disable(clk->id);
+ spin_unlock_irqrestore(&clocks_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return pc_clk_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_USE_MIN_MAX_TO_SET) {
+ ret = pc_clk_set_max_rate(clk->id, rate);
+ if (ret)
+ return ret;
+ return pc_clk_set_min_rate(clk->id, rate);
+ }
+ return pc_clk_set_rate(clk->id, rate);
+}
+EXPORT_SYMBOL(clk_set_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 pc_clk_set_flags(clk->id, flags);
+}
+EXPORT_SYMBOL(clk_set_flags);
+
+
+void __init msm_clock_init(void)
+{
+ unsigned n;
+
+ spin_lock_init(&clocks_lock);
+ mutex_lock(&clocks_mutex);
+ for (n = 0; n < msm_num_clocks; n++)
+ list_add_tail(&msm_clocks[n].list, &clocks);
+ mutex_unlock(&clocks_mutex);
+}
+
+/* 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;
+
+ mutex_lock(&clocks_mutex);
+ list_for_each_entry(clk, &clocks, list) {
+ if (clk->flags & CLKFLAG_AUTO_OFF) {
+ spin_lock_irqsave(&clocks_lock, flags);
+ if (!clk->count) {
+ count++;
+ pc_clk_disable(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 000000000000..f875e1544e5f
--- /dev/null
+++ b/arch/arm/mach-msm/clock.h
@@ -0,0 +1,48 @@
+/* arch/arm/mach-msm/clock.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_CLOCK_H
+#define __ARCH_ARM_MACH_MSM_CLOCK_H
+
+#include <linux/list.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_USE_MIN_MAX_TO_SET 0x00000200
+#define CLKFLAG_AUTO_OFF 0x00000400
+
+struct clk {
+ uint32_t id;
+ uint32_t count;
+ uint32_t flags;
+ const char *name;
+ struct list_head list;
+ struct device *dev;
+};
+
+#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)
+
+extern struct clk msm_clocks[];
+extern unsigned msm_num_clocks;
+
+#endif
+
diff --git a/arch/arm/mach-msm/common.c b/arch/arm/mach-msm/common.c
deleted file mode 100644
index 604f8ade9587..000000000000
--- a/arch/arm/mach-msm/common.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* linux/arch/arm/mach-msm/common.c
- *
- * Common setup code for MSM7K Boards
- *
- * 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/io.h>
-
-#include <asm/mach/flash.h>
-
-#include <asm/setup.h>
-
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-
-#include <mach/msm_iomap.h>
-
-#include <mach/board.h>
-
-struct flash_platform_data msm_nand_data = {
- .parts = 0,
- .nr_parts = 0,
-};
-
-static struct resource msm_nand_resources[] = {
- [0] = {
- .start = 7,
- .end = 7,
- .flags = IORESOURCE_DMA,
- },
-};
-
-static struct platform_device msm_nand_device = {
- .name = "msm_nand",
- .id = -1,
- .num_resources = ARRAY_SIZE(msm_nand_resources),
- .resource = msm_nand_resources,
- .dev = {
- .platform_data = &msm_nand_data,
- },
-};
-
-static struct platform_device msm_smd_device = {
- .name = "msm_smd",
- .id = -1,
-};
-
-static struct resource msm_i2c_resources[] = {
- {
- .start = MSM_I2C_BASE,
- .end = MSM_I2C_BASE + MSM_I2C_SIZE - 1,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = INT_PWB_I2C,
- .end = INT_PWB_I2C,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device msm_i2c_device = {
- .name = "msm_i2c",
- .id = 0,
- .num_resources = ARRAY_SIZE(msm_i2c_resources),
- .resource = msm_i2c_resources,
-};
-
-static struct resource usb_resources[] = {
- {
- .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,
- },
-};
-
-static struct platform_device msm_hsusb_device = {
- .name = "msm_hsusb",
- .id = -1,
- .num_resources = ARRAY_SIZE(usb_resources),
- .resource = usb_resources,
- .dev = {
- .coherent_dma_mask = 0xffffffff,
- },
-};
-
-static struct platform_device *devices[] __initdata = {
- &msm_nand_device,
- &msm_smd_device,
- &msm_i2c_device,
- &msm_hsusb_device,
-};
-
-void __init msm_add_devices(void)
-{
- platform_add_devices(devices, ARRAY_SIZE(devices));
-}
diff --git a/arch/arm/mach-msm/devices.c b/arch/arm/mach-msm/devices.c
new file mode 100644
index 000000000000..f2a74b92a97f
--- /dev/null
+++ b/arch/arm/mach-msm/devices.c
@@ -0,0 +1,267 @@
+/* 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 <mach/msm_iomap.h>
+#include "devices.h"
+
+#include <asm/mach/flash.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.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,
+ },
+};
+
+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,
+ },
+};
+
+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,
+ },
+};
+
+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_1,
+ .flags = IORESOURCE_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_1,
+ .flags = IORESOURCE_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_1,
+ .flags = IORESOURCE_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_1,
+ .flags = IORESOURCE_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,
+ },
+};
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
new file mode 100644
index 000000000000..0744c4a27d6a
--- /dev/null
+++ b/arch/arm/mach-msm/devices.h
@@ -0,0 +1,36 @@
+/* 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
+
+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 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_i2c;
+
+extern struct platform_device msm_device_smd;
+
+extern struct platform_device msm_device_nand;
+
+#endif
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index 0c8f252637e1..f5420f9585c5 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -26,7 +26,7 @@ enum {
};
static DEFINE_SPINLOCK(msm_dmov_lock);
-static struct msm_dmov_cmd active_command;
+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;
@@ -43,6 +43,11 @@ unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS;
#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;
@@ -60,6 +65,9 @@ void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd)
#endif
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 (list_empty(&active_commands[id]))
@@ -76,21 +84,19 @@ struct msm_dmov_exec_cmdptr_cmd {
struct completion complete;
unsigned id;
unsigned int result;
- unsigned int flush[6];
+ struct msm_dmov_errdata err;
};
-static void dmov_exec_cmdptr_complete_func(struct msm_dmov_cmd *_cmd, unsigned int result)
+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) {
- cmd->flush[0] = readl(DMOV_FLUSH0(cmd->id));
- cmd->flush[1] = readl(DMOV_FLUSH1(cmd->id));
- cmd->flush[2] = readl(DMOV_FLUSH2(cmd->id));
- cmd->flush[3] = readl(DMOV_FLUSH3(cmd->id));
- cmd->flush[4] = readl(DMOV_FLUSH4(cmd->id));
- cmd->flush[5] = readl(DMOV_FLUSH5(cmd->id));
- }
+ if (result != 0x80000002 && err)
+ memcpy(&cmd->err, err, sizeof(struct msm_dmov_errdata));
+
complete(&cmd->complete);
}
@@ -111,7 +117,7 @@ int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr)
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.flush[0], cmd.flush[1], cmd.flush[2], cmd.flush[3]);
+ 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);
@@ -159,25 +165,40 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
"for %p, result %x\n", id, cmd, ch_result);
if (cmd) {
list_del(&cmd->list);
- cmd->complete_func(cmd, ch_result);
+ cmd->complete_func(cmd, ch_result, NULL);
}
}
if (ch_result & DMOV_RSLT_FLUSH) {
- unsigned int flush0 = readl(DMOV_FLUSH0(id));
+ 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, flush0);
+ 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);
- cmd->complete_func(cmd, ch_result);
+ cmd->complete_func(cmd, ch_result, &errdata);
}
}
if (ch_result & DMOV_RSLT_ERROR) {
- unsigned int flush0 = readl(DMOV_FLUSH0(id));
+ 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, flush0);
+ 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);
- cmd->complete_func(cmd, ch_result);
+ 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 */
@@ -193,8 +214,14 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_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(INT_ADM_AARM);
+
spin_unlock_irqrestore(&msm_dmov_lock, irq_flags);
return IRQ_HANDLED;
}
@@ -202,12 +229,17 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
static int __init msm_init_datamover(void)
{
int i;
+ int ret;
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));
}
- return request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL);
+ 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/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index a7639493c095..264d62e519f3 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -33,5 +33,6 @@ 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(void);
#endif
diff --git a/arch/arm/mach-msm/include/mach/debug-macro.S b/arch/arm/mach-msm/include/mach/debug-macro.S
index 528eef4b605c..1db3c97dbc49 100644
--- a/arch/arm/mach-msm/include/mach/debug-macro.S
+++ b/arch/arm/mach-msm/include/mach/debug-macro.S
@@ -22,18 +22,22 @@
mrc p15, 0, \rx, c1, c0
tst \rx, #1
ldreq \rx, =MSM_UART1_PHYS
- ldrne \rx, =MSM_UART1_BASE
+ movne \rx, #0
.endm
.macro senduart,rd,rx
- str \rd, [\rx, #0x0C]
+ teq \rx, #0
+ strne \rd, [\rx, #0x0C]
.endm
.macro waituart,rd,rx
@ wait for TX_READY
+ teq \rx, #0
+ bne 2f
1: ldr \rd, [\rx, #0x08]
tst \rd, #0x04
beq 1b
+2:
.endm
.macro busyuart,rd,rx
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index ad1c87f86d10..5ab5bdffab07 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -1,4 +1,4 @@
-/* arch/arm/mach-msm/include/mach/dma.h
+/* linux/include/asm-arm/arch-msm/dma.h
*
* Copyright (C) 2007 Google, Inc.
*
@@ -18,17 +18,21 @@
#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);
-/* void (*user_result_func)(struct msm_dmov_cmd *cmd); */
+ void (*complete_func)(struct msm_dmov_cmd *cmd,
+ unsigned int result,
+ struct msm_dmov_errdata *err);
};
void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);
-void msm_dmov_stop_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);
-/* int msm_dmov_exec_cmd_etc(unsigned id, unsigned int cmdptr, int timeout, int interruptible); */
@@ -122,6 +126,16 @@ typedef struct {
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 */
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index e221f58ceea3..2f7b4c8620d9 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -37,11 +37,17 @@
*
*/
-#define MSM_VIC_BASE 0xE0000000
+#ifdef __ASSEMBLY__
+#define IOMEM(x) x
+#else
+#define IOMEM(x) ((void __force __iomem *)(x))
+#endif
+
+#define MSM_VIC_BASE IOMEM(0xE0000000)
#define MSM_VIC_PHYS 0xC0000000
#define MSM_VIC_SIZE SZ_4K
-#define MSM_CSR_BASE 0xE0001000
+#define MSM_CSR_BASE IOMEM(0xE0001000)
#define MSM_CSR_PHYS 0xC0100000
#define MSM_CSR_SIZE SZ_4K
@@ -49,56 +55,67 @@
#define MSM_GPT_BASE MSM_CSR_BASE
#define MSM_GPT_SIZE SZ_4K
-#define MSM_DMOV_BASE 0xE0002000
+#define MSM_DMOV_BASE IOMEM(0xE0002000)
#define MSM_DMOV_PHYS 0xA9700000
#define MSM_DMOV_SIZE SZ_4K
-#define MSM_UART1_BASE 0xE0003000
+#define MSM_GPIO1_BASE IOMEM(0xE0003000)
+#define MSM_GPIO1_PHYS 0xA9200000
+#define MSM_GPIO1_SIZE SZ_4K
+
+#define MSM_GPIO2_BASE IOMEM(0xE0004000)
+#define MSM_GPIO2_PHYS 0xA9300000
+#define MSM_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_BASE 0xE0004000
#define MSM_UART2_PHYS 0xA9B00000
#define MSM_UART2_SIZE SZ_4K
-#define MSM_UART3_BASE 0xE0005000
#define MSM_UART3_PHYS 0xA9C00000
#define MSM_UART3_SIZE SZ_4K
-#define MSM_I2C_BASE 0xE0006000
-#define MSM_I2C_PHYS 0xA9900000
-#define MSM_I2C_SIZE SZ_4K
+#define MSM_SDC1_PHYS 0xA0400000
+#define MSM_SDC1_SIZE SZ_4K
-#define MSM_GPIO1_BASE 0xE0007000
-#define MSM_GPIO1_PHYS 0xA9200000
-#define MSM_GPIO1_SIZE SZ_4K
+#define MSM_SDC2_PHYS 0xA0500000
+#define MSM_SDC2_SIZE SZ_4K
-#define MSM_GPIO2_BASE 0xE0008000
-#define MSM_GPIO2_PHYS 0xA9300000
-#define MSM_GPIO2_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_BASE 0xE0009000
#define MSM_HSUSB_PHYS 0xA0800000
#define MSM_HSUSB_SIZE SZ_4K
-#define MSM_CLK_CTL_BASE 0xE000A000
-#define MSM_CLK_CTL_PHYS 0xA8600000
-#define MSM_CLK_CTL_SIZE SZ_4K
-
-#define MSM_PMDH_BASE 0xE000B000
#define MSM_PMDH_PHYS 0xAA600000
#define MSM_PMDH_SIZE SZ_4K
-#define MSM_EMDH_BASE 0xE000C000
#define MSM_EMDH_PHYS 0xAA700000
#define MSM_EMDH_SIZE SZ_4K
-#define MSM_MDP_BASE 0xE0010000
#define MSM_MDP_PHYS 0xAA200000
#define MSM_MDP_SIZE 0x000F0000
-#define MSM_SHARED_RAM_BASE 0xE0100000
-#define MSM_SHARED_RAM_PHYS 0x01F00000
-#define MSM_SHARED_RAM_SIZE SZ_1M
+#define MSM_MDC_PHYS 0xAA500000
+#define MSM_MDC_SIZE SZ_1M
+
+#define MSM_AD5_PHYS 0xAC000000
+#define MSM_AD5_SIZE (SZ_1M*13)
+
#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 000000000000..9f9e25cb718e
--- /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);
+void 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
index 7999e4ba8e20..6e7692ff6f2c 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -28,7 +28,7 @@
#include <mach/board.h>
#define MSM_DEVICE(name) { \
- .virtual = MSM_##name##_BASE, \
+ .virtual = (unsigned long) MSM_##name##_BASE, \
.pfn = __phys_to_pfn(MSM_##name##_PHYS), \
.length = MSM_##name##_SIZE, \
.type = MT_DEVICE_NONSHARED, \
@@ -39,19 +39,11 @@ static struct map_desc msm_io_desc[] __initdata = {
MSM_DEVICE(CSR),
MSM_DEVICE(GPT),
MSM_DEVICE(DMOV),
- MSM_DEVICE(UART1),
- MSM_DEVICE(UART2),
- MSM_DEVICE(UART3),
- MSM_DEVICE(I2C),
MSM_DEVICE(GPIO1),
MSM_DEVICE(GPIO2),
- MSM_DEVICE(HSUSB),
MSM_DEVICE(CLK_CTL),
- MSM_DEVICE(PMDH),
- MSM_DEVICE(EMDH),
- MSM_DEVICE(MDP),
{
- .virtual = MSM_SHARED_RAM_BASE,
+ .virtual = (unsigned long) MSM_SHARED_RAM_BASE,
.pfn = __phys_to_pfn(MSM_SHARED_RAM_PHYS),
.length = MSM_SHARED_RAM_SIZE,
.type = MT_DEVICE,
diff --git a/arch/arm/mach-msm/irq.c b/arch/arm/mach-msm/irq.c
index 04b8d182ff8a..69ca0dd79bdf 100644
--- a/arch/arm/mach-msm/irq.c
+++ b/arch/arm/mach-msm/irq.c
@@ -66,20 +66,20 @@
static void msm_irq_ack(unsigned int irq)
{
- unsigned reg = VIC_INT_CLEAR0 + ((irq & 32) ? 4 : 0);
+ void __iomem *reg = VIC_INT_CLEAR0 + ((irq & 32) ? 4 : 0);
irq = 1 << (irq & 31);
writel(irq, reg);
}
static void msm_irq_mask(unsigned int irq)
{
- unsigned reg = VIC_INT_ENCLEAR0 + ((irq & 32) ? 4 : 0);
+ void __iomem *reg = VIC_INT_ENCLEAR0 + ((irq & 32) ? 4 : 0);
writel(1 << (irq & 31), reg);
}
static void msm_irq_unmask(unsigned int irq)
{
- unsigned reg = VIC_INT_ENSET0 + ((irq & 32) ? 4 : 0);
+ void __iomem *reg = VIC_INT_ENSET0 + ((irq & 32) ? 4 : 0);
writel(1 << (irq & 31), reg);
}
@@ -90,8 +90,8 @@ static int msm_irq_set_wake(unsigned int irq, unsigned int on)
static int msm_irq_set_type(unsigned int irq, unsigned int flow_type)
{
- unsigned treg = VIC_INT_TYPE0 + ((irq & 32) ? 4 : 0);
- unsigned preg = VIC_INT_POLARITY0 + ((irq & 32) ? 4 : 0);
+ void __iomem *treg = VIC_INT_TYPE0 + ((irq & 32) ? 4 : 0);
+ void __iomem *preg = VIC_INT_POLARITY0 + ((irq & 32) ? 4 : 0);
int b = 1 << (irq & 31);
if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
diff --git a/arch/arm/mach-msm/proc_comm.c b/arch/arm/mach-msm/proc_comm.c
new file mode 100644
index 000000000000..915ee704ed3c
--- /dev/null
+++ b/arch/arm/mach-msm/proc_comm.c
@@ -0,0 +1,110 @@
+/* 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"
+
+#define MSM_A2M_INT(n) (MSM_CSR_BASE + 0x400 + (n) * 4)
+
+static inline void notify_other_proc_comm(void)
+{
+ writel(1, MSM_A2M_INT(6));
+}
+
+#define APP_COMMAND 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;
+}
+
+
diff --git a/arch/arm/mach-msm/proc_comm.h b/arch/arm/mach-msm/proc_comm.h
new file mode 100644
index 000000000000..834760f25692
--- /dev/null
+++ b/arch/arm/mach-msm/proc_comm.h
@@ -0,0 +1,165 @@
+/* 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_
+
+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_NUM_CMDS,
+};
+
+enum {
+ PCOM_INVALID_STATUS = 0x0,
+ PCOM_READY,
+ PCOM_CMD_RUNNING,
+ PCOM_CMD_SUCCESS,
+ PCOM_CMD_FAIL,
+};
+
+/* List of VREGs that support the Pull Down Resistor setting. */
+enum {
+ 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
+};
+
+/* 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);
+
+#endif
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 2bffe9b7e9fe..345a14cb73c3 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -45,7 +45,7 @@ struct msm_clock {
struct clock_event_device clockevent;
struct clocksource clocksource;
struct irqaction irq;
- uint32_t regbase;
+ void __iomem *regbase;
uint32_t freq;
uint32_t shift;
};
diff --git a/arch/arm/mach-msm/vreg.c b/arch/arm/mach-msm/vreg.c
new file mode 100644
index 000000000000..fcb0b9f25684
--- /dev/null
+++ b/arch/arm/mach-msm/vreg.c
@@ -0,0 +1,143 @@
+/* arch/arm/mach-msm/vreg.c
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+#include <mach/vreg.h>
+
+#include "proc_comm.h"
+
+struct vreg {
+ const char *name;
+ unsigned id;
+};
+
+#define VREG(_name, _id) { .name = _name, .id = _id, }
+
+static struct vreg vregs[] = {
+ VREG("msma", 0),
+ VREG("msmp", 1),
+ VREG("msme1", 2),
+ VREG("msmc1", 3),
+ VREG("msmc2", 4),
+ VREG("gp3", 5),
+ VREG("msme2", 6),
+ VREG("gp4", 7),
+ VREG("gp1", 8),
+ VREG("tcxo", 9),
+ VREG("pa", 10),
+ VREG("rftx", 11),
+ VREG("rfrx1", 12),
+ VREG("rfrx2", 13),
+ VREG("synt", 14),
+ VREG("wlan", 15),
+ VREG("usb", 16),
+ VREG("boost", 17),
+ VREG("mmc", 18),
+ VREG("ruim", 19),
+ VREG("msmc0", 20),
+ VREG("gp2", 21),
+ VREG("gp5", 22),
+ VREG("gp6", 23),
+ VREG("rf", 24),
+ VREG("rf_vco", 26),
+ VREG("mpll", 27),
+ VREG("s2", 28),
+ VREG("s3", 29),
+ VREG("rfubm", 30),
+ VREG("ncp", 31),
+};
+
+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 0;
+}
+
+void vreg_put(struct vreg *vreg)
+{
+}
+
+int vreg_enable(struct vreg *vreg)
+{
+ unsigned id = vreg->id;
+ unsigned enable = 1;
+ return msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
+}
+
+void vreg_disable(struct vreg *vreg)
+{
+ unsigned id = vreg->id;
+ unsigned enable = 0;
+ msm_proc_comm(PCOM_VREG_SWITCH, &id, &enable);
+}
+
+int vreg_set_level(struct vreg *vreg, unsigned mv)
+{
+ unsigned id = vreg->id;
+ return msm_proc_comm(PCOM_VREG_SET_LEVEL, &id, &mv);
+}
+
+#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)
+{
+ return -ENOSYS;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(vreg_fops, vreg_debug_get, vreg_debug_set, "%llu\n");
+
+static int __init vreg_debug_init(void)
+{
+ struct dentry *dent;
+ int n;
+
+ 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);
+
+ return 0;
+}
+
+device_initcall(vreg_debug_init);
+#endif