* [PATCH 1/3 v3] ARM Realview PCIX map include file changes
From: Arnd Bergmann @ 2011-10-07 12:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHkRjk5MQUWiF3jmZJ_SBHdtmunoajR4eHftwdnFCKjeDxQDKA@mail.gmail.com>
On Friday 07 October 2011, Catalin Marinas wrote:
> > However, after changing both __io() and pcibios_min_io as Arnd suggested the boot still hangs after " Uncompressing Linux... done, booting the kernel."
>
> I haven't followed the patch series in detail but the __io() is also
> used by __io_address() in the RealView code and the former is just
> expected to do some type casting. By doing some arithmetic on the
> pointer, the static mappings for various peripherals (GIC etc.) are
> wrong.
>
> So if you convert __io() as per Arnd's suggestion, make sure that
> __io_address() is redefined, something like below:
>
> #define __io_address(n) __typesafe_io(IO_ADDRESS(n))
Ah, right. That definitely explains why it would not boot.
> Alternatively we could leave __io() as in the original kernel and
> define RealView specific in*/out* macros.
I wouldn't recommend that, since that would just have to be reverted
as we get closer to having a single zimage across platforms.
Your suggested fix above should be enough.
Arnd
^ permalink raw reply
* [patch] ARM: smpboot: Enable interrupts after marking CPU online/active
From: Thomas Gleixner @ 2011-10-07 12:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <01d501cc84d6$62720890$275619b0$%kim@samsung.com>
On Fri, 7 Oct 2011, Kukjin Kim wrote:
> I think, basically, if SPIs in GIC are used in local timer, the routing
> interrupt like calling irq_set_affinity() to offline CPUs should be
> available when boot time before calling set_cpu_online() because as you know
> the local_timer_setup() which includes setup interrupt is called in
> percpu_timer_setup() now...
>
> Is there any way to get the flags of struct irqaction from struct irq_data
> in gic_set_affinity()? Or?
No, and you should not even think about it at all.
The problem I can see from all this discussion is related to the early
enabling of interrupts and the per cpu timer setup before the cpu is
marked online. I really do not understand at all why this needs to be
done in order to call calibrate_delay().
calibrate_delay() monitors jiffies, which are updated from the CPU
which is waiting for the new CPU to set the online bit.
So you simply can call calibrate_delay() on the new CPU just from the
interrupt disabled region and move the local timer setup after you
stored the cpu data and before enabling interrupts.
This solves both the cpu_online vs. cpu_active problem and the
affinity setting of the per cpu timers.
Thanks,
tglx
----
Index: linux-2.6/arch/arm/kernel/smp.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/smp.c
+++ linux-2.6/arch/arm/kernel/smp.c
@@ -301,17 +301,7 @@ asmlinkage void __cpuinit secondary_star
*/
platform_secondary_init(cpu);
- /*
- * Enable local interrupts.
- */
notify_cpu_starting(cpu);
- local_irq_enable();
- local_fiq_enable();
-
- /*
- * Setup the percpu timer for this CPU.
- */
- percpu_timer_setup();
calibrate_delay();
@@ -323,10 +313,23 @@ asmlinkage void __cpuinit secondary_star
* before we continue.
*/
set_cpu_online(cpu, true);
+
+ /*
+ * Setup the percpu timer for this CPU.
+ */
+ percpu_timer_setup();
+
while (!cpu_active(cpu))
cpu_relax();
/*
+ * cpu_active bit is set, so it's safe to enable interrupts
+ * now.
+ */
+ local_irq_enable();
+ local_fiq_enable();
+
+ /*
* OK, it's off to the idle thread for us
*/
cpu_idle();
^ permalink raw reply
* [PATCH V2 2/2] ARM: S3C2410: irq: Remove __init attributes to fix compilation warning
From: Tushar Behera @ 2011-10-07 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317988513-20800-1-git-send-email-tushar.behera@linaro.org>
The structure *_irq_driver is passed as a parameter in
sysdev_driver_register(). This in turn would add this structure to a
list which may be traversed later.
Hence, even though the functions referenced through this structure have
__init attribute, we cannot possibly add __initdata attribute to it.
To remove compilation warnings, the functions referenced thorugh this
structure are also defined without __init attribute.
It removes following two warnings.
WARNING: vmlinux.o(.data+0x4f58): Section mismatch in reference from the
variable s3c2416_irq_driver to the function .init.text:s3c2416_irq_add()
The variable s3c2416_irq_driver references the function __init s3c2416_irq_add()
WARNING: vmlinux.o(.data+0x7c50): Section mismatch in reference from the
variable s3c2443_irq_driver to the function .init.text:s3c2443_irq_add()
The variable s3c2443_irq_driver references the function __init s3c2443_irq_add()
Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
---
arch/arm/mach-s3c2416/irq.c | 4 ++--
arch/arm/mach-s3c2443/irq.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-s3c2416/irq.c b/arch/arm/mach-s3c2416/irq.c
index 28ad20d..53e8e57 100644
--- a/arch/arm/mach-s3c2416/irq.c
+++ b/arch/arm/mach-s3c2416/irq.c
@@ -194,7 +194,7 @@ static struct irq_chip s3c2416_irq_uart3 = {
/* IRQ initialisation code */
-static int __init s3c2416_add_sub(unsigned int base,
+static int s3c2416_add_sub(unsigned int base,
void (*demux)(unsigned int,
struct irq_desc *),
struct irq_chip *chip,
@@ -213,7 +213,7 @@ static int __init s3c2416_add_sub(unsigned int base,
return 0;
}
-static int __init s3c2416_irq_add(struct sys_device *sysdev)
+static int s3c2416_irq_add(struct sys_device *sysdev)
{
printk(KERN_INFO "S3C2416: IRQ Support\n");
diff --git a/arch/arm/mach-s3c2443/irq.c b/arch/arm/mach-s3c2443/irq.c
index 83ecb11..18585dd 100644
--- a/arch/arm/mach-s3c2443/irq.c
+++ b/arch/arm/mach-s3c2443/irq.c
@@ -222,7 +222,7 @@ static struct irq_chip s3c2443_irq_cam = {
/* IRQ initialisation code */
-static int __init s3c2443_add_sub(unsigned int base,
+static int s3c2443_add_sub(unsigned int base,
void (*demux)(unsigned int,
struct irq_desc *),
struct irq_chip *chip,
@@ -241,7 +241,7 @@ static int __init s3c2443_add_sub(unsigned int base,
return 0;
}
-static int __init s3c2443_irq_add(struct sys_device *sysdev)
+static int s3c2443_irq_add(struct sys_device *sysdev)
{
printk("S3C2443: IRQ Support\n");
--
1.7.4.1
^ permalink raw reply related
* [PATCH V2 1/2] ARM: S3C2410: Add __init attribute to usb_simtec_init()
From: Tushar Behera @ 2011-10-07 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317988513-20800-1-git-send-email-tushar.behera@linaro.org>
usb_simtec_init() references s3c_ohci_set_platdata() which is defined
with __init attribute. Hence to remove section mismatch warning, __init
attribute is added to usb_simtec_init().
It removes following two warnigs.
WARNING: vmlinux.o(.text+0x1460c): Section mismatch in reference from
the function usb_simtec_init() to the function
.init.text:s3c_ohci_set_platdata()
The function usb_simtec_init() references the function
__init s3c_ohci_set_platdata().
WARNING: vmlinux.o(.text+0x14650): Section mismatch in reference from
the function usb_simtec_init() to the (unknown reference)
.init.data:(unknown)
The function usb_simtec_init() references the (unknown reference)
__initdata (unknown).
Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
---
arch/arm/mach-s3c2410/usb-simtec.c | 2 +-
arch/arm/mach-s3c2410/usb-simtec.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-s3c2410/usb-simtec.c b/arch/arm/mach-s3c2410/usb-simtec.c
index 29bd3d9..3a1028c 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.c
+++ b/arch/arm/mach-s3c2410/usb-simtec.c
@@ -104,7 +104,7 @@ static struct s3c2410_hcd_info usb_simtec_info __initdata = {
};
-int usb_simtec_init(void)
+int __init usb_simtec_init(void)
{
int ret;
diff --git a/arch/arm/mach-s3c2410/usb-simtec.h b/arch/arm/mach-s3c2410/usb-simtec.h
index 03842ed..43cc88f 100644
--- a/arch/arm/mach-s3c2410/usb-simtec.h
+++ b/arch/arm/mach-s3c2410/usb-simtec.h
@@ -12,5 +12,5 @@
* published by the Free Software Foundation.
*/
-extern int usb_simtec_init(void);
+extern int __init usb_simtec_init(void);
--
1.7.4.1
^ permalink raw reply related
* [PATCH V2 0/2] ARM: S3C2410: Remove section mismatch warning
From: Tushar Behera @ 2011-10-07 11:55 UTC (permalink / raw)
To: linux-arm-kernel
While compiling with s3c2410_defconfig, we receive 4 section mismatch
warnings.
Patch 1 addresses a couple of warnings related to usb_simtec_init().
Patch 2 addresses mismatch warnings in a couple of mach-*/irq.c files.
Changes for V2:
* The original patch is splitted to address to different logical
solutions.
* __initdata attribute is removed from struct sysdev_driver
structures and __init attribute is removed from all referenced
function definitions.
The patches are rebased on v3.1-rc8. They are only build tested,
they are not boot tested on any hardware.
Tushar Behera (2):
ARM: S3C2410: Add __init attribute to usb_simtec_init()
ARM: S3C2410: irq: Remove __init attributes to fix compilation
warning
arch/arm/mach-s3c2410/usb-simtec.c | 2 +-
arch/arm/mach-s3c2410/usb-simtec.h | 2 +-
arch/arm/mach-s3c2416/irq.c | 4 ++--
arch/arm/mach-s3c2443/irq.c | 4 ++--
4 files changed, 6 insertions(+), 6 deletions(-)
--
1.7.4.1
^ permalink raw reply
* Long stalls during boot with -next
From: Mark Brown @ 2011-10-07 11:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110929125035.GA2085@sirena.org.uk>
On Thu, Sep 29, 2011 at 01:50:36PM +0100, Mark Brown wrote:
> Since Tuesday I've been experiencing stalls on boot with -next kernels.
> The boot appears to proceed normally but there appears to be a good ten
> second delay somewhere around the late_initcall() stage with no
> indication in the logs:
I identified the problem here, the behaviour of LL_DEBUG was changed to
make it select DEBUG_ICEDCC by default which is unfortunate if one
doesn't have an EmbeddedICE connected.
^ permalink raw reply
* [PATCH] ARM: tegra: fix compilation error due to mach/hardware.h removal
From: Sergei Shtylyov @ 2011-10-07 11:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317954199-25284-1-git-send-email-olof@lixom.net>
Hello.
On 07-10-2011 6:23, Olof Johansson wrote:
> From: Marc Dietrich <marvin24@gmx.de>
> This fixes a compilation error in cpu-tegra.c which was introduced
> in commit dc8d966bccde0b8b6c9e8c6e663c747030c17435 which removed
Please also specify that commit's summary in parens.
> the now obsolete mach/hardware.h from the mach-tegra subtree.
> Signed-off-by: Marc Dietrich <marvin24@gmx.de>
> Signed-off-by: Olof Johansson <olof@lixom.net>
WBR, Sergei
^ permalink raw reply
* [PATCH v2 5/5] iommu/exynos: Use bus_set_iommu instead of register_iommu
From: Joerg Roedel @ 2011-10-07 11:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAHQjnOPiAOA_RiHnF-aVEYnWcdkwNzVD1BTNua+-ztZrW_+6_A@mail.gmail.com>
On Sat, Oct 01, 2011 at 08:52:45AM +0900, KyongHo Cho wrote:
> On Fri, Sep 30, 2011 at 10:46 PM, Roedel, Joerg <Joerg.Roedel@amd.com> wrote:
> > On Fri, Sep 30, 2011 at 03:31:49AM -0400, Kukjin Kim wrote:
> >> From: KyongHo Cho <pullip.cho@samsung.com>
> >>
> >> This replaces register_iommu() with bus_set_iommu() according to the
> >> suggestion of Joerg Roedel.
> >
> > This should be part of patch 3 already when the bus_set_iommu() change
> > is merged. Otherwise it breaks bisectability too.
> >
> Ok.
> Should I include fault handling feature (patch 4) in the patch 3 also?
Yes, makes sense to include patch 4 too.
^ permalink raw reply
* [PATCH V2 0/2] Add a common macro for creating struct clk_lookup entries
From: Tushar Behera @ 2011-10-07 11:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317981211-15745-1-git-send-email-rajeshwari.s@samsung.com>
On Friday 07 October 2011 03:23 PM, Rajeshwari Shinde wrote:
> This patchset consolidates the macro that creates 'struct clk_lookup'
> entries by introducing a common macro 'CLKDEV_INIT' as suggested by
> Russell King. Few of the platforms have been modified to use this new macro.
>
> I have done the replacement by using python script. I have only build tested
> for below platforms with existing defconfigs.
>
> Changes since V1:
> - Removed "&" and "," from the CLKDEV_INIT macro.
> - Replaced the platform specific macros to use the new CLKDEV_INIT macro.
> - Rebased the patches on the latest master branch of Linux-Next.
>
> Rajeshwari Shinde (2):
> ARM: CLKDEV: Add Common Macro for clk_lookup
> ARM: Using CLKDEV_INIT for creating clk_lookup instance
>
> arch/arm/mach-davinci/board-dm646x-evm.c | 5 +-
> arch/arm/mach-davinci/clock.h | 7 --
> arch/arm/mach-davinci/da830.c | 101 ++++++++++----------
> arch/arm/mach-davinci/da850.c | 95 ++++++++++----------
> arch/arm/mach-davinci/dm355.c | 87 +++++++++---------
> arch/arm/mach-davinci/dm365.c | 113 +++++++++++-----------
> arch/arm/mach-davinci/dm644x.c | 77 ++++++++--------
> arch/arm/mach-davinci/dm646x.c | 81 ++++++++--------
> arch/arm/mach-davinci/tnetv107x.c | 133 +++++++++++++-------------
> arch/arm/mach-ep93xx/clock.c | 61 ++++++-------
> arch/arm/mach-imx/clock-imx1.c | 38 +++-----
> arch/arm/mach-imx/clock-imx21.c | 91 +++++++++----------
> arch/arm/mach-imx/clock-imx25.c | 79 +++++++---------
> arch/arm/mach-imx/clock-imx27.c | 111 ++++++++++------------
> arch/arm/mach-imx/clock-imx31.c | 103 ++++++++++-----------
> arch/arm/mach-imx/clock-imx35.c | 117 +++++++++++------------
> arch/arm/mach-lpc32xx/clock.c | 75 +++++++--------
> arch/arm/mach-mx5/clock-mx51-mx53.c | 149 ++++++++++++++----------------
> arch/arm/mach-mxs/clock-mx23.c | 39 +++-----
> arch/arm/mach-mxs/clock-mx28.c | 71 +++++++--------
> arch/arm/mach-tcc8k/clock.c | 107 ++++++++++-----------
> include/linux/clkdev.h | 7 ++
> 22 files changed, 838 insertions(+), 909 deletions(-)
>
Consider applying the macro to following files too.
CLKDEV_CON_DEV_ID
arch/arm/mach-at91/at91cap9.c
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/clock.h
CLKDEV_CON_ID
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/clock.h
arch/arm/mach-shmobile/clock-sh7367.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/clock-sh7377.c
arch/arm/mach-shmobile/clock-sh73a0.c
INIT_CLKREG
arch/arm/mach-mmp/clock.h
arch/arm/mach-mmp/mmp2.c
arch/arm/mach-mmp/pxa168.c
arch/arm/mach-mmp/pxa910.c
arch/arm/mach-pxa/clock.h
arch/arm/mach-pxa/eseries.c
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-pxa/pxa300.c
arch/arm/mach-pxa/pxa320.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/pxa95x.c
DEF_LOOKUP
DEF_LOOKUP_CON
arch/arm/mach-u300/clock.c
DEF_CLKLOOK
arch/arm/mach-nuc93x/clock.h
arch/arm/mach-nuc93x/cpu.c
arch/arm/mach-w90x900/clock.h
arch/arm/mach-w90x900/cpu.c
CLK
arch/arm/mach-ux500/clock.c
arch/arm/mach-ux500/clock.h
Array unfolded:
arch/arm/mach-bcmring/core.c
arch/arm/mach-integrator/core.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-nomadik/clock.c
arch/arm/mach-prima2/clock.c
arch/arm/mach-realview/core.c
arch/arm/mach-versatile/core.c
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mach-vexpress/v2m.c
arch/arm/mach-spear3xx/clock.c
arch/arm/mach-spear6xx/clock.c
arch/arm/mach-pnx4008/clock.c
arch/arm/mach-tegra/tegra2_clocks.c
--
Tushar Behera
^ permalink raw reply
* [PATCH 1/3 v3] ARM Realview PCIX map include file changes
From: Catalin Marinas @ 2011-10-07 11:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <F01D8B85CFF58440B2A13965FBA90CA47375AC17BD@GEORGE.Emea.Arm.com>
On 6 October 2011 15:50, Colin Tuckley <Colin.Tuckley@arm.com> wrote:
>> -----Original Message-----
>> From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
>> Subject: Re: [PATCH 1/3 v3] ARM Realview PCIX map include file changes
>
>> All the points in this email all go together.
>
> Ah, that wasn't clear from the original email - I was making the changes incrementally and testing as I went.
>
>> This is how it works:
>>
>> 1. The PCI IO window is _supposed_ to be 64K in size.
>
> Yes, that bit was obvious after a bit of thought. I suspect the original value was just a cut 'n paste error.
>
>> 2. "pcibios_min_io" sets the minimum offset into the PCI IO window
>> which
>> ? ?PCI IO BARs should be assigned. ?It is assumed that a PCI IO BAR
>> value
>> ? ?of 0 corresponds with the virtual base address of this window.
>> 3. inb() et.al. take the PCI IO offset and _not_ the physical address
>> nor the virtual address of the desired access.
>
> That seems sensible.
>
> However, after changing both __io() and pcibios_min_io as Arnd suggested the boot still hangs after " Uncompressing Linux... done, booting the kernel."
I haven't followed the patch series in detail but the __io() is also
used by __io_address() in the RealView code and the former is just
expected to do some type casting. By doing some arithmetic on the
pointer, the static mappings for various peripherals (GIC etc.) are
wrong.
So if you convert __io() as per Arnd's suggestion, make sure that
__io_address() is redefined, something like below:
#define __io_address(n) __typesafe_io(IO_ADDRESS(n))
Alternatively we could leave __io() as in the original kernel and
define RealView specific in*/out* macros.
--
Catalin
^ permalink raw reply
* [PATCH] arm: exynos4: build is failing due to missing SZ_4K definition
From: Kukjin Kim @ 2011-10-07 11:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317938595-7007-1-git-send-email-angus.ainslie@linaro.org>
Angus Ainslie wrote:
>
> linux-next build is failing using the exynos4_defconfig. <asm/sizes.h>
needs to be
> for the SZ_4K definition
>
> Signed-off-by: Angus Ainslie <angus.ainslie@linaro.org>
> ---
> arch/arm/mach-exynos4/include/mach/map.h | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-
> exynos4/include/mach/map.h
> index 918a979..02d68f1 100644
> --- a/arch/arm/mach-exynos4/include/mach/map.h
> +++ b/arch/arm/mach-exynos4/include/mach/map.h
> @@ -13,6 +13,7 @@
> #ifndef __ASM_ARCH_MAP_H
> #define __ASM_ARCH_MAP_H __FILE__
>
> +#include <asm/sizes.h>
> #include <plat/map-base.h>
>
> /*
> --
> 1.7.4.1
Hi Angus,
I'm not sure why to add <asm/sizes.h> in mach/map.h is required now because
there was no adding SZ_ here between v3.1-rc1 and current HEAD in my -next.
Maybe if it is required, here is not proper place?......
Since I can't fetch linux-next from
git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git, I need
some time. Let me check again with latest linux-next soon.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [GIT PULL] ux500-timers
From: Linus Walleij @ 2011-10-07 11:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdZDUeP6pJt7W2ntGGdUgeGGwEG9we-Jmc9bvP40Oy+JQg@mail.gmail.com>
On Mon, Oct 3, 2011 at 9:41 AM, Linus Walleij <linus.walleij@linaro.org> wrote:
> Hi Arnd,
>
> could you please pull the updated ux500 timer branch into the arm-soc
> tree?
>
> The following changes since commit d93dc5c4478c1fd5de85a3e8aece9aad7bbae044:
>
> ?Linux 3.1-rc7 (2011-09-21 16:58:15 -0700)
>
> are available in the git repository at:
> ? git://git.linaro.org/people/triad/linux-stericsson.git ux500-nomadik-timers
Ping on this, note fixup patch at the end of the series, as requested.
Linus Walleij
^ permalink raw reply
* [GIT PULL] Samsung devel-2 for v3.2
From: Kukjin Kim @ 2011-10-07 10:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111006171418.GA23532@opensource.wolfsonmicro.com>
Mark Brown wrote:
>
> On Thu, Oct 06, 2011 at 04:57:01PM +0100, Mark Brown wrote:
>
> > The bisect did end up pointing at the GPIO commits, the build errors
> > were causing issues. Not really made any further progress on this issue
> > today, some other things came up.
>
> So, I've been trying some other directions here. What I'm seeing by
> pulling devices out of my config is that if I enable the LCD power
> control then the board fails to boot. Also, the I2C controllers appear
> to be non-functional - I'm getting timeouts waiting for the bus to
> become free which halt the boot for long enough that it'd look like it
> had crashed if all the devices came up (there's a lot of I2C devices
> there).
>
> I've not had time to actually drill down below that level but it did
> occur to me that there may be a problem with the pinmux code?
Mark, OK.
I will check and fix in this weekend before upcoming merge window ;)
Then it will be sent to upstream via arm-soc.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH 5/7] ARM: EXYNOS4: Add support external GIC
From: Kukjin Kim @ 2011-10-07 10:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4E8ECA1B.5010005@arm.com>
Marc Zyngier wrote:
>
> On 06/10/11 09:18, Marc Zyngier wrote:
> > On 06/10/11 07:30, Kukjin Kim wrote:
> >> Marc Zyngier wrote:
> >>>
> >>> Hi Changhwan,
> >>>
> >> Hi Marc,
> >>
> >> (Cc'ed Will Deacon and Russell King)
> >>
> >>> On 20/06/11 08:34, Changhwan Youn wrote:
> >>>> For full support of power modes, this patch adds implementation
> >>>> external GIC on EXYNOS4.
> >>>>
> >>>> External GIC of Exynos4 cannot support register banking so
> >>>> several interrupt related code for CPU1 should be different
> >>>> from that of CPU0.
> >>>
> >>> I just realized that patch has made it to mainline... Unfortunately,
it
> >>> seems quite broken to me:
> >>>
> >>>> Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
> >>>> ---
> >>>> arch/arm/mach-exynos4/cpu.c | 10 ++++++++
> >>>> arch/arm/mach-exynos4/include/mach/entry-macro.S | 5 ++++
> >>>> arch/arm/mach-exynos4/include/mach/map.h | 1 +
> >>>> arch/arm/mach-exynos4/platsmp.c | 27
> >>> +++++++++++++++++++++-
> >>>> 4 files changed, 42 insertions(+), 1 deletions(-)
> >>>>
> >>>> diff --git a/arch/arm/mach-exynos4/cpu.c
b/arch/arm/mach-exynos4/cpu.c
> >>>> index fa33294..40a866c 100644
> >>>> --- a/arch/arm/mach-exynos4/cpu.c
> >>>> +++ b/arch/arm/mach-exynos4/cpu.c
> >>>> @@ -16,6 +16,7 @@
> >>>>
> >>>> #include <asm/proc-fns.h>
> >>>> #include <asm/hardware/cache-l2x0.h>
> >>>> +#include <asm/hardware/gic.h>
> >>>>
> >>>> #include <plat/cpu.h>
> >>>> #include <plat/clock.h>
> >>>> @@ -159,11 +160,20 @@ void __init exynos4_init_clocks(int xtal)
> >>>> exynos4_setup_clocks();
> >>>> }
> >>>>
> >>>> +static void exynos4_gic_irq_eoi(struct irq_data *d)
> >>>> +{
> >>>> + struct gic_chip_data *gic_data =
irq_data_get_irq_chip_data(d);
> >>>> +
> >>>> + gic_data->cpu_base = S5P_VA_GIC_CPU +
> >>>> + (EXYNOS4_GIC_BANK_OFFSET *
> >>> smp_processor_id());
> >>>
> >>> Here, you're overwriting a field that is shared among *all* the
> >>> interrupts in the system. What if an interrupt comes up on another
CPU?
> >>> If you look at the implementation of gic_eoi_irq(), you'll definitely
> >>> see the race.
> >>>
> >> Hmm...as you can see in git log, the EXYNOS4210 cannot support register
> >> banking in GIC so this is needed.
> >
> > I don't dispute the need. I claim that the implementation is wrong, and
> > will fail given the right timings.
> >
> >>>> +}
> >>>> +
> >>>> void __init exynos4_init_irq(void)
> >>>> {
> >>>> int irq;
> >>>>
> >>>> gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST,
S5P_VA_GIC_CPU);
> >>>> + gic_arch_extn.irq_eoi = exynos4_gic_irq_eoi;
> >>>
> >>> And here you're abusing the GIC extension feature.
> >>>
> >> I think gic_arch_extn.irq_eoi can be overwritten in each architecture
to
> >> support own specific extensions like in the EXYNOS4 case.
> >
> > Sure. My point is you are diverting the GIC extension from its purpose,
> > which is mostly to be able to control wake-up sources (as for example in
> > the Tegra case). Here, you use this hooks to work around the fact that
> > the GIC driver is written with banking in mind, which is quite a
> > different thing.
> >
> >>> I've also had a look at -next, and this has been extended further to
> >>> support 4412. The problem with that is without banking, you're
painfully
> >>> working around the GIC driver. At that stage, I wonder if you wouldn't
> >>> be better off with a separate driver instead of abusing the existing
> >> one...
> >>>
> >> Well, in this case, you mean separate driver is better to us even
though
> >> there is a gic driver in arch/arm/common? I don't think so because
separate
> >> driver will probably have many duplicated codes and if common gic
driver can
> >> support every silicons which have different version's gic it's better
to us
> >> and should do.
> >
> > If you really insist on using the GIC common code, then I'd suggest to
> > adapt it to your needs instead of working around the problem.
> > What about making cpu_base a percpu field inside struct gic_chip_data?
> > No hook abuse, and no race conditions. You could also do that for
> > dist_base, as it looks to be required for the 4412.
>
> So to make my suggestion completely clear, here's a patch I'm now
> carrying in my tree. It's only been test compiled on EXYNOS4, but works
> nicely on my 11MP. It turns both dist_base and cpu_base into per-cpu
> variables, removes these callbacks, removes your private copy of
> gic_cpu_init, and makes struct gic_chip_data private again.
>
> What do you think?
Let me check this soon. Actually I need to sort this out to test on my board
with my git.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH v3] omap: dmtimer: convert printk to pr_err
From: Víctor M. Jáquez L. @ 2011-10-07 10:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111007092243.GC27281@n2100.arm.linux.org.uk>
On Fri, Oct 07, 2011 at 10:22:43AM +0100, Russell King - ARM Linux wrote:
> On Fri, Oct 07, 2011 at 10:50:16AM +0200, V?ctor Manuel J?quez Leal wrote:
> > Convert a printk(KERN_ERR) message in the driver to pr_err().
> ...
> > @@ -111,7 +111,7 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
> > while (!(__raw_readl(timer->sys_stat) & 1)) {
> > c++;
> > if (c > 100000) {
> > - printk(KERN_ERR "Timer failed to reset\n");
> > + pr_err("Timer failed to reset\n");
>
> What is the reason behind this change? It looks like it's to use the
> latest and greatest function.
>
> If so, please don't make these changes - we have on many occasions been
> blamed for size of diffstat, churn, needless change, and this patch is
> exactly that.
>
> By all means fix printk's without KERN_ constants, possibly converting
> them to pr_*, but don't go around replacing printk(KERN_* with pr_*(
> without ensuring that there's a real benefit to the change.
>
Thanks a lot Russell, and sorry for the noise. I'm still learning how to
collaborate in the kernel.
vmjl
^ permalink raw reply
* [PATCH v3 1/2] ARM: EXYNOS4: Change System MMU device definition
From: Kukjin Kim @ 2011-10-07 10:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111007102754.GF21464@n2100.arm.linux.org.uk>
Russell King - ARM Linux wrote:
>
> On Fri, Oct 07, 2011 at 06:56:21PM +0900, Kukjin Kim wrote:
> > +#define SYSMMU_RESOURCE(ipname, base, irq) \
> > +static struct resource sysmmu_resource_##ipname[] =\
> > +{\
> > + {\
> > + .start = EXYNOS4_PA_SYSMMU_##base,\
> > + .end = EXYNOS4_PA_SYSMMU_##base + SZ_4K - 1,\
> > + .flags = IORESOURCE_MEM,\
> > + }, {\
> > + .start = IRQ_SYSMMU_##irq##_0,\
> > + .end = IRQ_SYSMMU_##irq##_0,\
> > + .flags = IORESOURCE_IRQ,\
> > + },\
> > }
>
> #define SYSMMU_RESOURCE(ipname, base, irq) \
> static struct resource sysmmu_resource_##ipname[] = \
> { \
> DEFINE_RES_MEM(EXYNOS4_PA_SYSMMU_##base, SZ_4K), \
> DEFINE_RES_IRQ(IRQ_SYSMMU_##irq##_0), \
> }
Oops, I missed that.
OK, let him change it.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH] sam9g20ek/9m10g45ek/stam9g20: unbreak build after 'use -EINVAL for invalid gpio'
From: Nicolas Ferre @ 2011-10-07 10:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317915587-27474-1-git-send-email-jacmet@sunsite.dk>
From: Peter Korsgaard <jacmet@sunsite.dk>
Commit 36706ab70b26 (ARM: at91/boards: use -EINVAL for invalid gpio)
broke the build as it used ';' rather than ',' in structure initializers.
Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
[nicolas.ferre at atmel.com: change also -1 to -EINVAL for coherency]
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
---
arch/arm/mach-at91/board-sam9g20ek.c | 4 ++--
arch/arm/mach-at91/board-sam9m10g45ek.c | 2 +-
arch/arm/mach-at91/board-stamp9g20.c | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index b3ec5e6..52d122d 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -217,7 +217,7 @@ static struct mci_platform_data __initdata ek_mmc_data = {
.slot[1] = {
.bus_width = 4,
.detect_pin = AT91_PIN_PC9,
- .wp_pin = -1;
+ .wp_pin = -EINVAL,
},
};
@@ -237,7 +237,7 @@ static void __init ek_add_device_mmc(void)
if (ek_have_2mmc()) {
ek_mmc_data.slot[0].bus_width = 4;
ek_mmc_data.slot[0].detect_pin = AT91_PIN_PC2;
- ek_mmc_data.slot[0].wp_pin = -1;
+ ek_mmc_data.slot[0].wp_pin = -EINVAL;
}
at91_add_device_mci(0, &ek_mmc_data);
#else
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index 3c36f9f..8e7d8ad 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -100,7 +100,7 @@ static struct mci_platform_data __initdata mci0_data = {
.slot[0] = {
.bus_width = 4,
.detect_pin = AT91_PIN_PD10,
- .wp_pin = -1;
+ .wp_pin = -EINVAL,
},
};
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index 3c0cc86..0bd51ee 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -123,8 +123,8 @@ static void __init add_device_nand(void)
static struct mci_platform_data __initdata mmc_data = {
.slot[0] = {
.bus_width = 4,
- .detect_pin = -1;
- .wp_pin = -1;
+ .detect_pin = -EINVAL,
+ .wp_pin = -EINVAL,
},
};
#else
--
1.7.3
^ permalink raw reply related
* [PATCH v3 1/2] ARM: EXYNOS4: Change System MMU device definition
From: Russell King - ARM Linux @ 2011-10-07 10:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <01e001cc84d7$5e0b84b0$1a228e10$%kim@samsung.com>
On Fri, Oct 07, 2011 at 06:56:21PM +0900, Kukjin Kim wrote:
> +#define SYSMMU_RESOURCE(ipname, base, irq) \
> +static struct resource sysmmu_resource_##ipname[] =\
> +{\
> + {\
> + .start = EXYNOS4_PA_SYSMMU_##base,\
> + .end = EXYNOS4_PA_SYSMMU_##base + SZ_4K - 1,\
> + .flags = IORESOURCE_MEM,\
> + }, {\
> + .start = IRQ_SYSMMU_##irq##_0,\
> + .end = IRQ_SYSMMU_##irq##_0,\
> + .flags = IORESOURCE_IRQ,\
> + },\
> }
#define SYSMMU_RESOURCE(ipname, base, irq) \
static struct resource sysmmu_resource_##ipname[] = \
{ \
DEFINE_RES_MEM(EXYNOS4_PA_SYSMMU_##base, SZ_4K), \
DEFINE_RES_IRQ(IRQ_SYSMMU_##irq##_0), \
}
^ permalink raw reply
* [PATCH 13/26] ARM: pxa: use correct __iomem annotations
From: Arnd Bergmann @ 2011-10-07 10:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAMPhdO_CGvoc8GZQS3TWpv0gqOXhmHyEbamcQr28K5iLgOBnuw@mail.gmail.com>
On Friday 07 October 2011, Eric Miao wrote:
> > @@ -18,11 +24,11 @@
> > * peripherals on APB, let's count it into the ABP mapping area.
> > */
> > #define APB_PHYS_BASE 0xd4000000
> > -#define APB_VIRT_BASE 0xfe000000
> > +#define APB_VIRT_BASE IOMEM(0xfe000000)
>
> To be honest, I'd really like to keep the *_VIRT_BASE definitions to be
> type independent.
>
> And have the actual register definitions to be casted to void __iomem *
> when being defined, e.g.
>
> #define APBC_REG(x) IOMEM(APBC_VIRT_BASE + (x))
>
> #define APBC_UART1 APBC_REG(0x000)
>
> Arnd, do we have some standard guidelines on this for all SoCs
> to follow? As I know, it's currently still being a mess.
We don't have any formal guidelines yet, but I'd really love to get
rid of all the arbitrary type casts to make use of the built-in
type checking of the compiler and sparse. A virtual base address
for registers is conventionally an __iomem pointer, so defining it
as something else is completely bogus. I have started making patches
for a number of platforms for this.
Ideally we should have very little code directly using, but the fact
is that they are there and we won't remove them all anytime soon, so
we should at least use the correct types here.
Another issue that goes together with this is that right now our
readl/writel macros accept any input type (pointer, __iomem pointer,
unsigned long, unsigned int), and I have a patch to make that stricter
but that requires fixing up all the places where we do a
readl(APBC_VIRT_BASE + x) that Russell mentioned.
The only place where this requires adding extra type casts right now is
the iotable setup, which I hope we can also fix eventually by splitting
the static I/O mapping setup from other static mappings (MT_MEMORY,
MT_MEMORY_NONCACHED, ...).
Arnd
^ permalink raw reply
* [PATCH v3 RE-SEND 2/2] iommu/exynos: Add iommu driver for Exynos Platforms
From: Kukjin Kim @ 2011-10-07 10:09 UTC (permalink / raw)
To: linux-arm-kernel
From: KyongHo Cho <pullip.cho@samsung.com>
This is the System MMU driver and IOMMU API implementation for
Exynos SOC platforms. Exynos platforms has more than 10 System
MMUs dedicated for each multimedia accellerators.
The System MMU driver is already in arc/arm/plat-s5p but it is
moved to drivers/iommu due to Ohad Ben-Cohen gathered IOMMU drivers
there
This patch also includes fault handling feature in IOMMU driver
suggested by Ohad.
Users of IOMMU API can register its own fault handler with
iommu_set_fault_handler() and the handler is called by IRQ handler
of System MMU.
If no user installs fault handler, IOMMU driver prints debugging
message and generates kernel oops.
This IOMMU driver calls bus_set_iommu() instead of register_iommu()
since Joerg suggested that installing iommu_ops in bus_type.
Cc: Joerg Roedel <joerg.roedel@amd.com>
Cc: Ohad Ben-Cohen <ohad@wizery.com>
Signed-off-by: KyongHo Cho <pullip.cho@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
NOTE: Since previous sending has problem, I'm re-sending.
Sorry, please kindly ignore previous one.
arch/arm/plat-s5p/Kconfig | 14 -
arch/arm/plat-s5p/Makefile | 1 -
arch/arm/plat-s5p/sysmmu.c | 312 ---------
arch/arm/plat-samsung/include/plat/sysmmu.h | 95 ---
drivers/iommu/Kconfig | 14 +
drivers/iommu/Makefile | 1 +
drivers/iommu/exynos_iommu.c | 963 +++++++++++++++++++++++++++
7 files changed, 978 insertions(+), 422 deletions(-)
delete mode 100644 arch/arm/plat-s5p/sysmmu.c
delete mode 100644 arch/arm/plat-samsung/include/plat/sysmmu.h
create mode 100644 drivers/iommu/exynos_iommu.c
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 7b9dada..fa374cc 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -46,20 +46,6 @@ config S5P_PM
Common code for power management support on S5P and newer SoCs
Note: Do not select this for S5P6440 and S5P6450.
-comment "System MMU"
-
-config S5P_SYSTEM_MMU
- bool "S5P SYSTEM MMU"
- depends on ARCH_EXYNOS4
- help
- Say Y here if you want to enable System MMU
-
-config S5P_SLEEP
- bool
- help
- Internal config node to apply common S5P sleep management code.
- Can be selected by S5P and newer SoCs with similar sleep procedure.
-
config S5P_DEV_FIMC0
bool
help
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index 06401dc..7a9c4fc 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -19,7 +19,6 @@ 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_S5P_PM) += pm.o irq-pm.o
obj-$(CONFIG_S5P_SLEEP) += sleep.o
obj-$(CONFIG_S5P_HRT) += s5p-time.o
diff --git a/arch/arm/plat-s5p/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c
deleted file mode 100644
index e1cbc72..0000000
--- a/arch/arm/plat-s5p/sysmmu.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/* 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 <asm/pgtable.h>
-
-#include <mach/map.h>
-#include <mach/regs-sysmmu.h>
-#include <plat/sysmmu.h>
-
-#define CTRL_ENABLE 0x5
-#define CTRL_BLOCK 0x7
-#define CTRL_DISABLE 0x0
-
-static struct device *dev;
-
-static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = {
- S5P_PAGE_FAULT_ADDR,
- S5P_AR_FAULT_ADDR,
- S5P_AW_FAULT_ADDR,
- S5P_DEFAULT_SLAVE_ADDR,
- S5P_AR_FAULT_ADDR,
- S5P_AR_FAULT_ADDR,
- S5P_AW_FAULT_ADDR,
- S5P_AW_FAULT_ADDR
-};
-
-static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
- "PAGE FAULT",
- "AR MULTI-HIT FAULT",
- "AW MULTI-HIT FAULT",
- "BUS ERROR",
- "AR SECURITY PROTECTION FAULT",
- "AR ACCESS PROTECTION FAULT",
- "AW SECURITY PROTECTION FAULT",
- "AW ACCESS PROTECTION FAULT"
-};
-
-static int (*fault_handlers[S5P_SYSMMU_TOTAL_IPNUM])(
- enum S5P_SYSMMU_INTERRUPT_TYPE itype,
- unsigned long pgtable_base,
- unsigned long fault_addr);
-
-/*
- * If adjacent 2 bits are true, the system MMU is enabled.
- * The system MMU is disabled, otherwise.
- */
-static unsigned long sysmmu_states;
-
-static inline void set_sysmmu_active(sysmmu_ips ips)
-{
- sysmmu_states |= 3 << (ips * 2);
-}
-
-static inline void set_sysmmu_inactive(sysmmu_ips ips)
-{
- sysmmu_states &= ~(3 << (ips * 2));
-}
-
-static inline int is_sysmmu_active(sysmmu_ips ips)
-{
- return sysmmu_states & (3 << (ips * 2));
-}
-
-static void __iomem *sysmmusfrs[S5P_SYSMMU_TOTAL_IPNUM];
-
-static inline void sysmmu_block(sysmmu_ips ips)
-{
- __raw_writel(CTRL_BLOCK, sysmmusfrs[ips] + S5P_MMU_CTRL);
- dev_dbg(dev, "%s is blocked.\n", sysmmu_ips_name[ips]);
-}
-
-static inline void sysmmu_unblock(sysmmu_ips ips)
-{
- __raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
- dev_dbg(dev, "%s is unblocked.\n", sysmmu_ips_name[ips]);
-}
-
-static inline void __sysmmu_tlb_invalidate(sysmmu_ips ips)
-{
- __raw_writel(0x1, sysmmusfrs[ips] + S5P_MMU_FLUSH);
- dev_dbg(dev, "TLB of %s is invalidated.\n", sysmmu_ips_name[ips]);
-}
-
-static inline void __sysmmu_set_ptbase(sysmmu_ips ips, unsigned long pgd)
-{
- if (unlikely(pgd == 0)) {
- pgd = (unsigned long)ZERO_PAGE(0);
- __raw_writel(0x20, sysmmusfrs[ips] + S5P_MMU_CFG); /* 4KB LV1 */
- } else {
- __raw_writel(0x0, sysmmusfrs[ips] + S5P_MMU_CFG); /* 16KB LV1 */
- }
-
- __raw_writel(pgd, sysmmusfrs[ips] + S5P_PT_BASE_ADDR);
-
- dev_dbg(dev, "Page table base of %s is initialized with 0x%08lX.\n",
- sysmmu_ips_name[ips], pgd);
- __sysmmu_tlb_invalidate(ips);
-}
-
-void sysmmu_set_fault_handler(sysmmu_ips ips,
- int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
- unsigned long pgtable_base,
- unsigned long fault_addr))
-{
- BUG_ON(!((ips >= SYSMMU_MDMA) && (ips < S5P_SYSMMU_TOTAL_IPNUM)));
- fault_handlers[ips] = handler;
-}
-
-static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
-{
- /* SYSMMU is in blocked when interrupt occurred. */
- unsigned long base = 0;
- sysmmu_ips ips = (sysmmu_ips)dev_id;
- enum S5P_SYSMMU_INTERRUPT_TYPE itype;
-
- itype = (enum S5P_SYSMMU_INTERRUPT_TYPE)
- __ffs(__raw_readl(sysmmusfrs[ips] + S5P_INT_STATUS));
-
- BUG_ON(!((itype >= 0) && (itype < 8)));
-
- dev_alert(dev, "%s occurred by %s.\n", sysmmu_fault_name[itype],
- sysmmu_ips_name[ips]);
-
- if (fault_handlers[ips]) {
- unsigned long addr;
-
- base = __raw_readl(sysmmusfrs[ips] + S5P_PT_BASE_ADDR);
- addr = __raw_readl(sysmmusfrs[ips] + fault_reg_offset[itype]);
-
- if (fault_handlers[ips](itype, base, addr)) {
- __raw_writel(1 << itype,
- sysmmusfrs[ips] + S5P_INT_CLEAR);
- dev_notice(dev, "%s from %s is resolved."
- " Retrying translation.\n",
- sysmmu_fault_name[itype], sysmmu_ips_name[ips]);
- } else {
- base = 0;
- }
- }
-
- sysmmu_unblock(ips);
-
- if (!base)
- dev_notice(dev, "%s from %s is not handled.\n",
- sysmmu_fault_name[itype], sysmmu_ips_name[ips]);
-
- return IRQ_HANDLED;
-}
-
-void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
-{
- if (is_sysmmu_active(ips)) {
- sysmmu_block(ips);
- __sysmmu_set_ptbase(ips, pgd);
- sysmmu_unblock(ips);
- } else {
- dev_dbg(dev, "%s is disabled. "
- "Skipping initializing page table base.\n",
- sysmmu_ips_name[ips]);
- }
-}
-
-void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd)
-{
- if (!is_sysmmu_active(ips)) {
- sysmmu_clk_enable(ips);
-
- __sysmmu_set_ptbase(ips, pgd);
-
- __raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
-
- set_sysmmu_active(ips);
- dev_dbg(dev, "%s is enabled.\n", sysmmu_ips_name[ips]);
- } else {
- dev_dbg(dev, "%s is already enabled.\n", sysmmu_ips_name[ips]);
- }
-}
-
-void s5p_sysmmu_disable(sysmmu_ips ips)
-{
- if (is_sysmmu_active(ips)) {
- __raw_writel(CTRL_DISABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
- set_sysmmu_inactive(ips);
- sysmmu_clk_disable(ips);
- dev_dbg(dev, "%s is disabled.\n", sysmmu_ips_name[ips]);
- } else {
- dev_dbg(dev, "%s is already disabled.\n", sysmmu_ips_name[ips]);
- }
-}
-
-void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips)
-{
- if (is_sysmmu_active(ips)) {
- sysmmu_block(ips);
- __sysmmu_tlb_invalidate(ips);
- sysmmu_unblock(ips);
- } else {
- dev_dbg(dev, "%s is disabled. "
- "Skipping invalidating TLB.\n", sysmmu_ips_name[ips]);
- }
-}
-
-static int s5p_sysmmu_probe(struct platform_device *pdev)
-{
- int i, ret;
- struct resource *res, *mem;
-
- dev = &pdev->dev;
-
- for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
- int irq;
-
- sysmmu_clk_init(dev, i);
- sysmmu_clk_disable(i);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
- if (!res) {
- dev_err(dev, "Failed to get the resource of %s.\n",
- sysmmu_ips_name[i]);
- ret = -ENODEV;
- goto err_res;
- }
-
- mem = request_mem_region(res->start, resource_size(res),
- pdev->name);
- if (!mem) {
- dev_err(dev, "Failed to request the memory region of %s.\n",
- sysmmu_ips_name[i]);
- ret = -EBUSY;
- goto err_res;
- }
-
- sysmmusfrs[i] = ioremap(res->start, resource_size(res));
- if (!sysmmusfrs[i]) {
- dev_err(dev, "Failed to ioremap() for %s.\n",
- sysmmu_ips_name[i]);
- ret = -ENXIO;
- goto err_reg;
- }
-
- irq = platform_get_irq(pdev, i);
- if (irq <= 0) {
- dev_err(dev, "Failed to get the IRQ resource of %s.\n",
- sysmmu_ips_name[i]);
- ret = -ENOENT;
- goto err_map;
- }
-
- if (request_irq(irq, s5p_sysmmu_irq, IRQF_DISABLED,
- pdev->name, (void *)i)) {
- dev_err(dev, "Failed to request IRQ for %s.\n",
- sysmmu_ips_name[i]);
- ret = -ENOENT;
- goto err_map;
- }
- }
-
- return 0;
-
-err_map:
- iounmap(sysmmusfrs[i]);
-err_reg:
- release_mem_region(mem->start, resource_size(mem));
-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);
diff --git a/arch/arm/plat-samsung/include/plat/sysmmu.h b/arch/arm/plat-samsung/include/plat/sysmmu.h
deleted file mode 100644
index 5fe8ee0..0000000
--- a/arch/arm/plat-samsung/include/plat/sysmmu.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/sysmmu.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Samsung System MMU driver for S5P platform
- *
- * 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_SAMSUNG_SYSMMU_H
-#define __PLAT_SAMSUNG_SYSMMU_H __FILE__
-
-enum S5P_SYSMMU_INTERRUPT_TYPE {
- SYSMMU_PAGEFAULT,
- SYSMMU_AR_MULTIHIT,
- SYSMMU_AW_MULTIHIT,
- SYSMMU_BUSERROR,
- SYSMMU_AR_SECURITY,
- SYSMMU_AR_ACCESS,
- SYSMMU_AW_SECURITY,
- SYSMMU_AW_PROTECTION, /* 7 */
- SYSMMU_FAULTS_NUM
-};
-
-#ifdef CONFIG_S5P_SYSTEM_MMU
-
-#include <mach/sysmmu.h>
-
-/**
- * s5p_sysmmu_enable() - enable system mmu of ip
- * @ips: The ip connected system mmu.
- * #pgd: Base physical address of the 1st level page table
- *
- * This function enable system mmu to transfer address
- * from virtual address to physical address
- */
-void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd);
-
-/**
- * s5p_sysmmu_disable() - disable sysmmu mmu of ip
- * @ips: The ip connected system mmu.
- *
- * This function disable system mmu to transfer address
- * from virtual address to physical address
- */
-void s5p_sysmmu_disable(sysmmu_ips ips);
-
-/**
- * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table
- * @ips: The ip connected system mmu.
- * @pgd: The page table base address.
- *
- * This function set page table base address
- * When system mmu transfer address from virtaul address to physical address,
- * system mmu refer address information from page table
- */
-void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd);
-
-/**
- * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu
- * @ips: The ip connected system mmu.
- *
- * This function flush all TLB entry in system mmu
- */
-void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
-
-/** s5p_sysmmu_set_fault_handler() - Fault handler for System MMUs
- * @itype: type of fault.
- * @pgtable_base: the physical address of page table base. This is 0 if @ips is
- * SYSMMU_BUSERROR.
- * @fault_addr: the device (virtual) address that the System MMU tried to
- * translated. This is 0 if @ips is SYSMMU_BUSERROR.
- * Called when interrupt occurred by the System MMUs
- * The device drivers of peripheral devices that has a System MMU can implement
- * a fault handler to resolve address translation fault by System MMU.
- * The meanings of return value and parameters are described below.
-
- * return value: non-zero if the fault is correctly resolved.
- * zero if the fault is not handled.
- */
-void s5p_sysmmu_set_fault_handler(sysmmu_ips ips,
- int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
- unsigned long pgtable_base,
- unsigned long fault_addr));
-#else
-#define s5p_sysmmu_enable(ips, pgd) do { } while (0)
-#define s5p_sysmmu_disable(ips) do { } while (0)
-#define s5p_sysmmu_set_tablebase_pgd(ips, pgd) do { } while (0)
-#define s5p_sysmmu_tlb_invalidate(ips) do { } while (0)
-#define s5p_sysmmu_set_fault_handler(ips, handler) do { } while (0)
-#endif
-#endif /* __ASM_PLAT_SYSMMU_H */
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index b57b3fa..1c754cd 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -107,4 +107,18 @@ config INTR_REMAP
To use x2apic mode in the CPU's which support x2APIC enhancements or
to support platforms with CPU's having > 8 bit APIC ID, say Y.
+# EXYNOS IOMMU support
+config EXYNOS_IOMMU
+ bool "Exynos IOMMU Support"
+ depends on ARCH_EXYNOS4
+ select IOMMU_API
+ select EXYNOS4_DEV_SYSMMU
+ help
+ Support for the IOMMUs (System MMUs) Samsung Exynos application
+ processor family. This enables H/W multimedia accellerators to view
+ non-linear physical memory chunks as a linear memory in their virtual
+ address spaces.
+
+ If unsure, say N here.
+
endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 4d4d77d..1eb924f 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o
obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o
+obj-$(CONFIG_EXYNOS_IOMMU) += exynos_iommu.o
diff --git a/drivers/iommu/exynos_iommu.c b/drivers/iommu/exynos_iommu.c
new file mode 100644
index 0000000..b01345d
--- /dev/null
+++ b/drivers/iommu/exynos_iommu.c
@@ -0,0 +1,963 @@
+/* linux/drivers/iommu/exynos_iommu.c
+ *
+ * Copyright (c) 2010-2011 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/mm.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/iommu.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/atomic.h>
+#include <linux/spinlock.h>
+
+#include <asm/cacheflush.h>
+#include <asm/pgtable.h>
+
+#include <mach/map.h>
+#include <mach/regs-sysmmu.h>
+#include <mach/sysmmu.h>
+
+#define CTRL_ENABLE 0x5
+#define CTRL_BLOCK 0x7
+#define CTRL_DISABLE 0x0
+
+enum S5P_SYSMMU_INTERRUPT_TYPE {
+ SYSMMU_PAGEFAULT,
+ SYSMMU_AR_MULTIHIT,
+ SYSMMU_AW_MULTIHIT,
+ SYSMMU_BUSERROR,
+ SYSMMU_AR_SECURITY,
+ SYSMMU_AR_ACCESS,
+ SYSMMU_AW_SECURITY,
+ SYSMMU_AW_PROTECTION, /* 7 */
+ SYSMMU_FAULT_UNKNOWN,
+ SYSMMU_FAULTS_NUM
+};
+
+static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = {
+ S5P_PAGE_FAULT_ADDR,
+ S5P_AR_FAULT_ADDR,
+ S5P_AW_FAULT_ADDR,
+ S5P_DEFAULT_SLAVE_ADDR,
+ S5P_AR_FAULT_ADDR,
+ S5P_AR_FAULT_ADDR,
+ S5P_AW_FAULT_ADDR,
+ S5P_AW_FAULT_ADDR
+};
+
+static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM + 1] = {
+ "PAGE FAULT",
+ "AR MULTI-HIT FAULT",
+ "AW MULTI-HIT FAULT",
+ "BUS ERROR",
+ "AR SECURITY PROTECTION FAULT",
+ "AR ACCESS PROTECTION FAULT",
+ "AW SECURITY PROTECTION FAULT",
+ "AW ACCESS PROTECTION FAULT",
+ "UNKOWN FAULT"
+};
+
+struct exynos_iommu_domain {
+ struct device *dev;
+ unsigned long *pgtable;
+ spinlock_t lock;
+ spinlock_t pgtablelock;
+};
+
+typedef int (*s5p_sysmmu_fault_handler_t)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
+ unsigned long pgtable_base,
+ unsigned long fault_addr);
+struct sysmmu_drvdata {
+ struct list_head node;
+ struct device *dev;
+ struct device *owner;
+ void __iomem *sfrbase;
+ struct clk *clk;
+ int activations;
+ rwlock_t lock;
+ struct iommu_domain *domain;
+ s5p_sysmmu_fault_handler_t fault_handler;
+};
+
+
+/* List of sysmmu_drvdata */
+static LIST_HEAD(sysmmu_list);
+
+static struct sysmmu_drvdata *get_sysmmu_data(struct device *owner,
+ struct sysmmu_drvdata *start)
+{
+ if (start) {
+ list_for_each_entry_continue(start, &sysmmu_list, node)
+ if (start->owner == owner)
+ return start;
+ } else {
+ list_for_each_entry(start, &sysmmu_list, node)
+ if (start->owner == owner)
+ return start;
+ }
+
+ return NULL;
+}
+
+static struct sysmmu_drvdata *get_sysmmu_data_rollback(struct device *owner,
+ struct sysmmu_drvdata *start)
+{
+ if (start) {
+ list_for_each_entry_continue_reverse(start, &sysmmu_list, node)
+ if (start->owner == owner)
+ return start;
+ }
+
+ return NULL;
+}
+
+static bool set_sysmmu_active(struct sysmmu_drvdata *data)
+{
+ /* return true if the System MMU was not active previously
+ and it needs to be initialized */
+ data->activations++;
+ return data->activations == 1;
+}
+
+static bool set_sysmmu_inactive(struct sysmmu_drvdata *data)
+{
+ /* return true if the System MMU is needed to be disabled */
+ data->activations--;
+
+ WARN_ON(data->activations < 0);
+
+ return data->activations == 0;
+}
+
+static bool is_sysmmu_active(struct sysmmu_drvdata *data)
+{
+ return data->activations != 0;
+}
+
+static void sysmmu_block(void __iomem *sfrbase)
+{
+ __raw_writel(CTRL_BLOCK, sfrbase + S5P_MMU_CTRL);
+}
+
+static void sysmmu_unblock(void __iomem *sfrbase)
+{
+ __raw_writel(CTRL_ENABLE, sfrbase + S5P_MMU_CTRL);
+}
+
+static void __sysmmu_tlb_invalidate(void __iomem *sfrbase)
+{
+ __raw_writel(0x1, sfrbase + S5P_MMU_FLUSH);
+}
+
+static void __sysmmu_set_ptbase(void __iomem *sfrbase,
+ unsigned long pgd)
+{
+ if (unlikely(pgd == 0)) {
+ pgd = (unsigned long)ZERO_PAGE(0);
+ __raw_writel(0x20, sfrbase + S5P_MMU_CFG); /* 4KB LV1 */
+ } else {
+ __raw_writel(0x0, sfrbase + S5P_MMU_CFG); /* 16KB LV1 */
+ }
+
+ __raw_writel(pgd, sfrbase + S5P_PT_BASE_ADDR);
+
+ __sysmmu_tlb_invalidate(sfrbase);
+}
+
+static void __set_fault_handler(struct sysmmu_drvdata *data,
+ s5p_sysmmu_fault_handler_t handler)
+{
+ unsigned long flags;
+
+ write_lock_irqsave(&data->lock, flags);
+ data->fault_handler = handler;
+ write_unlock_irqrestore(&data->lock, flags);
+}
+
+void s5p_sysmmu_set_fault_handler(struct device *owner,
+ s5p_sysmmu_fault_handler_t handler)
+{
+ struct sysmmu_drvdata *data = NULL;
+
+ while ((data = get_sysmmu_data(owner, data)))
+ __set_fault_handler(data, handler);
+}
+
+static int default_fault_handler(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
+ unsigned long pgtable_base, unsigned long fault_addr)
+{
+ if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT))
+ itype = SYSMMU_FAULT_UNKNOWN;
+
+ pr_err("%s occured@0x%08lx(Page table base: 0x%08lx)\n",
+ sysmmu_fault_name[itype], fault_addr, pgtable_base);
+ pr_err("\t\tGenerating Kernel OOPS... because it is unrecoverable.\n");
+
+ BUG();
+
+ return 0;
+}
+
+static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id)
+{
+ /* SYSMMU is in blocked when interrupt occurred. */
+ struct sysmmu_drvdata *data = dev_id;
+ enum S5P_SYSMMU_INTERRUPT_TYPE itype;
+ unsigned long addr;
+ int ret = -ENOSYS;
+
+ read_lock(&data->lock);
+
+ WARN_ON(!is_sysmmu_active(data));
+
+ itype = (enum S5P_SYSMMU_INTERRUPT_TYPE)
+ __ffs(__raw_readl(data->sfrbase + S5P_INT_STATUS));
+
+ if (WARN_ON((itype < 0) && (itype >= 8)))
+ itype = SYSMMU_FAULT_UNKNOWN;
+
+ addr = __raw_readl(data->sfrbase + fault_reg_offset[itype]);
+
+ if (data->domain)
+ ret = report_iommu_fault(data->domain, data->owner, addr,
+ itype);
+
+ if ((ret == -ENOSYS) && (data->fault_handler)) {
+ unsigned long base;
+ base = __raw_readl(data->sfrbase + S5P_PT_BASE_ADDR);
+
+ ret = data->fault_handler(itype, base, addr);
+ }
+
+ if (!ret)
+ __raw_writel(1 << itype, data->sfrbase + S5P_INT_CLEAR);
+ else
+ dev_dbg(data->dev, "%s is not handled.\n",
+ sysmmu_fault_name[itype]);
+
+ sysmmu_unblock(data->sfrbase);
+
+ read_unlock(&data->lock);
+
+ return IRQ_HANDLED;
+}
+
+void exynos_sysmmu_set_tablebase_pgd(struct device *owner, unsigned long pgd)
+{
+ struct sysmmu_drvdata *data = NULL;
+
+ while ((data = get_sysmmu_data(owner, data))) {
+ unsigned long flags;
+
+ read_lock_irqsave(&data->lock, flags);
+
+ if (is_sysmmu_active(data)) {
+ sysmmu_block(data->sfrbase);
+ __sysmmu_set_ptbase(data->sfrbase, pgd);
+ sysmmu_unblock(data->sfrbase);
+ dev_dbg(data->dev,
+ "New page table base is 0x%08lx\n", pgd);
+ } else {
+ dev_dbg(data->dev,
+ "Disabled: Skipping setting page table base.\n");
+ }
+
+ read_unlock_irqrestore(&data->lock, flags);
+ }
+}
+
+static int __exynos_sysmmu_enable(struct device *owner, unsigned long pgtable,
+ struct iommu_domain *domain)
+{
+ int ret = 0;
+ unsigned long flags;
+ struct sysmmu_drvdata *data = NULL;
+
+ /* There are some devices that control more System MMUs than one such
+ * as MFC.
+ */
+ while ((data = get_sysmmu_data(owner, data))) {
+ ret = pm_runtime_get_sync(data->dev);
+ if (ret) {
+ set_sysmmu_active(data); /* for rollback */
+ break;
+ }
+
+ write_lock_irqsave(&data->lock, flags);
+
+ if (set_sysmmu_active(data)) {
+ __sysmmu_set_ptbase(data->sfrbase, pgtable);
+
+ __raw_writel(CTRL_ENABLE, data->sfrbase + S5P_MMU_CTRL);
+
+ data->domain = domain;
+
+ dev_dbg(data->dev, "Enabled.\n");
+ } else {
+ dev_dbg(data->dev, "Already enabled.\n");
+ }
+
+ write_unlock_irqrestore(&data->lock, flags);
+ }
+
+ if (ret) {
+ do {
+ write_lock_irqsave(&data->lock, flags);
+ set_sysmmu_inactive(data);
+ data->domain = NULL;
+ /* deinitialization is not required actually. */
+ write_unlock_irqrestore(&data->lock, flags);
+
+ pm_runtime_put_sync(data->dev);
+
+ dev_dbg(data->dev, "Failed to enable.\n");
+ } while ((data = get_sysmmu_data_rollback(owner, data)));
+ }
+
+ return ret;
+}
+
+static int exynos_iommu_enable(struct iommu_domain *domain)
+{
+ struct exynos_iommu_domain *priv = domain->priv;
+
+ if (!priv || !priv->dev)
+ return -EINVAL;
+
+ return __exynos_sysmmu_enable(priv->dev, __pa(priv->pgtable), domain);
+}
+
+int exynos_sysmmu_enable(struct device *owner, unsigned long pgtable)
+{
+ return __exynos_sysmmu_enable(owner, pgtable, NULL);
+}
+
+void exynos_sysmmu_disable(struct device *owner)
+{
+ struct sysmmu_drvdata *data = NULL;
+
+ while ((data = get_sysmmu_data(owner, data))) {
+ unsigned long flags;
+
+ write_lock_irqsave(&data->lock, flags);
+
+ if (set_sysmmu_inactive(data)) {
+ __raw_writel(CTRL_DISABLE,
+ data->sfrbase + S5P_MMU_CTRL);
+
+ dev_dbg(data->dev, "Disabled.\n");
+ } else {
+ dev_dbg(data->dev, "Inactivation request ignorred\n");
+ }
+
+ __raw_writel(CTRL_DISABLE, data->sfrbase + S5P_MMU_CTRL);
+
+ data->domain = NULL;
+
+ write_unlock_irqrestore(&data->lock, flags);
+
+ pm_runtime_put_sync(data->dev);
+ }
+}
+
+static void exynos_iommu_disable(struct iommu_domain *domain)
+{
+ struct exynos_iommu_domain *priv = domain->priv;
+
+ if (priv && priv->dev)
+ exynos_sysmmu_disable(priv->dev);
+}
+
+void exynos_sysmmu_tlb_invalidate(struct device *owner)
+{
+ struct sysmmu_drvdata *data = NULL;
+
+ while ((data = get_sysmmu_data(owner, data))) {
+ unsigned long flags;
+
+ read_lock_irqsave(&data->lock, flags);
+
+ if (is_sysmmu_active(data)) {
+ sysmmu_block(data->sfrbase);
+ __sysmmu_tlb_invalidate(data->sfrbase);
+ sysmmu_unblock(data->sfrbase);
+ } else {
+ dev_dbg(data->dev,
+ "Disabled: Skipping invalidating TLB.\n");
+ }
+
+ read_unlock_irqrestore(&data->lock, flags);
+ }
+}
+
+static int exynos_sysmmu_probe(struct platform_device *pdev)
+{
+ struct resource *res, *ioarea;
+ int ret = 0;
+ int irq;
+ struct device *dev;
+ void *sfr;
+ struct sysmmu_drvdata *data;
+ struct clk *clk;
+
+ dev = &pdev->dev;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ dev_err(dev, "Failed to probing System MMU: "
+ "Not enough memory");
+ return -ENOMEM;
+ }
+
+ if (!dev_get_platdata(dev)) {
+ dev_err(dev, "Failed to probing system MMU: "
+ "Owner device is not set.");
+
+ ret = -ENODEV;
+ goto err_init;
+ }
+
+ ret = dev_set_drvdata(dev, data);
+ if (ret) {
+ dev_err(dev, "Failed to probing system MMU: "
+ "Unable to set driver data.");
+ goto err_init;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev,
+ "Failed probing system MMU: failed to get resource.");
+ ret = -ENOENT;
+ goto err_init;
+ }
+
+ ioarea = request_mem_region(res->start, resource_size(res),
+ dev_name(dev));
+ if (ioarea == NULL) {
+ dev_err(dev, "Failed probing system MMU: "
+ "failed to request memory region.");
+ ret = -ENOENT;
+ goto err_init;
+ }
+
+ sfr = ioremap(res->start, resource_size(res));
+ if (!sfr) {
+ dev_err(dev, "Failed probing system MMU: "
+ "failed to call ioremap().");
+ ret = -ENOENT;
+ goto err_ioremap;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0) {
+ dev_err(dev, "Failed probing system MMU: "
+ "failed to get irq resource.");
+ ret = irq;
+ goto err_irq;
+ }
+
+ ret = request_irq(irq, exynos_sysmmu_irq, 0, dev_name(dev), data);
+ if (ret) {
+ dev_err(dev, "Failed probing system MMU: "
+ "failed to request irq.");
+ goto err_irq;
+ }
+
+ clk = clk_get(dev, "sysmmu");
+ if (IS_ERR(clk)) {
+ dev_err(dev, "Failed to probing System MMU: "
+ "failed to get clock descriptor");
+ ret = PTR_ERR(clk);
+ goto err_clk;
+ }
+
+ data->dev = dev;
+ data->owner = dev_get_platdata(dev);
+ data->clk = clk;
+ data->sfrbase = sfr;
+ __set_fault_handler(data, &default_fault_handler);
+ rwlock_init(&data->lock);
+ INIT_LIST_HEAD(&data->node);
+
+ list_add(&data->node, &sysmmu_list);
+
+ if (dev->parent)
+ pm_runtime_enable(dev);
+
+ dev_dbg(dev, "Initialized for %s.\n", dev_name(data->owner));
+ return 0;
+err_clk:
+ free_irq(irq, data);
+err_irq:
+ iounmap(sfr);
+err_ioremap:
+ release_resource(ioarea);
+ kfree(ioarea);
+err_init:
+ kfree(data);
+ dev_err(dev, "Probing system MMU failed.");
+ return ret;
+}
+
+int exynos_sysmmu_runtime_suspend(struct device *dev)
+{
+ struct sysmmu_drvdata *data = dev_get_drvdata(dev);
+
+ clk_disable(data->clk);
+
+ return 0;
+}
+
+int exynos_sysmmu_runtime_resume(struct device *dev)
+{
+ struct sysmmu_drvdata *data = dev_get_drvdata(dev);
+
+ return clk_enable(data->clk);
+}
+
+const struct dev_pm_ops exynos_sysmmu_pm_ops = {
+ .runtime_suspend = exynos_sysmmu_runtime_suspend,
+ .runtime_resume = exynos_sysmmu_runtime_resume,
+};
+
+static struct platform_driver exynos_sysmmu_driver = {
+ .probe = exynos_sysmmu_probe,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "s5p-sysmmu",
+ .pm = &exynos_sysmmu_pm_ops,
+ }
+};
+
+static int __init exynos_sysmmu_init(void)
+{
+ return platform_driver_register(&exynos_sysmmu_driver);
+}
+arch_initcall(exynos_sysmmu_init);
+
+/* We does not consider super section mapping (16MB) */
+#define S5P_SPAGE_SHIFT 12
+#define S5P_LPAGE_SHIFT 16
+#define S5P_SECTION_SHIFT 20
+
+#define S5P_SPAGE_SIZE (1 << S5P_SPAGE_SHIFT)
+#define S5P_LPAGE_SIZE (1 << S5P_LPAGE_SHIFT)
+#define S5P_SECTION_SIZE (1 << S5P_SECTION_SHIFT)
+
+#define S5P_SPAGE_MASK (~(S5P_SPAGE_SIZE - 1))
+#define S5P_LPAGE_MASK (~(S5P_LPAGE_SIZE - 1))
+#define S5P_SECTION_MASK (~(S5P_SECTION_SIZE - 1))
+
+#define S5P_SPAGE_ORDER (S5P_SPAGE_SHIFT - PAGE_SHIFT)
+#define S5P_LPAGE_ORDER (S5P_LPAGE_SHIFT - S5P_SPAGE_SHIFT)
+#define S5P_SECTION_ORDER (S5P_SECTION_SHIFT - S5P_SPAGE_SHIFT)
+
+#define S5P_LV1TABLE_ENTRIES (1 << (BITS_PER_LONG - S5P_SECTION_SHIFT))
+#define S5P_LV1TABLE_ORDER 2 /* get_order(S5P_LV1TABLE_ENTRIES) */
+
+#define S5P_LV2TABLE_ENTRIES (1 << S5P_SECTION_ORDER)
+#define S5P_LV2TABLE_SIZE (S5P_LV2TABLE_ENTRIES * sizeof(long))
+#define S5P_LV2TABLE_MASK (~(S5P_LV2TABLE_SIZE - 1)) /* 0xFFFFFC00 */
+
+#define S5P_SECTION_LV1_ENTRY(entry) ((entry & 0x40003) == 2)
+#define S5P_SUPSECT_LV1_ENTRY(entry) ((entry & 0x40003) == 0x40002)
+#define S5P_PAGE_LV1_ENTRY(entry) ((entry & 3) == 1)
+#define S5P_FAULT_LV1_ENTRY(entry) (((entry & 3) == 0) || (entry & 3) == 3)
+
+#define S5P_LPAGE_LV2_ENTRY(entry) ((entry & 3) == 1)
+#define S5P_SPAGE_LV2_ENTRY(entry) ((entry & 2) == 2)
+#define S5P_FAULT_LV2_ENTRY(entry) ((entry & 3) == 0)
+
+#define MAKE_FAULT_ENTRY(entry) do { entry = 0; } while (0)
+#define MAKE_SECTION_ENTRY(entry, pa) do { entry = pa | 2; } while (0)
+#define MAKE_SUPSECT_ENTRY(entry, pa) do { entry = pa | 0x40002; } while (0)
+#define MAKE_LV2TABLE_ENTRY(entry, pa) do { entry = pa | 1; } while (0)
+
+#define MAKE_LPAGE_ENTRY(entry, pa) do { entry = pa | 1; } while (0)
+#define MAKE_SPAGE_ENTRY(entry, pa) do { entry = pa | 3; } while (0)
+
+#define GET_LV2ENTRY(entry, iova) (\
+ (unsigned long *)phys_to_virt(entry & S5P_LV2TABLE_MASK) +\
+ ((iova & (~S5P_SECTION_MASK)) >> S5P_SPAGE_SHIFT))
+
+/* slab cache for level 2 page tables */
+static struct kmem_cache *l2table_cachep;
+
+static void pgtable_flush(void *vastart, void *vaend)
+{
+ dmac_flush_range(vastart, vaend);
+ outer_flush_range(virt_to_phys(vastart),
+ virt_to_phys(vaend));
+}
+
+static int exynos_iommu_domain_init(struct iommu_domain *domain)
+{
+ struct exynos_iommu_domain *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->pgtable = (unsigned long *)
+ __get_free_pages(S5P_LV1TABLE_ORDER, GFP_KERNEL);
+ if (!priv->pgtable) {
+ kfree(priv);
+ return -ENOMEM;
+ }
+
+ memset(priv->pgtable, 0, S5P_LV1TABLE_ENTRIES * sizeof(unsigned long));
+ pgtable_flush(priv->pgtable, priv->pgtable + S5P_LV1TABLE_ENTRIES);
+
+ spin_lock_init(&priv->lock);
+ spin_lock_init(&priv->pgtablelock);
+
+ domain->priv = priv;
+
+ return 0;
+}
+
+static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
+{
+ struct exynos_iommu_domain *priv = domain->priv;
+
+ free_pages((unsigned long)priv->pgtable, S5P_LV1TABLE_ORDER);
+
+ kfree(priv);
+
+ domain->priv = NULL;
+}
+
+static int exynos_iommu_attach_device(struct iommu_domain *domain,
+ struct device *dev)
+{
+ struct exynos_iommu_domain *priv = domain->priv;
+ int ret;
+
+ spin_lock(&priv->lock);
+
+ priv->dev = dev;
+
+ spin_unlock(&priv->lock);
+
+ ret = exynos_iommu_enable(domain);
+
+ return ret;
+}
+
+static void exynos_iommu_detach_device(struct iommu_domain *domain,
+ struct device *dev)
+{
+ struct exynos_iommu_domain *priv = domain->priv;
+
+ spin_lock(&priv->lock);
+
+ if (priv->dev == dev) {
+ priv->dev = NULL;
+
+ spin_unlock(&priv->lock);
+
+ exynos_iommu_disable(domain);
+ } else {
+ spin_unlock(&priv->lock);
+ }
+}
+
+static bool section_available(struct iommu_domain *domain,
+ unsigned long *lv1entry)
+{
+ struct exynos_iommu_domain *priv = domain->priv;
+
+ if (S5P_SECTION_LV1_ENTRY(*lv1entry)) {
+ dev_err(priv->dev, "1MB entry alread exists at 0x%08x\n",
+ (lv1entry - priv->pgtable) * SZ_1M);
+ return false;
+ }
+
+ if (S5P_PAGE_LV1_ENTRY(*lv1entry)) {
+ unsigned long *lv2end, *lv2base;
+
+ lv2base = phys_to_virt(*lv1entry & S5P_LV2TABLE_MASK);
+ lv2end = lv2base + S5P_LV2TABLE_ENTRIES;
+ while (lv2base != lv2end) {
+ if (!S5P_FAULT_LV2_ENTRY(*lv2base)) {
+ dev_err(priv->dev, "Failed to free L2 page "
+ "table for section mapping.\n");
+ return false;
+ }
+ lv2base++;
+ }
+
+ kmem_cache_free(l2table_cachep,
+ phys_to_virt(*lv1entry & S5P_LV2TABLE_MASK));
+
+ MAKE_FAULT_ENTRY(*lv1entry);
+ }
+
+ return true;
+}
+
+static bool write_lpage(unsigned long *head_entry, unsigned long phys_addr)
+{
+ unsigned long *entry, *end;
+
+ entry = head_entry;
+ end = entry + (1 << S5P_LPAGE_ORDER);
+
+ while (entry != end) {
+ if (!S5P_FAULT_LV2_ENTRY(*entry))
+ break;
+
+ MAKE_LPAGE_ENTRY(*entry, phys_addr);
+
+ entry++;
+ }
+
+ if (entry != end) {
+ end = entry;
+ while (entry != head_entry)
+ MAKE_FAULT_ENTRY(*(--entry));
+
+ return false;
+ }
+
+ return true;
+}
+
+static int exynos_iommu_map(struct iommu_domain *domain, unsigned long iova,
+ phys_addr_t paddr, int gfp_order, int prot)
+{
+ struct exynos_iommu_domain *priv = domain->priv;
+ unsigned long *start_entry, *entry, *end_entry;
+ int num_entry;
+ int ret = 0;
+ unsigned long flags;
+
+ BUG_ON(priv->pgtable == NULL);
+
+ spin_lock_irqsave(&priv->pgtablelock, flags);
+
+ start_entry = entry = priv->pgtable + (iova >> S5P_SECTION_SHIFT);
+
+ if (gfp_order >= S5P_SECTION_ORDER) {
+ BUG_ON(!IS_ALIGNED(paddr | iova, S5P_SECTION_SIZE));
+ /* 1MiB mapping */
+
+ num_entry = 1 << (gfp_order - S5P_SECTION_ORDER);
+ end_entry = entry + num_entry;
+
+ while (entry != end_entry) {
+ if (!section_available(domain, entry))
+ break;
+
+ MAKE_SECTION_ENTRY(*entry, paddr);
+
+ paddr += S5P_SECTION_SIZE;
+ entry++;
+ }
+
+ if (entry != end_entry)
+ goto mapping_error;
+
+ pgtable_flush(start_entry, entry);
+ goto mapping_done;
+ }
+
+ if (S5P_FAULT_LV1_ENTRY(*entry)) {
+ unsigned long *l2table;
+
+ l2table = kmem_cache_zalloc(l2table_cachep, GFP_KERNEL);
+ if (!l2table) {
+ ret = -ENOMEM;
+ goto nomem_error;
+ }
+
+ pgtable_flush(entry, entry + S5P_LV2TABLE_ENTRIES);
+
+ MAKE_LV2TABLE_ENTRY(*entry, virt_to_phys(l2table));
+ pgtable_flush(entry, entry + 1);
+ }
+
+ /* 'entry' points level 2 entries, hereafter */
+ entry = GET_LV2ENTRY(*entry, iova);
+
+ start_entry = entry;
+ num_entry = 1 << gfp_order;
+ end_entry = entry + num_entry;
+
+ if (gfp_order >= S5P_LPAGE_ORDER) {
+ /* large page(64KiB) mapping */
+ BUG_ON(!IS_ALIGNED(paddr | iova, S5P_LPAGE_SIZE));
+
+ while (entry != end_entry) {
+ if (!write_lpage(entry, paddr)) {
+ pr_err("%s: "
+ "Failed to allocate large page entry."
+ "\n", __func__);
+ break;
+ }
+
+ paddr += S5P_LPAGE_SIZE;
+ entry += (1 << S5P_LPAGE_ORDER);
+ }
+
+ if (entry != end_entry) {
+ entry -= 1 << S5P_LPAGE_ORDER;
+ goto mapping_error;
+ }
+ } else {
+ /* page (4KiB) mapping */
+ while (entry != end_entry && S5P_FAULT_LV2_ENTRY(*entry)) {
+
+ MAKE_SPAGE_ENTRY(*entry, paddr);
+
+ entry++;
+ paddr += S5P_SPAGE_SIZE;
+ }
+
+ if (entry != end_entry) {
+ pr_err("%s: Failed to allocate small page entry.\n",
+ __func__);
+ goto mapping_error;
+ }
+ }
+
+ pgtable_flush(start_entry, entry);
+mapping_error:
+ if (entry != end_entry) {
+ unsigned long *current_entry = entry;
+ while (entry != start_entry)
+ MAKE_FAULT_ENTRY(*(--entry));
+ pgtable_flush(start_entry, current_entry);
+ ret = -EADDRINUSE;
+ }
+
+nomem_error:
+mapping_done:
+ spin_unlock_irqrestore(&priv->pgtablelock, flags);
+
+ return 0;
+}
+
+static int exynos_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
+ int gfp_order)
+{
+ struct exynos_iommu_domain *priv = domain->priv;
+ unsigned long *entry;
+ int num_entry;
+ unsigned long flags;
+
+ BUG_ON(priv->pgtable == NULL);
+
+ spin_lock_irqsave(&priv->pgtablelock, flags);
+
+ entry = priv->pgtable + (iova >> S5P_SECTION_SHIFT);
+
+ if (gfp_order >= S5P_SECTION_ORDER) {
+ gfp_order -= S5P_SECTION_ORDER;
+ num_entry = 1 << (gfp_order - S5P_SECTION_ORDER);
+ while (num_entry--) {
+ if (S5P_SECTION_LV1_ENTRY(*entry)) {
+ MAKE_FAULT_ENTRY(*entry);
+ } else if (S5P_PAGE_LV1_ENTRY(*entry)) {
+ unsigned long *lv2beg, *lv2end;
+ lv2beg = phys_to_virt(
+ *entry & S5P_LV2TABLE_MASK);
+ lv2end = lv2beg + S5P_LV2TABLE_ENTRIES;
+ while (lv2beg != lv2end) {
+ MAKE_FAULT_ENTRY(*lv2beg);
+ lv2beg++;
+ }
+ }
+ entry++;
+ }
+ } else {
+ entry = GET_LV2ENTRY(*entry, iova);
+
+ BUG_ON(S5P_LPAGE_LV2_ENTRY(*entry) &&
+ (gfp_order < S5P_LPAGE_ORDER));
+
+ num_entry = 1 << gfp_order;
+
+ while (num_entry--) {
+ MAKE_FAULT_ENTRY(*entry);
+ entry++;
+ }
+ }
+
+ spin_unlock_irqrestore(&priv->pgtablelock, flags);
+
+ if (priv->dev)
+ exynos_sysmmu_tlb_invalidate(priv->dev);
+
+ return 0;
+}
+
+static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain,
+ unsigned long iova)
+{
+ struct exynos_iommu_domain *priv = domain->priv;
+ unsigned long *entry;
+ unsigned long offset;
+
+ entry = priv->pgtable + (iova >> S5P_SECTION_SHIFT);
+
+ if (S5P_FAULT_LV1_ENTRY(*entry))
+ return 0;
+
+ offset = iova & ~S5P_SECTION_MASK;
+
+ if (S5P_SECTION_LV1_ENTRY(*entry))
+ return (*entry & S5P_SECTION_MASK) + offset;
+
+ entry = GET_LV2ENTRY(*entry, iova);
+
+ if (S5P_SPAGE_LV2_ENTRY(*entry))
+ return (*entry & S5P_SPAGE_MASK) + (iova & ~S5P_SPAGE_MASK);
+
+ if (S5P_LPAGE_LV2_ENTRY(*entry))
+ return (*entry & S5P_LPAGE_MASK) + (iova & ~S5P_LPAGE_MASK);
+
+ return 0;
+}
+
+static int exynos_iommu_domain_has_cap(struct iommu_domain *domain,
+ unsigned long cap)
+{
+ return 0;
+}
+
+static struct iommu_ops exynos_iommu_ops = {
+ .domain_init = &exynos_iommu_domain_init,
+ .domain_destroy = &exynos_iommu_domain_destroy,
+ .attach_dev = &exynos_iommu_attach_device,
+ .detach_dev = &exynos_iommu_detach_device,
+ .map = &exynos_iommu_map,
+ .unmap = &exynos_iommu_unmap,
+ .iova_to_phys = &exynos_iommu_iova_to_phys,
+ .domain_has_cap = &exynos_iommu_domain_has_cap,
+};
+
+static int __init exynos_iommu_init(void)
+{
+ l2table_cachep = kmem_cache_create("SysMMU Lv2 Tables",
+ S5P_LV2TABLE_SIZE, S5P_LV2TABLE_SIZE, 0, NULL);
+ if (!l2table_cachep)
+ return -ENOMEM;
+
+ bus_set_iommu(&platform_bus_type, &exynos_iommu_ops);
+
+ return 0;
+}
+arch_initcall(exynos_iommu_init);
--
1.7.1
^ permalink raw reply related
* [PATCH 1/2] sam9g45: add trng clock and platform device
From: Nicolas Ferre @ 2011-10-07 10:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317915694-27564-1-git-send-email-jacmet@sunsite.dk>
On 10/06/2011 05:41 PM, Peter Korsgaard :
> For the new hw_random driver.
>
> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
I add it to at91-l2 and at91-next branches of:
git://github.com/at91linux/linux-at91.git
Thanks,
> ---
> arch/arm/mach-at91/at91sam9g45.c | 7 +++++++
> arch/arm/mach-at91/at91sam9g45_devices.c | 29 +++++++++++++++++++++++++++++
> 2 files changed, 36 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
> index 6da8ace..6850f1d 100644
> --- a/arch/arm/mach-at91/at91sam9g45.c
> +++ b/arch/arm/mach-at91/at91sam9g45.c
> @@ -54,6 +54,11 @@ static struct clk pioDE_clk = {
> .pmc_mask = 1 << AT91SAM9G45_ID_PIODE,
> .type = CLK_TYPE_PERIPHERAL,
> };
> +static struct clk trng_clk = {
> + .name = "trng_clk",
> + .pmc_mask = 1 << AT91SAM9G45_ID_TRNG,
> + .type = CLK_TYPE_PERIPHERAL,
> +};
> static struct clk usart0_clk = {
> .name = "usart0_clk",
> .pmc_mask = 1 << AT91SAM9G45_ID_US0,
> @@ -177,6 +182,7 @@ static struct clk *periph_clocks[] __initdata = {
> &pioB_clk,
> &pioC_clk,
> &pioDE_clk,
> + &trng_clk,
> &usart0_clk,
> &usart1_clk,
> &usart2_clk,
> @@ -216,6 +222,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
> CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
> CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
> CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
> + CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
> /* fake hclk clock */
> CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
> };
> diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
> index 2ee20bd..1ca6c62 100644
> --- a/arch/arm/mach-at91/at91sam9g45_devices.c
> +++ b/arch/arm/mach-at91/at91sam9g45_devices.c
> @@ -1101,6 +1101,34 @@ static void __init at91_add_device_rtt(void)
>
>
> /* --------------------------------------------------------------------
> + * TRNG
> + * -------------------------------------------------------------------- */
> +
> +#if defined(CONFIG_HW_RANDOM_ATMEL) || defined(CONFIG_HW_RANDOM_ATMEL_MODULE)
> +static struct resource trng_resources[] = {
> + {
> + .start = AT91SAM9G45_BASE_TRNG,
> + .end = AT91SAM9G45_BASE_TRNG + SZ_16K - 1,
> + .flags = IORESOURCE_MEM,
> + },
> +};
> +
> +static struct platform_device at91sam9g45_trng_device = {
> + .name = "atmel-trng",
> + .id = -1,
> + .resource = trng_resources,
> + .num_resources = ARRAY_SIZE(trng_resources),
> +};
> +
> +static void __init at91_add_device_trng(void)
> +{
> + platform_device_register(&at91sam9g45_trng_device);
> +}
> +#else
> +static void __init at91_add_device_trng(void) {}
> +#endif
> +
> +/* --------------------------------------------------------------------
> * Watchdog
> * -------------------------------------------------------------------- */
>
> @@ -1589,6 +1617,7 @@ static int __init at91_add_standard_devices(void)
> at91_add_device_hdmac();
> at91_add_device_rtc();
> at91_add_device_rtt();
> + at91_add_device_trng();
> at91_add_device_watchdog();
> at91_add_device_tc();
> return 0;
--
Nicolas Ferre
^ permalink raw reply
* [PATCH v3 RE-SEND 1/2] ARM: EXYNOS4: Change System MMU device definition
From: Kukjin Kim @ 2011-10-07 10:09 UTC (permalink / raw)
To: linux-arm-kernel
From: KyongHo Cho <pullip.cho@samsung.com>
This patch contains a lot of changes of System MMU device definition.
1. Removed sysmmu_ips enumeration that are definitions of ID of System MMU
Instead, a System MMU device descriptor must be bound with a device
descriptor that needs System MMU in machine initialization.
2. Removed MDMA that is included in LCD0 block because it is not used
anymore. Use MDMA in TOP block.
3. Changed System MMU definitions of platform device. It is not an array
anymore.
Signed-off-by: KyongHo Cho <pullip.cho@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
---
NOTE: Since previous sending has problem, I'm re-sending.
Sorry, please kindly ignore previous one.
arch/arm/mach-exynos4/Kconfig | 2 -
arch/arm/mach-exynos4/clock.c | 43 +++--
arch/arm/mach-exynos4/dev-sysmmu.c | 267 ++++++---------------------
arch/arm/mach-exynos4/include/mach/irqs.h | 1 -
arch/arm/mach-exynos4/include/mach/map.h | 1 -
arch/arm/mach-exynos4/include/mach/sysmmu.h | 85 +++++----
arch/arm/mach-exynos4/mach-armlex4210.c | 24 +++-
arch/arm/mach-exynos4/mach-smdkv310.c | 28 +++-
8 files changed, 183 insertions(+), 268 deletions(-)
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index dd660eb..2f4a032 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -157,7 +157,6 @@ config MACH_SMDKV310
select SAMSUNG_DEV_KEYPAD
select EXYNOS4_DEV_PD
select SAMSUNG_DEV_PWM
- select EXYNOS4_DEV_SYSMMU
select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_KEYPAD
@@ -175,7 +174,6 @@ config MACH_ARMLEX4210
select S3C_DEV_HSMMC2
select S3C_DEV_HSMMC3
select EXYNOS4_DEV_AHCI
- select EXYNOS4_DEV_SYSMMU
select EXYNOS4_SETUP_SDHCI
help
Machine support for Samsung ARMLEX4210 based on EXYNOS4210
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index db61691..1fc508c 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -691,59 +691,68 @@ static struct clk init_clocks_off[] = {
.enable = exynos4_clk_ip_peril_ctrl,
.ctrlbit = (1 << 14),
}, {
- .name = "SYSMMU_MDMA",
- .enable = exynos4_clk_ip_image_ctrl,
- .ctrlbit = (1 << 5),
- }, {
- .name = "SYSMMU_FIMC0",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(fimc0, 1),
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 7),
}, {
- .name = "SYSMMU_FIMC1",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(fimc1, 2),
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 8),
}, {
- .name = "SYSMMU_FIMC2",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(fimc2, 3),
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 9),
}, {
- .name = "SYSMMU_FIMC3",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(fimc3, 4),
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 10),
}, {
- .name = "SYSMMU_JPEG",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(jpeg, 5),
.enable = exynos4_clk_ip_cam_ctrl,
.ctrlbit = (1 << 11),
}, {
- .name = "SYSMMU_FIMD0",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(fimd0, 6),
.enable = exynos4_clk_ip_lcd0_ctrl,
.ctrlbit = (1 << 4),
}, {
- .name = "SYSMMU_FIMD1",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(fimd1, 7),
.enable = exynos4_clk_ip_lcd1_ctrl,
.ctrlbit = (1 << 4),
}, {
- .name = "SYSMMU_PCIe",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(pcie, 8),
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 18),
}, {
- .name = "SYSMMU_G2D",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(g2d, 9),
.enable = exynos4_clk_ip_image_ctrl,
.ctrlbit = (1 << 3),
}, {
- .name = "SYSMMU_ROTATOR",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(rot, 10),
.enable = exynos4_clk_ip_image_ctrl,
.ctrlbit = (1 << 4),
}, {
- .name = "SYSMMU_TV",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(tv, 12),
.enable = exynos4_clk_ip_tv_ctrl,
.ctrlbit = (1 << 4),
}, {
- .name = "SYSMMU_MFC_L",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(mfc_l, 13),
.enable = exynos4_clk_ip_mfc_ctrl,
.ctrlbit = (1 << 1),
}, {
- .name = "SYSMMU_MFC_R",
+ .name = "sysmmu",
+ .devname = SYSMMU_CLOCK_NAME(mfc_r, 14),
.enable = exynos4_clk_ip_mfc_ctrl,
.ctrlbit = (1 << 2),
}
diff --git a/arch/arm/mach-exynos4/dev-sysmmu.c b/arch/arm/mach-exynos4/dev-sysmmu.c
index 3b7cae0..a62b172 100644
--- a/arch/arm/mach-exynos4/dev-sysmmu.c
+++ b/arch/arm/mach-exynos4/dev-sysmmu.c
@@ -1,6 +1,6 @@
/* linux/arch/arm/mach-exynos4/dev-sysmmu.c
*
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* EXYNOS4 - System MMU support
@@ -16,217 +16,64 @@
#include <mach/map.h>
#include <mach/irqs.h>
#include <mach/sysmmu.h>
-#include <plat/s5p-clock.h>
-/* These names must be equal to the clock names in mach-exynos4/clock.c */
-const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM] = {
- "SYSMMU_MDMA" ,
- "SYSMMU_SSS" ,
- "SYSMMU_FIMC0" ,
- "SYSMMU_FIMC1" ,
- "SYSMMU_FIMC2" ,
- "SYSMMU_FIMC3" ,
- "SYSMMU_JPEG" ,
- "SYSMMU_FIMD0" ,
- "SYSMMU_FIMD1" ,
- "SYSMMU_PCIe" ,
- "SYSMMU_G2D" ,
- "SYSMMU_ROTATOR",
- "SYSMMU_MDMA2" ,
- "SYSMMU_TV" ,
- "SYSMMU_MFC_L" ,
- "SYSMMU_MFC_R" ,
-};
-
-static struct resource exynos4_sysmmu_resource[] = {
- [0] = {
- .start = EXYNOS4_PA_SYSMMU_MDMA,
- .end = EXYNOS4_PA_SYSMMU_MDMA + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_SYSMMU_MDMA0_0,
- .end = IRQ_SYSMMU_MDMA0_0,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = EXYNOS4_PA_SYSMMU_SSS,
- .end = EXYNOS4_PA_SYSMMU_SSS + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [3] = {
- .start = IRQ_SYSMMU_SSS_0,
- .end = IRQ_SYSMMU_SSS_0,
- .flags = IORESOURCE_IRQ,
- },
- [4] = {
- .start = EXYNOS4_PA_SYSMMU_FIMC0,
- .end = EXYNOS4_PA_SYSMMU_FIMC0 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [5] = {
- .start = IRQ_SYSMMU_FIMC0_0,
- .end = IRQ_SYSMMU_FIMC0_0,
- .flags = IORESOURCE_IRQ,
- },
- [6] = {
- .start = EXYNOS4_PA_SYSMMU_FIMC1,
- .end = EXYNOS4_PA_SYSMMU_FIMC1 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [7] = {
- .start = IRQ_SYSMMU_FIMC1_0,
- .end = IRQ_SYSMMU_FIMC1_0,
- .flags = IORESOURCE_IRQ,
- },
- [8] = {
- .start = EXYNOS4_PA_SYSMMU_FIMC2,
- .end = EXYNOS4_PA_SYSMMU_FIMC2 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [9] = {
- .start = IRQ_SYSMMU_FIMC2_0,
- .end = IRQ_SYSMMU_FIMC2_0,
- .flags = IORESOURCE_IRQ,
- },
- [10] = {
- .start = EXYNOS4_PA_SYSMMU_FIMC3,
- .end = EXYNOS4_PA_SYSMMU_FIMC3 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [11] = {
- .start = IRQ_SYSMMU_FIMC3_0,
- .end = IRQ_SYSMMU_FIMC3_0,
- .flags = IORESOURCE_IRQ,
- },
- [12] = {
- .start = EXYNOS4_PA_SYSMMU_JPEG,
- .end = EXYNOS4_PA_SYSMMU_JPEG + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [13] = {
- .start = IRQ_SYSMMU_JPEG_0,
- .end = IRQ_SYSMMU_JPEG_0,
- .flags = IORESOURCE_IRQ,
- },
- [14] = {
- .start = EXYNOS4_PA_SYSMMU_FIMD0,
- .end = EXYNOS4_PA_SYSMMU_FIMD0 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [15] = {
- .start = IRQ_SYSMMU_LCD0_M0_0,
- .end = IRQ_SYSMMU_LCD0_M0_0,
- .flags = IORESOURCE_IRQ,
- },
- [16] = {
- .start = EXYNOS4_PA_SYSMMU_FIMD1,
- .end = EXYNOS4_PA_SYSMMU_FIMD1 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [17] = {
- .start = IRQ_SYSMMU_LCD1_M1_0,
- .end = IRQ_SYSMMU_LCD1_M1_0,
- .flags = IORESOURCE_IRQ,
- },
- [18] = {
- .start = EXYNOS4_PA_SYSMMU_PCIe,
- .end = EXYNOS4_PA_SYSMMU_PCIe + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [19] = {
- .start = IRQ_SYSMMU_PCIE_0,
- .end = IRQ_SYSMMU_PCIE_0,
- .flags = IORESOURCE_IRQ,
- },
- [20] = {
- .start = EXYNOS4_PA_SYSMMU_G2D,
- .end = EXYNOS4_PA_SYSMMU_G2D + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [21] = {
- .start = IRQ_SYSMMU_2D_0,
- .end = IRQ_SYSMMU_2D_0,
- .flags = IORESOURCE_IRQ,
- },
- [22] = {
- .start = EXYNOS4_PA_SYSMMU_ROTATOR,
- .end = EXYNOS4_PA_SYSMMU_ROTATOR + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [23] = {
- .start = IRQ_SYSMMU_ROTATOR_0,
- .end = IRQ_SYSMMU_ROTATOR_0,
- .flags = IORESOURCE_IRQ,
- },
- [24] = {
- .start = EXYNOS4_PA_SYSMMU_MDMA2,
- .end = EXYNOS4_PA_SYSMMU_MDMA2 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [25] = {
- .start = IRQ_SYSMMU_MDMA1_0,
- .end = IRQ_SYSMMU_MDMA1_0,
- .flags = IORESOURCE_IRQ,
- },
- [26] = {
- .start = EXYNOS4_PA_SYSMMU_TV,
- .end = EXYNOS4_PA_SYSMMU_TV + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [27] = {
- .start = IRQ_SYSMMU_TV_M0_0,
- .end = IRQ_SYSMMU_TV_M0_0,
- .flags = IORESOURCE_IRQ,
- },
- [28] = {
- .start = EXYNOS4_PA_SYSMMU_MFC_L,
- .end = EXYNOS4_PA_SYSMMU_MFC_L + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [29] = {
- .start = IRQ_SYSMMU_MFC_M0_0,
- .end = IRQ_SYSMMU_MFC_M0_0,
- .flags = IORESOURCE_IRQ,
- },
- [30] = {
- .start = EXYNOS4_PA_SYSMMU_MFC_R,
- .end = EXYNOS4_PA_SYSMMU_MFC_R + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [31] = {
- .start = IRQ_SYSMMU_MFC_M1_0,
- .end = IRQ_SYSMMU_MFC_M1_0,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device exynos4_device_sysmmu = {
- .name = "s5p-sysmmu",
- .id = 32,
- .num_resources = ARRAY_SIZE(exynos4_sysmmu_resource),
- .resource = exynos4_sysmmu_resource,
-};
-EXPORT_SYMBOL(exynos4_device_sysmmu);
-
-static struct clk *sysmmu_clk[S5P_SYSMMU_TOTAL_IPNUM];
-void sysmmu_clk_init(struct device *dev, sysmmu_ips ips)
-{
- sysmmu_clk[ips] = clk_get(dev, sysmmu_ips_name[ips]);
- if (IS_ERR(sysmmu_clk[ips]))
- sysmmu_clk[ips] = NULL;
- else
- clk_put(sysmmu_clk[ips]);
+#define SYSMMU_RESOURCE(ipname, base, irq) \
+static struct resource sysmmu_resource_##ipname[] =\
+{\
+ {\
+ .start = EXYNOS4_PA_SYSMMU_##base,\
+ .end = EXYNOS4_PA_SYSMMU_##base + SZ_4K - 1,\
+ .flags = IORESOURCE_MEM,\
+ }, {\
+ .start = IRQ_SYSMMU_##irq##_0,\
+ .end = IRQ_SYSMMU_##irq##_0,\
+ .flags = IORESOURCE_IRQ,\
+ },\
}
-void sysmmu_clk_enable(sysmmu_ips ips)
-{
- if (sysmmu_clk[ips])
- clk_enable(sysmmu_clk[ips]);
+#define SYSMMU_PLATFORM_DEVICE(ipname, devid) \
+struct platform_device SYSMMU_PLATDEV(ipname) =\
+{\
+ .name = SYSMMU_DEVNAME_BASE,\
+ .id = devid,\
+ .num_resources = ARRAY_SIZE(sysmmu_resource_##ipname),\
+ .resource = sysmmu_resource_##ipname,\
+ .dev = {\
+ .dma_mask = &exynos_sysmmu_dma_mask,\
+ .coherent_dma_mask = DMA_BIT_MASK(32),\
+ },\
}
-void sysmmu_clk_disable(sysmmu_ips ips)
-{
- if (sysmmu_clk[ips])
- clk_disable(sysmmu_clk[ips]);
-}
+static u64 exynos_sysmmu_dma_mask = DMA_BIT_MASK(32);
+
+SYSMMU_RESOURCE(sss, SSS, SSS);
+SYSMMU_RESOURCE(fimc0, FIMC0, FIMC0);
+SYSMMU_RESOURCE(fimc1, FIMC1, FIMC1);
+SYSMMU_RESOURCE(fimc2, FIMC2, FIMC2);
+SYSMMU_RESOURCE(fimc3, FIMC3, FIMC3);
+SYSMMU_RESOURCE(jpeg, JPEG, JPEG);
+SYSMMU_RESOURCE(fimd0, FIMD0, LCD0_M0);
+SYSMMU_RESOURCE(fimd1, FIMD1, LCD1_M1);
+SYSMMU_RESOURCE(pcie, PCIe, PCIE);
+SYSMMU_RESOURCE(g2d, G2D, 2D);
+SYSMMU_RESOURCE(rot, ROTATOR, ROTATOR);
+SYSMMU_RESOURCE(mdma, MDMA2, MDMA1);
+SYSMMU_RESOURCE(tv, TV, TV_M0);
+SYSMMU_RESOURCE(mfc_l, MFC_L, MFC_M0);
+SYSMMU_RESOURCE(mfc_r, MFC_R, MFC_M1);
+
+SYSMMU_PLATFORM_DEVICE(sss, 0);
+SYSMMU_PLATFORM_DEVICE(fimc0, 1);
+SYSMMU_PLATFORM_DEVICE(fimc1, 2);
+SYSMMU_PLATFORM_DEVICE(fimc2, 3);
+SYSMMU_PLATFORM_DEVICE(fimc3, 4);
+SYSMMU_PLATFORM_DEVICE(jpeg, 5);
+SYSMMU_PLATFORM_DEVICE(fimd0, 6);
+SYSMMU_PLATFORM_DEVICE(fimd1, 7);
+SYSMMU_PLATFORM_DEVICE(pcie, 8);
+SYSMMU_PLATFORM_DEVICE(g2d, 9);
+SYSMMU_PLATFORM_DEVICE(rot, 10);
+SYSMMU_PLATFORM_DEVICE(mdma, 11);
+SYSMMU_PLATFORM_DEVICE(tv, 12);
+SYSMMU_PLATFORM_DEVICE(mfc_l, 13);
+SYSMMU_PLATFORM_DEVICE(mfc_r, 14);
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index dfd4b7e..a33fdd1 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -125,7 +125,6 @@
#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(128))
#define COMBINER_IRQ(x, y) (COMBINER_GROUP(x) + y)
-#define IRQ_SYSMMU_MDMA0_0 COMBINER_IRQ(4, 0)
#define IRQ_SYSMMU_SSS_0 COMBINER_IRQ(4, 1)
#define IRQ_SYSMMU_FIMC0_0 COMBINER_IRQ(4, 2)
#define IRQ_SYSMMU_FIMC1_0 COMBINER_IRQ(4, 3)
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index 918a979..aaf492c 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -71,7 +71,6 @@
#define EXYNOS4_PA_PDMA0 0x12680000
#define EXYNOS4_PA_PDMA1 0x12690000
-#define EXYNOS4_PA_SYSMMU_MDMA 0x10A40000
#define EXYNOS4_PA_SYSMMU_SSS 0x10A50000
#define EXYNOS4_PA_SYSMMU_FIMC0 0x11A20000
#define EXYNOS4_PA_SYSMMU_FIMC1 0x11A30000
diff --git a/arch/arm/mach-exynos4/include/mach/sysmmu.h b/arch/arm/mach-exynos4/include/mach/sysmmu.h
index 6a5fbb5..1811c20 100644
--- a/arch/arm/mach-exynos4/include/mach/sysmmu.h
+++ b/arch/arm/mach-exynos4/include/mach/sysmmu.h
@@ -3,44 +3,59 @@
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * Samsung sysmmu driver for EXYNOS4
+ * Exynos - System MMU 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 __ASM_ARM_ARCH_SYSMMU_H
-#define __ASM_ARM_ARCH_SYSMMU_H __FILE__
-
-enum exynos4_sysmmu_ips {
- SYSMMU_MDMA,
- SYSMMU_SSS,
- SYSMMU_FIMC0,
- SYSMMU_FIMC1,
- SYSMMU_FIMC2,
- SYSMMU_FIMC3,
- SYSMMU_JPEG,
- SYSMMU_FIMD0,
- SYSMMU_FIMD1,
- SYSMMU_PCIe,
- SYSMMU_G2D,
- SYSMMU_ROTATOR,
- SYSMMU_MDMA2,
- SYSMMU_TV,
- SYSMMU_MFC_L,
- SYSMMU_MFC_R,
- EXYNOS4_SYSMMU_TOTAL_IPNUM,
-};
-
-#define S5P_SYSMMU_TOTAL_IPNUM EXYNOS4_SYSMMU_TOTAL_IPNUM
-
-extern const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM];
-
-typedef enum exynos4_sysmmu_ips sysmmu_ips;
-
-void sysmmu_clk_init(struct device *dev, sysmmu_ips ips);
-void sysmmu_clk_enable(sysmmu_ips ips);
-void sysmmu_clk_disable(sysmmu_ips ips);
-
-#endif /* __ASM_ARM_ARCH_SYSMMU_H */
+#ifndef _ARM_MACH_EXYNOS_SYSMMU_H_
+#define _ARM_MACH_EXYNOS_SYSMMU_H_
+
+#include <linux/device.h>
+
+#define SYSMMU_DEVNAME_BASE "s5p-sysmmu"
+#define SYSMMU_CLOCK_NAME(ipname, id) SYSMMU_DEVNAME_BASE "." #id
+
+#ifdef CONFIG_EXYNOS4_DEV_SYSMMU
+
+#define SYSMMU_PLATDEV(ipname) exynos_device_sysmmu_##ipname
+
+#ifdef CONFIG_EXYNOS4_DEV_PD
+#define ASSIGN_SYSMMU_POWERDOMAIN(ipname, powerdomain) \
+ SYSMMU_PLATDEV(mfc_l).dev.parent = powerdomain
+#else
+#define ASSIGN_SYSMMU_POWERDOMAIN(ipname, powerdomain) do { } while (0)
+#endif
+
+extern struct platform_device SYSMMU_PLATDEV(sss);
+extern struct platform_device SYSMMU_PLATDEV(fimc0);
+extern struct platform_device SYSMMU_PLATDEV(fimc1);
+extern struct platform_device SYSMMU_PLATDEV(fimc2);
+extern struct platform_device SYSMMU_PLATDEV(fimc3);
+extern struct platform_device SYSMMU_PLATDEV(jpeg);
+extern struct platform_device SYSMMU_PLATDEV(fimd0);
+extern struct platform_device SYSMMU_PLATDEV(fimd1);
+extern struct platform_device SYSMMU_PLATDEV(pcie);
+extern struct platform_device SYSMMU_PLATDEV(g2d);
+extern struct platform_device SYSMMU_PLATDEV(rot);
+extern struct platform_device SYSMMU_PLATDEV(mdma);
+extern struct platform_device SYSMMU_PLATDEV(tv);
+extern struct platform_device SYSMMU_PLATDEV(mfc_l);
+extern struct platform_device SYSMMU_PLATDEV(mfc_r);
+extern struct platform_device SYSMMU_PLATDEV(g2d_acp);
+
+static inline void sysmmu_set_owner(struct device *sysmmu, struct device *owner)
+{
+ sysmmu->platform_data = owner;
+}
+
+#else /* CONFIG_EXYNOS4_DEV_SYSMMU */
+
+#define sysmmu_set_owner(sysmmu, owner) do { } while (0)
+#define ASSIGN_SYSMMU_POWERDOMAIN(ipname, powerdomain) do { } while (0)
+
+#endif /* CONFIG_EXYNOS4_DEV_SYSMMU */
+
+#endif /* _ARM_MACH_EXYNOS_SYSMMU_H_ */
diff --git a/arch/arm/mach-exynos4/mach-armlex4210.c b/arch/arm/mach-exynos4/mach-armlex4210.c
index b482c62..d7d2ff5 100644
--- a/arch/arm/mach-exynos4/mach-armlex4210.c
+++ b/arch/arm/mach-exynos4/mach-armlex4210.c
@@ -155,7 +155,23 @@ static struct platform_device *armlex4210_devices[] __initdata = {
&s3c_device_hsmmc3,
&s3c_device_rtc,
&s3c_device_wdt,
- &exynos4_device_sysmmu,
+#ifdef CONFIG_EXYNOS4_DEV_SYSMMU
+ &SYSMMU_PLATDEV(sss),
+ &SYSMMU_PLATDEV(fimc0),
+ &SYSMMU_PLATDEV(fimc1),
+ &SYSMMU_PLATDEV(fimc2),
+ &SYSMMU_PLATDEV(fimc3),
+ &SYSMMU_PLATDEV(jpeg),
+ &SYSMMU_PLATDEV(fimd0),
+ &SYSMMU_PLATDEV(fimd1),
+ &SYSMMU_PLATDEV(pcie),
+ &SYSMMU_PLATDEV(g2d),
+ &SYSMMU_PLATDEV(rot),
+ &SYSMMU_PLATDEV(mdma),
+ &SYSMMU_PLATDEV(tv),
+ &SYSMMU_PLATDEV(mfc_l),
+ &SYSMMU_PLATDEV(mfc_r),
+#endif
&samsung_asoc_dma,
&armlex4210_smsc911x,
&exynos4_device_ahci,
@@ -193,6 +209,10 @@ static void __init armlex4210_map_io(void)
ARRAY_SIZE(armlex4210_uartcfgs));
}
+static void __init sysmmu_init(void)
+{
+}
+
static void __init armlex4210_machine_init(void)
{
armlex4210_smsc911x_init();
@@ -201,6 +221,8 @@ static void __init armlex4210_machine_init(void)
armlex4210_wlan_init();
+ sysmmu_init();
+
platform_add_devices(armlex4210_devices,
ARRAY_SIZE(armlex4210_devices));
}
diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c
index cec2afa..341ee39 100644
--- a/arch/arm/mach-exynos4/mach-smdkv310.c
+++ b/arch/arm/mach-exynos4/mach-smdkv310.c
@@ -42,6 +42,7 @@
#include <plat/clock.h>
#include <mach/map.h>
+#include <mach/sysmmu.h>
/* Following are default values for UCON, ULCON and UFCON UART registers */
#define SMDKV310_UCON_DEFAULT (S3C2410_UCON_TXILEVEL | \
@@ -273,7 +274,23 @@ static struct platform_device *smdkv310_devices[] __initdata = {
&exynos4_device_pd[PD_TV],
&exynos4_device_pd[PD_GPS],
&exynos4_device_spdif,
- &exynos4_device_sysmmu,
+#ifdef CONFIG_S5P_SYSTEM_MMU
+ &SYSMMU_PLATDEV(sss),
+ &SYSMMU_PLATDEV(fimc0),
+ &SYSMMU_PLATDEV(fimc1),
+ &SYSMMU_PLATDEV(fimc2),
+ &SYSMMU_PLATDEV(fimc3),
+ &SYSMMU_PLATDEV(jpeg),
+ &SYSMMU_PLATDEV(fimd0),
+ &SYSMMU_PLATDEV(fimd1),
+ &SYSMMU_PLATDEV(pcie),
+ &SYSMMU_PLATDEV(g2d),
+ &SYSMMU_PLATDEV(rot),
+ &SYSMMU_PLATDEV(mdma),
+ &SYSMMU_PLATDEV(tv),
+ &SYSMMU_PLATDEV(mfc_l),
+ &SYSMMU_PLATDEV(mfc_r),
+#endif
&samsung_asoc_dma,
&samsung_asoc_idma,
&s5p_device_fimd0,
@@ -342,6 +359,13 @@ static void __init smdkv310_reserve(void)
s5p_mfc_reserve_mem(0x43000000, 8 << 20, 0x51000000, 8 << 20);
}
+static void __init sysmmu_init(void)
+{
+ ASSIGN_SYSMMU_POWERDOMAIN(mfc, &exynos4_device_pd[PD_MFC].dev);
+ sysmmu_set_owner(&SYSMMU_PLATDEV(mfc_l).dev, &s5p_device_mfc.dev);
+ sysmmu_set_owner(&SYSMMU_PLATDEV(mfc_r).dev, &s5p_device_mfc.dev);
+}
+
static void __init smdkv310_machine_init(void)
{
s3c_i2c1_set_platdata(NULL);
@@ -365,6 +389,8 @@ static void __init smdkv310_machine_init(void)
smdkv310_ehci_init();
clk_xusbxti.rate = 24000000;
+ sysmmu_init();
+
platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
}
--
1.7.1
^ permalink raw reply related
* [PATCH 4/5] gpiolib: handle deferral probe error
From: Alan Cox @ 2011-10-07 10:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1317963790-29426-5-git-send-email-manjugk@ti.com>
On Fri, 07 Oct 2011 10:33:09 +0500
"G, Manjunath Kondaiah" <manjugk@ti.com> wrote:
>
> The gpio library should return -EPROBE_DEFER in gpio_request
> if gpio driver is not ready.
Why not use the perfectly good existing error codes we have for this ?
We have EAGAIN and EUNATCH both of which look sensible.
^ permalink raw reply
* [PATCH 1/4] ARM: OMAP3 PM: Fix IO Daisychain sequence
From: Vishwanath Sripathy @ 2011-10-07 10:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1110070217000.4611@utopia.booyaka.com>
> -----Original Message-----
> From: Paul Walmsley [mailto:paul at pwsan.com]
> Sent: Friday, October 07, 2011 1:50 PM
> To: Vishwanath BS
> Cc: linux-omap at vger.kernel.org; khilman at ti.com; linux-arm-
> kernel at lists.infradead.org
> Subject: Re: [PATCH 1/4] ARM: OMAP3 PM: Fix IO Daisychain sequence
>
> Hi
>
> a few comments:
>
> On Tue, 4 Oct 2011, Vishwanath BS wrote:
>
> > As per OMAP3630 TRM Section 3.5.7.2.2, the right sequence for
> enabling IO Daisy
> > chain is "The I/O wake-up scheme is enabled by triggering the I/O
> daisy chain
> > control (Wu clock) by programming a dedicated register
> > (PRCM.PM_WKEN_WKUP[16] EN_IO_CHAIN) in the PRCM module.Software
> must wait for
> > the I/O daisy chain to complete before it transitions the PER
> domain to a
> > nonfunctional state. This is done by polling a dedicated status
> bit in the PRCM
> > module (PRCM.PM_WKST_WKUP[16] ST_IO_CHAIN). This status bit must
> be cleared by
> > software when the bit is read to 1".
> >
> > The original code was polling on a wrong register which is fixed
> in this patch.
> > Also omap3_enable_io_chain is made non static as it's going to be
> used in
> > subsequent patches.
>
> This patch should be split into a fix (for the WKEN/WKST bug) and
> then a
> new patch that drops the 'static'. The new patch should also move
> this
> function to prm2xxx_3xxx.c for the same reason that the OMAP4
> version of
> this function should be in prminst44xx.c.
OK, Understood.
>
> In the medium-term, a bunch of the functions from prm2xxx_3xxx.c,
> prminst44xx.c, etc. that are only used by the mach-omap2/pm*.c code
> should
> be moved into the PRM driver that Tero is working on that will live
> in
> drivers/.
OK.
Vishwa
>
> >
> > Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com>
> > ---
> > arch/arm/mach-omap2/pm.h | 1 +
> > arch/arm/mach-omap2/pm34xx.c | 6 +++---
> > 2 files changed, 4 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> > index 4e166ad..9a36a7c 100644
> > --- a/arch/arm/mach-omap2/pm.h
> > +++ b/arch/arm/mach-omap2/pm.h
> > @@ -21,6 +21,7 @@ extern void omap_sram_idle(void);
> > extern int omap3_can_sleep(void);
> > extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32
> state);
> > extern int omap3_idle_init(void);
> > +extern void omap3_enable_io_chain(void);
> >
> > #if defined(CONFIG_PM_OPP)
> > extern int omap3_opp_init(void);
> > diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-
> omap2/pm34xx.c
> > index 7255d9b..61f1a5b 100644
> > --- a/arch/arm/mach-omap2/pm34xx.c
> > +++ b/arch/arm/mach-omap2/pm34xx.c
> > @@ -95,7 +95,7 @@ static inline void
> omap3_per_restore_context(void)
> > omap_gpio_restore_context();
> > }
> >
> > -static void omap3_enable_io_chain(void)
> > +void omap3_enable_io_chain(void)
> > {
> > int timeout = 0;
> >
> > @@ -105,7 +105,7 @@ static void omap3_enable_io_chain(void)
> > /* Do a readback to assure write has been done */
> > omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
> >
> > - while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
> > + while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) &
> > OMAP3430_ST_IO_CHAIN_MASK)) {
> > timeout++;
> > if (timeout > 1000) {
> > @@ -114,7 +114,7 @@ static void omap3_enable_io_chain(void)
> > return;
> > }
> >
> omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
> > - WKUP_MOD, PM_WKEN);
> > + WKUP_MOD, PM_WKST);
> > }
> > }
> > }
> > --
> > 1.7.0.4
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-
> omap" in
> > the body of a message to majordomo at vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> >
>
>
> - Paul
^ permalink raw reply
* [PATCH 2/4] ARM: OMAP4 PM: Add IO Daisychain support
From: Vishwanath Sripathy @ 2011-10-07 10:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1110070209480.4611@utopia.booyaka.com>
> -----Original Message-----
> From: Paul Walmsley [mailto:paul at pwsan.com]
> Sent: Friday, October 07, 2011 1:44 PM
> To: Vishwanath BS
> Cc: linux-omap at vger.kernel.org; khilman at ti.com; linux-arm-
> kernel at lists.infradead.org; Rajendra Nayak
> Subject: Re: [PATCH 2/4] ARM: OMAP4 PM: Add IO Daisychain support
>
> Hi
>
> some comments:
>
> On Tue, 4 Oct 2011, Vishwanath BS wrote:
>
> > From: Rajendra Nayak <rnayak@ti.com>
> >
> > patch adds IO Daisychain support for OMAP4 as per section 3.9.4 in
> OMAP4430
> > Public TRM.
> >
> > Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> > Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com>
> > ---
> > arch/arm/mach-omap2/pm.h | 1 +
> > arch/arm/mach-omap2/pm44xx.c | 36
> ++++++++++++++++++++++++++++++++++++
> > 2 files changed, 37 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> > index 9a36a7c..2e09d72 100644
> > --- a/arch/arm/mach-omap2/pm.h
> > +++ b/arch/arm/mach-omap2/pm.h
> > @@ -22,6 +22,7 @@ extern int omap3_can_sleep(void);
> > extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32
> state);
> > extern int omap3_idle_init(void);
> > extern void omap3_enable_io_chain(void);
> > +extern void omap4_trigger_wuclk_ctrl(void);
> >
> > #if defined(CONFIG_PM_OPP)
> > extern int omap3_opp_init(void);
> > diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-
> omap2/pm44xx.c
> > index 59a870b..aa7cff4 100644
> > --- a/arch/arm/mach-omap2/pm44xx.c
> > +++ b/arch/arm/mach-omap2/pm44xx.c
> > @@ -16,8 +16,17 @@
> > #include <linux/err.h>
> > #include <linux/slab.h>
> >
> > +#include <plat/common.h>
> > +
> > #include "powerdomain.h"
> > #include <mach/omap4-common.h>
> > +#include "pm.h"
> > +#include "cm-regbits-44xx.h"
> > +#include "cminst44xx.h"
> > +#include "prm-regbits-44xx.h"
> > +#include "prcm44xx.h"
> > +#include "prm44xx.h"
> > +#include "prminst44xx.h"
> >
> > struct power_state {
> > struct powerdomain *pwrdm;
> > @@ -30,6 +39,33 @@ struct power_state {
> >
> > static LIST_HEAD(pwrst_list);
> >
> > +#define MAX_IOPAD_LATCH_TIME 1000
>
> This macro is missing a comment, which should precede it, describing
> what
> this value is.
OK
>
> > +
> > +void omap4_trigger_wuclk_ctrl(void)
> > +{
> > + int i = 0;
> > +
> > + /* Enable GLOBAL_WUEN */
> > + if (!omap4_cminst_read_inst_reg_bits(OMAP4430_PRM_PARTITION,
> > + OMAP4430_PRM_DEVICE_INST,
> OMAP4_PRM_IO_PMCTRL_OFFSET,
> > + OMAP4430_GLOBAL_WUEN_MASK))
>
> The above line doesn't look right. It's accessing a PRM instance
> register
> with omap4_cminst_*()? Shouldn't that be omap4_prminst_*()?
Ya, it would make sense to use omap4_prminst_* though functionally both
have the same effect.
>
> > +
> omap4_prminst_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK,
> > + OMAP4430_GLOBAL_WUEN_MASK, OMAP4430_PRM_PARTITION,
> > + OMAP4430_PRM_DEVICE_INST,
> OMAP4_PRM_IO_PMCTRL_OFFSET);
> > +
> > + /* Trigger WUCLKIN enable */
> > + omap4_prminst_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK,
> OMAP4430_WUCLK_CTRL_MASK,
> > + OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
> OMAP4_PRM_IO_PMCTRL_OFFSET);
> > + omap_test_timeout(
> > + ((omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
> OMAP4430_PRM_DEVICE_INST, OMAP4_PRM_IO_PMCTRL_OFFSET)
> > + >> OMAP4430_WUCLK_STATUS_SHIFT) == 1),
> > + MAX_IOPAD_LATCH_TIME, i);
> > + /* Trigger WUCLKIN disable */
> > + omap4_prminst_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0,
> > + OMAP4430_PRM_PARTITION, OMAP4430_PRM_DEVICE_INST,
> OMAP4_PRM_IO_PMCTRL_OFFSET);
> > + return;
> > +}
>
> This function belongs in mach-omap2/prminst44xx.c. I still think it
> would
> be good if we moved all PRM/CM direct register accesses into prm*.c
> or
> cm*.c files in mach-omap2/. Then none of those prm*.h includes
> would be
> needed in pm44xx.c either.
OK. Let me explore that.
Regards
Vishwa
>
> > +
> > #ifdef CONFIG_SUSPEND
> > static int omap4_pm_suspend(void)
> > {
> > --
> > 1.7.0.4
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-
> omap" in
> > the body of a message to majordomo at vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> >
>
>
> - Paul
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox