* [PATCH for 2.6.38] ARM: S5PC110: fix regulator names
From: Kukjin Kim @ 2011-02-18 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297760487-7930-1-git-send-email-m.szyprowski@samsung.com>
Marek Szyprowski wrote:
>
> Since commit 1130e5b3ff4 regulators are exported to debugfs. The names
> of the regulators that contains slash ('/') causes an ops during kernel
> boot. This patch fixes this issue.
>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> arch/arm/mach-s5pv210/mach-aquila.c | 6 +++---
> arch/arm/mach-s5pv210/mach-goni.c | 6 +++---
> 2 files changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-
> s5pv210/mach-aquila.c
> index 1236e19..557add4 100644
> --- a/arch/arm/mach-s5pv210/mach-aquila.c
> +++ b/arch/arm/mach-s5pv210/mach-aquila.c
> @@ -149,7 +149,7 @@ static struct regulator_init_data aquila_ldo2_data = {
>
> static struct regulator_init_data aquila_ldo3_data = {
> .constraints = {
> - .name = "VUSB/MIPI_1.1V",
> + .name = "VUSB+MIPI_1.1V",
> .min_uV = 1100000,
> .max_uV = 1100000,
> .apply_uV = 1,
> @@ -197,7 +197,7 @@ static struct regulator_init_data aquila_ldo7_data = {
>
> static struct regulator_init_data aquila_ldo8_data = {
> .constraints = {
> - .name = "VUSB/VADC_3.3V",
> + .name = "VUSB+VADC_3.3V",
> .min_uV = 3300000,
> .max_uV = 3300000,
> .apply_uV = 1,
> @@ -207,7 +207,7 @@ static struct regulator_init_data aquila_ldo8_data = {
>
> static struct regulator_init_data aquila_ldo9_data = {
> .constraints = {
> - .name = "VCC/VCAM_2.8V",
> + .name = "VCC+VCAM_2.8V",
> .min_uV = 2800000,
> .max_uV = 2800000,
> .apply_uV = 1,
> diff --git a/arch/arm/mach-s5pv210/mach-goni.c
b/arch/arm/mach-s5pv210/mach-
> goni.c
> index 2beeb66..056f5c7 100644
> --- a/arch/arm/mach-s5pv210/mach-goni.c
> +++ b/arch/arm/mach-s5pv210/mach-goni.c
> @@ -288,7 +288,7 @@ static struct regulator_init_data goni_ldo2_data = {
>
> static struct regulator_init_data goni_ldo3_data = {
> .constraints = {
> - .name = "VUSB/MIPI_1.1V",
> + .name = "VUSB+MIPI_1.1V",
> .min_uV = 1100000,
> .max_uV = 1100000,
> .apply_uV = 1,
> @@ -337,7 +337,7 @@ static struct regulator_init_data goni_ldo7_data = {
>
> static struct regulator_init_data goni_ldo8_data = {
> .constraints = {
> - .name = "VUSB/VADC_3.3V",
> + .name = "VUSB+VADC_3.3V",
> .min_uV = 3300000,
> .max_uV = 3300000,
> .apply_uV = 1,
> @@ -347,7 +347,7 @@ static struct regulator_init_data goni_ldo8_data = {
>
> static struct regulator_init_data goni_ldo9_data = {
> .constraints = {
> - .name = "VCC/VCAM_2.8V",
> + .name = "VCC+VCAM_2.8V",
> .min_uV = 2800000,
> .max_uV = 2800000,
> .apply_uV = 1,
> --
Ok, applied into s5p-fixes-for-linus for 38.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH 2/2] ARM i.MX23/28: Add framebuffer device support
From: Shawn Guo @ 2011-02-18 9:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110218084625.GF24426@pengutronix.de>
Hi Sascha,
On Fri, Feb 18, 2011 at 09:46:25AM +0100, Sascha Hauer wrote:
> On Fri, Feb 18, 2011 at 02:14:41PM +0800, Shawn Guo wrote:
> > On Wed, Feb 16, 2011 at 10:56:39AM +0100, Sascha Hauer wrote:
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > Cc: Shawn Guo <shawn.guo@freescale.com>
> > > ---
> > > arch/arm/mach-mxs/clock-mx23.c | 2 +-
> > > arch/arm/mach-mxs/clock-mx28.c | 1 +
> > > arch/arm/mach-mxs/devices-mx23.h | 4 ++
> > > arch/arm/mach-mxs/devices-mx28.h | 4 ++
> > > arch/arm/mach-mxs/devices/Kconfig | 4 ++
> > > arch/arm/mach-mxs/devices/Makefile | 1 +
> > > arch/arm/mach-mxs/devices/platform-mxsfb.c | 46 ++++++++++++++++++++++++++++
> > > 7 files changed, 61 insertions(+), 1 deletions(-)
> > > create mode 100644 arch/arm/mach-mxs/devices/platform-mxsfb.c
> > >
> > > diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
> > > index ca72a05..bfc7f27 100644
> > > --- a/arch/arm/mach-mxs/clock-mx23.c
> > > +++ b/arch/arm/mach-mxs/clock-mx23.c
> > > @@ -446,7 +446,7 @@ static struct clk_lookup lookups[] = {
> > > _REGISTER_CLOCK(NULL, "hclk", hbus_clk)
> > > _REGISTER_CLOCK(NULL, "usb", usb_clk)
> > > _REGISTER_CLOCK(NULL, "audio", audio_clk)
> > > - _REGISTER_CLOCK(NULL, "pwm", pwm_clk)
> > Introducing the warning below ...
> >
> > arch/arm/mach-mxs/clock-mx23.c:430: warning: ?pwm_clk? defined but not used
>
> Right, it was not intended to remove the pwm here. Will fix.
>
> >
> > > + _REGISTER_CLOCK("imx23-fb", NULL, lcdif_clk)
> > > };
> > >
> > > static int clk_misc_init(void)
> > > diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
> > > index fd1c4c5..6a7ebcb 100644
> > > --- a/arch/arm/mach-mxs/clock-mx28.c
> > > +++ b/arch/arm/mach-mxs/clock-mx28.c
> > > @@ -620,6 +620,7 @@ static struct clk_lookup lookups[] = {
> > > _REGISTER_CLOCK(NULL, "pwm", pwm_clk)
> > > _REGISTER_CLOCK(NULL, "lradc", lradc_clk)
> > > _REGISTER_CLOCK(NULL, "spdif", spdif_clk)
> > > + _REGISTER_CLOCK("imx28-fb", NULL, lcdif_clk)
> > > };
> > >
> > > static int clk_misc_init(void)
> > > diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
> > > index 1256788..b9745a2 100644
> > > --- a/arch/arm/mach-mxs/devices-mx23.h
> > > +++ b/arch/arm/mach-mxs/devices-mx23.h
> > > @@ -10,7 +10,11 @@
> > > */
> > > #include <mach/mx23.h>
> > > #include <mach/devices-common.h>
> > > +#include <mach/fb.h>
> > >
> > Why do we have mxsfb platform device code breaking the consistency
> > that we are maintaining well so far?
>
> The rule is that we include header files where we need them.
> devices-common.h is not touched in this patch and it does not need
> mach/fb.h, hence it is not include there.
>
> >
> > Generally, we have this header included in devices-common.h
> >
> > > extern const struct amba_device mx23_duart_device __initconst;
> > > #define mx23_add_duart() \
> > > mxs_add_duart(&mx23_duart_device)
> > > +
> > > +struct platform_device *__init mx23_add_mxsfb(
> > > + const struct mxsfb_platform_data *pdata);
> >
> > Generally, this goes to devices-common.h
>
> No, devices-common.h only declares the mxs_* functions. There is no
> mxs_add_mxsfb in this patch which indeed would go to devices-common.h
>
Well, if you break the consistency in one place, you break the
consistency every. If you follow the convention to add mxs_add_fb
in platform_fb.c, declare it in devices-common.h, ..., everything
gets consistent. We will not have the particular and noticeable fb
device code everywhere.
> >
> > > diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
> > > index 33773a6..c902dc7 100644
> > > --- a/arch/arm/mach-mxs/devices-mx28.h
> > > +++ b/arch/arm/mach-mxs/devices-mx28.h
> > > @@ -10,6 +10,7 @@
> > > */
> > > #include <mach/mx28.h>
> > > #include <mach/devices-common.h>
> > > +#include <mach/fb.h>
> > >
> > > extern const struct amba_device mx28_duart_device __initconst;
> > > #define mx28_add_duart() \
> > > @@ -18,3 +19,6 @@ extern const struct amba_device mx28_duart_device __initconst;
> > > extern const struct mxs_fec_data mx28_fec_data[] __initconst;
> > > #define mx28_add_fec(id, pdata) \
> > > mxs_add_fec(&mx28_fec_data[id], pdata)
> > > +
> > > +struct platform_device *__init mx28_add_mxsfb(
> > > + const struct mxsfb_platform_data *pdata);
> >
> > ditto
> >
> > > diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
> > > index cf7dc1a..1538cb9 100644
> > > --- a/arch/arm/mach-mxs/devices/Kconfig
> > > +++ b/arch/arm/mach-mxs/devices/Kconfig
> > > @@ -4,3 +4,7 @@ config MXS_HAVE_AMBA_DUART
> > >
> > > config MXS_HAVE_PLATFORM_FEC
> > > bool
> > > +
> > > +config MXS_HAVE_PLATFORM_MXSFB
> > > + bool
> > > +
> >
> > I understand that "mxsfb" was picked up for the device name to
> > reflect the driver name. But since this is the device under mach- mxs
> > folder, can we simply call it "fb" just like the way you name fb.h?
> >
> > In this way, we have all mxs platform device naming schema aligned,
> > auart, duart, dma, fb, fec, flexcan, mmc ...
>
> I see it the other way round. mach/fb.h is too generic, I would prefer
> mach/mxsfb.h to be able to add support for a different framebuffer
> later. So I better change fb.h to mxsfb.h.
>
I'm fine with either way, but just wondering what kind of fb later
it is and its naming, relatively to mxsfs.
> >
> > > diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
> > > index d0a09f6..0cf8b48 100644
> > > --- a/arch/arm/mach-mxs/devices/Makefile
> > > +++ b/arch/arm/mach-mxs/devices/Makefile
> > > @@ -1,2 +1,3 @@
> > > obj-$(CONFIG_MXS_HAVE_AMBA_DUART) += amba-duart.o
> > > obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
> > > +obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o
> > > diff --git a/arch/arm/mach-mxs/devices/platform-mxsfb.c b/arch/arm/mach-mxs/devices/platform-mxsfb.c
> > > new file mode 100644
> > > index 0000000..632bbdc
> > > --- /dev/null
> > > +++ b/arch/arm/mach-mxs/devices/platform-mxsfb.c
> > > @@ -0,0 +1,46 @@
> > > +/*
> > > + * Copyright (C) 2011 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
> > > + *
> > > + * This program is free software; you can redistribute it and/or modify it under
> > > + * the terms of the GNU General Public License version 2 as published by the
> > > + * Free Software Foundation.
> > > + */
> > > +#include <asm/sizes.h>
> > > +#include <mach/mx23.h>
> > > +#include <mach/mx28.h>
> > > +#include <mach/devices-common.h>
> > > +#include <mach/fb.h>
> >
> > Generally, this goes to devices-common.h
> >
> > > +
> > > +#ifdef CONFIG_SOC_IMX23
> > > +struct platform_device *__init mx23_add_mxsfb(
> > > + const struct mxsfb_platform_data *pdata)
> > > +{
> > > + struct resource res[] = {
> > > + {
> > > + .start = MX23_LCDIF_BASE_ADDR,
> > > + .end = MX23_LCDIF_BASE_ADDR + SZ_8K - 1,
> > > + .flags = IORESOURCE_MEM,
> > > + },
> > > + };
> > > +
> > > + return mxs_add_platform_device_dmamask("imx23-fb", -1,
> > > + res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
> > > +}
> > > +#endif /* ifdef CONFIG_SOC_IMX23 */
> > > +
> > > +#ifdef CONFIG_SOC_IMX28
> > > +struct platform_device *__init mx28_add_mxsfb(
> > > + const struct mxsfb_platform_data *pdata)
> > > +{
> > > + struct resource res[] = {
> > > + {
> > > + .start = MX28_LCDIF_BASE_ADDR,
> > > + .end = MX28_LCDIF_BASE_ADDR + SZ_8K - 1,
> > > + .flags = IORESOURCE_MEM,
> > > + },
> > > + };
> > > +
> > > + return mxs_add_platform_device_dmamask("imx28-fb", -1,
> > > + res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
> > > +}
> > > +#endif /* ifdef CONFIG_SOC_IMX28 */
> >
> > Generally, we have macro mxs_fb_data_entry and function mxs_add_fb
> > in this file. It's nothing but all about consistency. We do not
> > want some later coming platform device looking at this as example,
> > and bring more inconsistency into mach-mxs platform device codes.
>
> My opinion on this is that we should not use complex ## macro constructs
> where not necessary. With a device which is only present once on the SoC
> it is not necessary, so I skippped it. And yes, if someone is in the
> same situation with a single device on a system, he actually should take
> this as an example. So no, I don't agree with you.
>
With a device presents on more than one SoC, it's also not necessary?
With this inconsistency introduced, you need always keep an eye on
the new device code to ensure that it's not looking at the improper
example.
Anyway, I'm not going to argue with you on this, it's your call,
since Russell is pulling i.mx bits from your tree ;)
--
Regards,
Shawn
^ permalink raw reply
* [PATCH v2 09/13] can: pruss CAN driver.
From: Subhasish Ghosh @ 2011-02-18 9:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D5E2F86.1020400@pengutronix.de>
Ok, will do NAPI
On 02/18/2011 09:15 AM, Subhasish Ghosh wrote:
>> On 02/18/2011 08:07 AM, Subhasish Ghosh wrote:
>>> --------------------------------------------------
>>> From: "Kurt Van Dijck" <kurt.van.dijck@eia.be>
>>
>> ...
>>>>> + /* register interrupt handler */
>>>>> + err = request_irq(priv->trx_irq, &omapl_rx_can_intr, IRQF_SHARED,
>>>>> + "pru_can_irq", ndev);
>>>> you're doing a lot of work _in_ the irq handler. Maybe threaded irq?
>>>>
>>> SG -Ok, will do
>>
>> No, please use NAPI instead.
>
> We are using h/w filters, so the number of interrupts coming into the
> processor are not hogging it.
> I feel that we may not require an interrupt mitigation.
As davem stated the other day, all new drivers should use NAPI.
regards, Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH V3 3/4] ARM: Xilinx: base header files and assembly macros
From: Jamie Iles @ 2011-02-18 9:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2fdc2d92-486e-4319-866f-3882938363c3@VA3EHSMHS026.ehs.local>
On Thu, Feb 17, 2011 at 06:19:09PM -0700, John Linn wrote:
> > > +#define PHYS_OFFSET 0x0
> >
> > This should be PLAT_PHYS_OFFSET and could do with being surrounded
> with
> > UL() e.g.
> >
> > #define PLAT_PHYS_OFFSET UL(0x00000000)
>
> This doesn't build with 2.6.38-rc5, am I missing something?
>
> PHYS_OFFSET is still needed from what I can tell, but maybe I overlooked
> something.
The change is queued up in Russell's devel branch for the dynamic p2v
and will be in 2.6.39. For a patch series like this it's probably worth
developing off of linux-next[1]. This contains all of the trees that
will be mereged into the next kernel so carries the bigger changes like
dynamic p2v.
Jamie
1. git://git.kernel.org/pub/scm/linux/kernel/git/sfr/linux-next.git
^ permalink raw reply
* [PATCH] ARM: SAMSUNG: Drop exporting s3c24xx_ts_set_platdata
From: Kukjin Kim @ 2011-02-18 9:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297651767.13143.3.camel@mola>
Axel Lin wrote:
>
> s3c24xx_ts_set_platdata is annotated __init and not used by any module,
> thus don't export it.
> This patch fixes below warning:
>
> WARNING: arch/arm/plat-samsung/built-in.o(__ksymtab+0x90): Section
mismatch
> in reference from the variable __ksymtab_s3c24xx_ts_set_platdata to the
> function .init.text:s3c24xx_ts_set_platdata()
> The symbol s3c24xx_ts_set_platdata is exported and annotated __init
> Fix this by removing the __init annotation of s3c24xx_ts_set_platdata or
drop
> the export.
>
> Signed-off-by: Axel Lin <axel.lin@gmail.com>
> ---
> arch/arm/plat-samsung/dev-ts.c | 1 -
> 1 files changed, 0 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/plat-samsung/dev-ts.c
b/arch/arm/plat-samsung/dev-ts.c
> index 236ef84..3e4bd81 100644
> --- a/arch/arm/plat-samsung/dev-ts.c
> +++ b/arch/arm/plat-samsung/dev-ts.c
> @@ -58,4 +58,3 @@ void __init s3c24xx_ts_set_platdata(struct
> s3c2410_ts_mach_info *pd)
>
> s3c_device_ts.dev.platform_data = npd;
> }
> -EXPORT_SYMBOL(s3c24xx_ts_set_platdata);
> --
> 1.7.2
>
Ok, applied.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH 1/1] ARM: imx53: correct Silicon Revision definition following fuse map
From: Richard Zhao @ 2011-02-18 9:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110218070752.GC2343@tarshish>
Hi Baruch,
On Fri, Feb 18, 2011 at 09:07:52AM +0200, Baruch Siach wrote:
> Hi Richard,
>
> On Fri, Feb 18, 2011 at 01:47:29PM +0800, Richard Zhao wrote:
> > Signed-off-by: Richard Zhao <richard.zhao@freescale.com>
> >
> > diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c
> > index d40671d..95fd5f8 100644
> > --- a/arch/arm/mach-mx5/cpu.c
> > +++ b/arch/arm/mach-mx5/cpu.c
> > @@ -76,13 +76,25 @@ late_initcall(mx51_neon_fixup);
> > static int get_mx53_srev(void)
> > {
> > void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
> > - u32 rev = readl(iim_base + IIM_SREV) & 0xff;
> > + u32 reg = readl(iim_base + IIM_SREV) & 0xff;
> > + int rev;
> > +
> > + switch (reg) {
> > + case 0x0:
> > + rev = IMX_CHIP_REVISION_1_0;
> > + break;
> > + case 0x2:
> > + rev = IMX_CHIP_REVISION_2_0;
> > + break;
> > + case 0x3:
> > + rev = IMX_CHIP_REVISION_2_1;
> > + break;
> > + default:
> > + rev = IMX_CHIP_REVISION_UNKNOWN;
> > + break;
> > + }
> >
> > - if (rev == 0x0)
> > - return IMX_CHIP_REVISION_1_0;
> > - else if (rev == 0x10)
> > - return IMX_CHIP_REVISION_2_0;
> > - return 0;
> > + return rev;
> > }
> >
> > /*
>
> I think the following code is shorter and more readable:
>
> switch (reg) {
> case 0x0:
> return IMX_CHIP_REVISION_1_0;
> case 0x2:
> return IMX_CHIP_REVISION_2_0;
> case 0x3:
> return IMX_CHIP_REVISION_2_1;
> default:
> return IMX_CHIP_REVISION_UNKNOWN;
> }
Yes. I thought there would be compile warning, but not.
Thanks
Richard
>
> baruch
>
>
> --
> ~. .~ Tk Open Systems
> =}------------------------------------------------ooO--U--Ooo------------{=
> - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
>
^ permalink raw reply
* [PATCH RESEND 3/4] ARM: imx53_loco: add i2c device support
From: Richard Zhao @ 2011-02-18 8:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110218084533.GV22310@pengutronix.de>
Hi Uwe,
On Fri, Feb 18, 2011 at 09:45:33AM +0100, Uwe Kleine-K?nig wrote:
> On Fri, Feb 18, 2011 at 12:36:16PM +0800, Richard Zhao wrote:
> > Signed-off-by: Richard Zhao <richard.zhao@freescale.com>
> >
> > diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
> > index 10b6008..abea297 100644
> > --- a/arch/arm/mach-mx5/Kconfig
> > +++ b/arch/arm/mach-mx5/Kconfig
> > @@ -146,6 +146,7 @@ config MACH_MX53_LOCO
> > bool "Support MX53 LOCO platforms"
> > select SOC_IMX53
> > select IMX_HAVE_PLATFORM_IMX_UART
> > + select IMX_HAVE_PLATFORM_IMX_I2C
> please keep these sorted alphabetically
ok. I will move it up by one line.
Thanks
Richard
>
> Best regards
> Uwe
>
> --
> Pengutronix e.K. | Uwe Kleine-K?nig |
> Industrial Linux Solutions | http://www.pengutronix.de/ |
>
> _______________________________________________
> 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 6/6] pxa3xx_nand: clean the keep configure code
From: Lei Wen @ 2011-02-18 8:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298019428-7809-1-git-send-email-leiwen@marvell.com>
Signed-off-by: Lei Wen <leiwen@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>
---
arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 1 +
drivers/mtd/nand/pxa3xx_nand.c | 99 +++++++++-----------------
2 files changed, 34 insertions(+), 66 deletions(-)
diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 01a8448..0bd4e88 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -30,6 +30,7 @@ struct pxa3xx_nand_cmdset {
};
struct pxa3xx_nand_flash {
+ char *name;
uint32_t chip_id;
unsigned int page_per_block; /* Pages per block (PG_PER_BLK) */
unsigned int page_size; /* Page size in bytes (PAGE_SZ) */
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 36f7ef9..3746f0f 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -211,15 +211,15 @@ static struct pxa3xx_nand_timing timing[] = {
};
static struct pxa3xx_nand_flash builtin_flash_types[] = {
- { 0, 0, 2048, 8, 8, 0, &default_cmdset, &timing[0] },
- { 0x46ec, 32, 512, 16, 16, 4096, &default_cmdset, &timing[1] },
- { 0xdaec, 64, 2048, 8, 8, 2048, &default_cmdset, &timing[1] },
- { 0xd7ec, 128, 4096, 8, 8, 8192, &default_cmdset, &timing[1] },
- { 0xa12c, 64, 2048, 8, 8, 1024, &default_cmdset, &timing[2] },
- { 0xb12c, 64, 2048, 16, 16, 1024, &default_cmdset, &timing[2] },
- { 0xdc2c, 64, 2048, 8, 8, 4096, &default_cmdset, &timing[2] },
- { 0xcc2c, 64, 2048, 16, 16, 4096, &default_cmdset, &timing[2] },
- { 0xba20, 64, 2048, 16, 16, 2048, &default_cmdset, &timing[3] },
+{ "DEFAULT FLASH", 0, 0, 2048, 8, 8, 0, &default_cmdset, &timing[0] },
+{ "64MiB 16-bit", 0x46ec, 32, 512, 16, 16, 4096, &default_cmdset, &timing[1] },
+{ "256MiB 8-bit", 0xdaec, 64, 2048, 8, 8, 2048, &default_cmdset, &timing[1] },
+{ "4GiB 8-bit", 0xd7ec, 128, 4096, 8, 8, 8192, &default_cmdset, &timing[1] },
+{ "128MiB 8-bit", 0xa12c, 64, 2048, 8, 8, 1024, &default_cmdset, &timing[2] },
+{ "128MiB 16-bit", 0xb12c, 64, 2048, 16, 16, 1024, &default_cmdset, &timing[2] },
+{ "512MiB 8-bit", 0xdc2c, 64, 2048, 8, 8, 4096, &default_cmdset, &timing[2] },
+{ "512MiB 16-bit", 0xcc2c, 64, 2048, 16, 16, 4096, &default_cmdset, &timing[2] },
+{ "256MiB 16-bit", 0xba20, 64, 2048, 16, 16, 2048, &default_cmdset, &timing[3] },
};
/* Define a default flash type setting serve as flash detecting only */
@@ -781,7 +781,6 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
/* calculate flash information */
info->cmdset = f->cmdset;
info->page_size = f->page_size;
- info->oob_buff = info->data_buff + f->page_size;
info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
/* calculate addressing information */
@@ -811,45 +810,12 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
{
uint32_t ndcr = nand_readl(info, NDCR);
- struct nand_flash_dev *type = NULL;
- uint32_t id = -1, page_per_block, num_blocks;
- int i;
-
- page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
/* set info fields needed to read id */
info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
info->reg_ndcr = ndcr;
info->cmdset = &default_cmdset;
- pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
- id = *((uint16_t *)(info->data_buff));
- if (id == 0)
- return -ENODEV;
-
- /* Lookup the flash id */
- for (i = 0; nand_flash_ids[i].name != NULL; i++) {
- if (id == nand_flash_ids[i].id) {
- type = &nand_flash_ids[i];
- break;
- }
- }
-
- if (!type)
- return -ENODEV;
-
- /* fill the missing flash information */
- i = __ffs(page_per_block * info->page_size);
- num_blocks = type->chipsize << (20 - i);
-
- /* calculate addressing information */
- info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1;
-
- if (num_blocks * page_per_block > 65536)
- info->row_addr_cycles = 3;
- else
- info->row_addr_cycles = 2;
-
info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
@@ -916,13 +882,15 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
struct pxa3xx_nand_info *info = mtd->priv;
struct platform_device *pdev = info->pdev;
struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+ struct nand_flash_dev pxa3xx_flash_ids[2] = {{NULL,}, {NULL,}};
const struct pxa3xx_nand_flash *f = NULL;
struct nand_chip *chip = mtd->priv;
uint32_t id = -1;
+ uint64_t chipsize;
int i, ret;
if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
- return 0;
+ goto KEEP_CONFIG;
ret = pxa3xx_nand_sensing(info);
if (!ret) {
@@ -952,22 +920,11 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
f = &builtin_flash_types[i - pdata->num_flash + 1];
/* find the chip in default list */
- if (f->chip_id == id) {
- pxa3xx_nand_config_flash(info, f);
- mtd->writesize = f->page_size;
- mtd->writesize_shift = ffs(mtd->writesize) - 1;
- mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
- mtd->oobsize = mtd->writesize / 32;
- mtd->erasesize = f->page_size * f->page_per_block;
- mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
- mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
-
- mtd->name = mtd_names[0];
+ if (f->chip_id == id)
break;
- }
}
- if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) {
+ if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
kfree(mtd);
info->mtd = NULL;
printk(KERN_ERR "ERROR!! flash not defined!!!\n");
@@ -975,17 +932,27 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
return -EINVAL;
}
+ pxa3xx_nand_config_flash(info, f);
+ pxa3xx_flash_ids[0].name = f->name;
+ pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
+ pxa3xx_flash_ids[0].pagesize = f->page_size;
+ chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
+ pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
+ pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
+ pxa3xx_flash_ids[0].options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0;
+KEEP_CONFIG:
+ if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids))
+ return -ENODEV;
+ /* calculate addressing information */
+ info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+ info->oob_buff = info->data_buff + mtd->writesize;
+ if ((mtd->size >> chip->page_shift) > 65536)
+ info->row_addr_cycles = 3;
+ else
+ info->row_addr_cycles = 2;
+ mtd->name = mtd_names[0];
chip->ecc.mode = NAND_ECC_HW;
chip->ecc.size = f->page_size;
- chip->chipsize = (uint64_t)f->num_blocks * f->page_per_block
- * f->page_size;
- mtd->size = chip->chipsize;
-
- /* Calculate the address shift from the page size */
- chip->page_shift = ffs(mtd->writesize) - 1;
- chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1;
- chip->numchips = 1;
- chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
chip->options |= NAND_NO_AUTOINCR;
--
1.7.0.4
^ permalink raw reply related
* [PATCH 5/6] pxa3xx_nand: mtd scan id process could be defined by driver itself
From: Lei Wen @ 2011-02-18 8:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298019428-7809-1-git-send-email-leiwen@marvell.com>
Different NAND driver may require its unique detection. For pxa3xx_nand,
it use its self id database to get the necessary info.
Signed-off-by: Lei Wen <leiwen@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>
---
drivers/mtd/nand/pxa3xx_nand.c | 210 +++++++++++++++++++++++-----------------
1 files changed, 119 insertions(+), 91 deletions(-)
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 0895cf8..36f7ef9 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -123,6 +123,7 @@ enum {
struct pxa3xx_nand_info {
struct nand_chip nand_chip;
+ struct nand_hw_control controller;
struct platform_device *pdev;
struct pxa3xx_nand_cmdset *cmdset;
@@ -157,6 +158,7 @@ struct pxa3xx_nand_info {
int use_ecc; /* use HW ECC ? */
int use_dma; /* use DMA ? */
+ int is_ready;
unsigned int page_size; /* page size of attached chip */
unsigned int data_size; /* data size in FIFO */
@@ -223,6 +225,8 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
/* Define a default flash type setting serve as flash detecting only */
#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
+static const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+
#define NDTR0_tCH(c) (min((c), 7) << 19)
#define NDTR0_tCS(c) (min((c), 7) << 16)
#define NDTR0_tWH(c) (min((c), 7) << 11)
@@ -437,8 +441,10 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
info->state = STATE_CMD_DONE;
is_completed = 1;
}
- if (status & NDSR_FLASH_RDY)
+ if (status & NDSR_FLASH_RDY) {
+ info->is_ready = 1;
info->state = STATE_READY;
+ }
if (status & NDSR_WRCMDREQ) {
nand_writel(info, NDSR, NDSR_WRCMDREQ);
@@ -487,6 +493,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
info->buf_count = 0;
info->oob_size = 0;
info->use_ecc = 0;
+ info->is_ready = 0;
info->retcode = ERR_NONE;
switch (command) {
@@ -849,42 +856,6 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
return 0;
}
-static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
- const struct pxa3xx_nand_platform_data *pdata)
-{
- const struct pxa3xx_nand_flash *f;
- uint32_t id = -1;
- int i;
-
- if (pdata->keep_config)
- if (pxa3xx_nand_detect_config(info) == 0)
- return 0;
-
- /* we use default timing to detect id */
- f = DEFAULT_FLASH_TYPE;
- pxa3xx_nand_config_flash(info, f);
- pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0);
- id = *((uint16_t *)(info->data_buff));
-
- for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
- /* we first choose the flash definition from platfrom */
- if (i < pdata->num_flash)
- f = pdata->flash + i;
- else
- f = &builtin_flash_types[i - pdata->num_flash + 1];
- if (f->chip_id == id) {
- dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
- pxa3xx_nand_config_flash(info, f);
- return 0;
- }
- }
-
- dev_warn(&info->pdev->dev,
- "failed to detect configured nand flash; found %04x instead of\n",
- id);
- return -ENODEV;
-}
-
/* the maximum possible buffer size for large page with OOB data
* is: 2048 + 64 = 2112 bytes, allocate a page here for both the
* data buffer and the DMA descriptor
@@ -926,56 +897,107 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
return 0;
}
-static struct nand_ecclayout hw_smallpage_ecclayout = {
- .eccbytes = 6,
- .eccpos = {8, 9, 10, 11, 12, 13 },
- .oobfree = { {2, 6} }
-};
+static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
+{
+ struct mtd_info *mtd = info->mtd;
+ struct nand_chip *chip = mtd->priv;
-static struct nand_ecclayout hw_largepage_ecclayout = {
- .eccbytes = 24,
- .eccpos = {
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63},
- .oobfree = { {2, 38} }
-};
+ /* use the common timing to make a try */
+ pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+ chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+ if (info->is_ready)
+ return 1;
+ else
+ return 0;
+}
-static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
- struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_scan(struct mtd_info *mtd)
{
- struct nand_chip *this = &info->nand_chip;
-
- this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;
- this->options |= NAND_NO_AUTOINCR;
-
- this->waitfunc = pxa3xx_nand_waitfunc;
- this->select_chip = pxa3xx_nand_select_chip;
- this->dev_ready = pxa3xx_nand_dev_ready;
- this->cmdfunc = pxa3xx_nand_cmdfunc;
- this->ecc.read_page = pxa3xx_nand_read_page_hwecc;
- this->ecc.write_page = pxa3xx_nand_write_page_hwecc;
- this->read_word = pxa3xx_nand_read_word;
- this->read_byte = pxa3xx_nand_read_byte;
- this->read_buf = pxa3xx_nand_read_buf;
- this->write_buf = pxa3xx_nand_write_buf;
- this->verify_buf = pxa3xx_nand_verify_buf;
-
- this->ecc.mode = NAND_ECC_HW;
- this->ecc.size = info->page_size;
-
- if (info->page_size == 2048)
- this->ecc.layout = &hw_largepage_ecclayout;
- else
- this->ecc.layout = &hw_smallpage_ecclayout;
+ struct pxa3xx_nand_info *info = mtd->priv;
+ struct platform_device *pdev = info->pdev;
+ struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+ const struct pxa3xx_nand_flash *f = NULL;
+ struct nand_chip *chip = mtd->priv;
+ uint32_t id = -1;
+ int i, ret;
+
+ if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
+ return 0;
+
+ ret = pxa3xx_nand_sensing(info);
+ if (!ret) {
+ kfree(mtd);
+ info->mtd = NULL;
+ printk(KERN_INFO "There is no nand chip on cs 0!\n");
+
+ return -EINVAL;
+ }
+
+ chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
+ id = *((uint16_t *)(info->data_buff));
+ if (id != 0)
+ printk(KERN_INFO "Detect a flash id %x\n", id);
+ else {
+ kfree(mtd);
+ info->mtd = NULL;
+ printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n");
+
+ return -EINVAL;
+ }
- this->chip_delay = 25;
+ for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
+ if (i < pdata->num_flash)
+ f = pdata->flash + i;
+ else
+ f = &builtin_flash_types[i - pdata->num_flash + 1];
+
+ /* find the chip in default list */
+ if (f->chip_id == id) {
+ pxa3xx_nand_config_flash(info, f);
+ mtd->writesize = f->page_size;
+ mtd->writesize_shift = ffs(mtd->writesize) - 1;
+ mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
+ mtd->oobsize = mtd->writesize / 32;
+ mtd->erasesize = f->page_size * f->page_per_block;
+ mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
+ mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
+
+ mtd->name = mtd_names[0];
+ break;
+ }
+ }
+
+ if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash)) {
+ kfree(mtd);
+ info->mtd = NULL;
+ printk(KERN_ERR "ERROR!! flash not defined!!!\n");
+
+ return -EINVAL;
+ }
+
+ chip->ecc.mode = NAND_ECC_HW;
+ chip->ecc.size = f->page_size;
+ chip->chipsize = (uint64_t)f->num_blocks * f->page_per_block
+ * f->page_size;
+ mtd->size = chip->chipsize;
+
+ /* Calculate the address shift from the page size */
+ chip->page_shift = ffs(mtd->writesize) - 1;
+ chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1;
+ chip->numchips = 1;
+ chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1;
+
+ chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
+ chip->options |= NAND_NO_AUTOINCR;
+ chip->options |= NAND_NO_READRDY;
+
+ return nand_scan_tail(mtd);
}
static struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
{
- struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
struct pxa3xx_nand_info *info;
+ struct nand_chip *chip;
struct mtd_info *mtd;
struct resource *r;
int ret, irq;
@@ -988,12 +1010,27 @@ static struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev
}
info = (struct pxa3xx_nand_info *)(&mtd[1]);
+ chip = (struct nand_chip *)(&mtd[1]);
info->pdev = pdev;
-
- mtd->priv = info;
info->mtd = mtd;
+ mtd->priv = info;
mtd->owner = THIS_MODULE;
+ chip->ecc.read_page = pxa3xx_nand_read_page_hwecc;
+ chip->ecc.write_page = pxa3xx_nand_write_page_hwecc;
+ chip->controller = &info->controller;
+ chip->waitfunc = pxa3xx_nand_waitfunc;
+ chip->select_chip = pxa3xx_nand_select_chip;
+ chip->dev_ready = pxa3xx_nand_dev_ready;
+ chip->cmdfunc = pxa3xx_nand_cmdfunc;
+ chip->read_word = pxa3xx_nand_read_word;
+ chip->read_byte = pxa3xx_nand_read_byte;
+ chip->read_buf = pxa3xx_nand_read_buf;
+ chip->write_buf = pxa3xx_nand_write_buf;
+ chip->verify_buf = pxa3xx_nand_verify_buf;
+
+ spin_lock_init(&chip->controller->lock);
+ init_waitqueue_head(&chip->controller->wq);
info->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(info->clk)) {
dev_err(&pdev->dev, "failed to get nand clock\n");
@@ -1061,21 +1098,12 @@ static struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev
goto fail_free_buf;
}
- ret = pxa3xx_nand_detect_flash(info, pdata);
- if (ret) {
- dev_err(&pdev->dev, "failed to detect flash\n");
- ret = -ENODEV;
- goto fail_free_irq;
- }
-
- pxa3xx_nand_init_mtd(mtd, info);
platform_set_drvdata(pdev, info);
return info;
-fail_free_irq:
- free_irq(irq, info);
fail_free_buf:
+ free_irq(irq, info);
if (use_dma) {
pxa_free_dma(info->data_dma_ch);
dma_free_coherent(&pdev->dev, info->data_buff_size,
@@ -1145,7 +1173,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
if (info == NULL)
return -ENOMEM;
- if (nand_scan(info->mtd, 1)) {
+ if (pxa3xx_nand_scan(info->mtd)) {
dev_err(&pdev->dev, "failed to scan nand\n");
pxa3xx_nand_remove(pdev);
return -ENODEV;
--
1.7.0.4
^ permalink raw reply related
* [PATCH 4/6] pxa3xx_nand: unify prepare command
From: Lei Wen @ 2011-02-18 8:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298019428-7809-1-git-send-email-leiwen@marvell.com>
Make the interface simpler which could make both debug
and enhancement easier.
Signed-off-by: Lei Wen <leiwen@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>
---
drivers/mtd/nand/pxa3xx_nand.c | 286 ++++++++++++++++++++++------------------
1 files changed, 157 insertions(+), 129 deletions(-)
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 04aeea9..0895cf8 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -28,6 +28,7 @@
#define CHIP_DELAY_TIMEOUT (2 * HZ/10)
#define NAND_STOP_DELAY (2 * HZ/50)
+#define PAGE_CHUNK_SIZE (2048)
/* registers and bit definitions */
#define NDCR (0x00) /* Control register */
@@ -77,6 +78,7 @@
#define NDSR_RDDREQ (0x1 << 1)
#define NDSR_WRCMDREQ (0x1)
+#define NDCB0_ST_ROW_EN (0x1 << 26)
#define NDCB0_AUTO_RS (0x1 << 25)
#define NDCB0_CSEL (0x1 << 24)
#define NDCB0_CMD_TYPE_MASK (0x7 << 21)
@@ -319,66 +321,6 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
nand_writel(info, NDSR, NDSR_MASK);
}
-static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
- uint16_t cmd, int column, int page_addr)
-{
- const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
- pxa3xx_set_datasize(info);
-
- /* generate values for NDCBx registers */
- info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
- info->ndcb1 = 0;
- info->ndcb2 = 0;
- info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles);
-
- if (info->col_addr_cycles == 2) {
- /* large block, 2 cycles for column address
- * row address starts from 3rd cycle
- */
- info->ndcb1 |= page_addr << 16;
- if (info->row_addr_cycles == 3)
- info->ndcb2 = (page_addr >> 16) & 0xff;
- } else
- /* small block, 1 cycles for column address
- * row address starts from 2nd cycle
- */
- info->ndcb1 = page_addr << 8;
-
- if (cmd == cmdset->program)
- info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
-}
-
-static void prepare_erase_cmd(struct pxa3xx_nand_info *info,
- uint16_t cmd, int page_addr)
-{
- info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
- info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
- info->ndcb1 = page_addr;
- info->ndcb2 = 0;
-}
-
-static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
-{
- const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-
- info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
- info->ndcb1 = 0;
- info->ndcb2 = 0;
-
- info->oob_size = 0;
- if (cmd == cmdset->read_id) {
- info->ndcb0 |= NDCB0_CMD_TYPE(3) | NDCB0_ADDR_CYC(1);
- info->data_size = 8;
- } else if (cmd == cmdset->read_status) {
- info->ndcb0 |= NDCB0_CMD_TYPE(4);
- info->data_size = 8;
- } else if (cmd == cmdset->reset || cmd == cmdset->lock ||
- cmd == cmdset->unlock) {
- info->ndcb0 |= NDCB0_CMD_TYPE(5);
- } else
- BUG();
-}
-
static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
{
uint32_t ndcr;
@@ -529,81 +471,166 @@ static inline int is_buf_blank(uint8_t *buf, size_t len)
return 1;
}
+static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
+ uint16_t column, int page_addr)
+{
+ uint16_t cmd;
+ int addr_cycle, exec_cmd, ndcb0;
+ struct mtd_info *mtd = info->mtd;
+
+ ndcb0 = 0;
+ addr_cycle = 0;
+ exec_cmd = 1;
+
+ /* reset data and oob column point to handle data */
+ info->buf_start = 0;
+ info->buf_count = 0;
+ info->oob_size = 0;
+ info->use_ecc = 0;
+ info->retcode = ERR_NONE;
+
+ switch (command) {
+ case NAND_CMD_READ0:
+ case NAND_CMD_PAGEPROG:
+ info->use_ecc = 1;
+ case NAND_CMD_READOOB:
+ pxa3xx_set_datasize(info);
+ break;
+ case NAND_CMD_SEQIN:
+ exec_cmd = 0;
+ break;
+ default:
+ info->ndcb1 = 0;
+ info->ndcb2 = 0;
+ break;
+ }
+
+ info->ndcb0 = ndcb0;
+ addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
+ + info->col_addr_cycles);
+
+ switch (command) {
+ case NAND_CMD_READOOB:
+ case NAND_CMD_READ0:
+ cmd = info->cmdset->read1;
+ if (command == NAND_CMD_READOOB)
+ info->buf_start = mtd->writesize + column;
+ else
+ info->buf_start = column;
+
+ if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+ info->ndcb0 |= NDCB0_CMD_TYPE(0)
+ | addr_cycle
+ | (cmd & NDCB0_CMD1_MASK);
+ else
+ info->ndcb0 |= NDCB0_CMD_TYPE(0)
+ | NDCB0_DBC
+ | addr_cycle
+ | cmd;
+
+ case NAND_CMD_SEQIN:
+ /* small page addr setting */
+ if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+ info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+ | (column & 0xFF);
+
+ info->ndcb2 = 0;
+ }
+ else {
+ info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+ | (column & 0xFFFF);
+
+ if (page_addr & 0xFF0000)
+ info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+ else
+ info->ndcb2 = 0;
+ }
+
+ info->buf_count = mtd->writesize + mtd->oobsize;
+ memset(info->data_buff, 0xFF, info->buf_count);
+
+ break;
+
+ case NAND_CMD_PAGEPROG:
+ if (is_buf_blank(info->data_buff, (mtd->writesize + mtd->oobsize))) {
+ exec_cmd = 0;
+ break;
+ }
+
+ cmd = info->cmdset->program;
+ info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+ | NDCB0_AUTO_RS
+ | NDCB0_ST_ROW_EN
+ | NDCB0_DBC
+ | cmd
+ | addr_cycle;
+ break;
+
+ case NAND_CMD_READID:
+ cmd = info->cmdset->read_id;
+ info->buf_count = info->read_id_bytes;
+ info->ndcb0 |= NDCB0_CMD_TYPE(3)
+ | NDCB0_ADDR_CYC(1)
+ | cmd;
+
+ info->data_size = 8;
+ break;
+ case NAND_CMD_STATUS:
+ cmd = info->cmdset->read_status;
+ info->buf_count = 1;
+ info->ndcb0 |= NDCB0_CMD_TYPE(4)
+ | NDCB0_ADDR_CYC(1)
+ | cmd;
+
+ info->data_size = 8;
+ break;
+
+ case NAND_CMD_ERASE1:
+ cmd = info->cmdset->erase;
+ info->ndcb0 |= NDCB0_CMD_TYPE(2)
+ | NDCB0_AUTO_RS
+ | NDCB0_ADDR_CYC(3)
+ | NDCB0_DBC
+ | cmd;
+ info->ndcb1 = page_addr;
+ info->ndcb2 = 0;
+
+ break;
+ case NAND_CMD_RESET:
+ cmd = info->cmdset->reset;
+ info->ndcb0 |= NDCB0_CMD_TYPE(5)
+ | cmd;
+
+ break;
+
+ case NAND_CMD_ERASE2:
+ exec_cmd = 0;
+ break;
+
+ default:
+ exec_cmd = 0;
+ printk(KERN_ERR "pxa3xx-nand: non-supported command %x\n", command);
+ break;
+ }
+
+ return exec_cmd;
+}
+
static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
int column, int page_addr)
{
struct pxa3xx_nand_info *info = mtd->priv;
- const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
- int ret, exec_cmd = 0;
-
- info->use_dma = (use_dma) ? 1 : 0;
- info->use_ecc = 0;
- info->data_size = 0;
- info->state = 0;
- info->retcode = ERR_NONE;
-
- switch (command) {
- case NAND_CMD_READOOB:
- /* disable HW ECC to get all the OOB data */
- info->buf_count = mtd->writesize + mtd->oobsize;
- info->buf_start = mtd->writesize + column;
- memset(info->data_buff, 0xFF, info->buf_count);
-
- prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
- exec_cmd = 1;
- break;
-
- case NAND_CMD_READ0:
- info->use_ecc = 1;
- info->buf_start = column;
- info->buf_count = mtd->writesize + mtd->oobsize;
- memset(info->data_buff, 0xFF, info->buf_count);
+ int ret, exec_cmd;
- prepare_read_prog_cmd(info, cmdset->read1, column, page_addr);
- exec_cmd = 1;
- break;
- case NAND_CMD_SEQIN:
- info->buf_start = column;
- info->buf_count = mtd->writesize + mtd->oobsize;
- memset(info->data_buff, 0xff, info->buf_count);
-
- /* save column/page_addr for next CMD_PAGEPROG */
- info->seqin_column = column;
- info->seqin_page_addr = page_addr;
- break;
- case NAND_CMD_PAGEPROG:
- info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
-
- prepare_read_prog_cmd(info, cmdset->program,
- info->seqin_column, info->seqin_page_addr);
- exec_cmd = 1;
- break;
- case NAND_CMD_ERASE1:
- prepare_erase_cmd(info, cmdset->erase, page_addr);
- exec_cmd = 1;
- break;
- case NAND_CMD_ERASE2:
- break;
- case NAND_CMD_READID:
- case NAND_CMD_STATUS:
- info->use_dma = 0; /* force PIO read */
- info->buf_start = 0;
- info->buf_count = (command == NAND_CMD_READID) ?
- info->read_id_bytes : 1;
-
- prepare_other_cmd(info, (command == NAND_CMD_READID) ?
- cmdset->read_id : cmdset->read_status);
- exec_cmd = 1;
- break;
- case NAND_CMD_RESET:
- prepare_other_cmd(info, cmdset->reset);
- exec_cmd = 1;
- break;
- default:
- printk(KERN_ERR "non-supported command.\n");
- break;
- }
+ /*
+ * if this is a x16 device ,then convert the input
+ * "byte" address into a "word" address appropriate
+ * for indexing a word-oriented device
+ */
+ if (info->reg_ndcr & NDCR_DWIDTH_M)
+ column /= 2;
+ exec_cmd = prepare_command_pool(info, command, column, page_addr);
if (exec_cmd) {
init_completion(&info->cmd_complete);
pxa3xx_nand_start(info);
@@ -920,6 +947,7 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
struct nand_chip *this = &info->nand_chip;
this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;
+ this->options |= NAND_NO_AUTOINCR;
this->waitfunc = pxa3xx_nand_waitfunc;
this->select_chip = pxa3xx_nand_select_chip;
--
1.7.0.4
^ permalink raw reply related
* [PATCH 3/6] pxa3xx_nand: discard wait_for_event, write_cmd, __readid function
From: Lei Wen @ 2011-02-18 8:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298019428-7809-1-git-send-email-leiwen@marvell.com>
Since we have rework the irq process, we don't need additional
delay in wait_for_event. Also write_cmd and __readid is also
discarded for the same reason.
Signed-off-by: Lei Wen <leiwen@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Acked-by: Eric Miao <eric.y.miao@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>
---
drivers/mtd/nand/pxa3xx_nand.c | 77 +---------------------------------------
1 files changed, 1 insertions(+), 76 deletions(-)
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index dac522c..04aeea9 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -258,25 +258,6 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
nand_writel(info, NDTR1CS0, ndtr1);
}
-#define WAIT_EVENT_TIMEOUT 10
-
-static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
-{
- int timeout = WAIT_EVENT_TIMEOUT;
- uint32_t ndsr;
-
- while (timeout--) {
- ndsr = nand_readl(info, NDSR) & NDSR_MASK;
- if (ndsr & event) {
- nand_writel(info, NDSR, ndsr);
- return 0;
- }
- udelay(10);
- }
-
- return -ETIMEDOUT;
-}
-
static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
{
int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
@@ -414,35 +395,6 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
nand_writel(info, NDCR, ndcr | int_mask);
}
-/* NOTE: it is a must to set ND_RUN firstly, then write command buffer
- * otherwise, it does not work
- */
-static int write_cmd(struct pxa3xx_nand_info *info)
-{
- uint32_t ndcr;
-
- /* clear status bits and run */
- nand_writel(info, NDSR, NDSR_MASK);
-
- ndcr = info->reg_ndcr;
-
- ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
- ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
- ndcr |= NDCR_ND_RUN;
-
- nand_writel(info, NDCR, ndcr);
-
- if (wait_for_event(info, NDSR_WRCMDREQ)) {
- printk(KERN_ERR "timed out writing command\n");
- return -ETIMEDOUT;
- }
-
- nand_writel(info, NDCB0, info->ndcb0);
- nand_writel(info, NDCB0, info->ndcb1);
- nand_writel(info, NDCB0, info->ndcb2);
- return 0;
-}
-
static void handle_data_pio(struct pxa3xx_nand_info *info)
{
switch (info->state) {
@@ -779,33 +731,6 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
return 0;
}
-static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
-{
- const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
- uint32_t ndcr;
- uint8_t id_buff[8];
-
- prepare_other_cmd(info, cmdset->read_id);
-
- /* Send command */
- if (write_cmd(info))
- goto fail_timeout;
-
- /* Wait for CMDDM(command done successfully) */
- if (wait_for_event(info, NDSR_RDDREQ))
- goto fail_timeout;
-
- __raw_readsl(info->mmio_base + NDDB, id_buff, 2);
- *id = id_buff[0] | (id_buff[1] << 8);
- return 0;
-
-fail_timeout:
- ndcr = nand_readl(info, NDCR);
- nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
- udelay(10);
- return -ETIMEDOUT;
-}
-
static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
const struct pxa3xx_nand_flash *f)
{
@@ -858,7 +783,7 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
- /* set info fields needed to __readid */
+ /* set info fields needed to read id */
info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
info->reg_ndcr = ndcr;
info->cmdset = &default_cmdset;
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/2] video: Add i.MX23/28 framebuffer driver
From: Shawn Guo @ 2011-02-18 8:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110218083055.GE24426@pengutronix.de>
On Fri, Feb 18, 2011 at 09:30:55AM +0100, Sascha Hauer wrote:
> On Fri, Feb 18, 2011 at 01:24:20PM +0800, Shawn Guo wrote:
> > Sorry, I did not catch up with v1 of the patch set.
> >
> > I have a overall comment on the driver. There is many occurrences
> > of mx23, mx28 etc. throughout the file. IMHO, this is not a good
> > idea. It may be better to use the IP version to handle the
> > differences. In this way, if we have another SoC coming later
> > using the same LCDIF revision as i.MX28. The driver could
> > immediately fit in without code change, ideally.
> >
> > The only problem with version register is that the offset of LCDIF
> > version register is different on i.MX28 from i.MX23.
>
> Can opener inside can. I love it ;)
>
Well, that's the situation we have to deal with.
> > You still need
> > cpu_is_mx23 to read the correct version.
> >
> > BTW, I would try to use cpu_is_mx23 than cpu_is_mx28, as the 'else'
> > of cpu_is_mx23 could _possibly_ cover later SoC as well as i.MX28.
>
> There is only one cpu_is_mx28 in the driver without else. I can switch
> MXSFB_MX23 and MXSFB_MX28 to MXSFB_V3 and MXSFB_V4 if you like it
> better.
>
Yes, I like it better. With it, if we have a new SoC using LCDIF v4,
the driver needs no change.
--
Regards,
Shawn
^ permalink raw reply
* [PATCH 1/6] pxa3xx_nand: make scan procedure more clear
From: Lei Wen @ 2011-02-18 8:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298019428-7809-1-git-send-email-leiwen@marvell.com>
Signed-off-by: Lei Wen <leiwen@marvell.com>
Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com>
Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>
---
drivers/mtd/nand/pxa3xx_nand.c | 98 ++++++++++++++++++++++------------------
1 files changed, 54 insertions(+), 44 deletions(-)
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index ea2c288..6c0587b 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -126,6 +126,7 @@ struct pxa3xx_nand_info {
unsigned int buf_start;
unsigned int buf_count;
+ struct mtd_info *mtd;
/* DMA information */
int drcmr_dat;
int drcmr_cmd;
@@ -1044,34 +1045,26 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
this->chip_delay = 25;
}
-static int pxa3xx_nand_probe(struct platform_device *pdev)
+static struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
{
- struct pxa3xx_nand_platform_data *pdata;
+ struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
struct pxa3xx_nand_info *info;
- struct nand_chip *this;
struct mtd_info *mtd;
struct resource *r;
- int ret = 0, irq;
-
- pdata = pdev->dev.platform_data;
-
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data defined\n");
- return -ENODEV;
- }
+ int ret, irq;
mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
GFP_KERNEL);
if (!mtd) {
dev_err(&pdev->dev, "failed to allocate memory\n");
- return -ENOMEM;
+ return NULL;
}
info = (struct pxa3xx_nand_info *)(&mtd[1]);
info->pdev = pdev;
- this = &info->nand_chip;
mtd->priv = info;
+ info->mtd = mtd;
mtd->owner = THIS_MODULE;
info->clk = clk_get(&pdev->dev, NULL);
@@ -1149,31 +1142,9 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
}
pxa3xx_nand_init_mtd(mtd, info);
+ platform_set_drvdata(pdev, info);
- platform_set_drvdata(pdev, mtd);
-
- if (nand_scan(mtd, 1)) {
- dev_err(&pdev->dev, "failed to scan nand\n");
- ret = -ENXIO;
- goto fail_free_irq;
- }
-
-#ifdef CONFIG_MTD_PARTITIONS
- if (mtd_has_cmdlinepart()) {
- static const char *probes[] = { "cmdlinepart", NULL };
- struct mtd_partition *parts;
- int nr_parts;
-
- nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
-
- if (nr_parts)
- return add_mtd_partitions(mtd, parts, nr_parts);
- }
-
- return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
-#else
- return 0;
-#endif
+ return info;
fail_free_irq:
free_irq(irq, info);
@@ -1193,13 +1164,13 @@ fail_put_clk:
clk_put(info->clk);
fail_free_mtd:
kfree(mtd);
- return ret;
+ return NULL;
}
static int pxa3xx_nand_remove(struct platform_device *pdev)
{
- struct mtd_info *mtd = platform_get_drvdata(pdev);
- struct pxa3xx_nand_info *info = mtd->priv;
+ struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+ struct mtd_info *mtd = info->mtd;
struct resource *r;
int irq;
@@ -1230,11 +1201,50 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
return 0;
}
+static int pxa3xx_nand_probe(struct platform_device *pdev)
+{
+ struct pxa3xx_nand_platform_data *pdata;
+ struct pxa3xx_nand_info *info;
+
+ pdata = pdev->dev.platform_data;
+ if (!pdata) {
+ dev_err(&pdev->dev, "no platform data defined\n");
+ return -ENODEV;
+ }
+
+ info = alloc_nand_resource(pdev);
+ if (info == NULL)
+ return -ENOMEM;
+
+ if (nand_scan(info->mtd, 1)) {
+ dev_err(&pdev->dev, "failed to scan nand\n");
+ pxa3xx_nand_remove(pdev);
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_MTD_PARTITIONS
+ if (mtd_has_cmdlinepart()) {
+ static const char *probes[] = { "cmdlinepart", NULL };
+ struct mtd_partition *parts;
+ int nr_parts;
+
+ nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
+
+ if (nr_parts)
+ return add_mtd_partitions(mtd, parts, nr_parts);
+ }
+
+ return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
+#else
+ return 0;
+#endif
+}
+
#ifdef CONFIG_PM
static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
{
- struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
- struct pxa3xx_nand_info *info = mtd->priv;
+ struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+ struct mtd_info *mtd = info->mtd;
if (info->state != STATE_READY) {
dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
@@ -1246,8 +1256,8 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
static int pxa3xx_nand_resume(struct platform_device *pdev)
{
- struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
- struct pxa3xx_nand_info *info = mtd->priv;
+ struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+ struct mtd_info *mtd = info->mtd;
nand_writel(info, NDTR0CS0, info->ndtr0cs0);
nand_writel(info, NDTR1CS0, info->ndtr1cs0);
--
1.7.0.4
^ permalink raw reply related
* [PATCH V4 0/6] pxa3xx_nand update series set version 4
From: Lei Wen @ 2011-02-18 8:57 UTC (permalink / raw)
To: linux-arm-kernel
Change from previous version:
rework the patch set accroding to Eric's suggestion.
Move the recode judgement to the after command execution.
Lei Wen (6):
pxa3xx_nand: make scan procedure more clear
pxa3xx_nand: rework irq logic
pxa3xx_nand: discard wait_for_event,write_cmd,__readid function
pxa3xx_nand: unify prepare command
pxa3xx_nand: mtd scan id process could be defined by driver itself
pxa3xx_nand: clean the keep configure code
arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 1 +
drivers/mtd/nand/pxa3xx_nand.c | 1010 ++++++++++++--------------
2 files changed, 473 insertions(+), 538 deletions(-)
^ permalink raw reply
* [PATCH 2/2] ARM i.MX23/28: Add framebuffer device support
From: Sascha Hauer @ 2011-02-18 8:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110218061440.GA18085@S2100-06.ap.freescale.net>
On Fri, Feb 18, 2011 at 02:14:41PM +0800, Shawn Guo wrote:
> On Wed, Feb 16, 2011 at 10:56:39AM +0100, Sascha Hauer wrote:
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Cc: Shawn Guo <shawn.guo@freescale.com>
> > ---
> > arch/arm/mach-mxs/clock-mx23.c | 2 +-
> > arch/arm/mach-mxs/clock-mx28.c | 1 +
> > arch/arm/mach-mxs/devices-mx23.h | 4 ++
> > arch/arm/mach-mxs/devices-mx28.h | 4 ++
> > arch/arm/mach-mxs/devices/Kconfig | 4 ++
> > arch/arm/mach-mxs/devices/Makefile | 1 +
> > arch/arm/mach-mxs/devices/platform-mxsfb.c | 46 ++++++++++++++++++++++++++++
> > 7 files changed, 61 insertions(+), 1 deletions(-)
> > create mode 100644 arch/arm/mach-mxs/devices/platform-mxsfb.c
> >
> > diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
> > index ca72a05..bfc7f27 100644
> > --- a/arch/arm/mach-mxs/clock-mx23.c
> > +++ b/arch/arm/mach-mxs/clock-mx23.c
> > @@ -446,7 +446,7 @@ static struct clk_lookup lookups[] = {
> > _REGISTER_CLOCK(NULL, "hclk", hbus_clk)
> > _REGISTER_CLOCK(NULL, "usb", usb_clk)
> > _REGISTER_CLOCK(NULL, "audio", audio_clk)
> > - _REGISTER_CLOCK(NULL, "pwm", pwm_clk)
> Introducing the warning below ...
>
> arch/arm/mach-mxs/clock-mx23.c:430: warning: ?pwm_clk? defined but not used
Right, it was not intended to remove the pwm here. Will fix.
>
> > + _REGISTER_CLOCK("imx23-fb", NULL, lcdif_clk)
> > };
> >
> > static int clk_misc_init(void)
> > diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
> > index fd1c4c5..6a7ebcb 100644
> > --- a/arch/arm/mach-mxs/clock-mx28.c
> > +++ b/arch/arm/mach-mxs/clock-mx28.c
> > @@ -620,6 +620,7 @@ static struct clk_lookup lookups[] = {
> > _REGISTER_CLOCK(NULL, "pwm", pwm_clk)
> > _REGISTER_CLOCK(NULL, "lradc", lradc_clk)
> > _REGISTER_CLOCK(NULL, "spdif", spdif_clk)
> > + _REGISTER_CLOCK("imx28-fb", NULL, lcdif_clk)
> > };
> >
> > static int clk_misc_init(void)
> > diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
> > index 1256788..b9745a2 100644
> > --- a/arch/arm/mach-mxs/devices-mx23.h
> > +++ b/arch/arm/mach-mxs/devices-mx23.h
> > @@ -10,7 +10,11 @@
> > */
> > #include <mach/mx23.h>
> > #include <mach/devices-common.h>
> > +#include <mach/fb.h>
> >
> Why do we have mxsfb platform device code breaking the consistency
> that we are maintaining well so far?
The rule is that we include header files where we need them.
devices-common.h is not touched in this patch and it does not need
mach/fb.h, hence it is not include there.
>
> Generally, we have this header included in devices-common.h
>
> > extern const struct amba_device mx23_duart_device __initconst;
> > #define mx23_add_duart() \
> > mxs_add_duart(&mx23_duart_device)
> > +
> > +struct platform_device *__init mx23_add_mxsfb(
> > + const struct mxsfb_platform_data *pdata);
>
> Generally, this goes to devices-common.h
No, devices-common.h only declares the mxs_* functions. There is no
mxs_add_mxsfb in this patch which indeed would go to devices-common.h
>
> > diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
> > index 33773a6..c902dc7 100644
> > --- a/arch/arm/mach-mxs/devices-mx28.h
> > +++ b/arch/arm/mach-mxs/devices-mx28.h
> > @@ -10,6 +10,7 @@
> > */
> > #include <mach/mx28.h>
> > #include <mach/devices-common.h>
> > +#include <mach/fb.h>
> >
> > extern const struct amba_device mx28_duart_device __initconst;
> > #define mx28_add_duart() \
> > @@ -18,3 +19,6 @@ extern const struct amba_device mx28_duart_device __initconst;
> > extern const struct mxs_fec_data mx28_fec_data[] __initconst;
> > #define mx28_add_fec(id, pdata) \
> > mxs_add_fec(&mx28_fec_data[id], pdata)
> > +
> > +struct platform_device *__init mx28_add_mxsfb(
> > + const struct mxsfb_platform_data *pdata);
>
> ditto
>
> > diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
> > index cf7dc1a..1538cb9 100644
> > --- a/arch/arm/mach-mxs/devices/Kconfig
> > +++ b/arch/arm/mach-mxs/devices/Kconfig
> > @@ -4,3 +4,7 @@ config MXS_HAVE_AMBA_DUART
> >
> > config MXS_HAVE_PLATFORM_FEC
> > bool
> > +
> > +config MXS_HAVE_PLATFORM_MXSFB
> > + bool
> > +
>
> I understand that "mxsfb" was picked up for the device name to
> reflect the driver name. But since this is the device under mach- mxs
> folder, can we simply call it "fb" just like the way you name fb.h?
>
> In this way, we have all mxs platform device naming schema aligned,
> auart, duart, dma, fb, fec, flexcan, mmc ...
I see it the other way round. mach/fb.h is too generic, I would prefer
mach/mxsfb.h to be able to add support for a different framebuffer
later. So I better change fb.h to mxsfb.h.
>
> > diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
> > index d0a09f6..0cf8b48 100644
> > --- a/arch/arm/mach-mxs/devices/Makefile
> > +++ b/arch/arm/mach-mxs/devices/Makefile
> > @@ -1,2 +1,3 @@
> > obj-$(CONFIG_MXS_HAVE_AMBA_DUART) += amba-duart.o
> > obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
> > +obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o
> > diff --git a/arch/arm/mach-mxs/devices/platform-mxsfb.c b/arch/arm/mach-mxs/devices/platform-mxsfb.c
> > new file mode 100644
> > index 0000000..632bbdc
> > --- /dev/null
> > +++ b/arch/arm/mach-mxs/devices/platform-mxsfb.c
> > @@ -0,0 +1,46 @@
> > +/*
> > + * Copyright (C) 2011 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
> > + *
> > + * This program is free software; you can redistribute it and/or modify it under
> > + * the terms of the GNU General Public License version 2 as published by the
> > + * Free Software Foundation.
> > + */
> > +#include <asm/sizes.h>
> > +#include <mach/mx23.h>
> > +#include <mach/mx28.h>
> > +#include <mach/devices-common.h>
> > +#include <mach/fb.h>
>
> Generally, this goes to devices-common.h
>
> > +
> > +#ifdef CONFIG_SOC_IMX23
> > +struct platform_device *__init mx23_add_mxsfb(
> > + const struct mxsfb_platform_data *pdata)
> > +{
> > + struct resource res[] = {
> > + {
> > + .start = MX23_LCDIF_BASE_ADDR,
> > + .end = MX23_LCDIF_BASE_ADDR + SZ_8K - 1,
> > + .flags = IORESOURCE_MEM,
> > + },
> > + };
> > +
> > + return mxs_add_platform_device_dmamask("imx23-fb", -1,
> > + res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
> > +}
> > +#endif /* ifdef CONFIG_SOC_IMX23 */
> > +
> > +#ifdef CONFIG_SOC_IMX28
> > +struct platform_device *__init mx28_add_mxsfb(
> > + const struct mxsfb_platform_data *pdata)
> > +{
> > + struct resource res[] = {
> > + {
> > + .start = MX28_LCDIF_BASE_ADDR,
> > + .end = MX28_LCDIF_BASE_ADDR + SZ_8K - 1,
> > + .flags = IORESOURCE_MEM,
> > + },
> > + };
> > +
> > + return mxs_add_platform_device_dmamask("imx28-fb", -1,
> > + res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
> > +}
> > +#endif /* ifdef CONFIG_SOC_IMX28 */
>
> Generally, we have macro mxs_fb_data_entry and function mxs_add_fb
> in this file. It's nothing but all about consistency. We do not
> want some later coming platform device looking at this as example,
> and bring more inconsistency into mach-mxs platform device codes.
My opinion on this is that we should not use complex ## macro constructs
where not necessary. With a device which is only present once on the SoC
it is not necessary, so I skippped it. And yes, if someone is in the
same situation with a single device on a system, he actually should take
this as an example. So no, I don't agree with you.
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 RESEND 3/4] ARM: imx53_loco: add i2c device support
From: Uwe Kleine-König @ 2011-02-18 8:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1298003777-7687-3-git-send-email-richard.zhao@freescale.com>
On Fri, Feb 18, 2011 at 12:36:16PM +0800, Richard Zhao wrote:
> Signed-off-by: Richard Zhao <richard.zhao@freescale.com>
>
> diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
> index 10b6008..abea297 100644
> --- a/arch/arm/mach-mx5/Kconfig
> +++ b/arch/arm/mach-mx5/Kconfig
> @@ -146,6 +146,7 @@ config MACH_MX53_LOCO
> bool "Support MX53 LOCO platforms"
> select SOC_IMX53
> select IMX_HAVE_PLATFORM_IMX_UART
> + select IMX_HAVE_PLATFORM_IMX_I2C
please keep these sorted alphabetically
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH v2 1/3] dmaengine: mxs-dma: add dma support for i.MX23/28
From: Shawn Guo @ 2011-02-18 8:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201102171538.31061.arnd@arndb.de>
On Thu, Feb 17, 2011 at 03:38:30PM +0100, Arnd Bergmann wrote:
> On Monday 14 February 2011, Shawn Guo wrote:
> > This patch adds dma support for Freescale MXS-based SoC i.MX23/28,
> > including apbh-dma and apbx-dma.
> >
> > * apbh-dma and apbx-dma are supported in the driver as two instances,
> > and have to be filtered by dma clients via device id. It becomes
> > the convention that apbh-dma always gets registered prior to
> > apbx-dma.
> >
> > * apbh-dma is different between mx23 and mx28, hardware version
> > register is used to handle the differences.
> >
> > * mxs-dma supports pio function besides data transfer. The driver
> > uses dma_data_direction DMA_NONE to identify the pio mode, and
> > steals sgl and sg_len to get pio words and numbers from clients.
> >
> > * mxs dmaengine has some very specific features, like sense function
> > and the special NAND support (nand_lock, nand_wait4ready). These
> > are too specific to implemented in generic dmaengine driver.
> >
> > * The driver refers to imx-sdma and only a single descriptor is
> > statically assigned to each channel.
>
> Hi Shawn,
>
Hi Arnd,
> I took a look at this after our discussion about the MMC driver locking
Thanks for reviewing the dma code too.
> problem. My feeling is that you still need to get a better understanding
> of the locking interfaces in Linux.
>
Yes, I'm still learning Linux ;)
> > +struct mxs_dma_ccw {
> > + u32 next;
> > + u16 bits;
> > + u16 xfer_bytes;
> > +#define MAX_XFER_BYTES 0xff00
> > + dma_addr_t bufaddr;
> > +#define MXS_PIO_WORDS 16
> > + u32 pio_words[MXS_PIO_WORDS];
> > +};
>
> Unrelated, but should bufaddr really be dma_addr_t? If this is a hardware
> structure, you should make it u32, because dma_addr_t may be either 32 or
> 64 bit in the future, as we get to multiplatform kernels.
>
OK.
> > +struct mxs_dma_chan {
> > + struct mxs_dma_engine *mxs_dma;
> > + struct dma_chan chan;
> > + struct dma_async_tx_descriptor desc;
> > + struct tasklet_struct tasklet;
> > + spinlock_t lock;
> > + int chan_irq;
> > + struct mxs_dma_ccw *ccw;
> > + dma_addr_t ccw_phys;
> > + dma_cookie_t last_completed;
> > + enum dma_status status;
> > + unsigned int flags;
> > +#define MXS_DMA_SG_LOOP (1 << 0)
> > +};
> > +
> > +struct mxs_dma_engine {
> > + int dev_id;
> > + unsigned int version;
> > + void __iomem *base;
> > + struct clk *clk;
> > + struct dma_device dma_device;
> > + struct device_dma_parameters dma_parms;
> > +#define MXS_DMA_CHANNELS 16
> > + struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS];
> > +};
>
> So you have locking per channel, but there is no lock in the dma engine
> structure locking the global fields. This is probably fine.
>
> > +static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
> > +{
> > + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
> > + int chan_id = mxs_chan->chan.chan_id;
> > +
> > + if (dma_is_apbh() && apbh_is_old())
> > + __mxs_setl(1 << (chan_id + BP_APBH_CTRL0_RESET_CHANNEL),
> > + mxs_dma->base + HW_APBHX_CTRL0);
> > + else
> > + __mxs_setl(1 << (chan_id + BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL),
> > + mxs_dma->base + HW_APBHX_CHANNEL_CTRL);
> > +}
> > +
> > +static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
> > +{
> > + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
> > + int chan_id = mxs_chan->chan.chan_id;
> > +
> > + /* set cmd_addr up */
> > + __raw_writel(mxs_chan->ccw_phys,
> > + mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
> > +
> > + /* enable apbh channel clock */
> > + if (dma_is_apbh()) {
> > + if (apbh_is_old())
> > + __mxs_clrl(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
> > + mxs_dma->base + HW_APBHX_CTRL0);
> > + else
> > + __mxs_clrl(1 << chan_id, mxs_dma->base + HW_APBHX_CTRL0);
> > + }
> > +
> > + /* write 1 to SEMA to kick off the channel */
> > + __raw_writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id));
> > +}
>
> Just like the MMC driver, you also use __raw_writel(). If you have to do
> that, please encapsulate the access into a wrapper function that adds
> all the necessary serialization and add a comment explaining why you
> cannot use writel()/writel_relaxed().
>
> Or just use writel().
>
OK. Will change to readl/writel pair.
> > +static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
> > +{
> > + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
> > + int chan_id = mxs_chan->chan.chan_id;
> > +
> > + /* disable apbh channel clock */
> > + if (dma_is_apbh()) {
> > + if (apbh_is_old())
> > + __mxs_setl(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
> > + mxs_dma->base + HW_APBHX_CTRL0);
> > + else
> > + __mxs_setl(1 << chan_id, mxs_dma->base + HW_APBHX_CTRL0);
> > + }
> > +
> > + mxs_chan->status = DMA_SUCCESS;
> > +}
> > +
> > +static void mxs_dma_pause_chan(struct mxs_dma_chan *mxs_chan)
> > +{
> > + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
> > + int chan_id = mxs_chan->chan.chan_id;
> > +
> > + /* freeze the channel */
> > + if (dma_is_apbh() && apbh_is_old())
> > + __mxs_setl(1 << chan_id, mxs_dma->base + HW_APBHX_CTRL0);
> > + else
> > + __mxs_setl(1 << chan_id, mxs_dma->base + HW_APBHX_CHANNEL_CTRL);
> > +
> > + mxs_chan->status = DMA_PAUSED;
> > +}
> > +
> > +static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan)
> > +{
> > + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
> > + int chan_id = mxs_chan->chan.chan_id;
> > +
> > + /* unfreeze the channel */
> > + if (dma_is_apbh() && apbh_is_old())
> > + __mxs_clrl(1 << chan_id, mxs_dma->base + HW_APBHX_CTRL0);
> > + else
> > + __mxs_clrl(1 << chan_id, mxs_dma->base + HW_APBHX_CHANNEL_CTRL);
> > +
> > + mxs_chan->status = DMA_IN_PROGRESS;
> > +}
>
> Should these take the spinlock? What if they are called simultaneously on
> multiple CPUs, or while the interrupt handler is running on another CPU?
>
> Without a lock, another thread might see an incorrect value of mxs_chan->status.
>
The mxs dma hardware somehow simplified the design to dedicate each
channel to a specific client device, e.g. mmc 0 has to use channel 0.
And I simplified the driver design accordingly with less locking
since only that specific client device will access the channel, in
which case the situation you are concerning very likely will not
happen.
> > +static dma_cookie_t mxs_dma_assign_cookie(struct mxs_dma_chan *mxs_chan)
> > +{
> > + dma_cookie_t cookie = mxs_chan->chan.cookie;
> > +
> > + if (++cookie < 0)
> > + cookie = 1;
> > +
> > + mxs_chan->chan.cookie = cookie;
> > + mxs_chan->desc.cookie = cookie;
> > +
> > + return cookie;
> > +}
> > +
> > +static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan)
> > +{
> > + return container_of(chan, struct mxs_dma_chan, chan);
> > +}
> > +
> > +static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
> > +{
> > + struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(tx->chan);
> > + dma_cookie_t cookie;
> > + unsigned long flags;
> > +
> > + spin_lock_irqsave(&mxs_chan->lock, flags);
> > +
> > + cookie = mxs_dma_assign_cookie(mxs_chan);
> > +
> > + mxs_dma_enable_chan(mxs_chan);
> > +
> > + spin_unlock_irqrestore(&mxs_chan->lock, flags);
> > +
> > + return cookie;
> > +}
>
> Just like the MMC driver, you use spin_lock_irqsave() in the functions that
> are called by other drivers, but then don't actually lock in the interrupt
> handler. This is clearly wrong, as I explained before:
>
> The interrupt handler may already be running on another CPU, so it
> is not at all serialized with this code.
>
I may be wrong on this point, but spin_lock_irqsave/irqrestore pair
is only for the protection you described? I learnt that the pair
should be used to protect the critical region, where I'm not sure
if it's called from interrupt context. Here I'm intending to protect
the dma registers accessed in mxs_dma_enable_chan.
> > +static void mxs_dma_tasklet(unsigned long data)
> > +{
> > + struct mxs_dma_chan *mxs_chan = (struct mxs_dma_chan *) data;
> > + unsigned long flags;
> > +
> > + spin_lock_irqsave(&mxs_chan->lock, flags);
> > +
> > + if (mxs_chan->desc.callback)
> > + mxs_chan->desc.callback(mxs_chan->desc.callback_param);
> > +
> > + if (mxs_chan->status == DMA_SUCCESS)
> > + mxs_chan->last_completed = mxs_chan->desc.cookie;
> > +
> > + spin_unlock_irqrestore(&mxs_chan->lock, flags);
> > +}
>
> Here is a different problem. The entire tasklet has interrupts
> disabled and holds the spinlock that the interrupt handler does
> not hold.
>
> This actually makes the tasklet a stricter context than the
> actual interrupt handler, defeating the purpose of tasklets
> (i.e. that you can run code without disabling interrupts).
>
> I don't know what the rules for dmaengine callbacks are regarding
> the context in which they are called, but it seems you should
> either get rid of the spin_lock_irqsave here or do everything
> from the interrupt handler.
>
> That leaves the last_completed variable. This apparently
> needs to be protected using a spinlock, because
> it can be read from other tasks calling mxs_dma_tx_status,
> which in turn does not take the lock, so that is broken, too.
>
Thanks for teaching. I intend to take the fix that Russell offered.
(Thanks, Russell). Does that look good to you, or spin_lock_bh
version should be used than spin_lock_irqsave?
--
Regards,
Shawn
^ permalink raw reply
* [PATCH 16/17] mc13xxx: mfd_cell is now implicitly available to drivers
From: Uwe Kleine-König @ 2011-02-18 8:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110216090036.6fffed34@debxo>
On Wed, Feb 16, 2011 at 09:00:36AM -0800, Andres Salomon wrote:
> On Wed, 16 Feb 2011 10:41:54 +0100
> Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de> wrote:
>
> > On Fri, Feb 11, 2011 at 06:19:21PM -0800, Andres Salomon wrote:
> > >
> > > The cell's platform_data is now accessed with a helper function;
> > > change clients to use that, and remove the now-unused data_size.
> > >
> > > Note that mfd-core no longer makes a copy of platform_data, but the
> > why was this changed and where? I'm not able to find your complete
> > series via gmane.
>
> http://permalink.gmane.org/gmane.linux.kernel/1099164
I still don't get the motivation of your patch set. For drivers that
don't need the mfd_cells you introduce another level of indirection.
And drivers that want to use mfd_cells as platform_data, they can
already now.
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-K?nig |
Industrial Linux Solutions | http://www.pengutronix.de/ |
^ permalink raw reply
* [PATCH v2 09/13] can: pruss CAN driver.
From: Marc Kleine-Budde @ 2011-02-18 8:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <184FA07B783D4F5FAAC09D5C11737A3F@subhasishg>
On 02/18/2011 09:15 AM, Subhasish Ghosh wrote:
>> On 02/18/2011 08:07 AM, Subhasish Ghosh wrote:
>>> --------------------------------------------------
>>> From: "Kurt Van Dijck" <kurt.van.dijck@eia.be>
>>
>> ...
>>>>> + /* register interrupt handler */
>>>>> + err = request_irq(priv->trx_irq, &omapl_rx_can_intr, IRQF_SHARED,
>>>>> + "pru_can_irq", ndev);
>>>> you're doing a lot of work _in_ the irq handler. Maybe threaded irq?
>>>>
>>> SG -Ok, will do
>>
>> No, please use NAPI instead.
>
> We are using h/w filters, so the number of interrupts coming into the
> processor are not hogging it.
> I feel that we may not require an interrupt mitigation.
As davem stated the other day, all new drivers should use NAPI.
regards, Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 262 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110218/ce017071/attachment.sig>
^ permalink raw reply
* [PATCH 1/2] video: Add i.MX23/28 framebuffer driver
From: Sascha Hauer @ 2011-02-18 8:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110218052418.GA18053@S2100-06.ap.freescale.net>
On Fri, Feb 18, 2011 at 01:24:20PM +0800, Shawn Guo wrote:
> Sorry, I did not catch up with v1 of the patch set.
>
> I have a overall comment on the driver. There is many occurrences
> of mx23, mx28 etc. throughout the file. IMHO, this is not a good
> idea. It may be better to use the IP version to handle the
> differences. In this way, if we have another SoC coming later
> using the same LCDIF revision as i.MX28. The driver could
> immediately fit in without code change, ideally.
>
> The only problem with version register is that the offset of LCDIF
> version register is different on i.MX28 from i.MX23.
Can opener inside can. I love it ;)
> You still need
> cpu_is_mx23 to read the correct version.
>
> BTW, I would try to use cpu_is_mx23 than cpu_is_mx28, as the 'else'
> of cpu_is_mx23 could _possibly_ cover later SoC as well as i.MX28.
There is only one cpu_is_mx28 in the driver without else. I can switch
MXSFB_MX23 and MXSFB_MX28 to MXSFB_V3 and MXSFB_V4 if you like it
better.
--
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 v2 09/13] can: pruss CAN driver.
From: Subhasish Ghosh @ 2011-02-18 8:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D5E2570.10108@grandegger.com>
> On 02/18/2011 08:07 AM, Subhasish Ghosh wrote:
>> --------------------------------------------------
>> From: "Kurt Van Dijck" <kurt.van.dijck@eia.be>
>
> ...
>>>> + /* register interrupt handler */
>>>> + err = request_irq(priv->trx_irq, &omapl_rx_can_intr, IRQF_SHARED,
>>>> + "pru_can_irq", ndev);
>>> you're doing a lot of work _in_ the irq handler. Maybe threaded irq?
>>>
>> SG -Ok, will do
>
> No, please use NAPI instead.
We are using h/w filters, so the number of interrupts coming into the
processor are not hogging it.
I feel that we may not require an interrupt mitigation.
-Subhasish
^ permalink raw reply
* [PATCH 2/4] V4L: mx3_camera: convert to videobuf2
From: Guennadi Liakhovetski @ 2011-02-18 8:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <Pine.LNX.4.64.1102180857360.1851@axis700.grange>
Now that soc-camera supports videobuf API v1 and v2, camera-host drivers
can be converted to videobuf2 individually. This patch converts the
mx3_camera driver.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
This one is also on git.linuxtv.org already.
drivers/media/video/mx3_camera.c | 342 ++++++++++++++++----------------------
1 files changed, 143 insertions(+), 199 deletions(-)
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index b9cb4a4..d61ff0d 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -21,7 +21,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-dev.h>
-#include <media/videobuf-dma-contig.h>
+#include <media/videobuf2-dma-contig.h>
#include <media/soc_camera.h>
#include <media/soc_mediabus.h>
@@ -62,10 +62,16 @@
#define MAX_VIDEO_MEM 16
+enum csi_buffer_state {
+ CSI_BUF_NEEDS_INIT,
+ CSI_BUF_PREPARED,
+};
+
struct mx3_camera_buffer {
/* common v4l buffer stuff -- must be first */
- struct videobuf_buffer vb;
- enum v4l2_mbus_pixelcode code;
+ struct vb2_buffer vb;
+ enum csi_buffer_state state;
+ struct list_head queue;
/* One descriptot per scatterlist (per frame) */
struct dma_async_tx_descriptor *txd;
@@ -108,6 +114,9 @@ struct mx3_camera_dev {
struct list_head capture;
spinlock_t lock; /* Protects video buffer lists */
struct mx3_camera_buffer *active;
+ struct vb2_alloc_ctx *alloc_ctx;
+ enum v4l2_field field;
+ int sequence;
/* IDMAC / dmaengine interface */
struct idmac_channel *idmac_channel[1]; /* We need one channel */
@@ -130,6 +139,11 @@ static void csi_reg_write(struct mx3_camera_dev *mx3, u32 value, off_t reg)
__raw_writel(value, mx3->base + reg);
}
+static struct mx3_camera_buffer *to_mx3_vb(struct vb2_buffer *vb)
+{
+ return container_of(vb, struct mx3_camera_buffer, vb);
+}
+
/* Called from the IPU IDMAC ISR */
static void mx3_cam_dma_done(void *arg)
{
@@ -137,20 +151,20 @@ static void mx3_cam_dma_done(void *arg)
struct dma_chan *chan = desc->txd.chan;
struct idmac_channel *ichannel = to_idmac_chan(chan);
struct mx3_camera_dev *mx3_cam = ichannel->client;
- struct videobuf_buffer *vb;
dev_dbg(chan->device->dev, "callback cookie %d, active DMA 0x%08x\n",
desc->txd.cookie, mx3_cam->active ? sg_dma_address(&mx3_cam->active->sg) : 0);
spin_lock(&mx3_cam->lock);
if (mx3_cam->active) {
- vb = &mx3_cam->active->vb;
-
- list_del_init(&vb->queue);
- vb->state = VIDEOBUF_DONE;
- do_gettimeofday(&vb->ts);
- vb->field_count++;
- wake_up(&vb->done);
+ struct vb2_buffer *vb = &mx3_cam->active->vb;
+ struct mx3_camera_buffer *buf = to_mx3_vb(vb);
+
+ list_del_init(&buf->queue);
+ do_gettimeofday(&vb->v4l2_buf.timestamp);
+ vb->v4l2_buf.field = mx3_cam->field;
+ vb->v4l2_buf.sequence = mx3_cam->sequence++;
+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
}
if (list_empty(&mx3_cam->capture)) {
@@ -165,38 +179,10 @@ static void mx3_cam_dma_done(void *arg)
}
mx3_cam->active = list_entry(mx3_cam->capture.next,
- struct mx3_camera_buffer, vb.queue);
- mx3_cam->active->vb.state = VIDEOBUF_ACTIVE;
+ struct mx3_camera_buffer, queue);
spin_unlock(&mx3_cam->lock);
}
-static void free_buffer(struct videobuf_queue *vq, struct mx3_camera_buffer *buf)
-{
- struct soc_camera_device *icd = vq->priv_data;
- struct videobuf_buffer *vb = &buf->vb;
- struct dma_async_tx_descriptor *txd = buf->txd;
- struct idmac_channel *ichan;
-
- BUG_ON(in_interrupt());
-
- dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
- vb, vb->baddr, vb->bsize);
-
- /*
- * This waits until this buffer is out of danger, i.e., until it is no
- * longer in STATE_QUEUED or STATE_ACTIVE
- */
- videobuf_waiton(vq, vb, 0, 0);
- if (txd) {
- ichan = to_idmac_chan(txd->chan);
- async_tx_ack(txd);
- }
- videobuf_dma_contig_free(vq, vb);
- buf->txd = NULL;
-
- vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
/*
* Videobuf operations
*/
@@ -205,10 +191,11 @@ static void free_buffer(struct videobuf_queue *vq, struct mx3_camera_buffer *buf
* Calculate the __buffer__ (not data) size and number of buffers.
* Called with .vb_lock held
*/
-static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
- unsigned int *size)
+static int mx3_videobuf_setup(struct vb2_queue *vq,
+ unsigned int *count, unsigned int *num_planes,
+ unsigned long sizes[], void *alloc_ctxs[])
{
- struct soc_camera_device *icd = vq->priv_data;
+ struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
@@ -220,104 +207,68 @@ static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
if (!mx3_cam->idmac_channel[0])
return -EINVAL;
- *size = bytes_per_line * icd->user_height;
+ *num_planes = 1;
+
+ mx3_cam->sequence = 0;
+ sizes[0] = bytes_per_line * icd->user_height;
+ alloc_ctxs[0] = mx3_cam->alloc_ctx;
if (!*count)
*count = 32;
- if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
- *count = MAX_VIDEO_MEM * 1024 * 1024 / *size;
+ if (sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024)
+ *count = MAX_VIDEO_MEM * 1024 * 1024 / sizes[0];
return 0;
}
/* Called with .vb_lock held */
-static int mx3_videobuf_prepare(struct videobuf_queue *vq,
- struct videobuf_buffer *vb, enum v4l2_field field)
+static int mx3_videobuf_prepare(struct vb2_buffer *vb)
{
- struct soc_camera_device *icd = vq->priv_data;
+ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
- struct mx3_camera_buffer *buf =
- container_of(vb, struct mx3_camera_buffer, vb);
+ struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
+ struct scatterlist *sg;
+ struct mx3_camera_buffer *buf;
size_t new_size;
- int ret;
int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
icd->current_fmt->host_fmt);
if (bytes_per_line < 0)
return bytes_per_line;
- new_size = bytes_per_line * icd->user_height;
+ buf = to_mx3_vb(vb);
+ sg = &buf->sg;
- /*
- * I think, in buf_prepare you only have to protect global data,
- * the actual buffer is yours
- */
-
- if (buf->code != icd->current_fmt->code ||
- vb->width != icd->user_width ||
- vb->height != icd->user_height ||
- vb->field != field) {
- buf->code = icd->current_fmt->code;
- vb->width = icd->user_width;
- vb->height = icd->user_height;
- vb->field = field;
- if (vb->state != VIDEOBUF_NEEDS_INIT)
- free_buffer(vq, buf);
- }
+ new_size = bytes_per_line * icd->user_height;
- if (vb->baddr && vb->bsize < new_size) {
- /* User provided buffer, but it is too small */
- ret = -ENOMEM;
- goto out;
+ if (vb2_plane_size(vb, 0) < new_size) {
+ dev_err(icd->dev.parent, "Buffer too small (%lu < %zu)\n",
+ vb2_plane_size(vb, 0), new_size);
+ return -ENOBUFS;
}
- if (vb->state == VIDEOBUF_NEEDS_INIT) {
- struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
- struct scatterlist *sg = &buf->sg;
-
- /*
- * The total size of video-buffers that will be allocated / mapped.
- * *size that we calculated in videobuf_setup gets assigned to
- * vb->bsize, and now we use the same calculation to get vb->size.
- */
- vb->size = new_size;
-
- /* This actually (allocates and) maps buffers */
- ret = videobuf_iolock(vq, vb, NULL);
- if (ret)
- goto fail;
-
- /*
- * We will have to configure the IDMAC channel. It has two slots
- * for DMA buffers, we shall enter the first two buffers there,
- * and then submit new buffers in DMA-ready interrupts
- */
- sg_init_table(sg, 1);
- sg_dma_address(sg) = videobuf_to_dma_contig(vb);
- sg_dma_len(sg) = vb->size;
+ if (buf->state == CSI_BUF_NEEDS_INIT) {
+ sg_dma_address(sg) = (dma_addr_t)icd->vb2_vidq.mem_ops->cookie(
+ vb->planes[0].mem_priv);
+ sg_dma_len(sg) = new_size;
buf->txd = ichan->dma_chan.device->device_prep_slave_sg(
&ichan->dma_chan, sg, 1, DMA_FROM_DEVICE,
DMA_PREP_INTERRUPT);
- if (!buf->txd) {
- ret = -EIO;
- goto fail;
- }
+ if (!buf->txd)
+ return -EIO;
buf->txd->callback_param = buf->txd;
buf->txd->callback = mx3_cam_dma_done;
- vb->state = VIDEOBUF_PREPARED;
+ buf->state = CSI_BUF_PREPARED;
}
- return 0;
+ vb2_set_plane_payload(vb, 0, new_size);
-fail:
- free_buffer(vq, buf);
-out:
- return ret;
+ return 0;
}
static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc)
@@ -338,24 +289,20 @@ static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc)
}
/*
- * Called with .vb_lock mutex held and
- * under spinlock_irqsave(&mx3_cam->lock, ...)
+ * Called with .vb_lock mutex held
*/
-static void mx3_videobuf_queue(struct videobuf_queue *vq,
- struct videobuf_buffer *vb)
+static void mx3_videobuf_queue(struct vb2_buffer *vb)
{
- struct soc_camera_device *icd = vq->priv_data;
+ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
- struct mx3_camera_buffer *buf =
- container_of(vb, struct mx3_camera_buffer, vb);
+ struct mx3_camera_buffer *buf = to_mx3_vb(vb);
struct dma_async_tx_descriptor *txd = buf->txd;
struct idmac_channel *ichan = to_idmac_chan(txd->chan);
struct idmac_video_param *video = &ichan->params.video;
dma_cookie_t cookie;
u32 fourcc = icd->current_fmt->host_fmt->fourcc;
-
- BUG_ON(!irqs_disabled());
+ unsigned long flags;
/* This is the configuration of one sg-element */
video->out_pixel_fmt = fourcc_to_ipu_pix(fourcc);
@@ -365,17 +312,15 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq,
#ifdef DEBUG
/* helps to see what DMA actually has written */
- memset((void *)vb->baddr, 0xaa, vb->bsize);
+ if (vb2_plane_vaddr(vb, 0))
+ memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0));
#endif
- list_add_tail(&vb->queue, &mx3_cam->capture);
+ spin_lock_irqsave(&mx3_cam->lock, flags);
+ list_add_tail(&buf->queue, &mx3_cam->capture);
- if (!mx3_cam->active) {
+ if (!mx3_cam->active)
mx3_cam->active = buf;
- vb->state = VIDEOBUF_ACTIVE;
- } else {
- vb->state = VIDEOBUF_QUEUED;
- }
spin_unlock_irq(&mx3_cam->lock);
@@ -383,67 +328,88 @@ static void mx3_videobuf_queue(struct videobuf_queue *vq,
dev_dbg(icd->dev.parent, "Submitted cookie %d DMA 0x%08x\n",
cookie, sg_dma_address(&buf->sg));
- spin_lock_irq(&mx3_cam->lock);
-
if (cookie >= 0)
return;
- /* Submit error */
- vb->state = VIDEOBUF_PREPARED;
+ spin_lock_irq(&mx3_cam->lock);
- list_del_init(&vb->queue);
+ /* Submit error */
+ list_del_init(&buf->queue);
if (mx3_cam->active == buf)
mx3_cam->active = NULL;
+
+ spin_unlock_irqrestore(&mx3_cam->lock, flags);
+ vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
}
/* Called with .vb_lock held */
-static void mx3_videobuf_release(struct videobuf_queue *vq,
- struct videobuf_buffer *vb)
+static void mx3_videobuf_release(struct vb2_buffer *vb)
{
- struct soc_camera_device *icd = vq->priv_data;
+ struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
- struct mx3_camera_buffer *buf =
- container_of(vb, struct mx3_camera_buffer, vb);
+ struct mx3_camera_buffer *buf = to_mx3_vb(vb);
+ struct dma_async_tx_descriptor *txd = buf->txd;
unsigned long flags;
dev_dbg(icd->dev.parent,
- "Release%s DMA 0x%08x (state %d), queue %sempty\n",
+ "Release%s DMA 0x%08x, queue %sempty\n",
mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg),
- vb->state, list_empty(&vb->queue) ? "" : "not ");
+ list_empty(&buf->queue) ? "" : "not ");
+
spin_lock_irqsave(&mx3_cam->lock, flags);
- if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) &&
- !list_empty(&vb->queue)) {
- vb->state = VIDEOBUF_ERROR;
- list_del_init(&vb->queue);
- if (mx3_cam->active == buf)
- mx3_cam->active = NULL;
+ if (mx3_cam->active == buf)
+ mx3_cam->active = NULL;
+
+ /* Doesn't hurt also if the list is empty */
+ list_del_init(&buf->queue);
+ buf->state = CSI_BUF_NEEDS_INIT;
+
+ if (txd) {
+ buf->txd = NULL;
+ if (mx3_cam->idmac_channel[0])
+ async_tx_ack(txd);
}
+
spin_unlock_irqrestore(&mx3_cam->lock, flags);
- free_buffer(vq, buf);
}
-static struct videobuf_queue_ops mx3_videobuf_ops = {
- .buf_setup = mx3_videobuf_setup,
- .buf_prepare = mx3_videobuf_prepare,
- .buf_queue = mx3_videobuf_queue,
- .buf_release = mx3_videobuf_release,
+static int mx3_videobuf_init(struct vb2_buffer *vb)
+{
+ struct mx3_camera_buffer *buf = to_mx3_vb(vb);
+ /* This is for locking debugging only */
+ INIT_LIST_HEAD(&buf->queue);
+ sg_init_table(&buf->sg, 1);
+
+ buf->state = CSI_BUF_NEEDS_INIT;
+ buf->txd = NULL;
+
+ return 0;
+}
+
+static struct vb2_ops mx3_videobuf_ops = {
+ .queue_setup = mx3_videobuf_setup,
+ .buf_prepare = mx3_videobuf_prepare,
+ .buf_queue = mx3_videobuf_queue,
+ .buf_cleanup = mx3_videobuf_release,
+ .buf_init = mx3_videobuf_init,
+ .wait_prepare = soc_camera_unlock,
+ .wait_finish = soc_camera_lock,
};
-static void mx3_camera_init_videobuf(struct videobuf_queue *q,
+static int mx3_camera_init_videobuf(struct vb2_queue *q,
struct soc_camera_device *icd)
{
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
-
- videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, icd->dev.parent,
- &mx3_cam->lock,
- V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_NONE,
- sizeof(struct mx3_camera_buffer), icd,
- &icd->video_lock);
+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ q->io_modes = VB2_MMAP | VB2_USERPTR;
+ q->drv_priv = icd;
+ q->ops = &mx3_videobuf_ops;
+ q->mem_ops = &vb2_dma_contig_memops;
+ q->buf_struct_size = sizeof(struct mx3_camera_buffer);
+
+ return vb2_queue_init(q);
}
/* First part of ipu_csi_init_interface() */
@@ -538,18 +504,6 @@ static void mx3_camera_remove_device(struct soc_camera_device *icd)
icd->devnum);
}
-static bool channel_change_requested(struct soc_camera_device *icd,
- struct v4l2_rect *rect)
-{
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- struct mx3_camera_dev *mx3_cam = ici->priv;
- struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
-
- /* Do buffers have to be re-allocated or channel re-configured? */
- return ichan && rect->width * rect->height >
- icd->user_width * icd->user_height;
-}
-
static int test_platform_param(struct mx3_camera_dev *mx3_cam,
unsigned char buswidth, unsigned long *flags)
{
@@ -772,18 +726,6 @@ static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam)
struct dma_chan_request rq = {.mx3_cam = mx3_cam,
.id = IDMAC_IC_7};
- if (*ichan) {
- struct videobuf_buffer *vb, *_vb;
- dma_release_channel(&(*ichan)->dma_chan);
- *ichan = NULL;
- mx3_cam->active = NULL;
- list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) {
- list_del_init(&vb->queue);
- vb->state = VIDEOBUF_ERROR;
- wake_up(&vb->done);
- }
- }
-
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
dma_cap_set(DMA_PRIVATE, mask);
@@ -843,19 +785,8 @@ static int mx3_camera_set_crop(struct soc_camera_device *icd,
return ret;
}
- if (mf.width != icd->user_width || mf.height != icd->user_height) {
- /*
- * We now know pixel formats and can decide upon DMA-channel(s)
- * So far only direct camera-to-memory is supported
- */
- if (channel_change_requested(icd, rect)) {
- ret = acquire_dma_channel(mx3_cam);
- if (ret < 0)
- return ret;
- }
-
+ if (mf.width != icd->user_width || mf.height != icd->user_height)
configure_geometry(mx3_cam, mf.width, mf.height);
- }
dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n",
mf.width, mf.height);
@@ -887,10 +818,6 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
stride_align(&pix->width);
dev_dbg(icd->dev.parent, "Set format %dx%d\n", pix->width, pix->height);
- ret = acquire_dma_channel(mx3_cam);
- if (ret < 0)
- return ret;
-
/*
* Might have to perform a complete interface initialisation like in
* ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider
@@ -912,9 +839,16 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
if (mf.code != xlate->code)
return -EINVAL;
+ if (!mx3_cam->idmac_channel[0]) {
+ ret = acquire_dma_channel(mx3_cam);
+ if (ret < 0)
+ return ret;
+ }
+
pix->width = mf.width;
pix->height = mf.height;
pix->field = mf.field;
+ mx3_cam->field = mf.field;
pix->colorspace = mf.colorspace;
icd->current_fmt = xlate;
@@ -991,7 +925,7 @@ static unsigned int mx3_camera_poll(struct file *file, poll_table *pt)
{
struct soc_camera_device *icd = file->private_data;
- return videobuf_poll_stream(file, &icd->vb_vidq, pt);
+ return vb2_poll(&icd->vb2_vidq, file, pt);
}
static int mx3_camera_querycap(struct soc_camera_host *ici,
@@ -1165,7 +1099,7 @@ static struct soc_camera_host_ops mx3_soc_camera_host_ops = {
.set_fmt = mx3_camera_set_fmt,
.try_fmt = mx3_camera_try_fmt,
.get_formats = mx3_camera_get_formats,
- .init_videobuf = mx3_camera_init_videobuf,
+ .init_videobuf2 = mx3_camera_init_videobuf,
.reqbufs = mx3_camera_reqbufs,
.poll = mx3_camera_poll,
.querycap = mx3_camera_querycap,
@@ -1241,6 +1175,12 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev)
soc_host->v4l2_dev.dev = &pdev->dev;
soc_host->nr = pdev->id;
+ mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+ if (IS_ERR(mx3_cam->alloc_ctx)) {
+ err = PTR_ERR(mx3_cam->alloc_ctx);
+ goto eallocctx;
+ }
+
err = soc_camera_host_register(soc_host);
if (err)
goto ecamhostreg;
@@ -1251,6 +1191,8 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev)
return 0;
ecamhostreg:
+ vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx);
+eallocctx:
iounmap(base);
eioremap:
clk_put(mx3_cam->clk);
@@ -1280,6 +1222,8 @@ static int __devexit mx3_camera_remove(struct platform_device *pdev)
if (WARN_ON(mx3_cam->idmac_channel[0]))
dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan);
+ vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx);
+
vfree(mx3_cam);
dmaengine_put();
--
1.7.2.3
^ permalink raw reply related
* [PATCH 4/5] pxa25x_udc: stop handling gpio-vbus internally
From: Eric Miao @ 2011-02-18 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1297686800-27599-5-git-send-email-dbaryshkov@gmail.com>
On Mon, Feb 14, 2011 at 8:33 PM, Dmitry Eremin-Solenikov
<dbaryshkov@gmail.com> wrote:
> Stop handling gpio-vbus internally. All boards that depended on this
> functionality have been converted to use gpio-vbus tranceiver. All
> new boards can use it right from the start. Drop unused code.
>
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
I'm good with the change below. The original intention of is_vbus_present()
is actually to detect if it's connected. A name of is_connected() would be
better, and I'm fine using gadget.speed for this.
David or any other USB people please have a review and give an Ack-by?
I'd like this being merged through the ARM tree as the other four patches
better go there as well.
Thanks
> ---
> ?drivers/usb/gadget/pxa25x_udc.c | ? 76 ++++-----------------------------------
> ?1 files changed, 7 insertions(+), 69 deletions(-)
>
> diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
> index b37f92c..444b60a 100644
> --- a/drivers/usb/gadget/pxa25x_udc.c
> +++ b/drivers/usb/gadget/pxa25x_udc.c
> @@ -139,24 +139,6 @@ static const char ep0name [] = "ep0";
> ?static void pxa25x_ep_fifo_flush (struct usb_ep *ep);
> ?static void nuke (struct pxa25x_ep *, int status);
>
> -/* one GPIO should be used to detect VBUS from the host */
> -static int is_vbus_present(void)
> -{
> - ? ? ? struct pxa2xx_udc_mach_info ? ? ? ? ? ? *mach = the_controller->mach;
> -
> - ? ? ? if (gpio_is_valid(mach->gpio_vbus)) {
> - ? ? ? ? ? ? ? int value = gpio_get_value(mach->gpio_vbus);
> -
> - ? ? ? ? ? ? ? if (mach->gpio_vbus_inverted)
> - ? ? ? ? ? ? ? ? ? ? ? return !value;
> - ? ? ? ? ? ? ? else
> - ? ? ? ? ? ? ? ? ? ? ? return !!value;
> - ? ? ? }
> - ? ? ? if (mach->udc_is_connected)
> - ? ? ? ? ? ? ? return mach->udc_is_connected();
> - ? ? ? return 1;
> -}
> -
> ?/* one GPIO should control a D+ pullup, so host sees this device (or not) */
> ?static void pullup_off(void)
> ?{
> @@ -1055,7 +1037,7 @@ udc_seq_show(struct seq_file *m, void *_d)
> ? ? ? ? ? ? ? ?"%s version: %s\nGadget driver: %s\nHost %s\n\n",
> ? ? ? ? ? ? ? ?driver_name, DRIVER_VERSION SIZE_STR "(pio)",
> ? ? ? ? ? ? ? ?dev->driver ? dev->driver->driver.name : "(none)",
> - ? ? ? ? ? ? ? is_vbus_present() ? "full speed" : "disconnected");
> + ? ? ? ? ? ? ? dev->gadget.speed == USB_SPEED_FULL ? "full speed" : "disconnected");
>
> ? ? ? ?/* registers for device and ep0 */
> ? ? ? ?seq_printf(m,
> @@ -1094,7 +1076,7 @@ udc_seq_show(struct seq_file *m, void *_d)
> ? ? ? ? ? ? ? ? ? ? ? ?(tmp & UDCCFR_ACM) ? " acm" : "");
> ? ? ? ?}
>
> - ? ? ? if (!is_vbus_present() || !dev->driver)
> + ? ? ? if (dev->gadget.speed != USB_SPEED_FULL || !dev->driver)
> ? ? ? ? ? ? ? ?goto done;
>
> ? ? ? ?seq_printf(m, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n",
> @@ -1435,14 +1417,6 @@ lubbock_vbus_irq(int irq, void *_dev)
>
> ?#endif
>
> -static irqreturn_t udc_vbus_irq(int irq, void *_dev)
> -{
> - ? ? ? struct pxa25x_udc ? ? ? *dev = _dev;
> -
> - ? ? ? pxa25x_udc_vbus_session(&dev->gadget, is_vbus_present());
> - ? ? ? return IRQ_HANDLED;
> -}
> -
>
> ?/*-------------------------------------------------------------------------*/
>
> @@ -1766,12 +1740,9 @@ pxa25x_udc_irq(int irq, void *_dev)
> ? ? ? ? ? ? ? ?if (unlikely(udccr & UDCCR_SUSIR)) {
> ? ? ? ? ? ? ? ? ? ? ? ?udc_ack_int_UDCCR(UDCCR_SUSIR);
> ? ? ? ? ? ? ? ? ? ? ? ?handled = 1;
> - ? ? ? ? ? ? ? ? ? ? ? DBG(DBG_VERBOSE, "USB suspend%s\n", is_vbus_present()
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "" : "+disconnect");
> + ? ? ? ? ? ? ? ? ? ? ? DBG(DBG_VERBOSE, "USB suspend\n");
>
> - ? ? ? ? ? ? ? ? ? ? ? if (!is_vbus_present())
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? stop_activity(dev, dev->driver);
> - ? ? ? ? ? ? ? ? ? ? ? else if (dev->gadget.speed != USB_SPEED_UNKNOWN
> + ? ? ? ? ? ? ? ? ? ? ? if (dev->gadget.speed != USB_SPEED_UNKNOWN
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&& dev->driver
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&& dev->driver->suspend)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?dev->driver->suspend(&dev->gadget);
> @@ -1786,8 +1757,7 @@ pxa25x_udc_irq(int irq, void *_dev)
>
> ? ? ? ? ? ? ? ? ? ? ? ?if (dev->gadget.speed != USB_SPEED_UNKNOWN
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?&& dev->driver
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? && dev->driver->resume
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? && is_vbus_present())
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? && dev->driver->resume)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?dev->driver->resume(&dev->gadget);
> ? ? ? ? ? ? ? ?}
>
> @@ -2137,7 +2107,7 @@ static struct pxa25x_udc memory = {
> ?static int __init pxa25x_udc_probe(struct platform_device *pdev)
> ?{
> ? ? ? ?struct pxa25x_udc *dev = &memory;
> - ? ? ? int retval, vbus_irq, irq;
> + ? ? ? int retval, irq;
> ? ? ? ?u32 chiprev;
>
> ? ? ? ?/* insist on Intel/ARM/XScale */
> @@ -2199,19 +2169,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
>
> ? ? ? ?dev->transceiver = otg_get_transceiver();
>
> - ? ? ? if (gpio_is_valid(dev->mach->gpio_vbus)) {
> - ? ? ? ? ? ? ? if ((retval = gpio_request(dev->mach->gpio_vbus,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "pxa25x_udc GPIO VBUS"))) {
> - ? ? ? ? ? ? ? ? ? ? ? dev_dbg(&pdev->dev,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "can't get vbus gpio %d, err: %d\n",
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev->mach->gpio_vbus, retval);
> - ? ? ? ? ? ? ? ? ? ? ? goto err_gpio_vbus;
> - ? ? ? ? ? ? ? }
> - ? ? ? ? ? ? ? gpio_direction_input(dev->mach->gpio_vbus);
> - ? ? ? ? ? ? ? vbus_irq = gpio_to_irq(dev->mach->gpio_vbus);
> - ? ? ? } else
> - ? ? ? ? ? ? ? vbus_irq = 0;
> -
> ? ? ? ?if (gpio_is_valid(dev->mach->gpio_pullup)) {
> ? ? ? ? ? ? ? ?if ((retval = gpio_request(dev->mach->gpio_pullup,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"pca25x_udc GPIO PULLUP"))) {
> @@ -2237,7 +2194,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
> ? ? ? ?udc_disable(dev);
> ? ? ? ?udc_reinit(dev);
>
> - ? ? ? dev->vbus = !!is_vbus_present();
> + ? ? ? dev->vbus = 0;
>
> ? ? ? ?/* irq setup after old hardware state is cleaned up */
> ? ? ? ?retval = request_irq(irq, pxa25x_udc_irq,
> @@ -2273,22 +2230,10 @@ lubbock_fail0:
> ? ? ? ? ? ? ? ?}
> ? ? ? ?} else
> ?#endif
> - ? ? ? if (vbus_irq) {
> - ? ? ? ? ? ? ? retval = request_irq(vbus_irq, udc_vbus_irq,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? IRQF_DISABLED | IRQF_SAMPLE_RANDOM |
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? driver_name, dev);
> - ? ? ? ? ? ? ? if (retval != 0) {
> - ? ? ? ? ? ? ? ? ? ? ? pr_err("%s: can't get irq %i, err %d\n",
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? driver_name, vbus_irq, retval);
> - ? ? ? ? ? ? ? ? ? ? ? goto err_vbus_irq;
> - ? ? ? ? ? ? ? }
> - ? ? ? }
> ? ? ? ?create_debug_files(dev);
>
> ? ? ? ?return 0;
>
> - err_vbus_irq:
> ?#ifdef CONFIG_ARCH_LUBBOCK
> ? ? ? ?free_irq(LUBBOCK_USB_DISC_IRQ, dev);
> ?err_irq_lub:
> @@ -2298,9 +2243,6 @@ lubbock_fail0:
> ? ? ? ?if (gpio_is_valid(dev->mach->gpio_pullup))
> ? ? ? ? ? ? ? ?gpio_free(dev->mach->gpio_pullup);
> ?err_gpio_pullup:
> - ? ? ? if (gpio_is_valid(dev->mach->gpio_vbus))
> - ? ? ? ? ? ? ? gpio_free(dev->mach->gpio_vbus);
> - err_gpio_vbus:
> ? ? ? ?if (dev->transceiver) {
> ? ? ? ? ? ? ? ?otg_put_transceiver(dev->transceiver);
> ? ? ? ? ? ? ? ?dev->transceiver = NULL;
> @@ -2337,10 +2279,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
> ? ? ? ? ? ? ? ?free_irq(LUBBOCK_USB_IRQ, dev);
> ? ? ? ?}
> ?#endif
> - ? ? ? if (gpio_is_valid(dev->mach->gpio_vbus)) {
> - ? ? ? ? ? ? ? free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev);
> - ? ? ? ? ? ? ? gpio_free(dev->mach->gpio_vbus);
> - ? ? ? }
> ? ? ? ?if (gpio_is_valid(dev->mach->gpio_pullup))
> ? ? ? ? ? ? ? ?gpio_free(dev->mach->gpio_pullup);
>
> --
> 1.7.2.3
>
>
^ permalink raw reply
* [PATCH v2 07/13] da850: pruss CAN platform specific changes for gpios.
From: Subhasish Ghosh @ 2011-02-18 7:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D558455.8090709@mvista.com>
--------------------------------------------------
From: "Sergei Shtylyov" <sshtylyov@mvista.com>
Sent: Saturday, February 12, 2011 12:17 AM
To: "Subhasish Ghosh" <subhasish@mistralsolutions.com>
Cc: <davinci-linux-open-source@linux.davincidsp.com>;
<sachi@mistralsolutions.com>; "Russell King" <linux@arm.linux.org.uk>;
"Kevin Hilman" <khilman@deeprootsystems.com>; "Thomas Koeller"
<thomas.koeller@baslerweb.com>; <nsekhar@ti.com>; "open list"
<linux-kernel@vger.kernel.org>; "Victor Rodriguez" <vm.rod25@gmail.com>;
"Cyril Chemparathy" <cyril@ti.com>; <m-watkins@ti.com>;
<linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH v2 07/13] da850: pruss CAN platform specific changes for
gpios.
> Hello.
>
> Subhasish Ghosh wrote:
>
>> This patch adds the GPIOs for the pruss CAN device.
>
>> Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
>
> I still think this patch should be merged with patch 5, and patch 8
> with patch 6...
>
SG -- Ok, Will do.
> WBR, Sergei
^ permalink raw reply
* [PATCH v2 06/13] da850: pruss CAN board specific additions.
From: Subhasish Ghosh @ 2011-02-18 7:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4D5583CF.8010905@mvista.com>
--------------------------------------------------
From: "Sergei Shtylyov" <sshtylyov@mvista.com>
Sent: Saturday, February 12, 2011 12:15 AM
To: "Subhasish Ghosh" <subhasish@mistralsolutions.com>
Cc: <davinci-linux-open-source@linux.davincidsp.com>;
<sachi@mistralsolutions.com>; "Russell King" <linux@arm.linux.org.uk>;
"Kevin Hilman" <khilman@deeprootsystems.com>; <nsekhar@ti.com>; "open list"
<linux-kernel@vger.kernel.org>; <m-watkins@ti.com>;
<linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH v2 06/13] da850: pruss CAN board specific additions.
> Subhasish Ghosh wrote:
>
>> This patch adds the pruss CAN pin mux and registers the device
>> with the pruss mfd driver.
>
>> Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
> [...]
>
>> diff --git a/arch/arm/mach-davinci/board-da850-evm.c
>> b/arch/arm/mach-davinci/board-da850-evm.c
>> index 242d1ed..2ce5536 100644
>> --- a/arch/arm/mach-davinci/board-da850-evm.c
>> +++ b/arch/arm/mach-davinci/board-da850-evm.c
>> @@ -1053,8 +1053,43 @@ static __init int da850_evm_init_cpufreq(void)
> [...]
>> static struct da8xx_pruss_devices pruss_devices[] = {
>> - {.dev_name = NULL,},
>> + {
>> + .dev_name = "da8xx_pruss_can",
>> + .pdata = &can_data,
>> + .pdata_size = sizeof(can_data),
>> + .setup = da850_evm_setup_pruss_can,
>> + },
>> + {
>> + .dev_name = NULL,
>> + },
>
> No need to explicitly initialize to NULL.
SG -- ok, Will remove
>
> WBR, Sergei
^ 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