* [PATCH 11/16] pcmcia: sharpsl: don't discard sharpsl_pcmcia_ops
From: Arnd Bergmann @ 2012-10-05 14:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349448930-23976-1-git-send-email-arnd@arndb.de>
The sharpsl_pcmcia_ops structure gets passed into
sa11xx_drv_pcmcia_probe, where it gets accessed at run-time,
unlike all other pcmcia drivers that pass their structures
into platform_device_add_data, which makes a copy.
This means the gcc warning is valid and the structure
must not be marked as __initdata.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Pavel Machek <pavel@suse.cz>
Cc: linux-pcmcia at lists.infradead.org
Cc: Jochen Friedrich <jochen@scram.de>
Cc: stable at vger.kernel.org
---
drivers/pcmcia/pxa2xx_sharpsl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
index b066273..7dd879c 100644
--- a/drivers/pcmcia/pxa2xx_sharpsl.c
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c
@@ -194,7 +194,7 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
sharpsl_pcmcia_init_reset(skt);
}
-static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = {
+static struct pcmcia_low_level sharpsl_pcmcia_ops = {
.owner = THIS_MODULE,
.hw_init = sharpsl_pcmcia_hw_init,
.socket_state = sharpsl_pcmcia_socket_state,
--
1.7.10
^ permalink raw reply related
* [PATCH 12/16] video: mark nuc900fb_map_video_memory as __devinit
From: Arnd Bergmann @ 2012-10-05 14:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349448930-23976-1-git-send-email-arnd@arndb.de>
nuc900fb_map_video_memory is called by an devinit function
that may be called at run-time, but the function itself is
marked __init and will be discarded after boot.
To avoid calling into a function that may have been overwritten,
mark nuc900fb_map_video_memory itself as __devinit.
Without this patch, building nuc950_defconfig results in:
WARNING: drivers/video/built-in.o(.devinit.text+0x26c): Section mismatch in reference from the function nuc900fb_probe() to the function .init.text:nuc900fb_map_video_memory()
The function __devinit nuc900fb_probe() references
a function __init nuc900fb_map_video_memory().
If nuc900fb_map_video_memory is only used by nuc900fb_probe then
annotate nuc900fb_map_video_memory with a matching annotation.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Wan ZongShun <mcuos.com@gmail.com>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: linux-fbdev at vger.kernel.org
---
drivers/video/nuc900fb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index e10f551..b31b12b 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -387,7 +387,7 @@ static int nuc900fb_init_registers(struct fb_info *info)
* The buffer should be a non-cached, non-buffered, memory region
* to allow palette and pixel writes without flushing the cache.
*/
-static int __init nuc900fb_map_video_memory(struct fb_info *info)
+static int __devinit nuc900fb_map_video_memory(struct fb_info *info)
{
struct nuc900fb_info *fbi = info->par;
dma_addr_t map_dma;
--
1.7.10
^ permalink raw reply related
* [PATCH 13/16] ARM: be really quiet when building with 'make -s'
From: Arnd Bergmann @ 2012-10-05 14:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349448930-23976-1-git-send-email-arnd@arndb.de>
Sometimes we want the kernel build process to only print messages
on errors, e.g. in automated build testing. This uses the "kecho"
macro that the build system provides to hide a few informational
messages. Nothing changes for a regular "make" or "make V=1".
Without this patch, building any ARM kernel results in:
Kernel: arch/arm/boot/Image is ready
Kernel: arch/arm/boot/zImage is ready
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Nicolas Pitre <nicolas.pitre@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Michal Marek <mmarek@suse.cz>
---
arch/arm/boot/Makefile | 10 +++++-----
arch/arm/tools/Makefile | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index c877087..89680f2 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -31,7 +31,7 @@ ifeq ($(CONFIG_XIP_KERNEL),y)
$(obj)/xipImage: vmlinux FORCE
$(call if_changed,objcopy)
- @echo ' Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
+ $(kecho) ' Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
$(obj)/Image $(obj)/zImage: FORCE
@echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)'
@@ -46,14 +46,14 @@ $(obj)/xipImage: FORCE
$(obj)/Image: vmlinux FORCE
$(call if_changed,objcopy)
- @echo ' Kernel: $@ is ready'
+ $(kecho) ' Kernel: $@ is ready'
$(obj)/compressed/vmlinux: $(obj)/Image FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed $@
$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
- @echo ' Kernel: $@ is ready'
+ $(kecho) ' Kernel: $@ is ready'
endif
@@ -88,7 +88,7 @@ fi
$(obj)/uImage: $(obj)/zImage FORCE
@$(check_for_multiple_loadaddr)
$(call if_changed,uimage)
- @echo ' Image $@ is ready'
+ $(kecho) ' Image $@ is ready'
$(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
$(Q)$(MAKE) $(build)=$(obj)/bootp $@
@@ -96,7 +96,7 @@ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
$(obj)/bootpImage: $(obj)/bootp/bootp FORCE
$(call if_changed,objcopy)
- @echo ' Kernel: $@ is ready'
+ $(kecho) ' Kernel: $@ is ready'
PHONY += initrd FORCE
initrd:
diff --git a/arch/arm/tools/Makefile b/arch/arm/tools/Makefile
index 635cb18..cd60a81 100644
--- a/arch/arm/tools/Makefile
+++ b/arch/arm/tools/Makefile
@@ -5,6 +5,6 @@
#
include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
- @echo ' Generating $@'
+ $(kecho) ' Generating $@'
@mkdir -p $(dir $@)
$(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
--
1.7.10
^ permalink raw reply related
* [PATCH 14/16] ARM: pxa: armcore: fix PCI PIO warnings
From: Arnd Bergmann @ 2012-10-05 14:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349448930-23976-1-git-send-email-arnd@arndb.de>
The it8152 PCI host used on the pxa/cm_x2xx machines
uses the old-style I/O window registration. This should
eventually get converted to pci_ioremap_io() but for
now, let's cast the IT8152_IO_BASE constant to an integer
type to get rid of the warnings.
Without this patch, building cm_x2xx_defconfig results in:
arch/arm/common/it8152.c: In function 'it8152_pci_setup':
arch/arm/common/it8152.c:287:18: warning: assignment makes integer from pointer without a cast [enabled by default]
arch/arm/common/it8152.c:288:16: warning: assignment makes integer from pointer without a cast [enabled by default]
arch/arm/common/it8152.c:291:17: warning: assignment makes integer from pointer without a cast [enabled by default]
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Krzysztof Halasa <khc@pm.waw.pl>
Cc: Mike Rapoport <mike@compulab.co.il>
Cc: Igor Grinberg <grinberg@compulab.co.il>
Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
Cc: Eric Miao <eric.y.miao@gmail.com>
---
arch/arm/common/it8152.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c
index c4110d1..001f491 100644
--- a/arch/arm/common/it8152.c
+++ b/arch/arm/common/it8152.c
@@ -284,11 +284,17 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)
int __init it8152_pci_setup(int nr, struct pci_sys_data *sys)
{
- it8152_io.start = IT8152_IO_BASE + 0x12000;
- it8152_io.end = IT8152_IO_BASE + 0x12000 + 0x100000;
+ /*
+ * FIXME: use pci_ioremap_io to remap the IO space here and
+ * move over to the generic io.h implementation.
+ * This requires solving the same problem for PXA PCMCIA
+ * support.
+ */
+ it8152_io.start = (unsigned long)IT8152_IO_BASE + 0x12000;
+ it8152_io.end = (unsigned long)IT8152_IO_BASE + 0x12000 + 0x100000;
sys->mem_offset = 0x10000000;
- sys->io_offset = IT8152_IO_BASE;
+ sys->io_offset = (unsigned long)IT8152_IO_BASE;
if (request_resource(&ioport_resource, &it8152_io)) {
printk(KERN_ERR "PCI: unable to allocate IO region\n");
--
1.7.10
^ permalink raw reply related
* [PATCH 15/16] spi/s3c64xx: use correct dma_transfer_direction type
From: Arnd Bergmann @ 2012-10-05 14:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349448930-23976-1-git-send-email-arnd@arndb.de>
There is a subtle difference between dma_transfer_direction and
dma_data_direction: the former is used by the dmaengine framework,
while the latter is used by the dma-mapping API. Although the
purpose is comparable, the actual values are different and must
not be mixed. In this case, the driver just wants to use
dma_transfer_direction.
Without this patch, building s3c6400_defconfig results in:
drivers/spi/spi-s3c64xx.c: In function 's3c64xx_spi_dmacb':
drivers/spi/spi-s3c64xx.c:239:21: warning: comparison between
'enum dma_data_direction' and 'enum dma_transfer_direction' [-Wenum-compare]
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-samsung-soc at vger.kernel.org
Cc: spi-devel-general at lists.sourceforge.net
---
drivers/spi/spi-s3c64xx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
index d1c8441f..2e44dd6 100644
--- a/drivers/spi/spi-s3c64xx.c
+++ b/drivers/spi/spi-s3c64xx.c
@@ -132,7 +132,7 @@
struct s3c64xx_spi_dma_data {
unsigned ch;
- enum dma_data_direction direction;
+ enum dma_transfer_direction direction;
enum dma_ch dmach;
struct property *dma_prop;
};
--
1.7.10
^ permalink raw reply related
* [PATCH 16/16] ARM: pass -marm to gcc by default for both C and assembler
From: Arnd Bergmann @ 2012-10-05 14:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349448930-23976-1-git-send-email-arnd@arndb.de>
The Linaro cross toolchain and probably others nowadays default to
building in THUMB2 mode. When building a kernel for a CPU that does
not support THUMB2, the compiler complains about incorrect flags.
We can work around this by setting -marm for all non-T2 builds.
Without this patch, building assabet_defconfig results in:
usr/initramfs_data.S:1:0: warning: target CPU does not support THUMB instructions [enabled by default]
arch/arm/nwfpe/entry.S:1:0: warning: target CPU does not support THUMB instructions [enabled by default]
firmware/cis/PCMLM28.cis.gen.S:1:0: warning: target CPU does not support THUMB instructions [enabled by default]
(and many more)
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Dave Martin <dave.martin@linaro.org>
---
arch/arm/Makefile | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index a051dfb..4391427 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -21,8 +21,6 @@ endif
OBJCOPYFLAGS :=-O binary -R .comment -S
GZFLAGS :=-9
#KBUILD_CFLAGS +=-pipe
-# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
-KBUILD_CFLAGS +=$(call cc-option,-marm,)
# Never generate .eh_frame
KBUILD_CFLAGS += $(call cc-option,-fno-dwarf2-cfi-asm)
@@ -105,17 +103,20 @@ endif
ifeq ($(CONFIG_THUMB2_KERNEL),y)
AFLAGS_AUTOIT :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it)
AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
-CFLAGS_THUMB2 :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
-AFLAGS_THUMB2 :=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb
+CFLAGS_ISA :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
+AFLAGS_ISA :=$(CFLAGS_ISA) -Wa$(comma)-mthumb
# Work around buggy relocation from gas if requested:
ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y)
CFLAGS_MODULE +=-fno-optimize-sibling-calls
endif
+else
+CFLAGS_ISA :=$(call cc-option,-marm,)
+AFLAGS_ISA :=$(CFLAGS_ISA)
endif
# Need -Uarm for gcc < 3.x
-KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_THUMB2) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
-KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_THUMB2) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
+KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
+KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
CHECKFLAGS += -D__arm__
--
1.7.10
^ permalink raw reply related
* [PATCH 2/2] ARM: Exynos4: Register clocks via common clock framework
From: Sylwester Nawrocki @ 2012-10-05 15:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349093361-18820-3-git-send-email-thomas.abraham@linaro.org>
Hello,
On 10/01/2012 02:09 PM, chander.kashyap at linaro.org wrote:
> From: Thomas Abraham<thomas.abraham@linaro.org>
>
> Register clocks for Exynos4 platfotms using common clock framework.
> Also included are set of helper functions for clock registration
> that can be reused on other Samsung platforms as well.
>
> Cc: Mike Turquette<mturquette@linaro.org>
> Cc: Kukjin Kim<kgene.kim@samsung.com>
> Signed-off-by: Thomas Abraham<thomas.abraham@linaro.org>
> ---
> arch/arm/mach-exynos/Kconfig | 1 +
> arch/arm/mach-exynos/common.h | 3 +
> arch/arm/mach-exynos/mct.c | 11 +-
> arch/arm/plat-samsung/Kconfig | 4 +-
> drivers/clk/Makefile | 1 +
> drivers/clk/clk.c | 12 +-
> drivers/clk/samsung/Makefile | 6 +
> drivers/clk/samsung/clk-exynos4.c | 585 +++++++++++++++++++++++++++++++++++++
> drivers/clk/samsung/clk.c | 231 +++++++++++++++
> drivers/clk/samsung/clk.h | 190 ++++++++++++
> 10 files changed, 1037 insertions(+), 7 deletions(-)
> create mode 100644 drivers/clk/samsung/Makefile
> create mode 100644 drivers/clk/samsung/clk-exynos4.c
> create mode 100644 drivers/clk/samsung/clk.c
> create mode 100644 drivers/clk/samsung/clk.h
...
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 56e4495..456c50b 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1196,6 +1196,7 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
> int __clk_init(struct device *dev, struct clk *clk)
> {
> int i, ret = 0;
> + u8 index;
> struct clk *orphan;
> struct hlist_node *tmp, *tmp2;
>
> @@ -1259,6 +1260,7 @@ int __clk_init(struct device *dev, struct clk *clk)
> __clk_lookup(clk->parent_names[i]);
> }
>
> +
> clk->parent = __clk_init_parent(clk);
>
> /*
> @@ -1298,11 +1300,13 @@ int __clk_init(struct device *dev, struct clk *clk)
> * this clock
> */
> hlist_for_each_entry_safe(orphan, tmp, tmp2,&clk_orphan_list, child_node)
> - for (i = 0; i< orphan->num_parents; i++)
> - if (!strcmp(clk->name, orphan->parent_names[i])) {
> + if (orphan->num_parents> 1) {
> + index = orphan->ops->get_parent(orphan->hw);
> + if (!strcmp(clk->name, orphan->parent_names[index]))
> __clk_reparent(orphan, clk);
> - break;
> - }
> + } else if (!strcmp(clk->name, orphan->parent_names[0])) {
> + __clk_reparent(orphan, clk);
> + }
As this touches generic code it should rather be put into a separate patch,
along with an explanation why such a change is needed.
>
> /*
> * optional platform-specific magic
> diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
> new file mode 100644
> index 0000000..69487f7
> --- /dev/null
> +++ b/drivers/clk/samsung/Makefile
> @@ -0,0 +1,6 @@
> +#
> +# Samsung Clock specific Makefile
> +#
> +
> +obj-$(CONFIG_PLAT_SAMSUNG) += clk.o
> +obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o
> diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
> new file mode 100644
> index 0000000..74a6f03
> --- /dev/null
> +++ b/drivers/clk/samsung/clk-exynos4.c
> @@ -0,0 +1,585 @@
> +/*
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * Copyright (c) 2012 Linaro Ltd.
> + *
> + * 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.
> + *
> + * Common Clock Framework support for all Exynos4 platforms
> +*/
> +
> +#include<linux/clk.h>
> +#include<linux/clkdev.h>
> +#include<linux/io.h>
> +#include<linux/clk-provider.h>
> +
> +#include<plat/pll.h>
> +#include<plat/cpu.h>
> +#include<mach/regs-clock.h>
> +#include<mach/sysmmu.h>
> +#include<plat/map-s5p.h>
> +
> +#include "clk.h"
> +
> +#define EXYNOS4_OP_MODE (S5P_VA_CHIPID + 8)
> +
> +static const char *pll_parent_names[] __initdata = { "fin_pll" };
> +static const char *fin_pll_parents[] __initdata = { "xxti", "xusbxti" };
> +static const char *mout_apll_parents[] __initdata = { "fin_pll", "fout_apll", };
> +static const char *mout_mpll_parents[] __initdata = { "fin_pll", "fout_mpll", };
> +static const char *mout_epll_parents[] __initdata = { "fin_pll", "fout_epll", };
> +
> +static const char *sclk_ampll_parents[] __initdata = {
> + "mout_mpll", "sclk_apll", };
> +
> +static const char *sclk_evpll_parents[] __initdata = {
> + "mout_epll", "mout_vpll", };
> +
> +static const char *mout_core_parents[] __initdata = {
> + "mout_apll", "mout_mpll", };
> +
> +static const char *mout_mfc_parents[] __initdata = {
> + "mout_mfc0", "mout_mfc1", };
> +
> +static const char *mout_dac_parents[] __initdata = {
> + "mout_vpll", "sclk_hdmiphy", };
> +
> +static const char *mout_hdmi_parents[] __initdata = {
> + "sclk_pixel", "sclk_hdmiphy", };
> +
> +static const char *mout_mixer_parents[] __initdata = {
> + "sclk_dac", "sclk_hdmi", };
> +
> +static const char *group1_parents[] __initdata = {
> + "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
> + "none", "sclk_hdmiphy", "mout_mpll", "mout_epll",
> + "mout_vpll" };
> +
> +static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] = {
> + FRATE_CLK(NULL, "xxti", NULL, CLK_IS_ROOT, 24000000),
> + FRATE_CLK(NULL, "xusbxti", NULL, CLK_IS_ROOT, 24000000),
> + FRATE_CLK(NULL, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
> + FRATE_CLK(NULL, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
> + FRATE_CLK(NULL, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
> +};
> +
> +static struct samsung_mux_clock exynos4_mux_clks[] = {
> + MUXCLK(NULL, "fin_pll", fin_pll_parents, 0,
> + EXYNOS4_OP_MODE, 0, 1, 0),
> + MUXCLK(NULL, "mout_apll", mout_apll_parents, 0,
> + EXYNOS4_CLKSRC_CPU, 0, 1, 0),
> + MUXCLK(NULL, "mout_epll", mout_epll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 4, 1, 0),
> + MUXCLK(NULL, "mout_core", mout_core_parents, 0,
> + EXYNOS4_CLKSRC_CPU, 16, 1, 0),
> + MUXCLK(NULL, "mout_aclk_200", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 12, 1, 0),
> + MUXCLK(NULL, "mout_aclk_100", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 16, 1, 0),
> + MUXCLK(NULL, "mout_aclk_160", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 20, 1, 0),
> + MUXCLK(NULL, "mout_aclk_133", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_TOP0, 24, 1, 0),
> + MUXCLK("exynos4210-uart.0", "mout_uart0", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 0, 4, 0),
> + MUXCLK("exynos4210-uart.1", "mout_uart1", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 4, 4, 0),
> + MUXCLK("exynos4210-uart.2", "mout_uart2", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 8, 4, 0),
> + MUXCLK("exynos4210-uart.3", "mout_uart3", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL0, 12, 4, 0),
> + MUXCLK("exynos4-sdhci.0", "mout_mmc0", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 0, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc1", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 4, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc2", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 8, 4, 0),
> + MUXCLK("exynos4-sdhci.1", "mout_mmc3", group1_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 12, 4, 0),
> + MUXCLK("exynos4210-spi.0", "mout_spi0", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL1, 16, 4, 0),
> + MUXCLK("exynos4210-spi.1", "mout_spi1", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL1, 20, 4, 0),
> + MUXCLK("exynos4210-spi.2", "mout_spi2", group1_parents, 0,
> + EXYNOS4_CLKSRC_PERIL1, 24, 4, 0),
> + MUXCLK(NULL, "mout_sata", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_FSYS, 24, 1, 0),
> + MUXCLK(NULL, "mout_mfc0", sclk_ampll_parents, 0,
> + EXYNOS4_CLKSRC_MFC, 0, 1, 0),
> + MUXCLK(NULL, "mout_mfc1", sclk_evpll_parents, 0,
> + EXYNOS4_CLKSRC_MFC, 4, 1, 0),
> + MUXCLK("s5p-mfc", "mout_mfc", mout_mfc_parents, 0,
> + EXYNOS4_CLKSRC_MFC, 8, 1, 0),
> + MUXCLK("s5p-mipi-csis.0", "mout_csis0", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 24, 4, 0),
> + MUXCLK("s5p-mipi-csis.1", "mout_csis1", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 28, 4, 0),
> + MUXCLK(NULL, "mout_cam0", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 16, 4, 0),
> + MUXCLK(NULL, "mout_cam1", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 20, 4, 0),
> + MUXCLK("exynos4-fimc.0", "mout_fimc0", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 0, 4, 0),
> + MUXCLK("exynos4-fimc.1", "mout_fimc1", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 4, 4, 0),
> + MUXCLK("exynos4-fimc.2", "mout_fimc2", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 8, 4, 0),
> + MUXCLK("exynos4-fimc.3", "mout_fimc3", group1_parents, 0,
> + EXYNOS4_CLKSRC_CAM, 12, 4, 0),
> + MUXCLK("exynos4-fb.0", "mout_fimd0", group1_parents, 0,
> + EXYNOS4_CLKSRC_LCD0, 0, 4, 0),
> + MUXCLK(NULL, "sclk_dac", mout_dac_parents, 0,
> + EXYNOS4_CLKSRC_TV, 8, 1, 0),
> + MUXCLK(NULL, "sclk_hdmi", mout_hdmi_parents, 0,
> + EXYNOS4_CLKSRC_TV, 0, 1, 0),
> + MUXCLK(NULL, "sclk_mixer", mout_mixer_parents, 0,
> + EXYNOS4_CLKSRC_TV, 4, 1, 0),
> +};
> +
> +static struct samsung_div_clock exynos4_div_clks[] = {
> + DIVCLK(NULL, "sclk_apll", "mout_apll", 0,
> + EXYNOS4_CLKDIV_CPU, 24, 3, 0),
> + DIVCLK(NULL, "div_core", "mout_core", 0,
> + EXYNOS4_CLKDIV_CPU, 0, 3, 0),
> + DIVCLK(NULL, "armclk", "div_core", 0,
> + EXYNOS4_CLKDIV_CPU, 28, 3, 0),
> + DIVCLK(NULL, "aclk_200", "mout_aclk_200", 0,
> + EXYNOS4_CLKDIV_TOP, 0, 3, 0),
> + DIVCLK(NULL, "aclk_100", "mout_aclk_100", 0,
> + EXYNOS4_CLKDIV_TOP, 4, 4, 0),
> + DIVCLK(NULL, "aclk_160", "mout_aclk_160", 0,
> + EXYNOS4_CLKDIV_TOP, 8, 3, 0),
> + DIVCLK(NULL, "aclk_133", "mout_aclk_133", 0,
> + EXYNOS4_CLKDIV_TOP, 12, 3, 0),
> + DIVCLK("exynos4210-uart.0", "div_uart0", "mout_uart0", 0,
> + EXYNOS4_CLKDIV_PERIL0, 0, 4, 0),
> + DIVCLK("exynos4210-uart.1", "div_uart1", "mout_uart1", 0,
> + EXYNOS4_CLKDIV_PERIL0, 4, 4, 0),
> + DIVCLK("exynos4210-uart.2", "div_uart2", "mout_uart2", 0,
> + EXYNOS4_CLKDIV_PERIL0, 8, 4, 0),
> + DIVCLK("exynos4210-uart.3", "div_uart3", "mout_uart3", 0,
> + EXYNOS4_CLKDIV_PERIL0, 12, 4, 0),
> + DIVCLK("exynos4-sdhci.0", "div_mmc0", "mout_mmc0", 0,
> + EXYNOS4_CLKDIV_FSYS1, 0, 4, 0),
> + DIVCLK("exynos4-sdhci.0", "div_mmc0_pre", "div_mmc0", 0,
> + EXYNOS4_CLKDIV_FSYS1, 8, 8, 0),
> + DIVCLK("exynos4-sdhci.1", "div_mmc1", "mout_mmc1", 0,
> + EXYNOS4_CLKDIV_FSYS1, 16, 4, 0),
> + DIVCLK("exynos4-sdhci.1", "div_mmc1_pre", "div_mmc1", 0,
> + EXYNOS4_CLKDIV_FSYS1, 24, 8, 0),
> + DIVCLK("exynos4-sdhci.2", "div_mmc2", "mout_mmc2", 0,
> + EXYNOS4_CLKDIV_FSYS2, 0, 4, 0),
> + DIVCLK("exynos4-sdhci.2", "div_mmc2_pre", "div_mmc2", 0,
> + EXYNOS4_CLKDIV_FSYS2, 8, 8, 0),
> + DIVCLK("exynos4-sdhci.3", "div_mmc3", "mout_mmc3", 0,
> + EXYNOS4_CLKDIV_FSYS2, 16, 4, 0),
> + DIVCLK("exynos4-sdhci.3", "div_mmc3_pre", "div_mmc3", 0,
> + EXYNOS4_CLKDIV_FSYS2, 24, 8, 0),
> + DIVCLK("exynos4210-spi.0", "div_spi0", "mout_spi0", 0,
> + EXYNOS4_CLKDIV_PERIL1, 0, 4, 0),
> + DIVCLK("exynos4210-spi.1", "div_spi1", "mout_spi1", 0,
> + EXYNOS4_CLKDIV_PERIL1, 16, 4, 0),
> + DIVCLK("exynos4210-spi.2", "div_spi2", "mout_spi2", 0,
> + EXYNOS4_CLKDIV_PERIL2, 0, 4, 0),
> + DIVCLK("exynos4210-spi.0", "div_spi0_pre", "div_spi0", 0,
> + EXYNOS4_CLKDIV_PERIL1, 8, 8, 0),
> + DIVCLK("exynos4210-spi.1", "div_spi1_pre", "div_spi1", 0,
> + EXYNOS4_CLKDIV_PERIL1, 24, 8, 0),
> + DIVCLK("exynos4210-spi.2", "div_spi2_pre", "div_spi2", 0,
> + EXYNOS4_CLKDIV_PERIL2, 8, 8, 0),
> + DIVCLK(NULL, "div_sata", "mout_sata", 0,
> + EXYNOS4_CLKDIV_FSYS0, 20, 4, 0),
> + DIVCLK("s5p-mfc", "div_mfc", "mout_mfc", 0,
> + EXYNOS4_CLKDIV_MFC, 0, 4, 0),
> + DIVCLK("s5p-mipi-csis.0", "div_csis0", "mout_csis0", 0,
> + EXYNOS4_CLKDIV_CAM, 24, 4, 0),
> + DIVCLK("s5p-mipi-csis.1", "div_csis1", "mout_csis1", 0,
> + EXYNOS4_CLKDIV_CAM, 28, 4, 0),
> + DIVCLK(NULL, "div_cam0", "mout_cam0", 0,
> + EXYNOS4_CLKDIV_CAM, 16, 4, 0),
> + DIVCLK(NULL, "div_cam1", "mout_cam1", 0,
> + EXYNOS4_CLKDIV_CAM, 20, 4, 0),
> + DIVCLK("exynos4-fimc.0", "div_fimc0", "mout_fimc0", 0,
> + EXYNOS4_CLKDIV_CAM, 0, 4, 0),
> + DIVCLK("exynos4-fimc.1", "div_fimc1", "mout_fimc1", 0,
> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
> + DIVCLK("exynos4-fimc.2", "div_fimc2", "mout_fimc2", 0,
> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
> + DIVCLK("exynos4-fimc.3", "div_fimc3", "mout_fimc3", 0,
> + EXYNOS4_CLKDIV_CAM, 4, 4, 0),
> + DIVCLK("exynos4-fb.0", "div_fimd0", "mout_fimd0", 0,
> + EXYNOS4_CLKDIV_LCD0, 0, 4, 0),
> + DIVCLK(NULL, "sclk_pixel", "mout_vpll", 0,
> + EXYNOS4_CLKDIV_TV, 0, 4, 0),
> +};
> +
> +struct samsung_gate_clock exynos4_gate_clks[] = {
> + GATECLK("exynos4210-uart.0", "uart0", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 0, "uart"),
> + GATECLK("exynos4210-uart.1", "uart1", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 1, "uart"),
> + GATECLK("exynos4210-uart.2", "uart2", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 2, "uart"),
> + GATECLK("exynos4210-uart.3", "uart3", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 3, "uart"),
> + GATECLK("exynos4210-uart.4", "uart4", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 4, "uart"),
> + GATECLK("exynos4210-uart.5", "uart5", "aclk_100", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKGATE_IP_PERIL, 5, "uart"),
> + GATECLK("exynos4210-uart.0", "uclk0", "div_uart0", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 0, "clk_uart_baud0"),
> + GATECLK("exynos4210-uart.1", "uclk1", "div_uart1", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 4, "clk_uart_baud0"),
> + GATECLK("exynos4210-uart.2", "uclk2", "div_uart2", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 8, "clk_uart_baud0"),
> + GATECLK("exynos4210-uart.3", "uclk3", "div_uart3", CLK_SET_RATE_PARENT,
> + EXYNOS4_CLKSRC_MASK_PERIL0, 12, "clk_uart_baud0"),
> + GATECLK(NULL, "timers", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 24, NULL),
> + GATECLK("s5p-mipi-csis.0", "csis", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 5, NULL),
> + GATECLK(NULL, "jpeg", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 6, NULL),
> + GATECLK("exynos4-fimc.0", "fimc0", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 0, "fimc"),
> + GATECLK("exynos4-fimc.1", "fimc1", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 1, "fimc"),
> + GATECLK("exynos4-fimc.2", "fimc2", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 2, "fimc"),
> + GATECLK("exynos4-fimc.3", "fimc3", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 3, "fimc"),
> + GATECLK("exynos4-sdhci.0", "hsmmc0", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 5, "hsmmc"),
> + GATECLK("exynos4-sdhci.1", "hsmmc1", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 6, "hsmmc"),
> + GATECLK("exynos4-sdhci.2", "hsmmc2", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 7, "hsmmc"),
> + GATECLK("exynos4-sdhci.3", "hsmmc3", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 8, "hsmmc"),
> + GATECLK(NULL, "dwmmc", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 9, NULL),
> + GATECLK("s5p-sdo", "dac", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 2, NULL),
> + GATECLK("s5p-mixer", "mixer", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 1, NULL),
> + GATECLK("s5p-mixer", "vp", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 0, NULL),
> + GATECLK("exynos4-hdmi", "hdmi", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 3, NULL),
> + GATECLK("exynos4-hdmi", "hdmiphy", "aclk_160", 0,
> + S5P_HDMI_PHY_CONTROL, 0, NULL),
> + GATECLK("s5p-sdo", "dacphy", "aclk_160", 0,
> + S5P_DAC_PHY_CONTROL, 0, NULL),
> + GATECLK(NULL, "adc", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 15, NULL),
> + GATECLK(NULL, "keypad", "aclk_100", 0,
> + EXYNOS4210_CLKGATE_IP_PERIR, 16, NULL),
> + GATECLK(NULL, "rtc", "aclk_100", 0,
> + EXYNOS4210_CLKGATE_IP_PERIR, 15, NULL),
> + GATECLK(NULL, "watchdog", "aclk_100", 0,
> + EXYNOS4210_CLKGATE_IP_PERIR, 14, NULL),
> + GATECLK(NULL, "usbhost", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 12, NULL),
> + GATECLK(NULL, "otg", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 13, NULL),
> + GATECLK("exynos4210-spi.0", "spi0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 16, "spi"),
> + GATECLK("exynos4210-spi.1", "spi1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 17, "spi"),
> + GATECLK("exynos4210-spi.2", "spi2", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 18, "spi"),
> + GATECLK("samsung-i2s.0", "iis0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 19, "iis"),
> + GATECLK("samsung-i2s.1", "iis1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 20, "iis"),
> + GATECLK("samsung-i2s.2", "iis2", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 21, "iis"),
> + GATECLK("samsung-ac97", "ac97", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 27, NULL),
> + GATECLK("s5p-mfc", "mfc", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_MFC, 0, NULL),
> + GATECLK("s3c2440-i2c.0", "i2c0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 6, "i2c"),
> + GATECLK("s3c2440-i2c.1", "i2c1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 7, "i2c"),
> + GATECLK("s3c2440-i2c.2", "i2c2", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 8, "i2c"),
> + GATECLK("s3c2440-i2c.3", "i2c3", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 9, "i2c"),
> + GATECLK("s3c2440-i2c.4", "i2c4", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 10, "i2c"),
> + GATECLK("s3c2440-i2c.5", "i2c5", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 11, "i2c"),
> + GATECLK("s3c2440-i2c.6", "i2c6", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 12, "i2c"),
> + GATECLK("s3c2440-i2c.7", "i2c7", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 13, "i2c"),
> + GATECLK("s3c2440-hdmiphy-i2c", "i2c", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_PERIL, 14, NULL),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_l, 0), "sysmmu0", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_MFC, 1, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(mfc_r, 1), "sysmmu1", "aclk_100", 0,
> + EXYNOS4_CLKGATE_IP_MFC, 2, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(tv, 2), "sysmmu2", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_TV, 4, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(jpeg, 3), "sysmmu3", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 11, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(rot, 4), "sysmmu4", "aclk_200", 0,
> + EXYNOS4210_CLKGATE_IP_IMAGE, 4, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc0, 5), "sysmmu5", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 7, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc1, 6), "sysmmu6", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 8, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc2, 7), "sysmmu7", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 9, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimc3, 8), "sysmmu8", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_CAM, 10, "sysmmu"),
> + GATECLK(SYSMMU_CLOCK_DEVNAME(fimd, 10), "sysmmu10", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_LCD0, 4, "sysmmu"),
> + GATECLK("dma-pl330.0", "dma0", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 0, "dma"),
> + GATECLK("dma-pl330.1", "dma1", "aclk_133", 0,
> + EXYNOS4_CLKGATE_IP_FSYS, 1, "dma"),
> + GATECLK("exynos4-fb.0", "fimd", "aclk_160", 0,
> + EXYNOS4_CLKGATE_IP_LCD0, 0, "lcd"),
> + GATECLK("exynos4210-spi.0", "sclk_spi0", "div_spi0_pre", 0,
> + EXYNOS4_CLKSRC_MASK_PERIL1, 16, "spi_busclk0"),
> + GATECLK("exynos4210-spi.1", "sclk_spi1", "div_spi1_pre", 0,
> + EXYNOS4_CLKSRC_MASK_PERIL1, 20, "spi_busclk0"),
> + GATECLK("exynos4210-spi.2", "sclk_spi2", "div_spi2_pre", 0,
> + EXYNOS4_CLKSRC_MASK_PERIL1, 24, "spi_busclk0"),
> + GATECLK("exynos4-sdhci.0", "sclk_mmc0", "div_mmc0_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 0, "mmc_busclk.2"),
> + GATECLK("exynos4-sdhci.1", "sclk_mmc1", "div_mmc1_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 4, "mmc_busclk.2"),
> + GATECLK("exynos4-sdhci.2", "sclk_mmc2", "div_mmc2_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 8, "mmc_busclk.2"),
> + GATECLK("exynos4-sdhci.3", "sclk_mmc3", "div_mmc3_pre", 0,
> + EXYNOS4_CLKSRC_MASK_FSYS, 12, "mmc_busclk.2"),
> + GATECLK("s5p-mipi-csis.0", "sclk_csis0", "div_csis0", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 24, "sclk_csis"),
> + GATECLK("s5p-mipi-csis.1", "sclk_csis1", "div_csis1", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 28, "sclk_csis"),
> + GATECLK(NULL, "sclk_cam0", "div_cam0", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 16, NULL),
> + GATECLK(NULL, "sclk_cam1", "div_cam1", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 20, NULL),
> + GATECLK("exynos4-fimc.0", "sclk_fimc", "div_fimc0", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 0, "sclk_fimc"),
> + GATECLK("exynos4-fimc.1", "sclk_fimc", "div_fimc1", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 4, "sclk_fimc"),
> + GATECLK("exynos4-fimc.2", "sclk_fimc", "div_fimc2", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 8, "sclk_fimc"),
> + GATECLK("exynos4-fimc.3", "sclk_fimc", "div_fimc3", 0,
> + EXYNOS4_CLKSRC_MASK_CAM, 12, "sclk_fimc"),
> + GATECLK("exynos4-fb.0", "sclk_fimd", "div_fimd0", 0,
> + EXYNOS4_CLKSRC_MASK_LCD0, 0, "sclk_fimd"),
> +};
> +
> +/* register clock common to all Exynos4 platforms */
> +void __init exynos4_clk_init(void)
> +{
> + samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
> + ARRAY_SIZE(exynos4_fixed_rate_clks));
> + samsung_clk_register_mux(exynos4_mux_clks,
> + ARRAY_SIZE(exynos4_mux_clks));
> + samsung_clk_register_div(exynos4_div_clks,
> + ARRAY_SIZE(exynos4_div_clks));
> + samsung_clk_register_gate(exynos4_gate_clks,
> + ARRAY_SIZE(exynos4_gate_clks));
> +}
...
> diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
> new file mode 100644
> index 0000000..65156b9
> --- /dev/null
> +++ b/drivers/clk/samsung/clk.c
> @@ -0,0 +1,231 @@
> +/*
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * Copyright (c) 2012 Linaro Ltd.
> + *
> + * 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.
> + *
> + * This file includes utility functions to register clocks to common
> + * clock framework for Samsung platforms. This includes an implementation
> + * of Samsung 'pll type' clock to represent the implementation of the
> + * pll found on Samsung platforms. In addition to that, utility functions
> + * to register mux, div, gate and fixed rate types of clocks are included.
> +*/
> +
> +#include "clk.h"
> +
> +static DEFINE_SPINLOCK(lock);
> +
> +#define to_clk_pll(_hw) container_of(_hw, struct samsung_clk_pll, hw)
> +
> +/* determine the output clock speed of the pll */
> +static unsigned long samsung_clk_pll_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
> +
> + if (clk_pll->get_rate)
> + return to_clk_pll(hw)->get_rate(parent_rate);
> +
> + return 0;
> +}
> +
> +/* round operation not supported */
> +static long samsung_clk_pll_round_rate(struct clk_hw *hw, unsigned long drate,
> + unsigned long *prate)
> +{
> + return samsung_clk_pll_recalc_rate(hw, *prate);
> +}
> +
> +/* set the clock output rate of the pll */
> +static int samsung_clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
> + unsigned long prate)
> +{
> + struct samsung_clk_pll *clk_pll = to_clk_pll(hw);
> +
> + if (clk_pll->set_rate)
> + return to_clk_pll(hw)->set_rate(drate);
> +
> + return 0;
> +}
> +
> +/* clock operations for samsung pll clock type */
> +static const struct clk_ops samsung_clk_pll_ops = {
> + .recalc_rate = samsung_clk_pll_recalc_rate,
> + .round_rate = samsung_clk_pll_round_rate,
> + .set_rate = samsung_clk_pll_set_rate,
> +};
> +
> +/* register a samsung pll type clock */
> +void __init samsung_clk_register_pll(const char *name, const char **pnames,
> + int (*set_rate)(unsigned long rate),
> + unsigned long (*get_rate)(unsigned long rate))
> +{
> + struct samsung_clk_pll *clk_pll;
> + struct clk *clk;
> + struct clk_init_data init;
> + int ret;
> +
> + clk_pll = kzalloc(sizeof(*clk_pll), GFP_KERNEL);
> + if (!clk_pll) {
> + pr_err("%s: could not allocate pll clk %s\n", __func__, name);
> + return;
> + }
> +
> + init.name = name;
> + init.ops =&samsung_clk_pll_ops;
> + init.flags = CLK_GET_RATE_NOCACHE;
> + init.parent_names = pnames;
> + init.num_parents = 1;
> +
> + clk_pll->set_rate = set_rate;
> + clk_pll->get_rate = get_rate;
> + clk_pll->hw.init =&init;
> +
> + /* register the clock */
> + clk = clk_register(NULL,&clk_pll->hw);
> + if (IS_ERR(clk)) {
> + pr_err("%s: failed to register pll clock %s\n", __func__,
> + name);
> + kfree(clk_pll);
> + return;
> + }
> +
> + ret = clk_register_clkdev(clk, name, NULL);
> + if (ret)
> + pr_err("%s: failed to register clock lookup for %s", __func__,
> + name);
> +}
> +
> +/* register a list of fixed clocks */
> +void __init samsung_clk_register_fixed_rate(
> + struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
> + clk = clk_register_fixed_rate(NULL, clk_list->name,
> + clk_list->parent_name, clk_list->flags,
> + clk_list->fixed_rate);
> + if (IS_ERR_OR_NULL(clk)) {
clk_register_fixed_rate() always returns an error code (ERR_PTR()), i.e. never
NULL, thus IS_ERR(clk) is more appropriate here.
> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> + }
> +}
> +
> +/* register a list of mux clocks */
> +void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
> + unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
> + clk = clk_register_mux(NULL, clk_list->name,
> + clk_list->parent_names, clk_list->num_parents,
> + clk_list->flags, clk_list->reg, clk_list->shift,
> + clk_list->width, clk_list->mux_flags,&lock);
> + if (IS_ERR_OR_NULL(clk)) {
Ditto.
> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> +
> + if (clk_list->alias)
> + clk_register_clkdev(clk, clk_list->alias,
> + clk_list->dev_name);
> + }
> +}
> +
> +/* reguster a list of div clocks */
> +void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
> + unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
> + clk = clk_register_divider(NULL, clk_list->name,
> + clk_list->parent_name, clk_list->flags, clk_list->reg,
> + clk_list->shift, clk_list->width, clk_list->div_flags,
> + &lock);
> + if (IS_ERR_OR_NULL(clk)) {
Ditto.
> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> +
> + if (clk_list->alias)
> + clk_register_clkdev(clk, clk_list->alias,
> + clk_list->dev_name);
> + }
> +}
> +
> +/* register a list of gate clocks */
> +void __init samsung_clk_register_gate(struct samsung_gate_clock *clk_list,
> + unsigned int nr_clk)
> +{
> + struct clk *clk;
> + unsigned int idx, ret;
> +
> + for (idx = 0; idx< nr_clk; idx++, clk_list++) {
> + clk = clk_register_gate(NULL, clk_list->name,
> + clk_list->parent_name, clk_list->flags, clk_list->reg,
> + clk_list->bit_idx, clk_list->gate_flags,&lock);
> + if (IS_ERR_OR_NULL(clk)) {
Ditto.
> + pr_err("clock: failed to register clock %s\n",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->name,
> + clk_list->dev_name);
> + if (ret) {
> + pr_err("clock: failed to register clock lookup for %s",
> + clk_list->name);
> + continue;
> + }
> +
> + ret = clk_register_clkdev(clk, clk_list->alias,
> + clk_list->dev_name);
> + if (ret)
> + pr_err("clock: failed to register alias %s for clock "
> + " %s", clk_list->alias, clk_list->name);
> + }
> +}
Do we really need all these clock lookup entries registered for each clk
primitive ? There seem to be more struck clk objects than with the original
samsung clock code, now when each instance of struct clk_clksrc has been
replaced with a corresponding div and mux clock object. All these are not
needed to be referenced from drivers, so why do we see so many
clk_register_clkdev() here ?
Couldn't this be avoided by instantiating all platform clocks first and
then creating required clock object - device associations by adding the
clkdev lookup entries ? Something like this is done in case of
arch/arm/mach-imx for instance. I think this would result in less data
and more clear implementation.
> +/* utility function to get the rate of a specified clock */
> +unsigned long _get_rate(const char *clk_name)
> +{
> + struct clk *clk;
> + unsigned long rate;
> +
> + clk = clk_get(NULL, clk_name);
> + if (IS_ERR(clk))
> + return 0;
> + rate = clk_get_rate(clk);
> + clk_put(clk);
> + return rate;
> +}
> diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
> new file mode 100644
> index 0000000..40bdff9
> --- /dev/null
> +++ b/drivers/clk/samsung/clk.h
> @@ -0,0 +1,190 @@
> +/*
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + * Copyright (c) 2012 Linaro Ltd.
> + *
> + * 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.
> + *
> + * Common Clock Framework support for all Samsung platforms
> +*/
> +
> +#ifndef __SAMSUNG_CLK_H
> +#define __SAMSUNG_CLK_H
> +
> +#include<linux/clk.h>
> +#include<linux/clkdev.h>
> +#include<linux/io.h>
> +#include<linux/clk-provider.h>
> +#include<mach/regs-clock.h>
> +
> +/**
> + * struct samsung_clk_pll: represents a samsung pll type clock
> + * @hw: connection to struct clk.
> + * @set_rate: callback for setting the pll clock rate
> + * @get_rate: callback for determing the pll clock rate
> + *
> + * Internal representation of the pll type clock. Platform specific
> + * implementation can instantiate clocks of this type by calling
> + * samsung_clk_register_pll() function.
> + */
> +struct samsung_clk_pll {
> + struct clk_hw hw;
> + int (*set_rate)(unsigned long rate);
> + unsigned long (*get_rate)(unsigned long xtal_rate);
> +};
> +
> +/**
> + * struct samsung_fixed_rate_clock: information about fixed-rate clock
> + * @dev_name: name of the device to which this clock belongs.
> + * @name: name of this fixed-rate clock.
> + * @parent_name: optional parent clock name.
> + * @flags: optional fixed-rate clock flags.
> + * @fixed-rate: fixed clock rate of this clock.
> + */
> +struct samsung_fixed_rate_clock {
> + const char *dev_name;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + unsigned long fixed_rate;
> +};
> +
> +#define FRATE_CLK(dname, cname, pname, f, frate) \
> + { \
> + .dev_name = dname, \
> + .name = cname, \
> + .parent_name = pname, \
> + .flags = f, \
> + .fixed_rate = frate, \
> + }
> +
> +/**
> + * struct samsung_mux_clock: information about mux clock
> + * @dev_name: name of the device to which this clock belongs.
> + * @name: name of this mux clock.
> + * @parent_names: array of pointer to parent clock names.
> + * @num_parents: number of parents listed in @parent_names.
> + * @flags: optional flags for basic clock.
> + * @reg: address of register for configuring the mux.
> + * @shift: starting bit location of the mux control bit-field in @reg.
> + * @width: width of the mux control bit-field in @reg.
> + * @mux_flags: flags for mux-type clock.
> + * @alias: optional clock alias name to be assigned to this clock.
> + */
> +struct samsung_mux_clock {
> + const char *dev_name;
> + const char *name;
> + const char **parent_names;
> + u8 num_parents;
> + unsigned long flags;
> + void __iomem *reg;
> + u8 shift;
> + u8 width;
> + u8 mux_flags;
> + const char *alias;
> +};
> +
> +#define MUXCLK(dname, cname, pnames, f, r, s, w, mf) \
> + { \
> + .dev_name = dname, \
> + .name = cname, \
> + .parent_names = pnames, \
> + .num_parents = ARRAY_SIZE(pnames), \
> + .flags = f, \
> + .reg = r, \
> + .shift = s, \
> + .width = w, \
> + .mux_flags = mf, \
> + }
> +
> +/**
> + * struct samsung_div_clock: information about div clock
> + * @dev_name: name of the device to which this clock belongs.
> + * @name: name of this div clock.
> + * @parent_name: name of the parent clock.
> + * @flags: optional flags for basic clock.
> + * @reg: address of register for configuring the div.
> + * @shift: starting bit location of the div control bit-field in @reg.
> + * @div_flags: flags for div-type clock.
> + * @alias: optional clock alias name to be assigned to this clock.
> + */
> +struct samsung_div_clock {
> + const char *dev_name;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + void __iomem *reg;
> + u8 shift;
> + u8 width;
> + u8 div_flags;
> + const char *alias;
> +};
> +
> +#define DIVCLK(dname, cname, pname, f, r, s, w, df) \
> + { \
> + .dev_name = dname, \
> + .name = cname, \
> + .parent_name = pname, \
> + .flags = f, \
> + .reg = r, \
> + .shift = s, \
> + .width = w, \
> + .div_flags = df, \
> + }
> +
> +/**
> + * struct samsung_gate_clock: information about gate clock
> + * @dev_name: name of the device to which this clock belongs.
> + * @name: name of this gate clock.
> + * @parent_name: name of the parent clock.
> + * @flags: optional flags for basic clock.
> + * @reg: address of register for configuring the gate.
> + * @bit_idx: bit index of the gate control bit-field in @reg.
> + * @gate_flags: flags for gate-type clock.
> + * @alias: optional clock alias name to be assigned to this clock.
> + */
> +struct samsung_gate_clock {
> + const char *dev_name;
> + const char *name;
> + const char *parent_name;
> + unsigned long flags;
> + void __iomem *reg;
> + u8 bit_idx;
> + u8 gate_flags;
> + const char *alias;
> +};
> +
> +#define GATECLK(dname, cname, pname, f, r, b, a) \
> + { \
> + .dev_name = dname, \
> + .name = cname, \
> + .parent_name = pname, \
> + .flags = f, \
> + .reg = r, \
> + .bit_idx = b, \
> + .alias = a, \
> + }
--
Regards,
Sylwester
^ permalink raw reply
* [PATCH 00/10] Platform data clean-up and UIB device enablement
From: Lee Jones @ 2012-10-05 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In this patch-set we move all Device Tree start-up code from the u8500
board file and into the more persistent db8500 cpu file. This will aid
future endeavours to remove platform code completely from Mainline. We
also enable some of the devices found on the STUIB (User Interface
board), which attaches to some of ST-Ericsson's reference platforms.
.../devicetree/bindings/input/stmpe-keypad.txt | 39 +++++
Documentation/devicetree/bindings/mfd/stmpe.txt | 25 ++++
arch/arm/boot/dts/stuib.dtsi | 40 ++++++
drivers/input/keyboard/stmpe-keypad.c | 67 +++++++--
drivers/mfd/stmpe.c | 152 +++++++++++++-------
drivers/of/of_i2c.c | 3 +
include/linux/mfd/stmpe.h | 2 +
7 files changed, 271 insertions(+), 57 deletions(-)
^ permalink raw reply
* [PATCH 01/10] mfd: Prevent STMPE from abusing mfd_add_devices' irq_base parameter
From: Lee Jones @ 2012-10-05 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349451107-8009-1-git-send-email-lee.jones@linaro.org>
Originally IRQ incrementers were provided in some template resource
structures for keypad and touchscreen devices. These were passed as
IORESOURCE_IRQs to MFD core in the usual way. The true device IRQs
were instead added to the irq_base when mfd_add_devices was invoked.
This is clearly an abuse of the call, and does not scale when IRQ
Domains are brought into play. Before we can provide the STMPE with
its own IRQ Domain we must first fix this. This patche keeps most
of the driver's structure, keeping the template strategy. However,
instead of providing the IRQ as an increment to irq_base, we
dynamically populate the IORESOURCE_IRQ with the correct device IRQ.
Cc: Samuel Ortiz <sameo@linux.intel.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/mfd/stmpe.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index c94f521..ad13cb0 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -310,14 +310,10 @@ static struct mfd_cell stmpe_gpio_cell_noirq = {
static struct resource stmpe_keypad_resources[] = {
{
.name = "KEYPAD",
- .start = 0,
- .end = 0,
.flags = IORESOURCE_IRQ,
},
{
.name = "KEYPAD_OVER",
- .start = 1,
- .end = 1,
.flags = IORESOURCE_IRQ,
},
};
@@ -397,14 +393,10 @@ static struct stmpe_variant_info stmpe801_noirq = {
static struct resource stmpe_ts_resources[] = {
{
.name = "TOUCH_DET",
- .start = 0,
- .end = 0,
.flags = IORESOURCE_IRQ,
},
{
.name = "FIFO_TH",
- .start = 1,
- .end = 1,
.flags = IORESOURCE_IRQ,
},
};
@@ -959,10 +951,10 @@ static int __devinit stmpe_chip_init(struct stmpe *stmpe)
}
static int __devinit stmpe_add_device(struct stmpe *stmpe,
- struct mfd_cell *cell, int irq)
+ struct mfd_cell *cell)
{
return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
- NULL, stmpe->irq_base + irq, NULL);
+ NULL, stmpe->irq_base, NULL);
}
static int __devinit stmpe_devices_init(struct stmpe *stmpe)
@@ -970,7 +962,7 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
struct stmpe_variant_info *variant = stmpe->variant;
unsigned int platform_blocks = stmpe->pdata->blocks;
int ret = -EINVAL;
- int i;
+ int i, j;
for (i = 0; i < variant->num_blocks; i++) {
struct stmpe_variant_block *block = &variant->blocks[i];
@@ -978,8 +970,17 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
if (!(platform_blocks & block->block))
continue;
+ for (j = 0; j < block->cell->num_resources; j++) {
+ struct resource *res =
+ (struct resource *) &block->cell->resources[j];
+
+ /* Dynamically fill in a variant's IRQ. */
+ if (res->flags & IORESOURCE_IRQ)
+ res->start = res->end = block->irq + j;
+ }
+
platform_blocks &= ~block->block;
- ret = stmpe_add_device(stmpe, block->cell, block->irq);
+ ret = stmpe_add_device(stmpe, block->cell);
if (ret)
return ret;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH 02/10] mfd: Provide the STMPE driver with its own IRQ domain
From: Lee Jones @ 2012-10-05 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349451107-8009-1-git-send-email-lee.jones@linaro.org>
The STMPE driver is yet another IRQ controller which requires its
own IRQ domain. So, we provide it with one.
Cc: Samuel Ortiz <sameo@linux.intel.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/mfd/stmpe.c | 82 +++++++++++++++++++++++++++------------------
include/linux/mfd/stmpe.h | 2 ++
2 files changed, 52 insertions(+), 32 deletions(-)
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index ad13cb0..5c8d8f2 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/mfd/core.h>
@@ -757,7 +758,9 @@ static irqreturn_t stmpe_irq(int irq, void *data)
int i;
if (variant->id_val == STMPE801_ID) {
- handle_nested_irq(stmpe->irq_base);
+ int base = irq_create_mapping(stmpe->domain, 0);
+
+ handle_nested_irq(base);
return IRQ_HANDLED;
}
@@ -778,8 +781,9 @@ static irqreturn_t stmpe_irq(int irq, void *data)
while (status) {
int bit = __ffs(status);
int line = bank * 8 + bit;
+ int nestedirq = irq_create_mapping(stmpe->domain, line);
- handle_nested_irq(stmpe->irq_base + line);
+ handle_nested_irq(nestedirq);
status &= ~(1 << bit);
}
@@ -820,7 +824,7 @@ static void stmpe_irq_sync_unlock(struct irq_data *data)
static void stmpe_irq_mask(struct irq_data *data)
{
struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
- int offset = data->irq - stmpe->irq_base;
+ int offset = data->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@@ -830,7 +834,7 @@ static void stmpe_irq_mask(struct irq_data *data)
static void stmpe_irq_unmask(struct irq_data *data)
{
struct stmpe *stmpe = irq_data_get_irq_chip_data(data);
- int offset = data->irq - stmpe->irq_base;
+ int offset = data->hwirq;
int regoffset = offset / 8;
int mask = 1 << (offset % 8);
@@ -845,43 +849,62 @@ static struct irq_chip stmpe_irq_chip = {
.irq_unmask = stmpe_irq_unmask,
};
-static int __devinit stmpe_irq_init(struct stmpe *stmpe)
+static int stmpe_irq_map(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hwirq)
{
+ struct stmpe *stmpe = d->host_data;
struct irq_chip *chip = NULL;
- int num_irqs = stmpe->variant->num_irqs;
- int base = stmpe->irq_base;
- int irq;
if (stmpe->variant->id_val != STMPE801_ID)
chip = &stmpe_irq_chip;
- for (irq = base; irq < base + num_irqs; irq++) {
- irq_set_chip_data(irq, stmpe);
- irq_set_chip_and_handler(irq, chip, handle_edge_irq);
- irq_set_nested_thread(irq, 1);
+ irq_set_chip_data(virq, stmpe);
+ irq_set_chip_and_handler(virq, chip, handle_edge_irq);
+ irq_set_nested_thread(virq, 1);
#ifdef CONFIG_ARM
- set_irq_flags(irq, IRQF_VALID);
+ set_irq_flags(virq, IRQF_VALID);
#else
- irq_set_noprobe(irq);
+ irq_set_noprobe(virq);
#endif
- }
return 0;
}
-static void stmpe_irq_remove(struct stmpe *stmpe)
+static void stmpe_irq_unmap(struct irq_domain *d, unsigned int virq)
{
- int num_irqs = stmpe->variant->num_irqs;
- int base = stmpe->irq_base;
- int irq;
-
- for (irq = base; irq < base + num_irqs; irq++) {
#ifdef CONFIG_ARM
- set_irq_flags(irq, 0);
+ set_irq_flags(virq, 0);
#endif
- irq_set_chip_and_handler(irq, NULL, NULL);
- irq_set_chip_data(irq, NULL);
+ irq_set_chip_and_handler(virq, NULL, NULL);
+ irq_set_chip_data(virq, NULL);
+}
+
+static struct irq_domain_ops stmpe_irq_ops = {
+ .map = stmpe_irq_map,
+ .unmap = stmpe_irq_unmap,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static int __devinit stmpe_irq_init(struct stmpe *stmpe)
+{
+ int base = stmpe->irq_base;
+ int num_irqs = stmpe->variant->num_irqs;
+
+ if (base) {
+ stmpe->domain = irq_domain_add_legacy(
+ NULL, num_irqs, base, 0, &stmpe_irq_ops, stmpe);
+ }
+ else {
+ stmpe->domain = irq_domain_add_linear(
+ NULL, num_irqs, &stmpe_irq_ops, stmpe);
+ }
+
+ if (!stmpe->domain) {
+ dev_err(stmpe->dev, "Failed to create irqdomain\n");
+ return -ENOSYS;
}
+
+ return 0;
}
static int __devinit stmpe_chip_init(struct stmpe *stmpe)
@@ -954,7 +977,7 @@ static int __devinit stmpe_add_device(struct stmpe *stmpe,
struct mfd_cell *cell)
{
return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
- NULL, stmpe->irq_base, NULL);
+ NULL, stmpe->irq_base, stmpe->domain);
}
static int __devinit stmpe_devices_init(struct stmpe *stmpe)
@@ -1067,7 +1090,7 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
if (ret) {
dev_err(stmpe->dev, "failed to request IRQ: %d\n",
ret);
- goto out_removeirq;
+ goto free_gpio;
}
}
@@ -1083,9 +1106,6 @@ out_removedevs:
mfd_remove_devices(stmpe->dev);
if (stmpe->irq >= 0)
free_irq(stmpe->irq, stmpe);
-out_removeirq:
- if (stmpe->irq >= 0)
- stmpe_irq_remove(stmpe);
free_gpio:
if (pdata->irq_over_gpio)
gpio_free(pdata->irq_gpio);
@@ -1098,10 +1118,8 @@ int stmpe_remove(struct stmpe *stmpe)
{
mfd_remove_devices(stmpe->dev);
- if (stmpe->irq >= 0) {
+ if (stmpe->irq >= 0)
free_irq(stmpe->irq, stmpe);
- stmpe_irq_remove(stmpe);
- }
if (stmpe->pdata->irq_over_gpio)
gpio_free(stmpe->pdata->irq_gpio);
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h
index f8d5b4d..15dac79 100644
--- a/include/linux/mfd/stmpe.h
+++ b/include/linux/mfd/stmpe.h
@@ -62,6 +62,7 @@ struct stmpe_client_info;
* @lock: lock protecting I/O operations
* @irq_lock: IRQ bus lock
* @dev: device, mostly for dev_dbg()
+ * @irq_domain: IRQ domain
* @client: client - i2c or spi
* @ci: client specific information
* @partnum: part number
@@ -79,6 +80,7 @@ struct stmpe {
struct mutex lock;
struct mutex irq_lock;
struct device *dev;
+ struct irq_domain *domain;
void *client;
struct stmpe_client_info *ci;
enum stmpe_partnum partnum;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 03/10] mfd: Correct copy and paste mistake in stmpe
From: Lee Jones @ 2012-10-05 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349451107-8009-1-git-send-email-lee.jones@linaro.org>
When specifying IRQ numbers for the stmpe1601, IRQ defines for the
stmpe24xx were used instead. Fortunately, the defined numbers are
the same, hence why it survived testing. This fix is merely an
aesthetic one.
Cc: Samuel Ortiz <sameo@linux.intel.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/mfd/stmpe.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index 5c8d8f2..e50ebdf 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -519,12 +519,12 @@ static const u8 stmpe1601_regs[] = {
static struct stmpe_variant_block stmpe1601_blocks[] = {
{
.cell = &stmpe_gpio_cell,
- .irq = STMPE24XX_IRQ_GPIOC,
+ .irq = STMPE1601_IRQ_GPIOC,
.block = STMPE_BLOCK_GPIO,
},
{
.cell = &stmpe_keypad_cell,
- .irq = STMPE24XX_IRQ_KEYPAD,
+ .irq = STMPE1601_IRQ_KEYPAD,
.block = STMPE_BLOCK_KEYPAD,
},
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH 04/10] of/i2c: Add support for I2C_CLIENT_WAKE when booting with Device Tree
From: Lee Jones @ 2012-10-05 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349451107-8009-1-git-send-email-lee.jones@linaro.org>
It's important for wakeup sources such as keyboards, power buttons
and the like to identify themselves as wakeup devices. Until now
this has not been possible when platforms are booting via Device
Tree.
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: devicetree-discuss at lists.ozlabs.org
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/of/of_i2c.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
index 1e173f3..2f20019 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -61,6 +61,9 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
info.of_node = of_node_get(node);
info.archdata = &dev_ad;
+ if (of_get_property(node, "i2c-client-wake", NULL))
+ info.flags |= I2C_CLIENT_WAKE;
+
request_module("%s%s", I2C_MODULE_PREFIX, info.type);
result = i2c_new_device(adap, &info);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 05/10] mfd: Enable the STMPE MFD for Device Tree
From: Lee Jones @ 2012-10-05 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349451107-8009-1-git-send-email-lee.jones@linaro.org>
This patch allows the STMPE Multi-Functional Device to be correctly
initialised when booting with Device Tree support enabled. Its
children are specified by the addition of subordinate devices to the
STMPE node in the Device Tree file.
Cc: Samuel Ortiz <sameo@linux.intel.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/mfd/stmpe.c | 48 ++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index e50ebdf..ba157d4 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -885,18 +885,19 @@ static struct irq_domain_ops stmpe_irq_ops = {
.xlate = irq_domain_xlate_twocell,
};
-static int __devinit stmpe_irq_init(struct stmpe *stmpe)
+static int __devinit stmpe_irq_init(struct stmpe *stmpe,
+ struct device_node *np)
{
int base = stmpe->irq_base;
int num_irqs = stmpe->variant->num_irqs;
if (base) {
stmpe->domain = irq_domain_add_legacy(
- NULL, num_irqs, base, 0, &stmpe_irq_ops, stmpe);
+ np, num_irqs, base, 0, &stmpe_irq_ops, stmpe);
}
else {
stmpe->domain = irq_domain_add_linear(
- NULL, num_irqs, &stmpe_irq_ops, stmpe);
+ np, num_irqs, &stmpe_irq_ops, stmpe);
}
if (!stmpe->domain) {
@@ -1016,15 +1017,50 @@ static int __devinit stmpe_devices_init(struct stmpe *stmpe)
return ret;
}
+void __devinit stmpe_of_probe(struct stmpe_platform_data *pdata,
+ struct device_node *np)
+{
+ struct device_node *child;
+
+ of_property_read_u32(np, "st,autosleep-timeout",
+ &pdata->autosleep_timeout);
+
+ pdata->autosleep = (pdata->autosleep_timeout) ? true : false;
+
+ for_each_child_of_node(np, child) {
+ if (!strcmp(child->name, "stmpe_gpio")) {
+ pdata->blocks |= STMPE_BLOCK_GPIO;
+ }
+ if (!strcmp(child->name, "stmpe_keypad")) {
+ pdata->blocks |= STMPE_BLOCK_KEYPAD;
+ }
+ if (!strcmp(child->name, "stmpe_touchscreen")) {
+ pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN;
+ }
+ if (!strcmp(child->name, "stmpe_adc")) {
+ pdata->blocks |= STMPE_BLOCK_ADC;
+ }
+ }
+}
+
/* Called from client specific probe routines */
int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
{
struct stmpe_platform_data *pdata = dev_get_platdata(ci->dev);
+ struct device_node *np = ci->dev->of_node;
struct stmpe *stmpe;
int ret;
- if (!pdata)
- return -EINVAL;
+ if (!pdata) {
+ if (np) {
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ stmpe_of_probe(pdata, np);
+ } else
+ return -EINVAL;
+ }
stmpe = kzalloc(sizeof(struct stmpe), GFP_KERNEL);
if (!stmpe)
@@ -1080,7 +1116,7 @@ int __devinit stmpe_probe(struct stmpe_client_info *ci, int partnum)
goto free_gpio;
if (stmpe->irq >= 0) {
- ret = stmpe_irq_init(stmpe);
+ ret = stmpe_irq_init(stmpe, np);
if (ret)
goto free_gpio;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 06/10] Documentation: Describe bindings for STMPE Multi-Functional Device driver
From: Lee Jones @ 2012-10-05 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349451107-8009-1-git-send-email-lee.jones@linaro.org>
Here we add the required documentation for the STMPE Multi-Functional
Device (MFD) Device Tree bindings. It describes all of the bindings
currently supported by the driver.
Cc: Samuel Ortiz <sameo@linux.intel.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
Documentation/devicetree/bindings/mfd/stmpe.txt | 25 +++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/stmpe.txt
diff --git a/Documentation/devicetree/bindings/mfd/stmpe.txt b/Documentation/devicetree/bindings/mfd/stmpe.txt
new file mode 100644
index 0000000..8f0aeda
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/stmpe.txt
@@ -0,0 +1,25 @@
+* STMPE Multi-Functional Device
+
+Required properties:
+ - compatible : "st,stmpe[811|1601|2401|2403]"
+ - reg : I2C address of the device
+
+Optional properties:
+ - interrupts : The interrupt outputs from the controller
+ - interrupt-controller : Marks the device node as an interrupt controller
+ - interrupt-parent : Specifies which IRQ controller we're connected to
+ - i2c-client-wake : Marks the input device as wakable
+ - st,autosleep-timeout : Valid entries (ms); 4, 16, 32, 64, 128, 256, 512 and 1024
+
+Example:
+
+ stmpe1601: stmpe1601 at 40 {
+ compatible = "st,stmpe1601";
+ reg = <0x40>;
+ interrupts = <26 0x4>;
+ interrupt-parent = <&gpio6>;
+ interrupt-controller;
+
+ i2c-client-wake;
+ st,autosleep-timeout = <1024>;
+ };
--
1.7.9.5
^ permalink raw reply related
* [PATCH 07/10] input: Enable STMPE keypad driver for Device Tree
From: Lee Jones @ 2012-10-05 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349451107-8009-1-git-send-email-lee.jones@linaro.org>
This patch allows the STMPE driver to be successfully probed and
initialised when Device Tree support is enabled. Besides the usual
platform data changes, we also separate the process of filling in
the 'in use' pin bitmap, as we have to extract the information from
Device Tree in the DT boot case.
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: linux-input at vger.kernel.org
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/input/keyboard/stmpe-keypad.c | 67 ++++++++++++++++++++++++++++-----
drivers/mfd/stmpe.c | 1 +
2 files changed, 59 insertions(+), 9 deletions(-)
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
index 470a877..c722d23 100644
--- a/drivers/input/keyboard/stmpe-keypad.c
+++ b/drivers/input/keyboard/stmpe-keypad.c
@@ -257,19 +257,73 @@ static int __devinit stmpe_keypad_chip_init(struct stmpe_keypad *keypad)
(plat->debounce_ms << 1));
}
+static int stmpe_keypad_fill_used_pins(struct platform_device *pdev,
+ struct stmpe_keypad *keypad,
+ struct stmpe_keypad_platform_data *plat)
+{
+ struct device_node *np = pdev->dev.of_node;
+ unsigned int proplen;
+ const __be32 *prop;
+ int i;
+
+ if (np) {
+ prop = of_get_property(np, "linux,keymap", &proplen);
+ if (!prop) {
+ dev_err(&pdev->dev,
+ "linux,keymap property not defined\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < proplen / sizeof(u32); i++) {
+ unsigned int key = be32_to_cpup(prop + i);
+
+ keypad->cols |= 1 << KEY_COL(key);
+ keypad->rows |= 1 << KEY_ROW(key);
+ }
+ } else {
+ for (i = 0; i < plat->keymap_data->keymap_size; i++) {
+ unsigned int key = plat->keymap_data->keymap[i];
+
+ keypad->cols |= 1 << KEY_COL(key);
+ keypad->rows |= 1 << KEY_ROW(key);
+ }
+ }
+
+ return 0;
+}
+
+static void __devinit stmpe_keypad_of_probe(struct device_node *np,
+ struct stmpe_keypad_platform_data *plat)
+{
+ of_property_read_u32(np, "debounce-interval", &plat->debounce_ms);
+ of_property_read_u32(np, "stericsson,scan-count", &plat->scan_count);
+
+ if (of_get_property(np, "stericsson,no-autorepeat", NULL))
+ plat->no_autorepeat = true;
+}
+
static int __devinit stmpe_keypad_probe(struct platform_device *pdev)
{
struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
struct stmpe_keypad_platform_data *plat;
+ struct device_node *np = pdev->dev.of_node;
struct stmpe_keypad *keypad;
struct input_dev *input;
int ret;
int irq;
- int i;
plat = stmpe->pdata->keypad;
- if (!plat)
- return -ENODEV;
+ if (!plat) {
+ if (np) {
+ plat = devm_kzalloc(&pdev->dev,
+ sizeof(*plat), GFP_KERNEL);
+ if (!plat)
+ return -ENOMEM;
+
+ stmpe_keypad_of_probe(np, plat);
+ } else
+ return -ENODEV;
+ }
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@@ -300,12 +354,7 @@ static int __devinit stmpe_keypad_probe(struct platform_device *pdev)
if (!plat->no_autorepeat)
__set_bit(EV_REP, input->evbit);
- for (i = 0; i < plat->keymap_data->keymap_size; i++) {
- unsigned int key = plat->keymap_data->keymap[i];
-
- keypad->cols |= 1 << KEY_COL(key);
- keypad->rows |= 1 << KEY_ROW(key);
- }
+ stmpe_keypad_fill_used_pins(pdev, keypad, plat);
keypad->stmpe = stmpe;
keypad->plat = plat;
diff --git a/drivers/mfd/stmpe.c b/drivers/mfd/stmpe.c
index ba157d4..b03cc64 100644
--- a/drivers/mfd/stmpe.c
+++ b/drivers/mfd/stmpe.c
@@ -321,6 +321,7 @@ static struct resource stmpe_keypad_resources[] = {
static struct mfd_cell stmpe_keypad_cell = {
.name = "stmpe-keypad",
+ .of_compatible = "st,stmpe-keypad",
.resources = stmpe_keypad_resources,
.num_resources = ARRAY_SIZE(stmpe_keypad_resources),
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH 08/10] Documentation: Describe bindings for STMPE Keypad driver
From: Lee Jones @ 2012-10-05 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349451107-8009-1-git-send-email-lee.jones@linaro.org>
Here we add the required documentation for the STMPE Device
Tree bindings. It describes all of the bindings currently
supported by the driver.
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: linux-input at vger.kernel.org
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
.../devicetree/bindings/input/stmpe-keypad.txt | 39 ++++++++++++++++++++
1 file changed, 39 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/stmpe-keypad.txt
diff --git a/Documentation/devicetree/bindings/input/stmpe-keypad.txt b/Documentation/devicetree/bindings/input/stmpe-keypad.txt
new file mode 100644
index 0000000..e18e2de
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/stmpe-keypad.txt
@@ -0,0 +1,39 @@
+* STMPE Keypad
+
+Required properties:
+ - compatible : "st,stmpe-keypad"
+ - linux,keymap : See ./matrix-keymap.txt
+
+Optional properties:
+ - debounce-interval : Debouncing interval time in milliseconds
+ - stericsson,scan-count : Scanning cycles elapsed before key data is updated
+ - stericsson,no-autorepeat : If specified device will not autorepeat
+
+Example:
+
+ stmpe_keypad {
+ compatible = "st,stmpe-keypad";
+
+ debounce-interval = <64>;
+ stericsson,scan-count = <8>;
+ stericsson,no-autorepeat;
+
+ linux,keymap = <0x205006b
+ 0x4010074
+ 0x3050072
+ 0x1030004
+ 0x502006a
+ 0x500000a
+ 0x5008b
+ 0x706001c
+ 0x405000b
+ 0x6070003
+ 0x3040067
+ 0x303006c
+ 0x60400e7
+ 0x602009e
+ 0x4020073
+ 0x5050002
+ 0x4030069
+ 0x3020008>;
+ };
--
1.7.9.5
^ permalink raw reply related
* [PATCH 09/10] ARM: ux500: Apply a Device Tree node for the STMPE MFD
From: Lee Jones @ 2012-10-05 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349451107-8009-1-git-send-email-lee.jones@linaro.org>
Here we apply the STMPE Multi-Functional Device's node to the
ST User Interface Board Device Tree file. It includes all of
the properties required for correct device initialsation.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
arch/arm/boot/dts/stuib.dtsi | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm/boot/dts/stuib.dtsi b/arch/arm/boot/dts/stuib.dtsi
index 62f3ecd..b25663c 100644
--- a/arch/arm/boot/dts/stuib.dtsi
+++ b/arch/arm/boot/dts/stuib.dtsi
@@ -11,6 +11,19 @@
/ {
soc-u9500 {
+ i2c at 80004000 {
+ stmpe1601: stmpe1601 at 40 {
+ compatible = "st,stmpe1601";
+ reg = <0x40>;
+ interrupts = <26 0x4>;
+ interrupt-parent = <&gpio6>;
+ interrupt-controller;
+
+ i2c-client-wake;
+ st,autosleep-timeout = <1024>;
+ };
+ };
+
i2c at 80110000 {
bu21013_tp at 0x5c {
compatible = "rhom,bu21013_tp";
--
1.7.9.5
^ permalink raw reply related
* [PATCH 10/10] ARM: ux500: Supply the STMPE keypad Device Tree node to the STUIB DT
From: Lee Jones @ 2012-10-05 15:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349451107-8009-1-git-send-email-lee.jones@linaro.org>
This patch allows the STMPE keypad driver to be successfully probed
and initialised during a Device Tree enabled boot sequence. It
contains all of the required properties needed to setup and map
each key on the 6x3 keypad located on the ST User Interface Board.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
arch/arm/boot/dts/stuib.dtsi | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/arch/arm/boot/dts/stuib.dtsi b/arch/arm/boot/dts/stuib.dtsi
index b25663c..b492e3e 100644
--- a/arch/arm/boot/dts/stuib.dtsi
+++ b/arch/arm/boot/dts/stuib.dtsi
@@ -21,6 +21,33 @@
i2c-client-wake;
st,autosleep-timeout = <1024>;
+
+ stmpe_keypad {
+ compatible = "st,stmpe-keypad";
+
+ debounce-interval = <64>;
+ stericsson,scan-count = <8>;
+ stericsson,no-autorepeat;
+
+ linux,keymap = <0x205006b
+ 0x4010074
+ 0x3050072
+ 0x1030004
+ 0x502006a
+ 0x500000a
+ 0x5008b
+ 0x706001c
+ 0x405000b
+ 0x6070003
+ 0x3040067
+ 0x303006c
+ 0x60400e7
+ 0x602009e
+ 0x4020073
+ 0x5050002
+ 0x4030069
+ 0x3020008>;
+ };
};
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH 14/16] ARM: pxa: armcore: fix PCI PIO warnings
From: Igor Grinberg @ 2012-10-05 15:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349448930-23976-15-git-send-email-arnd@arndb.de>
On 10/05/12 16:55, Arnd Bergmann wrote:
> The it8152 PCI host used on the pxa/cm_x2xx machines
> uses the old-style I/O window registration. This should
> eventually get converted to pci_ioremap_io() but for
> now, let's cast the IT8152_IO_BASE constant to an integer
> type to get rid of the warnings.
>
> Without this patch, building cm_x2xx_defconfig results in:
>
> arch/arm/common/it8152.c: In function 'it8152_pci_setup':
> arch/arm/common/it8152.c:287:18: warning: assignment makes integer from pointer without a cast [enabled by default]
> arch/arm/common/it8152.c:288:16: warning: assignment makes integer from pointer without a cast [enabled by default]
> arch/arm/common/it8152.c:291:17: warning: assignment makes integer from pointer without a cast [enabled by default]
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Krzysztof Halasa <khc@pm.waw.pl>
> Cc: Mike Rapoport <mike@compulab.co.il>
> Cc: Igor Grinberg <grinberg@compulab.co.il>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: Eric Miao <eric.y.miao@gmail.com>
Acked-by: Igor Grinberg <grinberg@compulab.co.il>
Thanks!
> ---
> arch/arm/common/it8152.c | 12 +++++++++---
> 1 file changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c
> index c4110d1..001f491 100644
> --- a/arch/arm/common/it8152.c
> +++ b/arch/arm/common/it8152.c
> @@ -284,11 +284,17 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)
>
> int __init it8152_pci_setup(int nr, struct pci_sys_data *sys)
> {
> - it8152_io.start = IT8152_IO_BASE + 0x12000;
> - it8152_io.end = IT8152_IO_BASE + 0x12000 + 0x100000;
> + /*
> + * FIXME: use pci_ioremap_io to remap the IO space here and
> + * move over to the generic io.h implementation.
> + * This requires solving the same problem for PXA PCMCIA
> + * support.
> + */
> + it8152_io.start = (unsigned long)IT8152_IO_BASE + 0x12000;
> + it8152_io.end = (unsigned long)IT8152_IO_BASE + 0x12000 + 0x100000;
>
> sys->mem_offset = 0x10000000;
> - sys->io_offset = IT8152_IO_BASE;
> + sys->io_offset = (unsigned long)IT8152_IO_BASE;
>
> if (request_resource(&ioport_resource, &it8152_io)) {
> printk(KERN_ERR "PCI: unable to allocate IO region\n");
--
Regards,
Igor.
^ permalink raw reply
* mxc-nand + jffs2 : dir ino #9041 appears to be a hard link
From: Gaëtan Carlier @ 2012-10-05 15:34 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
I am working with iMX27 (3DS) with NAND support (and bbiswap patch :
mxc_nand : allow swapping the Bad block Indicator for NFC v1).
Here is errors that I have sometimes after updating a lot of of files.
Everything is working good until I power off the board (before that I
start that reboot script that sync and umount all filesystems and
remount / as ro (sync is also run before remount) before reboot.
While this update, there is several "ln -sf" because busybox must be
updated.
Sometimes it works and sometimes filesystem gets corrupted and gives me
following kind of errors :
jffs2: error: (1) jffs2_build_inode_pass1: child dir "share" (ino #9044)
of dir ino #9041 appears to be a hard link
jffs2: warning: (1022) jffs2_get_inode_nodes: Eep. No valid nodes for
ino #9044.
jffs2: warning: (1022) jffs2_do_read_inode_internal: no data nodes found
for ino #9044
This never occurs with kernel 2.6.22 from Freescale but with kernel
3.4.4, it occurs.
I am going to compile kernel 3.4.12 but I don't see anything in commits
about this problem.
Does anyone have an idea where the problem is ?
Thanks for your help.
Best regards,
Ga?tan Carlier.
^ permalink raw reply
* [PATCH v8 0/6] OMAP-GPMC cleanup for generic timing
From: Afzal Mohammed @ 2012-10-05 15:34 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This series prepares gpmc for generic timing. v7 of this series was
named "OMAP-GPMC: generic time calc, prepare for driver". generic
timing routine has been removed from this series. generic timing
will be posted as a new separate series shortly.
This rearrangement has been done so that generic timing series will
happen on top of another cleanup series required for common arm zImage.
Both will follow shortly. Intention is to make easy path for common
arm zImage cleanup.
This series contains minor cleanups that were low hanging fruits
came across upon implementing generic timing routine.
This series is same as v7, except that last 4 patches in v7 has been
removed from this series (those 4 patches were for generic timing)
This series is available
@ git://gitorious.org/x0148406-public/linux-kernel.git gpmc-prep-v8
and is based on
linux-next (next-20121005)
Regards
Afzal
v8:
Remove generic timing conversion patches
v7:
1. Use picoseconds throughout generic timing routine to prevent
rounding error.
2. Documentation on gpmc timings
3. Remove redundant rounding of nand timings (a new patch)
v6:
1. Generic timing calculation, move existing users of custom
calculation to use the new generic one
2. Set OneNAND part to async mode before gpmc configuration
3. Move extra delay time user handling to proper patch
(3/10 -> 2/10)
4. Modify nand init for OMAP3EVM too as support got added
v5:
Use flags for sync_read/write, hv, vhf
v4:
Reorganize OneNAND set_sync/async functions in a better way
v3:
1. Refactor OneNAND set_sync/async functions to separate out
timing and configurations
2. Handle bool type timings too
3. Swap patches 2 & 3 due to dependency of OneNAND change on
newly added bool type timings
v2:
1. Make use of timing api for setting clock activation time,
and remove direct writing to register for clock activation.
2. Move ensuring that async mode in OneNAND has been setup from
set_sync to setup function, improve commit message
Afzal Mohammed (5):
ARM: OMAP2+: nand: unify init functions
ARM: OMAP2+: nand: remove redundant rounding
ARM: OMAP2+: gpmc: handle additional timings
ARM: OMAP2+: onenand: refactor for clarity
ARM: OMAP2+: gpmc: remove cs# in sync clk div calc
Jon Hunter (1):
ARM: OMAP2+: GPMC: Remove unused OneNAND get_freq() platform function
arch/arm/mach-omap2/board-devkit8000.c | 8 +-
arch/arm/mach-omap2/board-flash.c | 45 ++---
arch/arm/mach-omap2/board-flash.h | 6 +-
arch/arm/mach-omap2/board-igep0020.c | 2 +-
arch/arm/mach-omap2/board-ldp.c | 4 +-
arch/arm/mach-omap2/board-omap3beagle.c | 8 +-
arch/arm/mach-omap2/board-omap3evm.c | 8 +-
arch/arm/mach-omap2/board-omap3touchbook.c | 8 +-
arch/arm/mach-omap2/board-overo.c | 7 +-
arch/arm/mach-omap2/board-zoom.c | 5 +-
arch/arm/mach-omap2/common-board-devices.c | 45 -----
arch/arm/mach-omap2/common-board-devices.h | 1 -
arch/arm/mach-omap2/gpmc-nand.c | 30 ++-
arch/arm/mach-omap2/gpmc-onenand.c | 232 ++++++++++++------------
arch/arm/mach-omap2/gpmc.c | 52 +++++-
arch/arm/mach-omap2/usb-tusb6010.c | 3 +-
arch/arm/plat-omap/include/plat/gpmc.h | 21 ++-
include/linux/platform_data/mtd-onenand-omap2.h | 8 -
18 files changed, 262 insertions(+), 231 deletions(-)
--
1.7.12
^ permalink raw reply
* [PATCH v8 1/6] ARM: OMAP2+: nand: unify init functions
From: Afzal Mohammed @ 2012-10-05 15:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349444935.git.afzal@ti.com>
Helper function for updating nand platform data has been
added the capability to take timing structure arguement.
Usage of omap_nand_flash_init() has been replaced by modifed
one, omap_nand_flash_init was doing things similar to
board_nand_init except that NAND CS# were being acquired
based on bootloader setting. As CS# is hardwired for a given
board, acquiring gpmc CS# has been removed, and updated with
the value on board.
NAND CS# used in beagle board & omap3evm was found to be CS0.
Thomas Weber <thomas.weber.linux@googlemail.com> reported
that value of devkit8000 to be CS0. Overo board was found
to be using CS0 based on u-boot, while google grep says
omap3touchbook too has CS0.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
Reviewed-by: Jon Hunter <jon-hunter@ti.com>
Acked-by: Igor Grinberg <grinberg@compulab.co.il>
---
arch/arm/mach-omap2/board-devkit8000.c | 8 ++++--
arch/arm/mach-omap2/board-flash.c | 45 +++++++++++++++---------------
arch/arm/mach-omap2/board-flash.h | 6 ++--
arch/arm/mach-omap2/board-igep0020.c | 2 +-
arch/arm/mach-omap2/board-ldp.c | 4 +--
arch/arm/mach-omap2/board-omap3beagle.c | 8 ++++--
arch/arm/mach-omap2/board-omap3evm.c | 8 ++++--
arch/arm/mach-omap2/board-omap3touchbook.c | 8 ++++--
arch/arm/mach-omap2/board-overo.c | 7 +++--
arch/arm/mach-omap2/board-zoom.c | 5 ++--
arch/arm/mach-omap2/common-board-devices.c | 45 ------------------------------
arch/arm/mach-omap2/common-board-devices.h | 1 -
12 files changed, 62 insertions(+), 85 deletions(-)
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 1fd161e..9933966 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -55,8 +55,11 @@
#include "sdram-micron-mt46h32m32lf-6.h"
#include "mux.h"
#include "hsmmc.h"
+#include "board-flash.h"
#include "common-board-devices.h"
+#define NAND_CS 0
+
#define OMAP_DM9000_GPIO_IRQ 25
#define OMAP3_DEVKIT_TS_GPIO 27
@@ -621,8 +624,9 @@ static void __init devkit8000_init(void)
usb_musb_init(NULL);
usbhs_init(&usbhs_bdata);
- omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions,
- ARRAY_SIZE(devkit8000_nand_partitions));
+ board_nand_init(devkit8000_nand_partitions,
+ ARRAY_SIZE(devkit8000_nand_partitions), NAND_CS,
+ NAND_BUSWIDTH_16, NULL);
omap_twl4030_audio_init("omap3beagle");
/* Ensure SDRC pins are mux'd for self-refresh */
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 0cabe61..f8b30cb 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -104,41 +104,41 @@ __init board_onenand_init(struct mtd_partition *onenand_parts,
defined(CONFIG_MTD_NAND_OMAP2_MODULE)
/* Note that all values in this struct are in nanoseconds */
-static struct gpmc_timings nand_timings = {
+struct gpmc_timings nand_default_timings[1] = {
+ {
+ .sync_clk = 0,
- .sync_clk = 0,
+ .cs_on = 0,
+ .cs_rd_off = 36,
+ .cs_wr_off = 36,
- .cs_on = 0,
- .cs_rd_off = 36,
- .cs_wr_off = 36,
+ .adv_on = 6,
+ .adv_rd_off = 24,
+ .adv_wr_off = 36,
- .adv_on = 6,
- .adv_rd_off = 24,
- .adv_wr_off = 36,
+ .we_off = 30,
+ .oe_off = 48,
- .we_off = 30,
- .oe_off = 48,
+ .access = 54,
+ .rd_cycle = 72,
+ .wr_cycle = 72,
- .access = 54,
- .rd_cycle = 72,
- .wr_cycle = 72,
-
- .wr_access = 30,
- .wr_data_mux_bus = 0,
+ .wr_access = 30,
+ .wr_data_mux_bus = 0,
+ },
};
-static struct omap_nand_platform_data board_nand_data = {
- .gpmc_t = &nand_timings,
-};
+static struct omap_nand_platform_data board_nand_data;
void
-__init board_nand_init(struct mtd_partition *nand_parts,
- u8 nr_parts, u8 cs, int nand_type)
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
+ int nand_type, struct gpmc_timings *gpmc_t)
{
board_nand_data.cs = cs;
board_nand_data.parts = nand_parts;
board_nand_data.nr_parts = nr_parts;
board_nand_data.devsize = nand_type;
+ board_nand_data.gpmc_t = gpmc_t;
board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
gpmc_nand_init(&board_nand_data);
@@ -238,5 +238,6 @@ void __init board_flash_init(struct flash_partitions partition_info[],
pr_err("NAND: Unable to find configuration in GPMC\n");
else
board_nand_init(partition_info[2].parts,
- partition_info[2].nr_parts, nandcs, nand_type);
+ partition_info[2].nr_parts, nandcs,
+ nand_type, nand_default_timings);
}
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index c44b70d..a3aa5fc 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -40,12 +40,14 @@ static inline void board_flash_init(struct flash_partitions part[],
#if defined(CONFIG_MTD_NAND_OMAP2) || \
defined(CONFIG_MTD_NAND_OMAP2_MODULE)
extern void board_nand_init(struct mtd_partition *nand_parts,
- u8 nr_parts, u8 cs, int nand_type);
+ u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t);
+extern struct gpmc_timings nand_default_timings[];
#else
static inline void board_nand_init(struct mtd_partition *nand_parts,
- u8 nr_parts, u8 cs, int nand_type)
+ u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t)
{
}
+#define nand_default_timings NULL
#endif
#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 48d5e41..f6b3ed0 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -175,7 +175,7 @@ static void __init igep_flash_init(void)
pr_info("IGEP: initializing NAND memory device\n");
board_nand_init(igep_flash_partitions,
ARRAY_SIZE(igep_flash_partitions),
- 0, NAND_BUSWIDTH_16);
+ 0, NAND_BUSWIDTH_16, nand_default_timings);
} else if (mux == IGEP_SYSBOOT_ONENAND) {
pr_info("IGEP: initializing OneNAND memory device\n");
board_onenand_init(igep_flash_partitions,
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index ee8c3cf..83383f3 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -420,8 +420,8 @@ static void __init omap_ldp_init(void)
omap_serial_init();
omap_sdrc_init(NULL, NULL);
usb_musb_init(NULL);
- board_nand_init(ldp_nand_partitions,
- ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
+ board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
+ ZOOM_NAND_CS, 0, nand_default_timings);
omap_hsmmc_init(mmc);
ldp_display_init();
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index a08bebc..f240e21 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -49,8 +49,11 @@
#include "mux.h"
#include "hsmmc.h"
#include "pm.h"
+#include "board-flash.h"
#include "common-board-devices.h"
+#define NAND_CS 0
+
/*
* OMAP3 Beagle revision
* Run time detection of Beagle revision is done by reading GPIO.
@@ -512,8 +515,9 @@ static void __init omap3_beagle_init(void)
usb_musb_init(NULL);
usbhs_init(&usbhs_bdata);
- omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
- ARRAY_SIZE(omap3beagle_nand_partitions));
+ board_nand_init(omap3beagle_nand_partitions,
+ ARRAY_SIZE(omap3beagle_nand_partitions), NAND_CS,
+ NAND_BUSWIDTH_16, NULL);
omap_twl4030_audio_init("omap3beagle");
/* Ensure msecure is mux'd to be able to set the RTC. */
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index a3959de..b23c81e 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -56,6 +56,9 @@
#include "sdram-micron-mt46h32m32lf-6.h"
#include "hsmmc.h"
#include "common-board-devices.h"
+#include "board-flash.h"
+
+#define NAND_CS 0
#define OMAP3_EVM_TS_GPIO 175
#define OMAP3_EVM_EHCI_VBUS 22
@@ -732,8 +735,9 @@ static void __init omap3_evm_init(void)
}
usb_musb_init(&musb_board_data);
usbhs_init(&usbhs_bdata);
- omap_nand_flash_init(NAND_BUSWIDTH_16, omap3evm_nand_partitions,
- ARRAY_SIZE(omap3evm_nand_partitions));
+ board_nand_init(omap3evm_nand_partitions,
+ ARRAY_SIZE(omap3evm_nand_partitions), NAND_CS,
+ NAND_BUSWIDTH_16, NULL);
omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);
omap3evm_init_smsc911x();
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 944ffc4..3f013c8 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -50,6 +50,7 @@
#include "mux.h"
#include "hsmmc.h"
+#include "board-flash.h"
#include "common-board-devices.h"
#include <asm/setup.h>
@@ -59,6 +60,8 @@
#define TB_BL_PWM_TIMER 9
#define TB_KILL_POWER_GPIO 168
+#define NAND_CS 0
+
static unsigned long touchbook_revision;
static struct mtd_partition omap3touchbook_nand_partitions[] = {
@@ -365,8 +368,9 @@ static void __init omap3_touchbook_init(void)
omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata);
usb_musb_init(NULL);
usbhs_init(&usbhs_bdata);
- omap_nand_flash_init(NAND_BUSWIDTH_16, omap3touchbook_nand_partitions,
- ARRAY_SIZE(omap3touchbook_nand_partitions));
+ board_nand_init(omap3touchbook_nand_partitions,
+ ARRAY_SIZE(omap3touchbook_nand_partitions), NAND_CS,
+ NAND_BUSWIDTH_16, NULL);
/* Ensure SDRC pins are mux'd for self-refresh */
omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index b700685..e2cf0f7 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -55,8 +55,11 @@
#include "mux.h"
#include "sdram-micron-mt46h32m32lf-6.h"
#include "hsmmc.h"
+#include "board-flash.h"
#include "common-board-devices.h"
+#define NAND_CS 0
+
#define OVERO_GPIO_BT_XGATE 15
#define OVERO_GPIO_W2W_NRESET 16
#define OVERO_GPIO_PENDOWN 114
@@ -495,8 +498,8 @@ static void __init overo_init(void)
omap_serial_init();
omap_sdrc_init(mt46h32m32lf6_sdrc_params,
mt46h32m32lf6_sdrc_params);
- omap_nand_flash_init(0, overo_nand_partitions,
- ARRAY_SIZE(overo_nand_partitions));
+ board_nand_init(overo_nand_partitions,
+ ARRAY_SIZE(overo_nand_partitions), NAND_CS, 0, NULL);
usb_musb_init(NULL);
usbhs_init(&usbhs_bdata);
overo_spi_init();
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index 4994438..c39578c 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -113,8 +113,9 @@ static void __init omap_zoom_init(void)
usbhs_init(&usbhs_bdata);
}
- board_nand_init(zoom_nand_partitions, ARRAY_SIZE(zoom_nand_partitions),
- ZOOM_NAND_CS, NAND_BUSWIDTH_16);
+ board_nand_init(zoom_nand_partitions,
+ ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS,
+ NAND_BUSWIDTH_16, nand_default_timings);
zoom_debugboard_init();
zoom_peripherals_init();
diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c
index 48daac2..90e0597 100644
--- a/arch/arm/mach-omap2/common-board-devices.c
+++ b/arch/arm/mach-omap2/common-board-devices.c
@@ -96,48 +96,3 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
{
}
#endif
-
-#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-static struct omap_nand_platform_data nand_data;
-
-void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
- int nr_parts)
-{
- u8 cs = 0;
- u8 nandcs = GPMC_CS_NUM + 1;
-
- /* find out the chip-select on which NAND exists */
- while (cs < GPMC_CS_NUM) {
- u32 ret = 0;
- ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
- if ((ret & 0xC00) == 0x800) {
- printk(KERN_INFO "Found NAND on CS%d\n", cs);
- if (nandcs > GPMC_CS_NUM)
- nandcs = cs;
- }
- cs++;
- }
-
- if (nandcs > GPMC_CS_NUM) {
- pr_info("NAND: Unable to find configuration in GPMC\n");
- return;
- }
-
- if (nandcs < GPMC_CS_NUM) {
- nand_data.cs = nandcs;
- nand_data.parts = parts;
- nand_data.nr_parts = nr_parts;
- nand_data.devsize = options;
-
- printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- if (gpmc_nand_init(&nand_data) < 0)
- printk(KERN_ERR "Unable to register NAND device\n");
- }
-}
-#else
-void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
- int nr_parts)
-{
-}
-#endif
diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h
index a0b4a428..72bb41b 100644
--- a/arch/arm/mach-omap2/common-board-devices.h
+++ b/arch/arm/mach-omap2/common-board-devices.h
@@ -10,6 +10,5 @@ struct ads7846_platform_data;
void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
struct ads7846_platform_data *board_pdata);
-void omap_nand_flash_init(int opts, struct mtd_partition *parts, int n_parts);
#endif /* __OMAP_COMMON_BOARD_DEVICES__ */
--
1.7.12
^ permalink raw reply related
* [PATCH v8 2/6] ARM: OMAP2+: nand: remove redundant rounding
From: Afzal Mohammed @ 2012-10-05 15:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349444935.git.afzal@ti.com>
gpmc_cs_set_timings() calculate ticks to be programmed by
rounding time in ns to next tick value. Hence remove
redundant rounding of nanosecond timing.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
arch/arm/mach-omap2/gpmc-nand.c | 30 +++++++++++++-----------------
1 file changed, 13 insertions(+), 17 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 4acf497..4eceaca 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -50,31 +50,27 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data
memset(&t, 0, sizeof(t));
t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk;
- t.cs_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_on);
- t.adv_on = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->adv_on);
+ t.cs_on = gpmc_nand_data->gpmc_t->cs_on;
+ t.adv_on = gpmc_nand_data->gpmc_t->adv_on;
/* Read */
- t.adv_rd_off = gpmc_round_ns_to_ticks(
- gpmc_nand_data->gpmc_t->adv_rd_off);
+ t.adv_rd_off = gpmc_nand_data->gpmc_t->adv_rd_off;
t.oe_on = t.adv_on;
- t.access = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->access);
- t.oe_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->oe_off);
- t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_rd_off);
- t.rd_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->rd_cycle);
+ t.access = gpmc_nand_data->gpmc_t->access;
+ t.oe_off = gpmc_nand_data->gpmc_t->oe_off;
+ t.cs_rd_off = gpmc_nand_data->gpmc_t->cs_rd_off;
+ t.rd_cycle = gpmc_nand_data->gpmc_t->rd_cycle;
/* Write */
- t.adv_wr_off = gpmc_round_ns_to_ticks(
- gpmc_nand_data->gpmc_t->adv_wr_off);
+ t.adv_wr_off = gpmc_nand_data->gpmc_t->adv_wr_off;
t.we_on = t.oe_on;
if (cpu_is_omap34xx()) {
- t.wr_data_mux_bus = gpmc_round_ns_to_ticks(
- gpmc_nand_data->gpmc_t->wr_data_mux_bus);
- t.wr_access = gpmc_round_ns_to_ticks(
- gpmc_nand_data->gpmc_t->wr_access);
+ t.wr_data_mux_bus = gpmc_nand_data->gpmc_t->wr_data_mux_bus;
+ t.wr_access = gpmc_nand_data->gpmc_t->wr_access;
}
- t.we_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->we_off);
- t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off);
- t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
+ t.we_off = gpmc_nand_data->gpmc_t->we_off;
+ t.cs_wr_off = gpmc_nand_data->gpmc_t->cs_wr_off;
+ t.wr_cycle = gpmc_nand_data->gpmc_t->wr_cycle;
/* Configure GPMC */
if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
--
1.7.12
^ permalink raw reply related
* [PATCH v8 3/6] ARM: OMAP2+: gpmc: handle additional timings
From: Afzal Mohammed @ 2012-10-05 15:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349444935.git.afzal@ti.com>
Configure busturnaround, cycle2cycledelay, waitmonitoringtime,
clkactivationtime in gpmc_cs_set_timings(). This is done so
that boards can configure these parameters of gpmc in Kernel
instead of relying on bootloader. Also configure bool type
timings like extradelay.
This needed change to the existing users that were configuring
clk activation time and extra delay by directly writing to
registers. Thanks to Tony for making me aware of users of clk
activation and being kind enough to test the modified one.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
---
arch/arm/mach-omap2/gpmc-onenand.c | 28 +++++---------------
arch/arm/mach-omap2/gpmc.c | 48 ++++++++++++++++++++++++++++++++++
arch/arm/mach-omap2/usb-tusb6010.c | 3 ++-
arch/arm/plat-omap/include/plat/gpmc.h | 19 ++++++++++++++
4 files changed, 75 insertions(+), 23 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 916716e..3b61544 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -284,27 +284,10 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
sync_read, sync_write, hf, vhf);
if (div == 1) {
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
- reg |= (1 << 7);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
- reg |= (1 << 7);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
- reg |= (1 << 7);
- reg |= (1 << 23);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
- } else {
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
- reg &= ~(1 << 7);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
- reg &= ~(1 << 7);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
- reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
- reg &= ~(1 << 7);
- reg &= ~(1 << 23);
- gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
+ t.bool_timings.cs_extra_delay = true;
+ t.bool_timings.adv_extra_delay = true;
+ t.bool_timings.oe_extra_delay = true;
+ t.bool_timings.we_extra_delay = true;
}
/* Set synchronous read timings */
@@ -329,6 +312,8 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div +
ticks_cez);
+ t.clk_activation = fclk_offset_ns;
+
/* Write */
if (sync_write) {
t.adv_wr_off = t.adv_rd_off;
@@ -362,7 +347,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
(sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
(sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
(sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
- GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
GPMC_CONFIG1_PAGE_LEN(2) |
(cpu_is_omap34xx() ? 0 :
(GPMC_CONFIG1_WAIT_READ_MON |
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 8ab1e1b..c2d90f6 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -73,6 +73,13 @@
#define GPMC_ECC_CTRL_ECCREG8 0x008
#define GPMC_ECC_CTRL_ECCREG9 0x009
+#define GPMC_CONFIG2_CSEXTRADELAY BIT(7)
+#define GPMC_CONFIG3_ADVEXTRADELAY BIT(7)
+#define GPMC_CONFIG4_OEEXTRADELAY BIT(7)
+#define GPMC_CONFIG4_WEEXTRADELAY BIT(23)
+#define GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN BIT(6)
+#define GPMC_CONFIG6_CYCLE2CYCLESAMECSEN BIT(7)
+
#define GPMC_CS0_OFFSET 0x60
#define GPMC_CS_SIZE 0x30
@@ -238,6 +245,39 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
return ticks * gpmc_get_fclk_period() / 1000;
}
+static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value)
+{
+ u32 l;
+
+ l = gpmc_cs_read_reg(cs, reg);
+ if (value)
+ l |= mask;
+ else
+ l &= ~mask;
+ gpmc_cs_write_reg(cs, reg, l);
+}
+
+static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p)
+{
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1,
+ GPMC_CONFIG1_TIME_PARA_GRAN,
+ p->time_para_granularity);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2,
+ GPMC_CONFIG2_CSEXTRADELAY, p->cs_extra_delay);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3,
+ GPMC_CONFIG3_ADVEXTRADELAY, p->adv_extra_delay);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+ GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+ GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+ GPMC_CONFIG6_CYCLE2CYCLESAMECSEN,
+ p->cycle2cyclesamecsen);
+ gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+ GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN,
+ p->cycle2cyclediffcsen);
+}
+
#ifdef DEBUG
static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
int time, const char *name)
@@ -331,6 +371,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
+ GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround);
+ GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
+
+ GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring);
+ GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation);
+
if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
if (gpmc_capability & GPMC_HAS_WR_ACCESS)
@@ -350,6 +396,8 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
}
+ gpmc_cs_bool_timings(cs, &t->bool_timings);
+
return 0;
}
diff --git a/arch/arm/mach-omap2/usb-tusb6010.c b/arch/arm/mach-omap2/usb-tusb6010.c
index 805bea6..7a85ebe 100644
--- a/arch/arm/mach-omap2/usb-tusb6010.c
+++ b/arch/arm/mach-omap2/usb-tusb6010.c
@@ -174,6 +174,8 @@ static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
+ t.clk_activation = gpmc_ticks_to_ns(1);
+
return gpmc_cs_set_timings(sync_cs, &t);
}
@@ -283,7 +285,6 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
| GPMC_CONFIG1_READTYPE_SYNC
| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
| GPMC_CONFIG1_WRITETYPE_SYNC
- | GPMC_CONFIG1_CLKACTIVATIONTIME(1)
| GPMC_CONFIG1_PAGE_LEN(2)
| GPMC_CONFIG1_WAIT_READ_MON
| GPMC_CONFIG1_WAIT_WRITE_MON
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 2e6e259..b7c9ea6 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -96,6 +96,17 @@ enum omap_ecc {
OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */
};
+/* bool type time settings */
+struct gpmc_bool_timings {
+ bool cycle2cyclediffcsen;
+ bool cycle2cyclesamecsen;
+ bool we_extra_delay;
+ bool oe_extra_delay;
+ bool adv_extra_delay;
+ bool cs_extra_delay;
+ bool time_para_granularity;
+};
+
/*
* Note that all values in this struct are in nanoseconds except sync_clk
* (which is in picoseconds), while the register values are in gpmc_fck cycles.
@@ -128,9 +139,17 @@ struct gpmc_timings {
u16 rd_cycle; /* Total read cycle time */
u16 wr_cycle; /* Total write cycle time */
+ u16 bus_turnaround;
+ u16 cycle2cycle_delay;
+
+ u16 wait_monitoring;
+ u16 clk_activation;
+
/* The following are only on OMAP3430 */
u16 wr_access; /* WRACCESSTIME */
u16 wr_data_mux_bus; /* WRDATAONADMUXBUS */
+
+ struct gpmc_bool_timings bool_timings;
};
struct gpmc_nand_regs {
--
1.7.12
^ permalink raw reply related
* [PATCH v8 4/6] ARM: OMAP2+: onenand: refactor for clarity
From: Afzal Mohammed @ 2012-10-05 15:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349444935.git.afzal@ti.com>
Refactor set_async_mode & set_sync_mode functions to
separate out timing calculation & actual configuration
(GPMC & OneNAND side).
Thanks to Jon for his suggestions.
Signed-off-by: Afzal Mohammed <afzal@ti.com>
Reviewed-by: Jon Hunter <jon-hunter@ti.com>
---
arch/arm/mach-omap2/gpmc-onenand.c | 174 +++++++++++++++++++++++--------------
1 file changed, 109 insertions(+), 65 deletions(-)
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 3b61544..e1328f5 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -16,6 +16,7 @@
#include <linux/mtd/onenand_regs.h>
#include <linux/io.h>
#include <linux/platform_data/mtd-onenand-omap2.h>
+#include <linux/err.h>
#include <asm/mach/flash.h>
@@ -25,6 +26,14 @@
#define ONENAND_IO_SIZE SZ_128K
+#define ONENAND_FLAG_SYNCREAD (1 << 0)
+#define ONENAND_FLAG_SYNCWRITE (1 << 1)
+#define ONENAND_FLAG_HF (1 << 2)
+#define ONENAND_FLAG_VHF (1 << 3)
+
+static unsigned onenand_flags;
+static unsigned latency;
+
static struct omap_onenand_platform_data *gpmc_onenand_data;
static struct resource gpmc_onenand_resource = {
@@ -38,11 +47,9 @@ static struct platform_device gpmc_onenand_device = {
.resource = &gpmc_onenand_resource,
};
-static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
+static struct gpmc_timings omap2_onenand_calc_async_timings(void)
{
struct gpmc_timings t;
- u32 reg;
- int err;
const int t_cer = 15;
const int t_avdp = 12;
@@ -55,11 +62,6 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
const int t_wpl = 40;
const int t_wph = 30;
- /* Ensure sync read and sync write are disabled */
- reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
- reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
- writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
-
memset(&t, 0, sizeof(t));
t.sync_clk = 0;
t.cs_on = 0;
@@ -86,25 +88,30 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
+ return t;
+}
+
+static int gpmc_set_async_mode(int cs, struct gpmc_timings *t)
+{
/* Configure GPMC for asynchronous read */
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
GPMC_CONFIG1_DEVICESIZE_16 |
GPMC_CONFIG1_MUXADDDATA);
- err = gpmc_cs_set_timings(cs, &t);
- if (err)
- return err;
+ return gpmc_cs_set_timings(cs, t);
+}
+
+static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
+{
+ u32 reg;
/* Ensure sync read and sync write are disabled */
reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
reg &= ~ONENAND_SYS_CFG1_SYNC_READ & ~ONENAND_SYS_CFG1_SYNC_WRITE;
writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
-
- return 0;
}
-static void set_onenand_cfg(void __iomem *onenand_base, int latency,
- int sync_read, int sync_write, int hf, int vhf)
+static void set_onenand_cfg(void __iomem *onenand_base)
{
u32 reg;
@@ -112,19 +119,19 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency,
reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
ONENAND_SYS_CFG1_BL_16;
- if (sync_read)
+ if (onenand_flags & ONENAND_FLAG_SYNCREAD)
reg |= ONENAND_SYS_CFG1_SYNC_READ;
else
reg &= ~ONENAND_SYS_CFG1_SYNC_READ;
- if (sync_write)
+ if (onenand_flags & ONENAND_FLAG_SYNCWRITE)
reg |= ONENAND_SYS_CFG1_SYNC_WRITE;
else
reg &= ~ONENAND_SYS_CFG1_SYNC_WRITE;
- if (hf)
+ if (onenand_flags & ONENAND_FLAG_HF)
reg |= ONENAND_SYS_CFG1_HF;
else
reg &= ~ONENAND_SYS_CFG1_HF;
- if (vhf)
+ if (onenand_flags & ONENAND_FLAG_VHF)
reg |= ONENAND_SYS_CFG1_VHF;
else
reg &= ~ONENAND_SYS_CFG1_VHF;
@@ -172,9 +179,9 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
return freq;
}
-static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
- void __iomem *onenand_base,
- int *freq_ptr)
+static struct gpmc_timings
+omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
+ int freq, bool clk_dep)
{
struct gpmc_timings t;
const int t_cer = 15;
@@ -184,29 +191,14 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
const int t_wpl = 40;
const int t_wph = 30;
int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
- int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
- int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
- int err, ticks_cez;
- int cs = cfg->cs, freq = *freq_ptr;
- u32 reg;
- bool clk_dep = false;
-
- if (cfg->flags & ONENAND_SYNC_READ) {
- sync_read = 1;
- } else if (cfg->flags & ONENAND_SYNC_READWRITE) {
- sync_read = 1;
- sync_write = 1;
- } else
- return omap2_onenand_set_async_mode(cs, onenand_base);
+ int div, fclk_offset_ns, fclk_offset, gpmc_clk_ns;
+ int ticks_cez;
+ int cs = cfg->cs;
- if (!freq) {
- /* Very first call freq is not known */
- err = omap2_onenand_set_async_mode(cs, onenand_base);
- if (err)
- return err;
- freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep);
- first_time = 1;
- }
+ if (cfg->flags & ONENAND_SYNC_READ)
+ onenand_flags = ONENAND_FLAG_SYNCREAD;
+ else if (cfg->flags & ONENAND_SYNC_READWRITE)
+ onenand_flags = ONENAND_FLAG_SYNCREAD | ONENAND_FLAG_SYNCWRITE;
switch (freq) {
case 104:
@@ -244,19 +236,23 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
t_ach = 9;
t_aavdh = 7;
t_rdyo = 15;
- sync_write = 0;
+ onenand_flags &= ~ONENAND_FLAG_SYNCWRITE;
break;
}
div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
gpmc_clk_ns = gpmc_ticks_to_ns(div);
if (gpmc_clk_ns < 15) /* >66Mhz */
- hf = 1;
+ onenand_flags |= ONENAND_FLAG_HF;
+ else
+ onenand_flags &= ~ONENAND_FLAG_HF;
if (gpmc_clk_ns < 12) /* >83Mhz */
- vhf = 1;
- if (vhf)
+ onenand_flags |= ONENAND_FLAG_VHF;
+ else
+ onenand_flags &= ~ONENAND_FLAG_VHF;
+ if (onenand_flags & ONENAND_FLAG_VHF)
latency = 8;
- else if (hf)
+ else if (onenand_flags & ONENAND_FLAG_HF)
latency = 6;
else if (gpmc_clk_ns >= 25) /* 40 MHz*/
latency = 3;
@@ -279,9 +275,8 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
}
}
- if (first_time)
- set_onenand_cfg(onenand_base, latency,
- sync_read, sync_write, hf, vhf);
+ /* Set synchronous read timings */
+ memset(&t, 0, sizeof(t));
if (div == 1) {
t.bool_timings.cs_extra_delay = true;
@@ -290,8 +285,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
t.bool_timings.we_extra_delay = true;
}
- /* Set synchronous read timings */
- memset(&t, 0, sizeof(t));
t.sync_clk = min_gpmc_clk_period;
t.cs_on = 0;
t.adv_on = 0;
@@ -315,7 +308,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
t.clk_activation = fclk_offset_ns;
/* Write */
- if (sync_write) {
+ if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
t.adv_wr_off = t.adv_rd_off;
t.we_on = 0;
t.we_off = t.cs_rd_off;
@@ -340,6 +333,14 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
}
}
+ return t;
+}
+
+static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
+{
+ unsigned sync_read = onenand_flags & ONENAND_FLAG_SYNCREAD;
+ unsigned sync_write = onenand_flags & ONENAND_FLAG_SYNCWRITE;
+
/* Configure GPMC for synchronous read */
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
GPMC_CONFIG1_WRAPBURST_SUPP |
@@ -355,11 +356,47 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
GPMC_CONFIG1_DEVICETYPE_NOR |
GPMC_CONFIG1_MUXADDDATA);
- err = gpmc_cs_set_timings(cs, &t);
- if (err)
- return err;
+ return gpmc_cs_set_timings(cs, t);
+}
+
+static int omap2_onenand_setup_async(void __iomem *onenand_base)
+{
+ struct gpmc_timings t;
+ int ret;
+
+ omap2_onenand_set_async_mode(onenand_base);
+
+ t = omap2_onenand_calc_async_timings();
+
+ ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ omap2_onenand_set_async_mode(onenand_base);
+
+ return 0;
+}
+
+static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
+{
+ int ret, freq = *freq_ptr;
+ struct gpmc_timings t;
+ bool clk_dep = false;
+
+ if (!freq) {
+ /* Very first call freq is not known */
+ freq = omap2_onenand_get_freq(gpmc_onenand_data,
+ onenand_base, &clk_dep);
+ set_onenand_cfg(onenand_base);
+ }
+
+ t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq, clk_dep);
- set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
+ ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ set_onenand_cfg(onenand_base);
*freq_ptr = freq;
@@ -369,15 +406,22 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
{
struct device *dev = &gpmc_onenand_device.dev;
+ unsigned l = ONENAND_SYNC_READ | ONENAND_SYNC_READWRITE;
+ int ret;
- /* Set sync timings in GPMC */
- if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base,
- freq_ptr) < 0) {
- dev_err(dev, "Unable to set synchronous mode\n");
- return -EINVAL;
+ ret = omap2_onenand_setup_async(onenand_base);
+ if (ret) {
+ dev_err(dev, "unable to set to async mode\n");
+ return ret;
}
- return 0;
+ if (!(gpmc_onenand_data->flags & l))
+ return 0;
+
+ ret = omap2_onenand_setup_sync(onenand_base, freq_ptr);
+ if (ret)
+ dev_err(dev, "unable to set to sync mode\n");
+ return ret;
}
void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
--
1.7.12
^ permalink raw reply related
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