* [PATCH v5 08/10] ARM: mxs: add ocotp read function
From: Sascha Hauer @ 2011-01-14 8:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294989894-20780-1-git-send-email-shawn.guo@freescale.com>
On Fri, Jan 14, 2011 at 03:24:54PM +0800, Shawn Guo wrote:
> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
> ---
> arch/arm/mach-mxs/Kconfig | 4 ++
> arch/arm/mach-mxs/Makefile | 3 +
> arch/arm/mach-mxs/include/mach/common.h | 1 +
> arch/arm/mach-mxs/ocotp.c | 90 +++++++++++++++++++++++++++++++
> 4 files changed, 98 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/mach-mxs/ocotp.c
>
> diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
> index 8bfc8df..cd2fbdf 100644
> --- a/arch/arm/mach-mxs/Kconfig
> +++ b/arch/arm/mach-mxs/Kconfig
> @@ -2,6 +2,9 @@ if ARCH_MXS
>
> source "arch/arm/mach-mxs/devices/Kconfig"
>
> +config MXS_OCOTP
> + bool
> +
> config SOC_IMX23
> bool
> select CPU_ARM926T
> @@ -26,6 +29,7 @@ config MACH_MX28EVK
> select SOC_IMX28
> select MXS_HAVE_AMBA_DUART
> select MXS_HAVE_PLATFORM_FEC
> + select MXS_OCOTP
> default y
> help
> Include support for MX28EVK platform. This includes specific
> diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
> index 39d3f9c..623899b 100644
> --- a/arch/arm/mach-mxs/Makefile
> +++ b/arch/arm/mach-mxs/Makefile
> @@ -1,6 +1,9 @@
> # Common support
> obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o
>
> +obj-$(CONFIG_PM) += pm.o
> +obj-$(CONFIG_MXS_OCOTP) += ocotp.o
> +
> obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
> obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
>
> diff --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h
> index 59133eb..635bb5d 100644
> --- a/arch/arm/mach-mxs/include/mach/common.h
> +++ b/arch/arm/mach-mxs/include/mach/common.h
> @@ -13,6 +13,7 @@
>
> struct clk;
>
> +extern const u32 *mxs_get_ocotp(void);
> extern int mxs_reset_block(void __iomem *);
> extern void mxs_timer_init(struct clk *, int);
>
> diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
> new file mode 100644
> index 0000000..eb2eab7
> --- /dev/null
> +++ b/arch/arm/mach-mxs/ocotp.c
> @@ -0,0 +1,90 @@
> +/*
> + * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +
> +#include <mach/mxs.h>
> +
> +#define OCOTP_WORD_OFFSET 0x20
> +#define OCOTP_WORD_COUNT 0x20
> +
> +#define BM_OCOTP_CTRL_BUSY (1 << 8)
> +#define BM_OCOTP_CTRL_ERROR (1 << 9)
> +#define BM_OCOTP_CTRL_RD_BANK_OPEN (1 << 12)
> +
> +static DEFINE_MUTEX(ocotp_mutex);
> +static u32 ocotp_words[OCOTP_WORD_COUNT];
> +
> +const u32 *mxs_get_ocotp(void)
> +{
> + void __iomem *ocotp_base = MXS_IO_ADDRESS(MXS_OCOTP_BASE_ADDR);
> + int timeout = 0x400;
> + size_t i;
> + static int once = 0;
> +
> + if (once)
> + return ocotp_words;
> +
> + mutex_lock(&ocotp_mutex);
> +
> + /*
> + * clk_enable(hbus_clk) for ocotp can be skipped
> + * as it must be on when system is running.
> + */
> +
> + /* try to clear ERROR bit */
> + __mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base);
> +
> + /* check both BUSY and ERROR cleared */
> + while ((__raw_readl(ocotp_base) &
> + (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout)
> + cpu_relax();
> +
> + if (unlikely(!timeout))
> + goto error_unlock;
> +
> + /* open OCOTP banks for read */
> + __mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
> +
> + /* approximately wait 32 hclk cycles */
> + udelay(1);
> +
> + /* poll BUSY bit becoming cleared */
> + timeout = 0x400;
> + while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout)
> + cpu_relax();
> +
> + if (unlikely(!timeout))
> + goto error_unlock;
> +
> + for (i = 0; i < OCOTP_WORD_COUNT; i++)
> + ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET +
> + i * 0x10);
> +
> + /* close banks for power saving */
> + __mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
> +
> + mutex_unlock(&ocotp_mutex);
> +
> + once = 1;
> +
> + return ocotp_words;
> +
> +error_unlock:
> + mutex_unlock(&ocotp_mutex);
> + pr_err("%s: timeout in reading OCOTP\n", __func__);
> + return NULL;
> +}
EXPORT_SYMBOL?
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH v5 08/10] ARM: mxs: add ocotp read function
From: Uwe Kleine-König @ 2011-01-14 8:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294989894-20780-1-git-send-email-shawn.guo@freescale.com>
On Fri, Jan 14, 2011 at 03:24:54PM +0800, Shawn Guo wrote:
> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
> ---
> arch/arm/mach-mxs/Kconfig | 4 ++
> arch/arm/mach-mxs/Makefile | 3 +
> arch/arm/mach-mxs/include/mach/common.h | 1 +
> arch/arm/mach-mxs/ocotp.c | 90 +++++++++++++++++++++++++++++++
> 4 files changed, 98 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/mach-mxs/ocotp.c
>
> diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
> index 8bfc8df..cd2fbdf 100644
> --- a/arch/arm/mach-mxs/Kconfig
> +++ b/arch/arm/mach-mxs/Kconfig
> @@ -2,6 +2,9 @@ if ARCH_MXS
>
> source "arch/arm/mach-mxs/devices/Kconfig"
>
> +config MXS_OCOTP
> + bool
> +
> config SOC_IMX23
> bool
> select CPU_ARM926T
> @@ -26,6 +29,7 @@ config MACH_MX28EVK
> select SOC_IMX28
> select MXS_HAVE_AMBA_DUART
> select MXS_HAVE_PLATFORM_FEC
> + select MXS_OCOTP
> default y
> help
> Include support for MX28EVK platform. This includes specific
> diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
> index 39d3f9c..623899b 100644
> --- a/arch/arm/mach-mxs/Makefile
> +++ b/arch/arm/mach-mxs/Makefile
> @@ -1,6 +1,9 @@
> # Common support
> obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o
>
> +obj-$(CONFIG_PM) += pm.o
this line doesn't belong here.
> +obj-$(CONFIG_MXS_OCOTP) += ocotp.o
> +
> obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
> obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
>
> diff --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h
> index 59133eb..635bb5d 100644
> --- a/arch/arm/mach-mxs/include/mach/common.h
> +++ b/arch/arm/mach-mxs/include/mach/common.h
> @@ -13,6 +13,7 @@
>
> struct clk;
>
> +extern const u32 *mxs_get_ocotp(void);
> extern int mxs_reset_block(void __iomem *);
> extern void mxs_timer_init(struct clk *, int);
>
> diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
> new file mode 100644
> index 0000000..eb2eab7
> --- /dev/null
> +++ b/arch/arm/mach-mxs/ocotp.c
> @@ -0,0 +1,90 @@
> +/*
> + * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/mutex.h>
> +
> +#include <mach/mxs.h>
> +
> +#define OCOTP_WORD_OFFSET 0x20
> +#define OCOTP_WORD_COUNT 0x20
> +
> +#define BM_OCOTP_CTRL_BUSY (1 << 8)
> +#define BM_OCOTP_CTRL_ERROR (1 << 9)
> +#define BM_OCOTP_CTRL_RD_BANK_OPEN (1 << 12)
> +
> +static DEFINE_MUTEX(ocotp_mutex);
> +static u32 ocotp_words[OCOTP_WORD_COUNT];
> +
> +const u32 *mxs_get_ocotp(void)
> +{
> + void __iomem *ocotp_base = MXS_IO_ADDRESS(MXS_OCOTP_BASE_ADDR);
> + int timeout = 0x400;
> + size_t i;
> + static int once = 0;
> +
> + if (once)
> + return ocotp_words;
> +
> + mutex_lock(&ocotp_mutex);
> +
> + /*
> + * clk_enable(hbus_clk) for ocotp can be skipped
> + * as it must be on when system is running.
> + */
> +
> + /* try to clear ERROR bit */
> + __mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base);
> +
> + /* check both BUSY and ERROR cleared */
> + while ((__raw_readl(ocotp_base) &
> + (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout)
> + cpu_relax();
> +
> + if (unlikely(!timeout))
> + goto error_unlock;
> +
> + /* open OCOTP banks for read */
> + __mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
> +
> + /* approximately wait 32 hclk cycles */
> + udelay(1);
> +
> + /* poll BUSY bit becoming cleared */
> + timeout = 0x400;
> + while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout)
> + cpu_relax();
> +
> + if (unlikely(!timeout))
> + goto error_unlock;
> +
> + for (i = 0; i < OCOTP_WORD_COUNT; i++)
> + ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET +
> + i * 0x10);
> +
> + /* close banks for power saving */
> + __mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
> +
> + mutex_unlock(&ocotp_mutex);
> +
> + once = 1;
once needs to be protected by the mutex, too.
Best regards
Uwe
> +
> + return ocotp_words;
> +
> +error_unlock:
> + mutex_unlock(&ocotp_mutex);
> + pr_err("%s: timeout in reading OCOTP\n", __func__);
> + return NULL;
> +}
> --
> 1.7.1
>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH] mm/init.c: fix compilation warning
From: viresh kumar @ 2011-01-14 8:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110114083524.GK24149@n2100.arm.linux.org.uk>
On 01/14/2011 02:05 PM, Russell King - ARM Linux wrote:
> On Fri, Jan 14, 2011 at 12:40:51PM +0530, Viresh Kumar wrote:
>> This patch fixes following warning:
>> mm/init.c:606: warning: format '%08lx' expects type 'long unsigned int', but
>> argument 12 has type 'unsigned int'
>
> The problem is in your definition of VMALLOC_END. It should be typed
> unsigned long - so have a UL suffix on the number.
>
Ok. Will correct that.
thanks.
--
viresh
^ permalink raw reply
* [PATCH] ARM: use memblock memory regions for "System RAM" I/O resources
From: Russell King - ARM Linux @ 2011-01-14 9:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294877317-25832-1-git-send-email-dima@android.com>
On Wed, Jan 12, 2011 at 04:08:37PM -0800, Dima Zavin wrote:
> Do not use memory bank info to request the "system ram" resources as
> they do not track holes created by memblock_remove inside
> machine's reserve callback. If the removed memory is passed as
> platform_device's ioresource, then drivers that call
> request_mem_region would fail due to a conflict with the incorrectly
> configured system ram resource.
Patch looks fine - please send it to the patch system, thanks.
^ permalink raw reply
* [PATCH v2] i.MX51 Framebuffer support
From: Julien Boibessot @ 2011-01-14 9:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110106094237.GB31708@n2100.arm.linux.org.uk>
Russell King - ARM Linux a ?crit :
> On Wed, Jan 05, 2011 at 02:04:20PM +0100, Julien Boibessot wrote:
>
>> The only strange thing I noticed was a kind of uggly sprite/artefact
>> (32x32, I would say) appearing at the same time as the Linux console. I
>> think it may be related to a hardware cursor badly (?) initialised, but
>> I didn't find a fix yet.
>> It disappears when I launch a graphical application (Qt or SDL).
>>
>
> In the top left corner? That'll be the linux penguin logo, and if it's
> not coming out correctly, your framebuffer driver is badly broken.
> Maybe your RGB bitfield information or visual is wrong?
>
Sorry for my late answer...
Penguin logo is OK, the artefact is just under the penguin and is
looking like a blinking cursor until login message is displayed. At that
time it becomes a kind of uggly rectangular black and white lines mix,
overlapping logging message.
I will follow Sascha's advise and try to play with i.MX51 hardware cursor.
Regards,
Julien
^ permalink raw reply
* Pull request i.MX
From: Sascha Hauer @ 2011-01-14 9:23 UTC (permalink / raw)
To: linux-arm-kernel
Russell,
Please pull the following i.MX patches. These are mostly compile fixes
plus some patches to make the recently merged i.MX features usable.
Sascha
The following changes since commit 52cfd503ad7176d23a5dd7af3981744feb60622f:
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6 (2011-01-13 20:15:35 -0800)
are available in the git repository at:
git://git.pengutronix.de/git/imx/linux-2.6.git for-rmk
Arnaud Patard (2):
Fix pwm-related build failure
mx51: add support for pwm
Fabio Estevam (3):
ARM: imx/mx27_3ds: Add debug board support
ARM: mx5: dynamically allocate pwm devices
ARM: mx5: dynamically allocate imx-keypad devices
Richard Zhao (1):
arm: mxc: move IOMUX_CONFIG_SION definition to iomux-v3.h
Sascha Hauer (3):
ARM i.MX27 3ds: Fix mc13783 regulator names
ARM i.MX mx31_3ds: Fix MC13783 regulator names
ARM mxs: clkdev related compile fixes
Shawn Guo (3):
ARM: mx28: update clock and device name for dual fec support
ARM: mx28: add the second fec device registration
ARM: mxs: Change duart device to use amba-pl011
Yong Shen (10):
ARM i.MX53: enable fec driver on EVK board
ARM i.MX53 enable i2c on EVK board
ARM i.MX53 enable sdhc support on EVK board
ARM i.MX53 enable spi on EVK board
ARM i.MX5 uart clock bug fix
ARM: i.MX53: add IOMUX pad for ecspi
ARM: i.MX53 EVK: add ecspi IOMUX setting
ARM: i.MX53 EVK: add spi nor device
ARM i.MX53 enable SMD board bootup
ARM i.MX53 enable LOCO board bootup
arch/arm/Kconfig | 2 +-
arch/arm/mach-imx/Kconfig | 1 +
arch/arm/mach-imx/mach-mx27_3ds.c | 10 ++-
arch/arm/mach-mx3/mach-mx31_3ds.c | 4 +-
arch/arm/mach-mx5/Kconfig | 20 ++++
arch/arm/mach-mx5/Makefile | 2 +
arch/arm/mach-mx5/board-mx51_3ds.c | 5 +-
arch/arm/mach-mx5/board-mx53_evk.c | 74 +++++++++++++
arch/arm/mach-mx5/board-mx53_loco.c | 111 ++++++++++++++++++++
arch/arm/mach-mx5/board-mx53_smd.c | 111 ++++++++++++++++++++
arch/arm/mach-mx5/clock-mx51-mx53.c | 18 +++-
arch/arm/mach-mx5/devices-imx51.h | 8 ++
arch/arm/mach-mx5/devices-imx53.h | 18 +++
arch/arm/mach-mx5/devices.c | 19 ----
arch/arm/mach-mx5/devices.h | 1 -
arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c | 5 +-
arch/arm/mach-mxs/Kconfig | 4 +-
arch/arm/mach-mxs/clock-mx23.c | 13 ++-
arch/arm/mach-mxs/clock-mx28.c | 14 +++-
arch/arm/mach-mxs/devices-mx23.h | 4 +-
arch/arm/mach-mxs/devices-mx28.h | 4 +-
arch/arm/mach-mxs/devices.c | 17 +++-
arch/arm/mach-mxs/devices/Kconfig | 3 +-
arch/arm/mach-mxs/devices/Makefile | 2 +-
arch/arm/mach-mxs/devices/amba-duart.c | 40 +++++++
arch/arm/mach-mxs/devices/platform-duart.c | 48 ---------
arch/arm/mach-mxs/devices/platform-fec.c | 2 +-
arch/arm/mach-mxs/include/mach/devices-common.h | 11 +--
arch/arm/mach-mxs/mach-mx28evk.c | 26 ++++-
arch/arm/plat-mxc/devices/Kconfig | 2 +-
arch/arm/plat-mxc/devices/platform-fec.c | 5 +
arch/arm/plat-mxc/devices/platform-imx-i2c.c | 9 ++
arch/arm/plat-mxc/devices/platform-imx-keypad.c | 5 +
arch/arm/plat-mxc/devices/platform-mxc_pwm.c | 9 ++
.../plat-mxc/devices/platform-sdhci-esdhc-imx.c | 12 ++
arch/arm/plat-mxc/devices/platform-spi_imx.c | 12 ++
arch/arm/plat-mxc/include/mach/iomux-mx53.h | 4 +-
arch/arm/plat-mxc/include/mach/iomux-v3.h | 1 +
arch/arm/plat-mxc/include/mach/mx51.h | 6 +-
arch/arm/plat-mxc/include/mach/mx53.h | 28 +++---
arch/arm/plat-mxc/pwm.c | 2 +-
41 files changed, 567 insertions(+), 125 deletions(-)
create mode 100644 arch/arm/mach-mx5/board-mx53_loco.c
create mode 100644 arch/arm/mach-mx5/board-mx53_smd.c
create mode 100644 arch/arm/mach-mxs/devices/amba-duart.c
delete mode 100644 arch/arm/mach-mxs/devices/platform-duart.c
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH] MTD: atmel_nand: Add DMA support to access Nandflash
From: Hong Xu @ 2011-01-14 9:34 UTC (permalink / raw)
To: linux-arm-kernel
Some SAM9 chips have the ability to perform DMA between CPU and SMC controller.
This patch adds DMA support for SAM9RL, SAM9G45, SSAM9G46,AM9M10, SAM9M11.
Signed-off-by: Hong Xu <hong.xu@atmel.com>
---
drivers/mtd/nand/atmel_nand.c | 140 ++++++++++++++++++++++++++++++++++++++++-
1 files changed, 138 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index ccce0f0..c2fbffe 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -48,6 +48,12 @@
#define no_ecc 0
#endif
+/* DMA for large buffers only */
+#define DMA_MIN_BYTES 512
+
+static int use_dma = 1;
+module_param(use_dma, int, 0);
+
static int on_flash_bbt = 0;
module_param(on_flash_bbt, int, 0);
@@ -89,11 +95,20 @@ struct atmel_nand_host {
struct nand_chip nand_chip;
struct mtd_info mtd;
void __iomem *io_base;
+ void __iomem *io_phys;
struct atmel_nand_data *board;
struct device *dev;
void __iomem *ecc;
+
+ struct completion comp;
+ struct dma_chan *dma_chan;
};
+static int cpu_has_dma(void)
+{
+ return cpu_is_at91sam9rl() || cpu_is_at91sam9g45();
+}
+
/*
* Enable NAND.
*/
@@ -150,7 +165,7 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
/*
* Minimal-overhead PIO for data access.
*/
-static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
{
struct nand_chip *nand_chip = mtd->priv;
@@ -164,7 +179,7 @@ static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
__raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
}
-static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
{
struct nand_chip *nand_chip = mtd->priv;
@@ -178,6 +193,102 @@ static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
__raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
}
+static void dma_complete_func(void *completion)
+{
+ complete(completion);
+}
+
+static void atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
+ int is_read)
+{
+ struct dma_device *dma_dev;
+ enum dma_ctrl_flags flags;
+ dma_addr_t dma_src_addr, dma_dst_addr, phys_addr;
+ struct dma_async_tx_descriptor *tx = NULL;
+ dma_cookie_t cookie;
+ struct nand_chip *chip = mtd->priv;
+ struct atmel_nand_host *host = chip->priv;
+
+ dma_dev = host->dma_chan->device;
+
+ flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT |
+ DMA_COMPL_SKIP_SRC_UNMAP;
+
+ if (is_read)
+ phys_addr = dma_map_single(dma_dev->dev, buf, len,
+ DMA_FROM_DEVICE);
+ else
+ phys_addr = dma_map_single(dma_dev->dev, buf, len,
+ DMA_TO_DEVICE);
+ if (!phys_addr) {
+ dev_err(host->dev, "Failed to dma_map_single\n");
+ goto err_dma_map;
+ }
+
+ if (is_read) {
+ dma_src_addr = (dma_addr_t)host->io_phys;
+ dma_dst_addr = phys_addr;
+ } else {
+ dma_src_addr = phys_addr;
+ dma_dst_addr = (dma_addr_t)host->io_phys;
+ }
+
+ tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr,
+ dma_src_addr, len, flags);
+ if (!tx) {
+ dev_err(host->dev, "Failed to prepare DMA memcpy\n");
+ goto err;
+ }
+
+ init_completion(&host->comp);
+ tx->callback = dma_complete_func;
+ tx->callback_param = &host->comp;
+
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ dev_err(host->dev, "Failed to do DMA tx_submit\n");
+ goto err;
+ }
+
+ dma_async_issue_pending(host->dma_chan);
+
+ wait_for_completion(&host->comp);
+
+err:
+ if (is_read)
+ dma_unmap_single(dma_dev->dev, phys_addr, len, DMA_FROM_DEVICE);
+ else
+ dma_unmap_single(dma_dev->dev, phys_addr, len, DMA_TO_DEVICE);
+err_dma_map:
+ return;
+}
+
+static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct atmel_nand_host *host = chip->priv;
+
+ if (use_dma && len >= DMA_MIN_BYTES)
+ atmel_nand_dma_op(mtd, buf, len, 1);
+ else if (host->board->bus_width_16)
+ atmel_read_buf16(mtd, buf, len);
+ else
+ atmel_read_buf8(mtd, buf, len);
+}
+
+static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+ struct nand_chip *chip = mtd->priv;
+ struct atmel_nand_host *host = chip->priv;
+
+ if (use_dma && len >= DMA_MIN_BYTES)
+ atmel_nand_dma_op(mtd, (u8 *)buf, len, 0);
+ else if (host->board->bus_width_16)
+ atmel_write_buf16(mtd, buf, len);
+ else
+ atmel_write_buf8(mtd, buf, len);
+}
+
/*
* Calculate HW ECC
*
@@ -398,6 +509,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ host->io_phys = (void __iomem *)mem->start;
+
host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
if (host->io_base == NULL) {
printk(KERN_ERR "atmel_nand: ioremap failed\n");
@@ -516,6 +629,23 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
}
}
+ if (cpu_has_dma() && use_dma) {
+ dma_cap_mask_t mask;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_MEMCPY, mask);
+ host->dma_chan = dma_request_channel(mask, 0, NULL);
+
+ if (!host->dma_chan) {
+ dev_err(host->dev, "Failed to request DMA channel\n");
+ use_dma = 0;
+ }
+ }
+ if (use_dma)
+ dev_info(host->dev, "Using DMA for NAND access.\n");
+ else
+ dev_info(host->dev, "No DMA support for NAND access.\n");
+
/* second phase scan */
if (nand_scan_tail(mtd)) {
res = -ENXIO;
@@ -555,6 +685,8 @@ err_scan_ident:
err_no_card:
atmel_nand_disable(host);
platform_set_drvdata(pdev, NULL);
+ if (host->dma_chan)
+ dma_release_channel(host->dma_chan);
if (host->ecc)
iounmap(host->ecc);
err_ecc_ioremap:
@@ -578,6 +710,10 @@ static int __exit atmel_nand_remove(struct platform_device *pdev)
if (host->ecc)
iounmap(host->ecc);
+
+ if (host->dma_chan)
+ dma_release_channel(host->dma_chan);
+
iounmap(host->io_base);
kfree(host);
--
1.7.3.3
^ permalink raw reply related
* [PATCH v2 1/2] arm: mx50_rdp: add fec support
From: Richard Zhao @ 2011-01-14 9:48 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Richard Zhao <richard.zhao@freescale.com>
---
arch/arm/mach-mx5/Kconfig | 1 +
arch/arm/mach-mx5/board-mx50_rdp.c | 22 ++++++++++++++++++++--
arch/arm/mach-mx5/devices-mx50.h | 5 +++++
arch/arm/plat-mxc/devices/platform-fec.c | 5 +++++
4 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index f2f0731..64d2bf9 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -142,6 +142,7 @@ config MACH_MX50_RDP
select IMX_HAVE_PLATFORM_IMX_UART
select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
select IMX_HAVE_PLATFORM_SPI_IMX
+ select IMX_HAVE_PLATFORM_FEC
help
Include support for MX50 reference design platform (RDP) board. This
includes specific configurations for the board and its peripherals.
diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c
index fd32e4c..884c003 100644
--- a/arch/arm/mach-mx5/board-mx50_rdp.c
+++ b/arch/arm/mach-mx5/board-mx50_rdp.c
@@ -37,6 +37,9 @@
#include "devices-mx50.h"
+#define FEC_EN IMX_GPIO_NR(6, 23)
+#define FEC_RESET_B IMX_GPIO_NR(4, 12)
+
static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
/* SD1 */
MX50_PAD_ECSPI2_SS0__GPIO_4_19,
@@ -102,7 +105,7 @@ static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
MX50_PAD_I2C3_SCL__USBOTG_OC,
MX50_PAD_SSI_RXC__FEC_MDIO,
- MX50_PAD_SSI_RXC__FEC_MDIO,
+ MX50_PAD_SSI_RXFS__FEC_MDC,
MX50_PAD_DISP_D0__FEC_TXCLK,
MX50_PAD_DISP_D1__FEC_RX_ER,
MX50_PAD_DISP_D2__FEC_RX_DV,
@@ -111,7 +114,6 @@ static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
MX50_PAD_DISP_D5__FEC_TX_EN,
MX50_PAD_DISP_D6__FEC_TXD1,
MX50_PAD_DISP_D7__FEC_TXD0,
- MX50_PAD_SSI_RXFS__FEC_MDC,
MX50_PAD_I2C3_SDA__GPIO_6_23,
MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
@@ -168,6 +170,20 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
.flags = IMXUART_HAVE_RTSCTS,
};
+static const struct fec_platform_data fec_data __initconst = {
+ .phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static inline void mx50_rdp_fec_reset(void)
+{
+ gpio_request(FEC_EN, "fec-en");
+ gpio_direction_output(FEC_EN, 0);
+ gpio_request(FEC_RESET_B, "fec-reset_b");
+ gpio_direction_output(FEC_RESET_B, 0);
+ msleep(1);
+ gpio_set_value(FEC_RESET_B, 1);
+}
+
/*
* Board specific initialization.
*/
@@ -178,6 +194,8 @@ static void __init mx50_rdp_board_init(void)
imx50_add_imx_uart(0, &uart_pdata);
imx50_add_imx_uart(1, &uart_pdata);
+ mx50_rdp_fec_reset();
+ imx50_add_fec(&fec_data);
}
static void __init mx50_rdp_timer_init(void)
diff --git a/arch/arm/mach-mx5/devices-mx50.h b/arch/arm/mach-mx5/devices-mx50.h
index 98ab074..e1093db 100644
--- a/arch/arm/mach-mx5/devices-mx50.h
+++ b/arch/arm/mach-mx5/devices-mx50.h
@@ -24,3 +24,8 @@
extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[] __initconst;
#define imx50_add_imx_uart(id, pdata) \
imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
+
+extern const struct imx_fec_data imx50_fec_data __initconst;
+#define imx50_add_fec(pdata) \
+ imx_add_fec(&imx50_fec_data, pdata)
+
diff --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c
index b50c351..4f52996 100644
--- a/arch/arm/plat-mxc/devices/platform-fec.c
+++ b/arch/arm/plat-mxc/devices/platform-fec.c
@@ -31,6 +31,11 @@ const struct imx_fec_data imx35_fec_data __initconst =
imx_fec_data_entry_single(MX35);
#endif
+#ifdef CONFIG_SOC_IMX50
+const struct imx_fec_data imx50_fec_data __initconst =
+ imx_fec_data_entry_single(MX50);
+#endif
+
#ifdef CONFIG_SOC_IMX51
const struct imx_fec_data imx51_fec_data __initconst =
imx_fec_data_entry_single(MX51);
--
1.6.3.3
^ permalink raw reply related
* [PATCH v2 2/2] arm: mx50_rdp: add i2c bus support
From: Richard Zhao @ 2011-01-14 9:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294998484-32361-1-git-send-email-richard.zhao@freescale.com>
Signed-off-by: Richard Zhao <richard.zhao@freescale.com>
---
arch/arm/mach-mx5/board-mx50_rdp.c | 7 +++++++
arch/arm/mach-mx5/devices-mx50.h | 3 +++
arch/arm/plat-mxc/devices/platform-imx-i2c.c | 10 ++++++++++
3 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c
index 884c003..5038b43 100644
--- a/arch/arm/mach-mx5/board-mx50_rdp.c
+++ b/arch/arm/mach-mx5/board-mx50_rdp.c
@@ -184,6 +184,10 @@ static inline void mx50_rdp_fec_reset(void)
gpio_set_value(FEC_RESET_B, 1);
}
+static const struct imxi2c_platform_data i2c_data __initconst = {
+ .bitrate = 100000,
+};
+
/*
* Board specific initialization.
*/
@@ -196,6 +200,9 @@ static void __init mx50_rdp_board_init(void)
imx50_add_imx_uart(1, &uart_pdata);
mx50_rdp_fec_reset();
imx50_add_fec(&fec_data);
+ imx50_add_imx_i2c(0, &i2c_data);
+ imx50_add_imx_i2c(1, &i2c_data);
+ imx50_add_imx_i2c(2, &i2c_data);
}
static void __init mx50_rdp_timer_init(void)
diff --git a/arch/arm/mach-mx5/devices-mx50.h b/arch/arm/mach-mx5/devices-mx50.h
index e1093db..c9e4282 100644
--- a/arch/arm/mach-mx5/devices-mx50.h
+++ b/arch/arm/mach-mx5/devices-mx50.h
@@ -29,3 +29,6 @@ extern const struct imx_fec_data imx50_fec_data __initconst;
#define imx50_add_fec(pdata) \
imx_add_fec(&imx50_fec_data, pdata)
+extern const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst;
+#define imx50_add_imx_i2c(id, pdata) \
+ imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata)
diff --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
index 7ba94e1..2ab74f0 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
@@ -69,6 +69,16 @@ const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = {
};
#endif /* ifdef CONFIG_SOC_IMX35 */
+#ifdef CONFIG_SOC_IMX50
+const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst = {
+#define imx50_imx_i2c_data_entry(_id, _hwid) \
+ imx_imx_i2c_data_entry(MX50, _id, _hwid, SZ_4K)
+ imx50_imx_i2c_data_entry(0, 1),
+ imx50_imx_i2c_data_entry(1, 2),
+ imx50_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
#ifdef CONFIG_SOC_IMX51
const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
#define imx51_imx_i2c_data_entry(_id, _hwid) \
--
1.6.3.3
^ permalink raw reply related
* [PATCH v5 08/10] ARM: mxs: add ocotp read function
From: Uwe Kleine-König @ 2011-01-14 9:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110114084009.GL26617@pengutronix.de>
Hello Sascha,
On Fri, Jan 14, 2011 at 09:40:09AM +0100, Sascha Hauer wrote:
> On Fri, Jan 14, 2011 at 03:24:54PM +0800, Shawn Guo wrote:
> > +const u32 *mxs_get_ocotp(void)
> > +{
> > + [...]
> > +}
>
> EXPORT_SYMBOL?
I don't think this should be necessary. mxs_get_ocotp should only be
called from platform code that cannot (ot at least should not) be
modular. I suggest to skip it for now and if we really need it later
only add it then.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH v2] ux500: platform data for SFH7741 proximity sensor driver (standard Keyboard GPIO driver)
From: Philippe Langlais @ 2011-01-14 9:53 UTC (permalink / raw)
To: linux-arm-kernel
Proximity sensor is managed as an input event (SW_PROXIMITY).
Signed-off-by: Philippe Langlais <philippe.langlais@stericsson.com>
---
arch/arm/mach-ux500/board-mop500-regulators.c | 4 ++
arch/arm/mach-ux500/board-mop500.c | 52 +++++++++++++++++++++++++
2 files changed, 56 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
index 7584a16..42c920a 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.c
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -18,6 +18,10 @@ static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
.dev = NULL,
.supply = "v-display",
},
+ {
+ .dev_name = "gpio-keys",
+ .supply = "v-proximity",
+ },
#ifdef CONFIG_SENSORS_BH1780
{
.dev_name = "bh1780",
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 2635bb7..c0ee1d7 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -21,6 +21,8 @@
#include <linux/spi/spi.h>
#include <linux/mfd/ab8500.h>
#include <linux/mfd/tc3589x.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -171,8 +173,58 @@ static void __init mop500_i2c_init(void)
db8500_add_i2c3(&u8500_i2c3_data);
}
+static struct gpio_keys_button mop500_gpio_keys[] = {
+ {
+ .desc = "SFH7741 Proximity Sensor",
+ .type = EV_SW,
+ .code = SW_FRONT_PROXIMITY,
+ .gpio = MOP500_EGPIO(7),
+ .active_low = 0,
+ .can_disable = 1,
+ }
+};
+
+static struct regulator *prox_regulator;
+static int mop500_prox_activate(struct device *dev);
+static void mop500_prox_deactivate(struct device *dev);
+
+static struct gpio_keys_platform_data mop500_gpio_keys_data = {
+ .buttons = mop500_gpio_keys,
+ .nbuttons = ARRAY_SIZE(mop500_gpio_keys),
+ .enable = mop500_prox_activate,
+ .disable = mop500_prox_deactivate,
+};
+
+static struct platform_device mop500_gpio_keys_device = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &mop500_gpio_keys_data,
+ },
+};
+
+static int mop500_prox_activate(struct device *dev)
+{
+ prox_regulator = regulator_get(&mop500_gpio_keys_device.dev,
+ "v-proximity");
+ if (IS_ERR(prox_regulator)) {
+ dev_err(&mop500_gpio_keys_device.dev,
+ "regulator_get(\"v-proximity\") failed\n");
+ return PTR_ERR(prox_regulator);
+ }
+ regulator_enable(prox_regulator);
+ return 0;
+}
+
+static void mop500_prox_deactivate(struct device *dev)
+{
+ regulator_disable(prox_regulator);
+ regulator_put(prox_regulator);
+}
+
/* add any platform devices here - TODO */
static struct platform_device *platform_devs[] __initdata = {
+ &mop500_gpio_keys_device,
};
#ifdef CONFIG_STE_DMA40
--
1.7.3.1
^ permalink raw reply related
* [PATCH] MTD: atmel_nand: Add DMA support to access Nandflash
From: Jamie Iles @ 2011-01-14 10:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294997687-12515-1-git-send-email-hong.xu@atmel.com>
Hi Hong,
A couple of minor comments inline but otherwise looks good to me.
Jamie
On Fri, Jan 14, 2011 at 05:34:47PM +0800, Hong Xu wrote:
> diff --git a/drivers/mtd/nand/atmel_nand.c
> b/drivers/mtd/nand/atmel_nand.c
> index ccce0f0..c2fbffe 100644
> --- a/drivers/mtd/nand/atmel_nand.c
> +++ b/drivers/mtd/nand/atmel_nand.c
> @@ -48,6 +48,12 @@
> #define no_ecc 0
> #endif
>
> +/* DMA for large buffers only */
> +#define DMA_MIN_BYTES 512
> +
Is it worth making this a module parameter and defaulting to 512?
> +static int use_dma = 1;
> +module_param(use_dma, int, 0);
> +
> static int on_flash_bbt = 0;
> module_param(on_flash_bbt, int, 0);
>
> @@ -89,11 +95,20 @@ struct atmel_nand_host {
> struct nand_chip nand_chip;
> struct mtd_info mtd;
> void __iomem *io_base;
> + void __iomem *io_phys;
This should be of type dma_addr_t and this will eliminate some casting
later.
> struct atmel_nand_data *board;
> struct device *dev;
> void __iomem *ecc;
> +
> + struct completion comp;
> + struct dma_chan *dma_chan;
> };
>
> +static int cpu_has_dma(void)
> +{
> + return cpu_is_at91sam9rl() || cpu_is_at91sam9g45();
> +}
> +
> /*
> * Enable NAND.
> */
> @@ -150,7 +165,7 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
> /*
> * Minimal-overhead PIO for data access.
> */
> -static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
> +static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
> {
> struct nand_chip *nand_chip = mtd->priv;
>
> @@ -164,7 +179,7 @@ static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
> __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
> }
>
> -static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
> +static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
> {
> struct nand_chip *nand_chip = mtd->priv;
>
> @@ -178,6 +193,102 @@ static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
> __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
> }
>
> +static void dma_complete_func(void *completion)
> +{
> + complete(completion);
> +}
> +
> +static void atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
> + int is_read)
> +{
> + struct dma_device *dma_dev;
> + enum dma_ctrl_flags flags;
> + dma_addr_t dma_src_addr, dma_dst_addr, phys_addr;
> + struct dma_async_tx_descriptor *tx = NULL;
> + dma_cookie_t cookie;
> + struct nand_chip *chip = mtd->priv;
> + struct atmel_nand_host *host = chip->priv;
> +
> + dma_dev = host->dma_chan->device;
> +
> + flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT |
> + DMA_COMPL_SKIP_SRC_UNMAP;
> +
> + if (is_read)
> + phys_addr = dma_map_single(dma_dev->dev, buf, len,
> + DMA_FROM_DEVICE);
> + else
> + phys_addr = dma_map_single(dma_dev->dev, buf, len,
> + DMA_TO_DEVICE);
> + if (!phys_addr) {
> + dev_err(host->dev, "Failed to dma_map_single\n");
> + goto err_dma_map;
> + }
I don't think this is right - you should check phys_addr() with
dma_mapping_error() rather than comparing to 0.
> +
> + if (is_read) {
> + dma_src_addr = (dma_addr_t)host->io_phys;
> + dma_dst_addr = phys_addr;
> + } else {
> + dma_src_addr = phys_addr;
> + dma_dst_addr = (dma_addr_t)host->io_phys;
> + }
> +
> + tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr,
> + dma_src_addr, len, flags);
> + if (!tx) {
> + dev_err(host->dev, "Failed to prepare DMA memcpy\n");
> + goto err;
> + }
> +
> + init_completion(&host->comp);
> + tx->callback = dma_complete_func;
> + tx->callback_param = &host->comp;
> +
> + cookie = tx->tx_submit(tx);
> + if (dma_submit_error(cookie)) {
> + dev_err(host->dev, "Failed to do DMA tx_submit\n");
> + goto err;
> + }
> +
> + dma_async_issue_pending(host->dma_chan);
> +
> + wait_for_completion(&host->comp);
> +
> +err:
> + if (is_read)
> + dma_unmap_single(dma_dev->dev, phys_addr, len, DMA_FROM_DEVICE);
> + else
> + dma_unmap_single(dma_dev->dev, phys_addr, len, DMA_TO_DEVICE);
> +err_dma_map:
> + return;
> +}
> +
> +static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
> +{
> + struct nand_chip *chip = mtd->priv;
> + struct atmel_nand_host *host = chip->priv;
> +
> + if (use_dma && len >= DMA_MIN_BYTES)
> + atmel_nand_dma_op(mtd, buf, len, 1);
> + else if (host->board->bus_width_16)
> + atmel_read_buf16(mtd, buf, len);
> + else
> + atmel_read_buf8(mtd, buf, len);
> +}
> +
> +static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
> +{
> + struct nand_chip *chip = mtd->priv;
> + struct atmel_nand_host *host = chip->priv;
> +
> + if (use_dma && len >= DMA_MIN_BYTES)
> + atmel_nand_dma_op(mtd, (u8 *)buf, len, 0);
> + else if (host->board->bus_width_16)
> + atmel_write_buf16(mtd, buf, len);
> + else
> + atmel_write_buf8(mtd, buf, len);
> +}
> +
> /*
> * Calculate HW ECC
> *
> @@ -398,6 +509,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
> return -ENOMEM;
> }
>
> + host->io_phys = (void __iomem *)mem->start;
> +
> host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
> if (host->io_base == NULL) {
> printk(KERN_ERR "atmel_nand: ioremap failed\n");
> @@ -516,6 +629,23 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
> }
> }
>
> + if (cpu_has_dma() && use_dma) {
> + dma_cap_mask_t mask;
> +
> + dma_cap_zero(mask);
> + dma_cap_set(DMA_MEMCPY, mask);
> + host->dma_chan = dma_request_channel(mask, 0, NULL);
> +
> + if (!host->dma_chan) {
> + dev_err(host->dev, "Failed to request DMA channel\n");
> + use_dma = 0;
> + }
> + }
> + if (use_dma)
> + dev_info(host->dev, "Using DMA for NAND access.\n");
> + else
> + dev_info(host->dev, "No DMA support for NAND access.\n");
> +
> /* second phase scan */
> if (nand_scan_tail(mtd)) {
> res = -ENXIO;
> @@ -555,6 +685,8 @@ err_scan_ident:
> err_no_card:
> atmel_nand_disable(host);
> platform_set_drvdata(pdev, NULL);
> + if (host->dma_chan)
> + dma_release_channel(host->dma_chan);
> if (host->ecc)
> iounmap(host->ecc);
> err_ecc_ioremap:
> @@ -578,6 +710,10 @@ static int __exit atmel_nand_remove(struct platform_device *pdev)
>
> if (host->ecc)
> iounmap(host->ecc);
> +
> + if (host->dma_chan)
> + dma_release_channel(host->dma_chan);
> +
> iounmap(host->io_base);
> kfree(host);
>
> --
> 1.7.3.3
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH] Introduce VPR200 board.
From: Wolfram Sang @ 2011-01-14 10:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110114083408.GD24920@pengutronix.de>
Hi,
> > +static void vpr200_init_keys(void)
> > +{
> > + gpio_request(GPIO_BUTTON1, "BUTTON1");
> > + gpio_direction_input(GPIO_BUTTON1);
> > + gpio_free(GPIO_BUTTON1);
> > +
> > + gpio_request(GPIO_BUTTON2, "BUTTON2");
> > + gpio_direction_input(GPIO_BUTTON2);
> > + gpio_free(GPIO_BUTTON2);
> > +
> > + gpio_request(GPIO_BUTTON3, "BUTTON3");
> > + gpio_direction_input(GPIO_BUTTON3);
> > + gpio_free(GPIO_BUTTON3);
> > +
> > + gpio_request(GPIO_BUTTON4, "BUTTON4");
> > + gpio_direction_input(GPIO_BUTTON4);
> > + gpio_free(GPIO_BUTTON4);
> > +
> > + gpio_request(GPIO_BUTTON5, "BUTTON5");
> > + gpio_direction_input(GPIO_BUTTON5);
> > + gpio_free(GPIO_BUTTON5);
> > +
> > + gpio_request(GPIO_BUTTON6, "BUTTON6");
> > + gpio_direction_input(GPIO_BUTTON6);
> > + gpio_free(GPIO_BUTTON6);
> > +
> > + gpio_request(GPIO_BUTTON7, "BUTTON7");
> > + gpio_direction_input(GPIO_BUTTON7);
> > + gpio_free(GPIO_BUTTON7);
> > +
> > + gpio_request(GPIO_BUTTON8, "BUTTON8");
> > + gpio_direction_input(GPIO_BUTTON8);
> > + gpio_free(GPIO_BUTTON8);
> Hmm, doesn't the gpio-keys driver does that already?
I'd think so, too.
> And to do it really correct, you need to check for errors returned by
> gpio_request and gpio_direction_input.
>
> Provided you really need it, I'd do it as follows:
>
> int ret;
>
> #define setup_for_gpiokey(nr) \
> ret = gpio_request(GPIO_BUTTON ## nr, "BUTTON" #nr); \
> if (ret) \
> return ret; \
> ret = gpio_direction_input(GPIO_BUTTON ## nr); \
> if (ret) \
> return ret; \
> gpio_free(GPIO_BUTTON ## nr);
>
> setup_for_gpiokey(1);
> setup_for_gpiokey(2);
> setup_for_gpiokey(3);
> setup_for_gpiokey(4);
> ...
I'd think using gpio_request_array() is the better option ;)
Regards,
Wolfram
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110114/a5c66e98/attachment.sig>
^ permalink raw reply
* [PATCH] Introduce VPR200 board.
From: Sascha Hauer @ 2011-01-14 10:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294962532-15790-2-git-send-email-marc@cpdesign.com.au>
On Fri, Jan 14, 2011 at 10:48:52AM +1100, Marc Reilly wrote:
> Signed-off-by: Marc Reilly <marc@cpdesign.com.au>
> ---
> arch/arm/mach-mx3/Kconfig | 15 ++
> arch/arm/mach-mx3/Makefile | 1 +
> arch/arm/mach-mx3/mach-vpr200.c | 404 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 420 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/mach-mx3/mach-vpr200.c
>
> diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
> index 0717f88..ca63c35 100644
> --- a/arch/arm/mach-mx3/Kconfig
> +++ b/arch/arm/mach-mx3/Kconfig
> @@ -229,4 +229,19 @@ config MACH_EUKREA_MBIMXSD35_BASEBOARD
>
> endchoice
>
> +config MACH_VPR200
> + bool "Support VPR200 platform"
> + select SOC_IMX35
> + select IMX_HAVE_PLATFORM_FSL_USB2_UDC
> + select IMX_HAVE_PLATFORM_IMX2_WDT
> + select IMX_HAVE_PLATFORM_IMX_UART
> + select IMX_HAVE_PLATFORM_IMX_I2C
> + select IMX_HAVE_PLATFORM_MXC_EHCI
> + select IMX_HAVE_PLATFORM_MXC_NAND
> + select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
> + select IMX_HAVE_PLATFORM_MXC_PWM
> + help
> + Include support for VPR200 platform. This includes specific
> + configurations for the board and its peripherals.
> +
> endif
> diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile
> index 8db1329..bc7294f 100644
> --- a/arch/arm/mach-mx3/Makefile
> +++ b/arch/arm/mach-mx3/Makefile
> @@ -22,3 +22,4 @@ obj-$(CONFIG_MACH_MX35_3DS) += mach-mx35_3ds.o
> obj-$(CONFIG_MACH_KZM_ARM11_01) += mach-kzm_arm11_01.o
> obj-$(CONFIG_MACH_EUKREA_CPUIMX35) += mach-cpuimx35.o
> obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd-baseboard.o
> +obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
> diff --git a/arch/arm/mach-mx3/mach-vpr200.c b/arch/arm/mach-mx3/mach-vpr200.c
> new file mode 100644
> index 0000000..a4f0514
> --- /dev/null
> +++ b/arch/arm/mach-mx3/mach-vpr200.c
> @@ -0,0 +1,404 @@
> +/*
> + * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
> + * Copyright (C) 2009 Marc Kleine-Budde, Pengutronix
> + * Copyright 2010 Creative Product Design
> + *
> + * Derived from mx35 3stack.
> + * Original author: Fabio Estevam <fabio.estevam@freescale.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/types.h>
> +#include <linux/init.h>
> +#include <linux/platform_device.h>
> +#include <linux/mtd/physmap.h>
> +#include <linux/memory.h>
> +#include <linux/gpio.h>
> +
> +#include <asm/mach-types.h>
> +#include <asm/mach/arch.h>
> +#include <asm/mach/time.h>
> +#include <asm/mach/map.h>
> +
> +#include <mach/hardware.h>
> +#include <mach/common.h>
> +#include <mach/iomux-mx35.h>
> +#include <mach/irqs.h>
> +#include <mach/ipu.h>
> +#include <mach/mx3fb.h>
> +
> +#include <linux/i2c.h>
> +#include <linux/i2c/at24.h>
> +#include <linux/regulator/machine.h>
> +#include <linux/mfd/mc13xxx.h>
> +#include <video/platform_lcd.h>
> +
> +#include "devices-imx35.h"
> +#include "devices.h"
> +
> +#define GPIO_LCDPWR IMX_GPIO_NR(1, 2)
> +#define GPIO_PMIC_INT IMX_GPIO_NR(2, 0)
> +
> +#define GPIO_BUTTON1 IMX_GPIO_NR(1, 4)
> +#define GPIO_BUTTON2 IMX_GPIO_NR(1, 5)
> +#define GPIO_BUTTON3 IMX_GPIO_NR(1, 7)
> +#define GPIO_BUTTON4 IMX_GPIO_NR(1, 8)
> +#define GPIO_BUTTON5 IMX_GPIO_NR(1, 9)
> +#define GPIO_BUTTON6 IMX_GPIO_NR(1, 10)
> +#define GPIO_BUTTON7 IMX_GPIO_NR(1, 11)
> +#define GPIO_BUTTON8 IMX_GPIO_NR(1, 12)
> +
> +static const struct fb_videomode fb_modedb[] = {
> + {
> + /* 800x480 @ 60 Hz */
> + .name = "PT0708048",
> + .refresh = 60,
> + .xres = 800,
> + .yres = 480,
> + .pixclock = KHZ2PICOS(33260),
> + .left_margin = 50,
> + .right_margin = 156,
> + .upper_margin = 10,
> + .lower_margin = 10,
> + .hsync_len = 1, /* note: DE only display */
> + .vsync_len = 1, /* note: DE only display */
> + .sync = FB_SYNC_CLK_IDLE_EN | FB_SYNC_OE_ACT_HIGH,
> + .vmode = FB_VMODE_NONINTERLACED,
> + .flag = 0,
> + }, {
> + /* 800x480 @ 60 Hz */
> + .name = "CTP-CLAA070LC0ACW",
> + .refresh = 60,
> + .xres = 800,
> + .yres = 480,
> + .pixclock = KHZ2PICOS(27000),
> + .left_margin = 50,
> + .right_margin = 50, /* whole line should have 900 clocks */
> + .upper_margin = 10,
> + .lower_margin = 10, /* whole frame should have 500 lines */
> + .hsync_len = 1, /* note: DE only display */
> + .vsync_len = 1, /* note: DE only display */
> + .sync = FB_SYNC_CLK_IDLE_EN | FB_SYNC_OE_ACT_HIGH,
> + .vmode = FB_VMODE_NONINTERLACED,
> + .flag = 0,
> + }
> +};
> +
> +static struct ipu_platform_data mx3_ipu_data = {
> + .irq_base = MXC_IPU_IRQ_START,
> +};
> +
> +static struct mx3fb_platform_data mx3fb_pdata = {
> + .dma_dev = &mx3_ipu.dev,
> + .name = "PT0708048",
> + .mode = fb_modedb,
> + .num_modes = ARRAY_SIZE(fb_modedb),
> +};
> +
> +static struct physmap_flash_data vpr200_flash_data = {
> + .width = 2,
> +};
> +
> +static struct resource vpr200_flash_resource = {
> + .start = MX35_CS0_BASE_ADDR,
> + .end = MX35_CS0_BASE_ADDR + SZ_64M - 1,
> + .flags = IORESOURCE_MEM,
> +};
> +
> +static struct platform_device vpr200_flash = {
> + .name = "physmap-flash",
> + .id = 0,
> + .dev = {
> + .platform_data = &vpr200_flash_data,
> + },
> + .resource = &vpr200_flash_resource,
> + .num_resources = 1,
> +};
> +
> +static const struct mxc_nand_platform_data
> + vpr200_nand_board_info __initconst = {
> + .width = 1,
> + .hw_ecc = 1,
> + .flash_bbt = 1,
> +};
> +
> +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
> +#include <linux/gpio_keys.h>
> +#define VPR_KEY_DEBOUNCE 500
> +
> +static struct gpio_keys_button vpr200_gpio_keys_table[] = {
> + {KEY_F2, GPIO_BUTTON1, 1, "vpr-keys: F2", 0, VPR_KEY_DEBOUNCE},
> + {KEY_F3, GPIO_BUTTON2, 1, "vpr-keys: F3", 0, VPR_KEY_DEBOUNCE},
> + {KEY_F4, GPIO_BUTTON3, 1, "vpr-keys: F4", 0, VPR_KEY_DEBOUNCE},
> + {KEY_F5, GPIO_BUTTON4, 1, "vpr-keys: F5", 0, VPR_KEY_DEBOUNCE},
> + {KEY_F6, GPIO_BUTTON5, 1, "vpr-keys: F6", 0, VPR_KEY_DEBOUNCE},
> + {KEY_F7, GPIO_BUTTON6, 1, "vpr-keys: F7", 0, VPR_KEY_DEBOUNCE},
> + {KEY_F8, GPIO_BUTTON7, 1, "vpr-keys: F8", 1, VPR_KEY_DEBOUNCE},
> + {KEY_F9, GPIO_BUTTON8, 1, "vpr-keys: F9", 1, VPR_KEY_DEBOUNCE},
> +};
> +
> +static struct gpio_keys_platform_data vpr200_gpio_keys_data = {
> + .buttons = vpr200_gpio_keys_table,
> + .nbuttons = ARRAY_SIZE(vpr200_gpio_keys_table),
> +};
> +
> +static struct platform_device vpr200_device_gpiokeys = {
> + .name = "gpio-keys",
> + .dev = {
> + .platform_data = &vpr200_gpio_keys_data,
> + }
> +};
> +
> +static void vpr200_init_keys(void)
> +{
> + gpio_request(GPIO_BUTTON1, "BUTTON1");
> + gpio_direction_input(GPIO_BUTTON1);
> + gpio_free(GPIO_BUTTON1);
> +
> + gpio_request(GPIO_BUTTON2, "BUTTON2");
> + gpio_direction_input(GPIO_BUTTON2);
> + gpio_free(GPIO_BUTTON2);
> +
> + gpio_request(GPIO_BUTTON3, "BUTTON3");
> + gpio_direction_input(GPIO_BUTTON3);
> + gpio_free(GPIO_BUTTON3);
> +
> + gpio_request(GPIO_BUTTON4, "BUTTON4");
> + gpio_direction_input(GPIO_BUTTON4);
> + gpio_free(GPIO_BUTTON4);
> +
> + gpio_request(GPIO_BUTTON5, "BUTTON5");
> + gpio_direction_input(GPIO_BUTTON5);
> + gpio_free(GPIO_BUTTON5);
> +
> + gpio_request(GPIO_BUTTON6, "BUTTON6");
> + gpio_direction_input(GPIO_BUTTON6);
> + gpio_free(GPIO_BUTTON6);
> +
> + gpio_request(GPIO_BUTTON7, "BUTTON7");
> + gpio_direction_input(GPIO_BUTTON7);
> + gpio_free(GPIO_BUTTON7);
> +
> + gpio_request(GPIO_BUTTON8, "BUTTON8");
> + gpio_direction_input(GPIO_BUTTON8);
> + gpio_free(GPIO_BUTTON8);
What is this good for? The gpio-keys driver handles setting the
direction itself.
> +
> + platform_device_register(&vpr200_device_gpiokeys);
> +}
> +#else
> +
> +static void vpr200_init_keys(void)
> +{
> +}
> +#endif
> +
> +static struct mc13xxx_platform_data board_pmic = {
> + .flags = MC13XXX_USE_ADC | MC13XXX_USE_TOUCHSCREEN,
> +};
> +
> +#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
> +static const struct imxi2c_platform_data vpr200_i2c0_data __initconst = {
> + .bitrate = 50000,
> +};
> +
> +static struct at24_platform_data board_eeprom = {
> + .byte_len = 2048 / 8,
> + .page_size = 1,
> +};
> +
> +static struct i2c_board_info vpr200_i2c_devices[] = {
> + {
> + I2C_BOARD_INFO("at24", 0x50), /* E0=0, E1=0, E2=0 */
> + .platform_data = &board_eeprom,
> + }, {
> + I2C_BOARD_INFO("mc13892", 0x08),
> + .platform_data = &board_pmic,
> + .irq = gpio_to_irq(GPIO_PMIC_INT),
> + }
> +};
> +#endif
> +
> +static iomux_v3_cfg_t vpr200_pads[] = {
> + /* UART1 */
> + MX35_PAD_CTS1__UART1_CTS,
> + MX35_PAD_RTS1__UART1_RTS,
> + MX35_PAD_TXD1__UART1_TXD_MUX,
> + MX35_PAD_RXD1__UART1_RXD_MUX,
> + /* UART3 */
> + MX35_PAD_ATA_DATA10__UART3_RXD_MUX,
> + MX35_PAD_ATA_DATA11__UART3_TXD_MUX,
> + /* FEC */
> + MX35_PAD_FEC_TX_CLK__FEC_TX_CLK,
> + MX35_PAD_FEC_RX_CLK__FEC_RX_CLK,
> + MX35_PAD_FEC_RX_DV__FEC_RX_DV,
> + MX35_PAD_FEC_COL__FEC_COL,
> + MX35_PAD_FEC_RDATA0__FEC_RDATA_0,
> + MX35_PAD_FEC_TDATA0__FEC_TDATA_0,
> + MX35_PAD_FEC_TX_EN__FEC_TX_EN,
> + MX35_PAD_FEC_MDC__FEC_MDC,
> + MX35_PAD_FEC_MDIO__FEC_MDIO,
> + MX35_PAD_FEC_TX_ERR__FEC_TX_ERR,
> + MX35_PAD_FEC_RX_ERR__FEC_RX_ERR,
> + MX35_PAD_FEC_CRS__FEC_CRS,
> + MX35_PAD_FEC_RDATA1__FEC_RDATA_1,
> + MX35_PAD_FEC_TDATA1__FEC_TDATA_1,
> + MX35_PAD_FEC_RDATA2__FEC_RDATA_2,
> + MX35_PAD_FEC_TDATA2__FEC_TDATA_2,
> + MX35_PAD_FEC_RDATA3__FEC_RDATA_3,
> + MX35_PAD_FEC_TDATA3__FEC_TDATA_3,
> + /* Display */
> + MX35_PAD_LD0__IPU_DISPB_DAT_0,
> + MX35_PAD_LD1__IPU_DISPB_DAT_1,
> + MX35_PAD_LD2__IPU_DISPB_DAT_2,
> + MX35_PAD_LD3__IPU_DISPB_DAT_3,
> + MX35_PAD_LD4__IPU_DISPB_DAT_4,
> + MX35_PAD_LD5__IPU_DISPB_DAT_5,
> + MX35_PAD_LD6__IPU_DISPB_DAT_6,
> + MX35_PAD_LD7__IPU_DISPB_DAT_7,
> + MX35_PAD_LD8__IPU_DISPB_DAT_8,
> + MX35_PAD_LD9__IPU_DISPB_DAT_9,
> + MX35_PAD_LD10__IPU_DISPB_DAT_10,
> + MX35_PAD_LD11__IPU_DISPB_DAT_11,
> + MX35_PAD_LD12__IPU_DISPB_DAT_12,
> + MX35_PAD_LD13__IPU_DISPB_DAT_13,
> + MX35_PAD_LD14__IPU_DISPB_DAT_14,
> + MX35_PAD_LD15__IPU_DISPB_DAT_15,
> + MX35_PAD_LD16__IPU_DISPB_DAT_16,
> + MX35_PAD_LD17__IPU_DISPB_DAT_17,
> + MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK,
> + MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY,
> + MX35_PAD_CONTRAST__IPU_DISPB_CONTR,
> + /* LCD Enable */
> + MX35_PAD_D3_VSYNC__GPIO1_2,
> + /* USBOTG */
> + MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR,
> + MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC,
> + /* SDCARD */
> + MX35_PAD_SD1_CMD__ESDHC1_CMD,
> + MX35_PAD_SD1_CLK__ESDHC1_CLK,
> + MX35_PAD_SD1_DATA0__ESDHC1_DAT0,
> + MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
> + MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
> + MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
> + /* PMIC */
> + MX35_PAD_GPIO2_0__GPIO2_0,
> + /* GPIO keys */
> + MX35_PAD_SCKR__GPIO1_4,
> + MX35_PAD_COMPARE__GPIO1_5,
> + MX35_PAD_SCKT__GPIO1_7,
> + MX35_PAD_FST__GPIO1_8,
> + MX35_PAD_HCKT__GPIO1_9,
> + MX35_PAD_TX5_RX0__GPIO1_10,
> + MX35_PAD_TX4_RX1__GPIO1_11,
> + MX35_PAD_TX3_RX2__GPIO1_12,
> +};
> +static void vpr200_lcd_power_set(struct plat_lcd_data *pd,
> + unsigned int power)
> +{
> + if (power)
> + gpio_direction_output(GPIO_LCDPWR, 0);
> + else
> + gpio_direction_output(GPIO_LCDPWR, 1);
> +}
> +
> +static struct plat_lcd_data vpr200_lcd_power_data = {
> + .set_power = vpr200_lcd_power_set,
> +};
> +
> +static struct platform_device vpr200_lcd_powerdev = {
> + .name = "platform-lcd",
> + .dev.platform_data = &vpr200_lcd_power_data,
> +};
> +
> +/* USB Device config */
> +static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
> + .operating_mode = FSL_USB2_DR_DEVICE,
> + .phy_mode = FSL_USB2_PHY_UTMI,
> + .workaround = FLS_USB2_WORKAROUND_ENGCM09152,
> +};
> +
> +#if defined(CONFIG_USB_ULPI)
> +/* USB HOST config */
> +static const struct mxc_usbh_platform_data usb_host_pdata __initconst = {
> + .portsc = MXC_EHCI_MODE_SERIAL,
> + .flags = MXC_EHCI_INTERFACE_SINGLE_UNI |
> + MXC_EHCI_INTERNAL_PHY,
> +};
> +#endif
> +
> +static struct platform_device *devices[] __initdata = {
> + &vpr200_flash,
> + &vpr200_lcd_powerdev,
> +};
> +
> +/*
> + * Board specific initialization.
> + */
> +static void __init mxc_board_init(void)
> +{
> + mxc_iomux_v3_setup_multiple_pads(vpr200_pads, ARRAY_SIZE(vpr200_pads));
> +
> + imx35_add_fec(NULL);
> + imx35_add_imx2_wdt(NULL);
> +
> + platform_add_devices(devices, ARRAY_SIZE(devices));
> +
> + gpio_request(GPIO_LCDPWR, "LCDPWR");
> + gpio_direction_output(GPIO_LCDPWR, 0);
> + gpio_free(GPIO_LCDPWR);
> +
> + gpio_request(GPIO_PMIC_INT, "PMIC_INT");
> + gpio_direction_input(GPIO_PMIC_INT);
> + gpio_free(GPIO_PMIC_INT);
> +
> + imx35_add_imx_uart0(NULL);
You configure the RTS/CTS pins for uart0 in the iomuxer, so it's
probably a good idea to add platform data for this device and add
the IMXUART_HAVE_RTSCTS flag.
> + imx35_add_imx_uart2(NULL);
> +
> + mxc_register_device(&mx3_ipu, &mx3_ipu_data);
> + mxc_register_device(&mx3_fb, &mx3fb_pdata);
> +
> + imx35_add_fsl_usb2_udc(&otg_device_pdata);
> +
> +#if defined(CONFIG_USB_ULPI)
> + imx35_add_mxc_ehci_hs(&usb_host_pdata);
> +#endif
obviously you are not using ulpi, so no need to make this dependent on
ulpi.
> +
> + imx35_add_mxc_nand(&vpr200_nand_board_info);
> + imx35_add_sdhci_esdhc_imx(0, NULL);
> +
> +#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
> + i2c_register_board_info(0, vpr200_i2c_devices,
> + ARRAY_SIZE(vpr200_i2c_devices));
> +
> + imx35_add_imx_i2c0(&vpr200_i2c0_data);
> +#endif
Please remove the ifdefs around i2c.
> +
> + vpr200_init_keys();
> +}
> +
> +static void __init vpr200_timer_init(void)
> +{
> + mx35_clocks_init();
> +}
> +
> +struct sys_timer vpr200_timer = {
> + .init = vpr200_timer_init,
> +};
> +
> +MACHINE_START(VPR200, "VPR200")
> + /* Maintainer: Creative Product Design */
> + .boot_params = MX3x_PHYS_OFFSET + 0x100,
> + .map_io = mx35_map_io,
> + .init_irq = mx35_init_irq,
> + .init_machine = mxc_board_init,
> + .timer = &vpr200_timer,
> +MACHINE_END
> --
> 1.7.1
>
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH V3 07/63] ST SPEAr13XX: Adding machine specific src files
From: stanley.miao @ 2011-01-14 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a2b0ef370a46a862cd4c745c04bb73c4c4657103.1292833228.git.viresh.kumar@st.com>
Viresh Kumar wrote:
> <snip>
> +
> +void __cpuinit platform_secondary_init(unsigned int cpu)
> +{
> <snip>
> +
> + /*
> + * let the primary processor know we're out of the
> + * pen, then head off into the C entry point
> + */
> + pen_release = -1;
> + smp_wmb();
>
Russell has fixed this line. See commit
3705ff6da538aff6dba535e2e9cbcbb9456d0d53 in the latest kernel.
> +
> + /*
> + * Synchronise with the boot thread.
> + */
> + spin_lock(&boot_lock);
> + spin_unlock(&boot_lock);
> +}
> +
> <snip>
> +void __init smp_prepare_cpus(unsigned int max_cpus)
> +{
> + unsigned int ncores = get_core_count();
> + unsigned int cpu = smp_processor_id();
> + int i;
> +
> + /* sanity check */
> + if (ncores == 0) {
> + pr_err("Realview: strange CM count of 0? Default to 1\n");
>
RealView ?
Stanley.
^ permalink raw reply
* [PATCH V3 07/63] ST SPEAr13XX: Adding machine specific src files
From: viresh kumar @ 2011-01-14 10:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D302081.3040708@windriver.com>
Stanley,
Thanks for reviewing!!
On 01/14/2011 03:38 PM, stanley.miao wrote:
> Viresh Kumar wrote:
>> <snip>
>> +
>> +void __cpuinit platform_secondary_init(unsigned int cpu)
>> +{
>> <snip>
>> +
>> + /*
>> + * let the primary processor know we're out of the
>> + * pen, then head off into the C entry point
>> + */
>> + pen_release = -1;
>> + smp_wmb();
>>
>
> Russell has fixed this line. See commit
> 3705ff6da538aff6dba535e2e9cbcbb9456d0d53 in the latest kernel.
>
Ya. I have already seen that in latest kernel and have updated it in
V4.
>> +
>> + /*
>> + * Synchronise with the boot thread.
>> + */
>> + spin_lock(&boot_lock);
>> + spin_unlock(&boot_lock);
>> +}
>> +
>> <snip>
>> +void __init smp_prepare_cpus(unsigned int max_cpus)
>> +{
>> + unsigned int ncores = get_core_count();
>> + unsigned int cpu = smp_processor_id();
>> + int i;
>> +
>> + /* sanity check */
>> + if (ncores == 0) {
>> + pr_err("Realview: strange CM count of 0? Default to 1\n");
>>
>
> RealView ?
Oops!! Anyway this routine is changed now and this error is
also removed.
--
viresh
^ permalink raw reply
* [PATCH] Introduce VPR200 board.
From: Uwe Kleine-König @ 2011-01-14 10:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110114100640.GA4589@pengutronix.de>
Hi Wolfram,
On Fri, Jan 14, 2011 at 11:06:40AM +0100, Wolfram Sang wrote:
> > And to do it really correct, you need to check for errors returned by
> > gpio_request and gpio_direction_input.
> >
> > Provided you really need it, I'd do it as follows:
> >
> > int ret;
> >
> > #define setup_for_gpiokey(nr) \
> > ret = gpio_request(GPIO_BUTTON ## nr, "BUTTON" #nr); \
> > if (ret) \
> > return ret; \
> > ret = gpio_direction_input(GPIO_BUTTON ## nr); \
> > if (ret) \
> > return ret; \
> > gpio_free(GPIO_BUTTON ## nr);
> >
> > setup_for_gpiokey(1);
> > setup_for_gpiokey(2);
> > setup_for_gpiokey(3);
> > setup_for_gpiokey(4);
> > ...
>
> I'd think using gpio_request_array() is the better option ;)
didn't know that one, nice.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* i.MX & IRQF_ONESHOT
From: Thomas Gleixner @ 2011-01-14 10:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D2FFCBE.3010704@eukrea.com>
On Fri, 14 Jan 2011, Eric B?nard wrote:
> On 13/01/2011 22:24, Uwe Kleine-K?nig wrote:
> > On Thu, Jan 13, 2011 at 10:12:23PM +0100, Eric B?nard wrote:
> > > On 13/01/2011 19:15, Thomas Gleixner wrote:
> > > > On Thu, 13 Jan 2011, Nicolas Ferre wrote:
> > > > > Le 13/01/2011 10:13, Uwe Kleine-K?nig :
> > > > > > On Thu, Jan 13, 2011 at 09:25:19AM +0100, Eric B?nard wrote:
> > > > > > > Commenting out this line in the ads7846 driver makes it work
> > > > > > > again.
> > > > > > > Am I missing something obvious or is there a reason for
> > > > > > > IRQF_ONESHOT
> > > > > > > creating trouble with gpio irq or SPI on i.MX ?
> > > > > > I don't know. Is the irq masked? pending?
> > > > >
> > > > > Just to let you know that I have the same issue on my at91sam9g10ek:
> > > > > atmel_spi + ads7846 (using ADS7843e actually).
> > > > > ... solved by same workaround.
> > > >
> > > > Eric, Nicolas: How are the interrupt handlers set for the relevant
> > > > interrupt lines and how are the interrupt pins configured?
> > > >
> > > on the i.MX27 :
> > > - gpio configured as a plain input (in function ads7846_dev_init()
> > > in arch/arm/mach-imx/eukrea_mbimx27-baseboard.c)
> > > - threaded interrupt handler registered with flags
> > > IRQF_TRIGGER_FALLING | IRQF_ONESHOT (in function ads7846_probe() in
> > > drivers/input/touchscreen/ads7846.c)
> > I didn't recheck the hw manual, but adding IRQF_TRIGGER_FALLING calls
> > gpio_set_irq_type (defined in arch/arm/plat-mxc/gpio.c) which results
> > into something called GPIO_INT_FALL_EDGE being written into a register.
> >
> > So I'd say it's configured to be edge sensitive.
> >
> I confirm this point : the gpio is configured to trigger an irq on falling
> edge.
Right, but that does not tell me which flow handler is used for this
particular irq. Looking at arch/arm/plat-mxc/gpio.c it seems that the
gpio irqs are set up using handle_level_irq ! That explains the
ONESHOT wreckage nicely as you are missing an edge irq which comes in
_BEFORE_ the finalize code unmasks the line.
So there are several things wrong here:
1) Using handle_level_irq for an edge interrupt is wrong. That's not
restricted to the TS driver problem at hand. That's wrong in
general. Other set_type() functions adjust the handler as well when
they switch the edge/level types.
2) Using ONESHOT for an edge interrupt is wrong as well. Removing the
ONESHOT flag is just papering over the problem because it does not
make the #1 problem go away, it just hides it.
The TS driver uses probably edge for historical reasons to avoid an
interrupt storm. But now with the oneshot mechanism we really should
use level type interrupts and keep the ONESHOT flag.
Thanks,
tglx
^ permalink raw reply
* i.MX & IRQF_ONESHOT
From: Nicolas Ferre @ 2011-01-14 11:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.00.1101131839010.2678@localhost6.localdomain6>
Le 13/01/2011 19:15, Thomas Gleixner :
> On Thu, 13 Jan 2011, Nicolas Ferre wrote:
>> Le 13/01/2011 10:13, Uwe Kleine-K?nig :
>>> On Thu, Jan 13, 2011 at 09:25:19AM +0100, Eric B?nard wrote:
>>>> while testing 2.6.37 on our i.MX27 based board - code in
>>>> arch/arm/mach-imx/eukrea_mbimx27-baseboard.c - I noticed the
>>>> touchscreen controller (ADS7846) doesn't work anymore.
>>>>
>>>> A few IRQ are generated when probing for the chipset and starting
>>>> calibration (usually first point works), then nothing more (even if
>>>> the IRQ signals is generated as seen on the scope, the irq count
>>>> doesn't increase anymore and stays <= 4 and no data is reported to
>>>> the input layer).
>>>>
>>>> drivers/input/touchscreen/ads7846.c was switched to threaded IRQ in
>>>> commit 2991a1ca6e9b13b639a82c0eec0cbc191bf1f42f where was added :
>>>> irq_flags |= IRQF_ONESHOT;
>>> AFAIK this is how threaded irq usually work. The irq should get
>>> reenabled by irq_thread -> irq_finalize_oneshot then.
>
> Well, yes and no. That applies only when you have a level type
> interrupt as you want to keep the irq line masked until the thread did
> it's magic with the device. Keeping the line masked for edge type
> interrupts would be fatal as you might loose interrupts. That's why we
> have the different flow handlers and the ONESHOT check is only
> implemented in handle_level_irq().
>
> Though the driver sets the ONESHOT flag unconditionally, which should
> be not a problem in theory as we don't handle oneshot stuff in other
> flow handlers. The only problem could be irq_finalize_oneshot()
> fiddling with the irq line, but that's guarded by a IRQ_DISABLED and
> IRQ_MASKED check so this should not hurt.
>
> Though it might hurt when the interrupt line has handle_level_irq()
> and the interrupt pin is configured for edge. The driver uses
> TRIGGER_RAISING/FALLING which is usually a sign of edge type. So I
> assume that there is some wreckage lurking in there, which just got
> covered up by the old code in some way.
>
>>>> Commenting out this line in the ads7846 driver makes it work again.
>>>> Am I missing something obvious or is there a reason for IRQF_ONESHOT
>>>> creating trouble with gpio irq or SPI on i.MX ?
>>> I don't know. Is the irq masked? pending?
>>
>> Just to let you know that I have the same issue on my at91sam9g10ek:
>> atmel_spi + ads7846 (using ADS7843e actually).
>> ... solved by same workaround.
>
> Eric, Nicolas: How are the interrupt handlers set for the relevant
> interrupt lines and how are the interrupt pins configured?
Thomas,
For AT91:
- the platform does not provides irq_flags so default to
IRQF_TRIGGER_FALLING | IRQF_ONESHOT as stated in the driver.
- on at91sam9g10ek the touchscreen is wired to an full featured IRQ
entry (configured with pullup in arch/arm/mach-at91/board-sam9261ek.c).
- the irq description of plain interrupts is in arch/arm/mach-at91/irq.c
and at91_aic_set_type() has an IRQ_TYPE_EDGE_FALLING entry.
So it should be configured on falling edge...
But: is seems that looking at at91_aic_set_type() initialization
function, AIC is configured with:
set_irq_handler(i, handle_level_irq);
I do not know if it is the same as i.MX but it sound to be covered by
explanation that you gave...
Thanks, best regards,
--
Nicolas Ferre
^ permalink raw reply
* [PATCH] ARM: vfp: Fix up exception location in Thumb mode
From: Catalin Marinas @ 2011-01-14 11:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294990949-2729-1-git-send-email-ccross@android.com>
On 14 January 2011 07:42, Colin Cross <ccross@android.com> wrote:
> The exception handler in entry-armv.S checks for thumb mode and
> correctly determines the exception location and instruction,
> but VFP_bounce uses the uncorrected location off the stack.
> If the VFP exception occured in Thumb mode, fix up the
> exception location to match the value that would be returned
> in ARM mode.
>
> Fixes segfaults in userspace applications running in Thumb mode
> caused by a handled VFP exception returning to the middle of the
> instruction that triggered the exception.
>
> Change-Id: I6c6ba1ab88e107bec166ea334d7e0974a4f6bfba
> Signed-off-by: Colin Cross <ccross@android.com>
> ---
> ?arch/arm/vfp/vfpmodule.c | ? 10 ++++++++++
> ?1 files changed, 10 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
> index 0797cb5..63ed73d 100644
> --- a/arch/arm/vfp/vfpmodule.c
> +++ b/arch/arm/vfp/vfpmodule.c
> @@ -275,6 +275,16 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
> ? ? ? ?pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc);
>
> ? ? ? ?/*
> + ? ? ? ?* If the exception occured in thumb mode, pc is exception location + 2,
> + ? ? ? ?* the middle of the 32-bit VFP instruction. ?Add 2 to get exception
> + ? ? ? ?* location + 4, the same we get in ARM mode.
> + ? ? ? ?*/
> +#ifdef CONFIG_ARM_THUMB
> + ? ? ? if (regs->ARM_cpsr & PSR_T_BIT)
> + ? ? ? ? ? ? ? regs->ARM_pc += 2;
> +#endif
You can use "if (thumb_mode(regs))" and avoid the #ifdef entirely.
--
Catalin
^ permalink raw reply
* [PATCH] MTD: atmel_nand: Add DMA support to access Nandflash
From: Peter Korsgaard @ 2011-01-14 11:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1294997687-12515-1-git-send-email-hong.xu@atmel.com>
>>>>> "Hong" == Hong Xu <hong.xu@atmel.com> writes:
Hong> Some SAM9 chips have the ability to perform DMA between CPU and
Hong> SMC controller. This patch adds DMA support for SAM9RL, SAM9G45,
Hong> SSAM9G46,AM9M10, SAM9M11.
Hong> Signed-off-by: Hong Xu <hong.xu@atmel.com>
But mtd buffers are not guaranteed to be DMA safe (E.G. might come from
vmalloc), so you'll need to walk the page tables.
--
Bye, Peter Korsgaard
^ permalink raw reply
* i.MX & IRQF_ONESHOT
From: Thomas Gleixner @ 2011-01-14 11:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D30329F.5040201@atmel.com>
On Fri, 14 Jan 2011, Nicolas Ferre wrote:
> For AT91:
> - the platform does not provides irq_flags so default to
> IRQF_TRIGGER_FALLING | IRQF_ONESHOT as stated in the driver.
> - on at91sam9g10ek the touchscreen is wired to an full featured IRQ
> entry (configured with pullup in arch/arm/mach-at91/board-sam9261ek.c).
> - the irq description of plain interrupts is in arch/arm/mach-at91/irq.c
> and at91_aic_set_type() has an IRQ_TYPE_EDGE_FALLING entry.
>
> So it should be configured on falling edge...
>
> But: is seems that looking at at91_aic_set_type() initialization
> function, AIC is configured with:
> set_irq_handler(i, handle_level_irq);
>
> I do not know if it is the same as i.MX but it sound to be covered by
> explanation that you gave...
Seems to be the same problem.
Thanks,
tglx
^ permalink raw reply
* ARM: CPU hotplug: fix hard-coded control register constants
From: viresh kumar @ 2011-01-14 11:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D303758.4060608@st.com>
Russell,
I was just tracking latest changes in realview, for preparing SPEAr
support V4. I found below patch and didn't understood it very well.
> Subject: [PATCH] ARM: CPU hotplug: fix hard-coded control register constants
>
> Use the definition we've provided in asm/system.h rather than
> numeric constants.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> ---
> arch/arm/mach-realview/hotplug.c | 8 ++++----
> arch/arm/mach-s5pv310/hotplug.c | 8 ++++----
> arch/arm/mach-tegra/hotplug.c | 8 ++++----
> 3 files changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c
> index b6387cf..a87523d 100644
> --- a/arch/arm/mach-realview/hotplug.c
> +++ b/arch/arm/mach-realview/hotplug.c
> @@ -31,10 +31,10 @@ static inline void cpu_enter_lowpower(void)
> " bic %0, %0, #0x20\n"
> " mcr p15, 0, %0, c1, c0, 1\n"
> " mrc p15, 0, %0, c1, c0, 0\n"
> - " bic %0, %0, #0x04\n"
> + " bic %0, %0, %2\n"
> " mcr p15, 0, %0, c1, c0, 0\n"
> : "=&r" (v)
> - : "r" (0)
> + : "r" (0), "Ir" (CR_C)
> : "cc");
> }
This looks fine as you have replaced 0x04 with CR_C, which itself is (1 << 2).
>
> @@ -43,13 +43,13 @@ static inline void cpu_leave_lowpower(void)
> unsigned int v;
>
> asm volatile( "mrc p15, 0, %0, c1, c0, 0\n"
> - " orr %0, %0, #0x04\n"
> + " orr %0, %0, %1\n"
> " mcr p15, 0, %0, c1, c0, 0\n"
> " mrc p15, 0, %0, c1, c0, 1\n"
> " orr %0, %0, #0x20\n"
> " mcr p15, 0, %0, c1, c0, 1\n"
> : "=&r" (v)
> - :
> + : "Ir" (CR_C)
> : "cc");
> }
fine here also.
>
> diff --git a/arch/arm/mach-s5pv310/hotplug.c b/arch/arm/mach-s5pv310/hotplug.c
> index 951ba6d..afa5392 100644
> --- a/arch/arm/mach-s5pv310/hotplug.c
> +++ b/arch/arm/mach-s5pv310/hotplug.c
> @@ -30,13 +30,13 @@ static inline void cpu_enter_lowpower(void)
> * Turn off coherency
> */
> " mrc p15, 0, %0, c1, c0, 1\n"
> - " bic %0, %0, #0x20\n"
> + " bic %0, %0, %2\n"
but why replace 0x20 with CR_C instead of CR_D
> " mcr p15, 0, %0, c1, c0, 1\n"
> " mrc p15, 0, %0, c1, c0, 0\n"
> " bic %0, %0, #0x04\n"
> " mcr p15, 0, %0, c1, c0, 0\n"
> : "=&r" (v)
> - : "r" (0)
> + : "r" (0), "Ir" (CR_C)
> : "cc");
> }
>
> @@ -46,13 +46,13 @@ static inline void cpu_leave_lowpower(void)
>
> asm volatile(
> "mrc p15, 0, %0, c1, c0, 0\n"
> - " orr %0, %0, #0x04\n"
> + " orr %0, %0, %1\n"
> " mcr p15, 0, %0, c1, c0, 0\n"
> " mrc p15, 0, %0, c1, c0, 1\n"
> " orr %0, %0, #0x20\n"
> " mcr p15, 0, %0, c1, c0, 1\n"
> : "=&r" (v)
> - :
> + : "Ir" (CR_C)
> : "cc");
> }
>
> diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
> index 17faf77..a5cb1ce 100644
> --- a/arch/arm/mach-tegra/hotplug.c
> +++ b/arch/arm/mach-tegra/hotplug.c
> @@ -26,13 +26,13 @@ static inline void cpu_enter_lowpower(void)
> * Turn off coherency
> */
> " mrc p15, 0, %0, c1, c0, 1\n"
> - " bic %0, %0, #0x20\n"
> + " bic %0, %0, %2\n"
here also.
Was this code wrong earlier??
--
viresh
^ permalink raw reply
* [PATCH] ARM: vfp: Fix up exception location in Thumb mode
From: Russell King - ARM Linux @ 2011-01-14 12:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <AANLkTimqiqABxCejdeOQWZZ62DVUZW2v-yMpdu1aNDQT@mail.gmail.com>
On Fri, Jan 14, 2011 at 11:43:04AM +0000, Catalin Marinas wrote:
> > ? ? ? ?pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc);
> >
> > ? ? ? ?/*
> > + ? ? ? ?* If the exception occured in thumb mode, pc is exception location + 2,
> > + ? ? ? ?* the middle of the 32-bit VFP instruction. ?Add 2 to get exception
> > + ? ? ? ?* location + 4, the same we get in ARM mode.
> > + ? ? ? ?*/
> > +#ifdef CONFIG_ARM_THUMB
> > + ? ? ? if (regs->ARM_cpsr & PSR_T_BIT)
> > + ? ? ? ? ? ? ? regs->ARM_pc += 2;
> > +#endif
>
> You can use "if (thumb_mode(regs))" and avoid the #ifdef entirely.
I don't think this is correct. On entry to the undefined instruction
handler, we get the uncorrected PC value, so PC points to the
instruction after the faulting instruction.
If it was an ARM instruction, that is located at PC-4. If it was a
Thumb instruction, it is located at PC-2. This PC value is passed
unmodified to the VFP entry code, and the passed r2 reflect the
value in regs->ARM_pc.
The VFP entry assembly doesn't touch the PC value, except when it
wants to retry an instruction:
sub r2, r2, #4
str r2, [sp, #S_PC] @ retry the instruction
So I think that 2 to the PC when in thumb mode is incorrect, as that'll
cause us to skip the instruction following the faulted one.
I think that the undefined instruction handling needs reworking for
Thumb entirely as we could be dealing with a 16-bit or 32-bit thumb
instruction, and we have no way of knowing without repeatedly
decoding that instruction.
^ permalink raw reply
* ARM: CPU hotplug: fix hard-coded control register constants
From: Russell King - ARM Linux @ 2011-01-14 12:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D30386B.7020200@st.com>
On Fri, Jan 14, 2011 at 05:20:03PM +0530, viresh kumar wrote:
> > diff --git a/arch/arm/mach-s5pv310/hotplug.c b/arch/arm/mach-s5pv310/hotplug.c
> > index 951ba6d..afa5392 100644
> > --- a/arch/arm/mach-s5pv310/hotplug.c
> > +++ b/arch/arm/mach-s5pv310/hotplug.c
> > @@ -30,13 +30,13 @@ static inline void cpu_enter_lowpower(void)
> > * Turn off coherency
> > */
> > " mrc p15, 0, %0, c1, c0, 1\n"
> > - " bic %0, %0, #0x20\n"
> > + " bic %0, %0, %2\n"
>
> but why replace 0x20 with CR_C instead of CR_D
Looks like a mistake - it should've been the one below.
> > " mcr p15, 0, %0, c1, c0, 1\n"
> > " mrc p15, 0, %0, c1, c0, 0\n"
> > " bic %0, %0, #0x04\n"
> > " mcr p15, 0, %0, c1, c0, 0\n"
> > : "=&r" (v)
> > - : "r" (0)
> > + : "r" (0), "Ir" (CR_C)
> > : "cc");
In any case, this code is probably doing the wrong thing - if s5pv310
is not an ARMv6 MPCore the its fiddling with the auxillary control
register is already broken.
> > diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
> > index 17faf77..a5cb1ce 100644
> > --- a/arch/arm/mach-tegra/hotplug.c
> > +++ b/arch/arm/mach-tegra/hotplug.c
> > @@ -26,13 +26,13 @@ static inline void cpu_enter_lowpower(void)
> > * Turn off coherency
> > */
> > " mrc p15, 0, %0, c1, c0, 1\n"
> > - " bic %0, %0, #0x20\n"
> > + " bic %0, %0, %2\n"
>
> here also.
Same comment.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox