summaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-s5p
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-s5p')
-rw-r--r--arch/arm/plat-s5p/Kconfig18
-rw-r--r--arch/arm/plat-s5p/Makefile3
-rw-r--r--arch/arm/plat-s5p/cpu.c5
-rw-r--r--arch/arm/plat-s5p/dev-csis0.c34
-rw-r--r--arch/arm/plat-s5p/dev-csis1.c34
-rw-r--r--arch/arm/plat-s5p/include/plat/csis.h28
-rw-r--r--arch/arm/plat-s5p/include/plat/map-s5p.h1
-rw-r--r--arch/arm/plat-s5p/include/plat/regs-srom.h54
-rw-r--r--arch/arm/plat-s5p/irq-eint.c86
-rw-r--r--arch/arm/plat-s5p/irq-gpioint.c50
-rw-r--r--arch/arm/plat-s5p/irq-pm.c6
-rw-r--r--arch/arm/plat-s5p/sysmmu.c326
12 files changed, 575 insertions, 70 deletions
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 65dbfa8e0a8..557f8c507f6 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -37,6 +37,14 @@ config S5P_GPIO_INT
help
Common code for the GPIO interrupts (other than external interrupts.)
+comment "System MMU"
+
+config S5P_SYSTEM_MMU
+ bool "S5P SYSTEM MMU"
+ depends on ARCH_S5PV310
+ help
+ Say Y here if you want to enable System MMU
+
config S5P_DEV_FIMC0
bool
help
@@ -56,3 +64,13 @@ config S5P_DEV_ONENAND
bool
help
Compile in platform device definition for OneNAND controller
+
+config S5P_DEV_CSIS0
+ bool
+ help
+ Compile in platform device definitions for MIPI-CSIS channel 0
+
+config S5P_DEV_CSIS1
+ bool
+ help
+ Compile in platform device definitions for MIPI-CSIS channel 1
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index de65238a7ae..4bd5cf90897 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -19,6 +19,7 @@ obj-y += clock.o
obj-y += irq.o
obj-$(CONFIG_S5P_EXT_INT) += irq-eint.o
obj-$(CONFIG_S5P_GPIO_INT) += irq-gpioint.o
+obj-$(CONFIG_S5P_SYSTEM_MMU) += sysmmu.o
obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_PM) += irq-pm.o
@@ -28,3 +29,5 @@ obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o
obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o
obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o
obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o
+obj-$(CONFIG_S5P_DEV_CSIS0) += dev-csis0.o
+obj-$(CONFIG_S5P_DEV_CSIS1) += dev-csis1.o
diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
index 74f7f5a5446..047d31c1bbd 100644
--- a/arch/arm/plat-s5p/cpu.c
+++ b/arch/arm/plat-s5p/cpu.c
@@ -108,6 +108,11 @@ static struct map_desc s5p_iodesc[] __initdata = {
.pfn = __phys_to_pfn(S3C_PA_WDT),
.length = SZ_4K,
.type = MT_DEVICE,
+ }, {
+ .virtual = (unsigned long)S5P_VA_SROMC,
+ .pfn = __phys_to_pfn(S5P_PA_SROMC),
+ .length = SZ_4K,
+ .type = MT_DEVICE,
},
};
diff --git a/arch/arm/plat-s5p/dev-csis0.c b/arch/arm/plat-s5p/dev-csis0.c
new file mode 100644
index 00000000000..dfab1c85f54
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-csis0.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * S5P series device definition for MIPI-CSIS channel 0
+ *
+ * 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/interrupt.h>
+#include <linux/platform_device.h>
+#include <mach/map.h>
+
+static struct resource s5p_mipi_csis0_resource[] = {
+ [0] = {
+ .start = S5P_PA_MIPI_CSIS0,
+ .end = S5P_PA_MIPI_CSIS0 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_MIPI_CSIS0,
+ .end = IRQ_MIPI_CSIS0,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+struct platform_device s5p_device_mipi_csis0 = {
+ .name = "s5p-mipi-csis",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(s5p_mipi_csis0_resource),
+ .resource = s5p_mipi_csis0_resource,
+};
diff --git a/arch/arm/plat-s5p/dev-csis1.c b/arch/arm/plat-s5p/dev-csis1.c
new file mode 100644
index 00000000000..e3053f27fbb
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-csis1.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * S5P series device definition for MIPI-CSIS channel 1
+ *
+ * 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/interrupt.h>
+#include <linux/platform_device.h>
+#include <mach/map.h>
+
+static struct resource s5p_mipi_csis1_resource[] = {
+ [0] = {
+ .start = S5P_PA_MIPI_CSIS1,
+ .end = S5P_PA_MIPI_CSIS1 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_MIPI_CSIS1,
+ .end = IRQ_MIPI_CSIS1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device s5p_device_mipi_csis1 = {
+ .name = "s5p-mipi-csis",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(s5p_mipi_csis1_resource),
+ .resource = s5p_mipi_csis1_resource,
+};
diff --git a/arch/arm/plat-s5p/include/plat/csis.h b/arch/arm/plat-s5p/include/plat/csis.h
new file mode 100644
index 00000000000..51e308c7981
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/csis.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * S5P series MIPI CSI slave device support
+ *
+ * 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.
+ */
+
+#ifndef PLAT_S5P_CSIS_H_
+#define PLAT_S5P_CSIS_H_ __FILE__
+
+/**
+ * struct s5p_platform_mipi_csis - platform data for MIPI-CSIS
+ * @clk_rate: bus clock frequency
+ * @lanes: number of data lanes used
+ * @alignment: data alignment in bits
+ * @hs_settle: HS-RX settle time
+ */
+struct s5p_platform_mipi_csis {
+ unsigned long clk_rate;
+ u8 lanes;
+ u8 alignment;
+ u8 hs_settle;
+};
+
+#endif /* PLAT_S5P_CSIS_H_ */
diff --git a/arch/arm/plat-s5p/include/plat/map-s5p.h b/arch/arm/plat-s5p/include/plat/map-s5p.h
index fef353d4451..d973d39666a 100644
--- a/arch/arm/plat-s5p/include/plat/map-s5p.h
+++ b/arch/arm/plat-s5p/include/plat/map-s5p.h
@@ -15,6 +15,7 @@
#define S5P_VA_CHIPID S3C_ADDR(0x02000000)
#define S5P_VA_CMU S3C_ADDR(0x02100000)
+#define S5P_VA_PMU S3C_ADDR(0x02180000)
#define S5P_VA_GPIO S3C_ADDR(0x02200000)
#define S5P_VA_GPIO1 S5P_VA_GPIO
#define S5P_VA_GPIO2 S3C_ADDR(0x02240000)
diff --git a/arch/arm/plat-s5p/include/plat/regs-srom.h b/arch/arm/plat-s5p/include/plat/regs-srom.h
new file mode 100644
index 00000000000..f121ab5e76c
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/regs-srom.h
@@ -0,0 +1,54 @@
+/* linux/arch/arm/plat-s5p/include/plat/regs-srom.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * S5P SROMC register definitions
+ *
+ * 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.
+*/
+
+#ifndef __ASM_PLAT_S5P_REGS_SROM_H
+#define __ASM_PLAT_S5P_REGS_SROM_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_SROMREG(x) (S5P_VA_SROMC + (x))
+
+#define S5P_SROM_BW S5P_SROMREG(0x0)
+#define S5P_SROM_BC0 S5P_SROMREG(0x4)
+#define S5P_SROM_BC1 S5P_SROMREG(0x8)
+#define S5P_SROM_BC2 S5P_SROMREG(0xc)
+#define S5P_SROM_BC3 S5P_SROMREG(0x10)
+#define S5P_SROM_BC4 S5P_SROMREG(0x14)
+#define S5P_SROM_BC5 S5P_SROMREG(0x18)
+
+/* one register BW holds 4 x 4-bit packed settings for NCS0 - NCS3 */
+
+#define S5P_SROM_BW__DATAWIDTH__SHIFT 0
+#define S5P_SROM_BW__ADDRMODE__SHIFT 1
+#define S5P_SROM_BW__WAITENABLE__SHIFT 2
+#define S5P_SROM_BW__BYTEENABLE__SHIFT 3
+
+#define S5P_SROM_BW__CS_MASK 0xf
+
+#define S5P_SROM_BW__NCS0__SHIFT 0
+#define S5P_SROM_BW__NCS1__SHIFT 4
+#define S5P_SROM_BW__NCS2__SHIFT 8
+#define S5P_SROM_BW__NCS3__SHIFT 12
+#define S5P_SROM_BW__NCS4__SHIFT 16
+#define S5P_SROM_BW__NCS5__SHIFT 20
+
+/* applies to same to BCS0 - BCS3 */
+
+#define S5P_SROM_BCX__PMC__SHIFT 0
+#define S5P_SROM_BCX__TACP__SHIFT 4
+#define S5P_SROM_BCX__TCAH__SHIFT 8
+#define S5P_SROM_BCX__TCOH__SHIFT 12
+#define S5P_SROM_BCX__TACC__SHIFT 16
+#define S5P_SROM_BCX__TCOS__SHIFT 24
+#define S5P_SROM_BCX__TACS__SHIFT 28
+
+#endif /* __ASM_PLAT_S5P_REGS_SROM_H */
diff --git a/arch/arm/plat-s5p/irq-eint.c b/arch/arm/plat-s5p/irq-eint.c
index 752f1a645f9..225aa25405d 100644
--- a/arch/arm/plat-s5p/irq-eint.c
+++ b/arch/arm/plat-s5p/irq-eint.c
@@ -28,39 +28,40 @@
#include <plat/gpio-cfg.h>
#include <mach/regs-gpio.h>
-static inline void s5p_irq_eint_mask(unsigned int irq)
+static inline void s5p_irq_eint_mask(struct irq_data *data)
{
u32 mask;
- mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(irq)));
- mask |= eint_irq_to_bit(irq);
- __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(irq)));
+ mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+ mask |= eint_irq_to_bit(data->irq);
+ __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
}
-static void s5p_irq_eint_unmask(unsigned int irq)
+static void s5p_irq_eint_unmask(struct irq_data *data)
{
u32 mask;
- mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(irq)));
- mask &= ~(eint_irq_to_bit(irq));
- __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(irq)));
+ mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+ mask &= ~(eint_irq_to_bit(data->irq));
+ __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
}
-static inline void s5p_irq_eint_ack(unsigned int irq)
+static inline void s5p_irq_eint_ack(struct irq_data *data)
{
- __raw_writel(eint_irq_to_bit(irq), S5P_EINT_PEND(EINT_REG_NR(irq)));
+ __raw_writel(eint_irq_to_bit(data->irq),
+ S5P_EINT_PEND(EINT_REG_NR(data->irq)));
}
-static void s5p_irq_eint_maskack(unsigned int irq)
+static void s5p_irq_eint_maskack(struct irq_data *data)
{
/* compiler should in-line these */
- s5p_irq_eint_mask(irq);
- s5p_irq_eint_ack(irq);
+ s5p_irq_eint_mask(data);
+ s5p_irq_eint_ack(data);
}
-static int s5p_irq_eint_set_type(unsigned int irq, unsigned int type)
+static int s5p_irq_eint_set_type(struct irq_data *data, unsigned int type)
{
- int offs = EINT_OFFSET(irq);
+ int offs = EINT_OFFSET(data->irq);
int shift;
u32 ctrl, mask;
u32 newvalue = 0;
@@ -94,10 +95,10 @@ static int s5p_irq_eint_set_type(unsigned int irq, unsigned int type)
shift = (offs & 0x7) * 4;
mask = 0x7 << shift;
- ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(irq)));
+ ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
ctrl &= ~mask;
ctrl |= newvalue << shift;
- __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(irq)));
+ __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
if ((0 <= offs) && (offs < 8))
s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
@@ -119,13 +120,13 @@ static int s5p_irq_eint_set_type(unsigned int irq, unsigned int type)
static struct irq_chip s5p_irq_eint = {
.name = "s5p-eint",
- .mask = s5p_irq_eint_mask,
- .unmask = s5p_irq_eint_unmask,
- .mask_ack = s5p_irq_eint_maskack,
- .ack = s5p_irq_eint_ack,
- .set_type = s5p_irq_eint_set_type,
+ .irq_mask = s5p_irq_eint_mask,
+ .irq_unmask = s5p_irq_eint_unmask,
+ .irq_mask_ack = s5p_irq_eint_maskack,
+ .irq_ack = s5p_irq_eint_ack,
+ .irq_set_type = s5p_irq_eint_set_type,
#ifdef CONFIG_PM
- .set_wake = s3c_irqext_wake,
+ .irq_set_wake = s3c_irqext_wake,
#endif
};
@@ -159,42 +160,43 @@ static void s5p_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
s5p_irq_demux_eint(IRQ_EINT(24));
}
-static inline void s5p_irq_vic_eint_mask(unsigned int irq)
+static inline void s5p_irq_vic_eint_mask(struct irq_data *data)
{
- void __iomem *base = get_irq_chip_data(irq);
+ void __iomem *base = irq_data_get_irq_chip_data(data);
- s5p_irq_eint_mask(irq);
- writel(1 << EINT_OFFSET(irq), base + VIC_INT_ENABLE_CLEAR);
+ s5p_irq_eint_mask(data);
+ writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE_CLEAR);
}
-static void s5p_irq_vic_eint_unmask(unsigned int irq)
+static void s5p_irq_vic_eint_unmask(struct irq_data *data)
{
- void __iomem *base = get_irq_chip_data(irq);
+ void __iomem *base = irq_data_get_irq_chip_data(data);
- s5p_irq_eint_unmask(irq);
- writel(1 << EINT_OFFSET(irq), base + VIC_INT_ENABLE);
+ s5p_irq_eint_unmask(data);
+ writel(1 << EINT_OFFSET(data->irq), base + VIC_INT_ENABLE);
}
-static inline void s5p_irq_vic_eint_ack(unsigned int irq)
+static inline void s5p_irq_vic_eint_ack(struct irq_data *data)
{
- __raw_writel(eint_irq_to_bit(irq), S5P_EINT_PEND(EINT_REG_NR(irq)));
+ __raw_writel(eint_irq_to_bit(data->irq),
+ S5P_EINT_PEND(EINT_REG_NR(data->irq)));
}
-static void s5p_irq_vic_eint_maskack(unsigned int irq)
+static void s5p_irq_vic_eint_maskack(struct irq_data *data)
{
- s5p_irq_vic_eint_mask(irq);
- s5p_irq_vic_eint_ack(irq);
+ s5p_irq_vic_eint_mask(data);
+ s5p_irq_vic_eint_ack(data);
}
static struct irq_chip s5p_irq_vic_eint = {
.name = "s5p_vic_eint",
- .mask = s5p_irq_vic_eint_mask,
- .unmask = s5p_irq_vic_eint_unmask,
- .mask_ack = s5p_irq_vic_eint_maskack,
- .ack = s5p_irq_vic_eint_ack,
- .set_type = s5p_irq_eint_set_type,
+ .irq_mask = s5p_irq_vic_eint_mask,
+ .irq_unmask = s5p_irq_vic_eint_unmask,
+ .irq_mask_ack = s5p_irq_vic_eint_maskack,
+ .irq_ack = s5p_irq_vic_eint_ack,
+ .irq_set_type = s5p_irq_eint_set_type,
#ifdef CONFIG_PM
- .set_wake = s3c_irqext_wake,
+ .irq_set_wake = s3c_irqext_wake,
#endif
};
diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c
index 0e5dc8cbf5e..3b6bf89d173 100644
--- a/arch/arm/plat-s5p/irq-gpioint.c
+++ b/arch/arm/plat-s5p/irq-gpioint.c
@@ -30,9 +30,9 @@
static struct s3c_gpio_chip *irq_chips[S5P_GPIOINT_GROUP_MAXNR];
-static int s5p_gpioint_get_group(unsigned int irq)
+static int s5p_gpioint_get_group(struct irq_data *data)
{
- struct gpio_chip *chip = get_irq_data(irq);
+ struct gpio_chip *chip = irq_data_get_irq_data(data);
struct s3c_gpio_chip *s3c_chip = container_of(chip,
struct s3c_gpio_chip, chip);
int group;
@@ -44,22 +44,22 @@ static int s5p_gpioint_get_group(unsigned int irq)
return group;
}
-static int s5p_gpioint_get_offset(unsigned int irq)
+static int s5p_gpioint_get_offset(struct irq_data *data)
{
- struct gpio_chip *chip = get_irq_data(irq);
+ struct gpio_chip *chip = irq_data_get_irq_data(data);
struct s3c_gpio_chip *s3c_chip = container_of(chip,
struct s3c_gpio_chip, chip);
- return irq - s3c_chip->irq_base;
+ return data->irq - s3c_chip->irq_base;
}
-static void s5p_gpioint_ack(unsigned int irq)
+static void s5p_gpioint_ack(struct irq_data *data)
{
int group, offset, pend_offset;
unsigned int value;
- group = s5p_gpioint_get_group(irq);
- offset = s5p_gpioint_get_offset(irq);
+ group = s5p_gpioint_get_group(data);
+ offset = s5p_gpioint_get_offset(data);
pend_offset = group << 2;
value = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
@@ -67,13 +67,13 @@ static void s5p_gpioint_ack(unsigned int irq)
__raw_writel(value, S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
}
-static void s5p_gpioint_mask(unsigned int irq)
+static void s5p_gpioint_mask(struct irq_data *data)
{
int group, offset, mask_offset;
unsigned int value;
- group = s5p_gpioint_get_group(irq);
- offset = s5p_gpioint_get_offset(irq);
+ group = s5p_gpioint_get_group(data);
+ offset = s5p_gpioint_get_offset(data);
mask_offset = group << 2;
value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
@@ -81,13 +81,13 @@ static void s5p_gpioint_mask(unsigned int irq)
__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
}
-static void s5p_gpioint_unmask(unsigned int irq)
+static void s5p_gpioint_unmask(struct irq_data *data)
{
int group, offset, mask_offset;
unsigned int value;
- group = s5p_gpioint_get_group(irq);
- offset = s5p_gpioint_get_offset(irq);
+ group = s5p_gpioint_get_group(data);
+ offset = s5p_gpioint_get_offset(data);
mask_offset = group << 2;
value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
@@ -95,19 +95,19 @@ static void s5p_gpioint_unmask(unsigned int irq)
__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
}
-static void s5p_gpioint_mask_ack(unsigned int irq)
+static void s5p_gpioint_mask_ack(struct irq_data *data)
{
- s5p_gpioint_mask(irq);
- s5p_gpioint_ack(irq);
+ s5p_gpioint_mask(data);
+ s5p_gpioint_ack(data);
}
-static int s5p_gpioint_set_type(unsigned int irq, unsigned int type)
+static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
{
int group, offset, con_offset;
unsigned int value;
- group = s5p_gpioint_get_group(irq);
- offset = s5p_gpioint_get_offset(irq);
+ group = s5p_gpioint_get_group(data);
+ offset = s5p_gpioint_get_offset(data);
con_offset = group << 2;
switch (type) {
@@ -142,11 +142,11 @@ static int s5p_gpioint_set_type(unsigned int irq, unsigned int type)
struct irq_chip s5p_gpioint = {
.name = "s5p_gpioint",
- .ack = s5p_gpioint_ack,
- .mask = s5p_gpioint_mask,
- .mask_ack = s5p_gpioint_mask_ack,
- .unmask = s5p_gpioint_unmask,
- .set_type = s5p_gpioint_set_type,
+ .irq_ack = s5p_gpioint_ack,
+ .irq_mask = s5p_gpioint_mask,
+ .irq_mask_ack = s5p_gpioint_mask_ack,
+ .irq_unmask = s5p_gpioint_unmask,
+ .irq_set_type = s5p_gpioint_set_type,
};
static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
diff --git a/arch/arm/plat-s5p/irq-pm.c b/arch/arm/plat-s5p/irq-pm.c
index dc33b9ecda4..5259ad458bc 100644
--- a/arch/arm/plat-s5p/irq-pm.c
+++ b/arch/arm/plat-s5p/irq-pm.c
@@ -37,14 +37,14 @@
unsigned long s3c_irqwake_intallow = 0x00000006L;
unsigned long s3c_irqwake_eintallow = 0xffffffffL;
-int s3c_irq_wake(unsigned int irqno, unsigned int state)
+int s3c_irq_wake(struct irq_data *data, unsigned int state)
{
unsigned long irqbit;
- switch (irqno) {
+ switch (data->irq) {
case IRQ_RTC_TIC:
case IRQ_RTC_ALARM:
- irqbit = 1 << (irqno + 1 - IRQ_RTC_ALARM);
+ irqbit = 1 << (data->irq + 1 - IRQ_RTC_ALARM);
if (!state)
s3c_irqwake_intmask |= irqbit;
else
diff --git a/arch/arm/plat-s5p/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c
new file mode 100644
index 00000000000..ffe8a48bc3c
--- /dev/null
+++ b/arch/arm/plat-s5p/sysmmu.c
@@ -0,0 +1,326 @@
+/* linux/arch/arm/plat-s5p/sysmmu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * 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/io.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <mach/map.h>
+#include <mach/regs-sysmmu.h>
+#include <mach/sysmmu.h>
+
+struct sysmmu_controller s5p_sysmmu_cntlrs[S5P_SYSMMU_TOTAL_IPNUM];
+
+void s5p_sysmmu_register(struct sysmmu_controller *sysmmuconp)
+{
+ unsigned int reg_mmu_ctrl;
+ unsigned int reg_mmu_status;
+ unsigned int reg_pt_base_addr;
+ unsigned int reg_int_status;
+ unsigned int reg_page_ft_addr;
+
+ reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
+ reg_mmu_ctrl = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+ reg_mmu_status = __raw_readl(sysmmuconp->regs + S5P_MMU_STATUS);
+ reg_pt_base_addr = __raw_readl(sysmmuconp->regs + S5P_PT_BASE_ADDR);
+ reg_page_ft_addr = __raw_readl(sysmmuconp->regs + S5P_PAGE_FAULT_ADDR);
+
+ printk(KERN_INFO "%s: ips:%s\n", __func__, sysmmuconp->name);
+ printk(KERN_INFO "%s: MMU_CTRL:0x%X, ", __func__, reg_mmu_ctrl);
+ printk(KERN_INFO "MMU_STATUS:0x%X, PT_BASE_ADDR:0x%X\n", reg_mmu_status, reg_pt_base_addr);
+ printk(KERN_INFO "%s: INT_STATUS:0x%X, PAGE_FAULT_ADDR:0x%X\n", __func__, reg_int_status, reg_page_ft_addr);
+
+ switch (reg_int_status & 0xFF) {
+ case 0x1:
+ printk(KERN_INFO "%s: Page fault\n", __func__);
+ printk(KERN_INFO "%s: Virtual address causing last page fault or bus error : 0x%x\n", __func__ , reg_page_ft_addr);
+ break;
+ case 0x2:
+ printk(KERN_INFO "%s: AR multi-hit fault\n", __func__);
+ break;
+ case 0x4:
+ printk(KERN_INFO "%s: AW multi-hit fault\n", __func__);
+ break;
+ case 0x8:
+ printk(KERN_INFO "%s: Bus error\n", __func__);
+ break;
+ case 0x10:
+ printk(KERN_INFO "%s: AR Security protection fault\n", __func__);
+ break;
+ case 0x20:
+ printk(KERN_INFO "%s: AR Access protection fault\n", __func__);
+ break;
+ case 0x40:
+ printk(KERN_INFO "%s: AW Security protection fault\n", __func__);
+ break;
+ case 0x80:
+ printk(KERN_INFO "%s: AW Access protection fault\n", __func__);
+ break;
+ }
+}
+
+static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
+{
+ unsigned int i;
+ unsigned int reg_int_status;
+ struct sysmmu_controller *sysmmuconp;
+
+ for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
+ sysmmuconp = &s5p_sysmmu_cntlrs[i];
+
+ if (sysmmuconp->enable == true) {
+ reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
+
+ if (reg_int_status & 0xFF)
+ s5p_sysmmu_register(sysmmuconp);
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+int s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
+{
+ struct sysmmu_controller *sysmmuconp = NULL;
+
+ sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+
+ if (sysmmuconp == NULL) {
+ printk(KERN_ERR "failed to get ip's sysmmu info\n");
+ return 1;
+ }
+
+ /* Set sysmmu page table base address */
+ __raw_writel(pgd, sysmmuconp->regs + S5P_PT_BASE_ADDR);
+
+ if (s5p_sysmmu_tlb_invalidate(ips) != 0)
+ printk(KERN_ERR "failed s5p_sysmmu_tlb_invalidate\n");
+
+ return 0;
+}
+
+static int s5p_sysmmu_set_tablebase(sysmmu_ips ips)
+{
+ unsigned int pg;
+ struct sysmmu_controller *sysmmuconp;
+
+ sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+
+ if (sysmmuconp == NULL) {
+ printk(KERN_ERR "failed to get ip's sysmmu info\n");
+ return 1;
+ }
+
+ __asm__("mrc p15, 0, %0, c2, c0, 0" \
+ : "=r" (pg) : : "cc"); \
+ pg &= ~0x3fff;
+
+ printk(KERN_INFO "%s: CP15 TTBR0 : 0x%x\n", __func__, pg);
+
+ /* Set sysmmu page table base address */
+ __raw_writel(pg, sysmmuconp->regs + S5P_PT_BASE_ADDR);
+
+ return 0;
+}
+
+int s5p_sysmmu_enable(sysmmu_ips ips)
+{
+ unsigned int reg;
+
+ struct sysmmu_controller *sysmmuconp;
+
+ sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+
+ if (sysmmuconp == NULL) {
+ printk(KERN_ERR "failed to get ip's sysmmu info\n");
+ return 1;
+ }
+
+ s5p_sysmmu_set_tablebase(ips);
+
+ /* replacement policy : LRU */
+ reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
+ reg |= 0x1;
+ __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
+
+ /* Enable interrupt, Enable MMU */
+ reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+ reg |= (0x1 << 2) | (0x1 << 0);
+
+ __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+
+ sysmmuconp->enable = true;
+
+ return 0;
+}
+
+int s5p_sysmmu_disable(sysmmu_ips ips)
+{
+ unsigned int reg;
+
+ struct sysmmu_controller *sysmmuconp = NULL;
+
+ if (ips > S5P_SYSMMU_TOTAL_IPNUM)
+ printk(KERN_ERR "failed to get ips parameter\n");
+
+ sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+
+ if (sysmmuconp == NULL) {
+ printk(KERN_ERR "failed to get ip's sysmmu info\n");
+ return 1;
+ }
+
+ reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
+
+ /* replacement policy : LRU */
+ reg |= 0x1;
+ __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
+
+ reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+
+ /* Disable MMU */
+ reg &= ~0x1;
+ __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+
+ sysmmuconp->enable = false;
+
+ return 0;
+}
+
+int s5p_sysmmu_tlb_invalidate(sysmmu_ips ips)
+{
+ unsigned int reg;
+ struct sysmmu_controller *sysmmuconp = NULL;
+
+ sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+
+ if (sysmmuconp == NULL) {
+ printk(KERN_ERR "failed to get ip's sysmmu info\n");
+ return 1;
+ }
+
+ /* set Block MMU for flush TLB */
+ reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+ reg |= 0x1 << 1;
+ __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+
+ /* flush all TLB entry */
+ __raw_writel(0x1, sysmmuconp->regs + S5P_MMU_FLUSH);
+
+ /* set Un-block MMU after flush TLB */
+ reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+ reg &= ~(0x1 << 1);
+ __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+
+ return 0;
+}
+
+static int s5p_sysmmu_probe(struct platform_device *pdev)
+{
+ int i;
+ int ret;
+ struct resource *res;
+ struct sysmmu_controller *sysmmuconp;
+ sysmmu_ips ips;
+
+ for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
+ sysmmuconp = &s5p_sysmmu_cntlrs[i];
+ if (sysmmuconp == NULL) {
+ printk(KERN_ERR "failed to get ip's sysmmu info\n");
+ ret = -ENOENT;
+ goto err_res;
+ }
+
+ sysmmuconp->name = sysmmu_ips_name[i];
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res) {
+ printk(KERN_ERR "failed to get sysmmu resource\n");
+ ret = -ENODEV;
+ goto err_res;
+ }
+
+ sysmmuconp->mem = request_mem_region(res->start,
+ ((res->end) - (res->start)) + 1, pdev->name);
+ if (!sysmmuconp->mem) {
+ pr_err("failed to request sysmmu memory region\n");
+ ret = -EBUSY;
+ goto err_res;
+ }
+
+ sysmmuconp->regs = ioremap(res->start, res->end - res->start + 1);
+ if (!sysmmuconp->regs) {
+ pr_err("failed to sysmmu ioremap\n");
+ ret = -ENXIO;
+ goto err_reg;
+ }
+
+ sysmmuconp->irq = platform_get_irq(pdev, i);
+ if (sysmmuconp->irq <= 0) {
+ pr_err("failed to get sysmmu irq resource\n");
+ ret = -ENOENT;
+ goto err_map;
+ }
+
+ ret = request_irq(sysmmuconp->irq, s5p_sysmmu_irq, IRQF_DISABLED, pdev->name, sysmmuconp);
+ if (ret) {
+ pr_err("failed to request irq\n");
+ ret = -ENOENT;
+ goto err_map;
+ }
+
+ ips = (sysmmu_ips)i;
+
+ sysmmuconp->ips = ips;
+ }
+
+ return 0;
+
+err_reg:
+ release_mem_region((resource_size_t)sysmmuconp->mem, (resource_size_t)((res->end) - (res->start) + 1));
+err_map:
+ iounmap(sysmmuconp->regs);
+err_res:
+ return ret;
+}
+
+static int s5p_sysmmu_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+int s5p_sysmmu_runtime_suspend(struct device *dev)
+{
+ return 0;
+}
+
+int s5p_sysmmu_runtime_resume(struct device *dev)
+{
+ return 0;
+}
+
+const struct dev_pm_ops s5p_sysmmu_pm_ops = {
+ .runtime_suspend = s5p_sysmmu_runtime_suspend,
+ .runtime_resume = s5p_sysmmu_runtime_resume,
+};
+
+static struct platform_driver s5p_sysmmu_driver = {
+ .probe = s5p_sysmmu_probe,
+ .remove = s5p_sysmmu_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "s5p-sysmmu",
+ .pm = &s5p_sysmmu_pm_ops,
+ }
+};
+
+static int __init s5p_sysmmu_init(void)
+{
+ return platform_driver_register(&s5p_sysmmu_driver);
+}
+arch_initcall(s5p_sysmmu_init);