* [PATCH 0/6] Adding support for SATA in EXYNO5
From: vasanthananthan at gmail.com @ 2012-10-09 11:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Vasanth Ananthan <vasanthananthan@gmail.com>
The following set of patches provides drivers for SATA
and SATA PHY controller and also an interface for the
two entity to interact.
Vasanth Ananthan (6):
ARM: EXYNOS5: Clock settings for SATA and SATA PHY
ARM: EXYNOS5: DT Support for SATA and SATA PHY
DRIVERS: ATA: SATA PHY utility framework
ARM: S3C2410: I2C driver polling mode support
ARM: EYNOS5: SATA controller driver
ARM: EXYNOS5: SATA PHY controller driver
arch/arm/boot/dts/exynos5250-smdk5250.dts | 11 +
arch/arm/boot/dts/exynos5250.dtsi | 20 ++
arch/arm/mach-exynos/clock-exynos5.c | 19 ++-
arch/arm/mach-exynos/include/mach/map.h | 7 +
arch/arm/mach-exynos/include/mach/regs-pmu.h | 3 +
arch/arm/mach-exynos/mach-exynos5-dt.c | 6 +
drivers/ata/Kconfig | 9 +
drivers/ata/Makefile | 1 +
drivers/ata/sata_exynos.c | 274 +++++++++++++++++++++++
drivers/ata/sata_exynos_phy.c | 303 ++++++++++++++++++++++++++
drivers/ata/sata_phy.c | 99 +++++++++
drivers/ata/sata_phy.h | 44 ++++
drivers/i2c/busses/i2c-s3c2410.c | 84 ++++++--
13 files changed, 859 insertions(+), 21 deletions(-)
create mode 100644 drivers/ata/sata_exynos.c
create mode 100644 drivers/ata/sata_exynos_phy.c
create mode 100644 drivers/ata/sata_phy.c
create mode 100644 drivers/ata/sata_phy.h
--
1.7.5.4
^ permalink raw reply
* pm: add suspend_mem and suspend_standby support
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-09 11:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3272225.kVAjWI8INL@vostro.rjw.lan>
On 22:02 Sun 07 Oct , Rafael J. Wysocki wrote:
> On Sunday 07 of October 2012 15:12:01 Jean-Christophe PLAGNIOL-VILLARD wrote:
> > On 00:18 Sun 07 Oct , Rafael J. Wysocki wrote:
> > > On Saturday 06 of October 2012 18:14:29 Jean-Christophe PLAGNIOL-VILLARD wrote:
> > > > Hi,
> > > >
> > > > The following changes since commit 5f3d2f2e1a63679cf1c4a4210f2f1cc2f335bef6:
> > > >
> > > > Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc (2012-10-06 03:16:12 +0900)
> > > >
> > > > are available in the git repository at:
> > > >
> > > >
> > > > git://git.jcrosoft.org/linux-2.6.git tags/pm_suspend_standby_mem
> > > >
> > > > for you to fetch changes up to b73c8f97aa8e720bd3b921159687d00626c99d63:
> > > >
> > > > arm: at91: drop at91_suspend_entering_slow_clock (2012-10-06 18:06:25 +0800)
> > > >
> > > > ----------------------------------------------------------------
> > > > pm: add suspend_mem and suspend_standby support
> > > >
> > > > Today when we go to suspend we can not knwon at drivers level if we go in
> > > > STANDBY or MEM. Fix this by introducing two new callback suspend_mem and
> > > > suspend_standby.
> > >
> > > No way. Device drivers shouldn't be concerned about that.
> > I do need it on at91 as we swith to slow_clock in MEM suspend and some ip
> > need special handling when switching to slow_clock
>
> Well, my answer to that is: please fix your platform code instead of
> hacking the PM core to work around its problems.
how can I fix drivers pm issue when I no way to known at driver level the
real suspend, the PM core is supposed to proivde the right information to the
drivers so the driver can put it's in the right pm mode. If the pm core can not
provide such inforation the PM core is broken as we will have to do dirty
hack.
Any generic framework is supposed to evolve for real user need here I've one
so I udpate the core to mach a need
Best Regards,
J.
^ permalink raw reply
* [PATCH v3] GPIO: Add support for GPIO on CLPS711X-target platform
From: Linus Walleij @ 2012-10-09 11:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349106153-27371-1-git-send-email-shc_work@mail.ru>
On Mon, Oct 1, 2012 at 5:42 PM, Alexander Shiyan <shc_work@mail.ru> wrote:
> The CLPS711X CPUs provide some GPIOs for use in the system. This
> driver provides support for these via gpiolib. Due to platform
> limitations, driver does not support interrupts, only inputs and
> outputs.
>
> Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
I agree with Russell's comment that all register access macros need
to be pushed down to drivers/gpio/gpio-clps711x.c.
Preferably they should also be replaced by register #defines
and ioremap:ed accesses but I'm not going to be pushy about
that since the driver certainly looks way better after this than
before, so it can be fixed up later.
Yours,
Linus Walleij
^ permalink raw reply
* Booting vanilla kernel on the beaglebone
From: Richard Cochran @ 2012-10-09 11:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <79CD15C6BA57404B839C016229A409A83EB39D66@DBDE01.ent.ti.com>
On Tue, Oct 09, 2012 at 11:19:28AM +0000, Hiremath, Vaibhav wrote:
> On Tue, Oct 09, 2012 at 16:30:50, Richard Cochran wrote:
> > On Tue, Oct 09, 2012 at 05:57:22AM +0000, Hiremath, Vaibhav wrote:
> > >
> > > I use omap2plus_defconfig + CONFIG_ARM_APPENDED_DTB + CONFIG_ARM_ATAG_DTB_COMPAT and nothing more.
> > ^
> > -----------------------------------------+ ???
> >
> > But in the u-boot console example you post, you load the dtb into
> > memory.
> >
>
> Its standard mechanism to boot kernel with DT and it is nothing to do
> with .config. as mentioned before I have already submitted patch to add dtb
> target to 'make dtbs'.
You say that you use CONFIG_ARM_APPENDED_DTB, which means:
CONFIG_ARM_APPENDED_DTB:
With this option, the boot code will look for a device tree binary
(DTB) appended to zImage
(e.g. cat zImage <filename>.dtb > zImage_w_dtb).
This is meant as a backward compatibility convenience for those
systems with a bootloader that can't be upgraded to accommodate
the documented boot protocol using a device tree.
But in the example you gave, you seem to load the dtb in the "normal"
way, with a dtb-aware u-boot.
So how do you boot this? With the APPENDED hack? Or just using a
recent u-boot?
Thanks,
Richard
^ permalink raw reply
* [PATCH 1/1] spi:clk: preparation for switch to common clock framework
From: Sekhar Nori @ 2012-10-09 11:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1347900122-25101-2-git-send-email-m-karicheri2@ti.com>
On 9/17/2012 10:12 PM, Murali Karicheri wrote:
> As a first step towards migrating davinci platforms to use common clock
> framework, replace all instances of clk_enable() with clk_prepare_enable()
> and clk_disable() with clk_disable_unprepare(). Until the platform is
> switched to use the CONFIG_HAVE_CLK_PREPARE Kconfig variable, this just
> adds a might_sleep() call and would work without any issues.
>
> This will make it easy later to switch to common clk based implementation
> of clk driver from DaVinci specific driver.
>
> Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
> Reviewed-by: Mike Turquette <mturquette@linaro.org>
This patch had to be applied manually and with some fuzz when I applied
it to latest linus/master. There were no conflicts though and once I
applied it, I was able to test SPI flash on DA850 EVM successfully using it.
Acked-by: Sekhar Nori <nsekhar@ti.com>
I am hoping this patch can still go in v3.7. I realize we are in the
middle of the merge window though.
Thanks,
Sekhar
^ permalink raw reply
* Booting vanilla kernel on the beaglebone
From: Hiremath, Vaibhav @ 2012-10-09 11:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121009110049.GB2274@netboy.at.omicron.at>
On Tue, Oct 09, 2012 at 16:30:50, Richard Cochran wrote:
> On Tue, Oct 09, 2012 at 05:57:22AM +0000, Hiremath, Vaibhav wrote:
> > On Tue, Oct 09, 2012 at 00:46:57, Richard Cochran wrote:
> > > 2. Can you post your .config?
> > >
> >
> > I use omap2plus_defconfig + CONFIG_ARM_APPENDED_DTB + CONFIG_ARM_ATAG_DTB_COMPAT and nothing more.
> ^
> -----------------------------------------+ ???
>
> But in the u-boot console example you post, you load the dtb into
> memory.
>
Its standard mechanism to boot kernel with DT and it is nothing to do
with .config. as mentioned before I have already submitted patch to add dtb
target to 'make dtbs'.
Thanks,
Vaibhav
^ permalink raw reply
* [PATCH] ARM: kirkwood: DT board setup for Network Space v2 and parents
From: Andrew Lunn @ 2012-10-09 11:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <506DAE12.7000003@wwwdotorg.org>
> >> The question is, what is the appropriate name. How common is
> >> this common C code? Are there ns2 where this C code is not
> >> appropriate. One thing to remember is that most of this C code
> >> will soon disappear and become DT. All the mpp will be replaced
> >> with pinctrl in 3.8. I hope we can get the Ethernet setup in DT
> >> as well. You are working on ns2_led, so all the C code will be
> >> replaced by DT. So all we are really left with is power off GPIO
> >> handling.
> >>
> >> So i think the danger of using lacie,ns2_common, and then finding
> >> it does not work with some other ns2 device is quite low.
>
> lacie,ns2_common doesn't sound like a HW description, but rather a SW
> invention. DT should be describing purely the HW. If there's no common
> HW between these compatible boards (which seems unlikely), then there
> shouldn't be a shared compatible value.
Actually, there is common hardware between these boards:
NS2 LED driver
Pinctrl setup
GPIO used for power off
Ethernet configuration.
At the moment, we don't have DT for these, so there is C code. The
"lacie,ns2_common" compatibility string would be used to enable this C
code for these boards.
Andrew
^ permalink raw reply
* [PATCH v2 2/2] [media]: mx2_camera: Fix regression caused by clock conversion
From: javier Martin @ 2012-10-09 11:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349735823-30315-1-git-send-email-festevam@gmail.com>
On 9 October 2012 00:37, Fabio Estevam <festevam@gmail.com> wrote:
> From: Fabio Estevam <fabio.estevam@freescale.com>
>
> Since mx27 transitioned to the commmon clock framework in 3.5, the correct way
> to acquire the csi clock is to get csi_ahb and csi_per clocks separately.
>
> By not doing so the camera sensor does not probe correctly:
>
> soc-camera-pdrv soc-camera-pdrv.0: Probing soc-camera-pdrv.0
> mx2-camera mx2-camera.0: Camera driver attached to camera 0
> ov2640 0-0030: Product ID error fb:fb
> mx2-camera mx2-camera.0: Camera driver detached from camera 0
> mx2-camera mx2-camera.0: MX2 Camera (CSI) driver probed, clock frequency: 66500000
>
> Adapt the mx2_camera driver to the new clock framework and make it functional
> again.
>
> Signed-off-by: Fabio Estevam <fabio.estevam@freescale.com>
> ---
> Changes since v1:
> - Rebased against linux-next 20121008.
>
> drivers/media/platform/soc_camera/mx2_camera.c | 47 +++++++++++++++++-------
> 1 file changed, 34 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
> index 403d7f1..9f8c5f0 100644
> --- a/drivers/media/platform/soc_camera/mx2_camera.c
> +++ b/drivers/media/platform/soc_camera/mx2_camera.c
> @@ -272,7 +272,8 @@ struct mx2_camera_dev {
> struct device *dev;
> struct soc_camera_host soc_host;
> struct soc_camera_device *icd;
> - struct clk *clk_csi, *clk_emma_ahb, *clk_emma_ipg;
> + struct clk *clk_emma_ahb, *clk_emma_ipg;
> + struct clk *clk_csi_ahb, *clk_csi_per;
>
> void __iomem *base_csi, *base_emma;
>
> @@ -432,7 +433,8 @@ static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
> {
> unsigned long flags;
>
> - clk_disable_unprepare(pcdev->clk_csi);
> + clk_disable_unprepare(pcdev->clk_csi_ahb);
> + clk_disable_unprepare(pcdev->clk_csi_per);
> writel(0, pcdev->base_csi + CSICR1);
> if (cpu_is_mx27()) {
> writel(0, pcdev->base_emma + PRP_CNTL);
> @@ -460,7 +462,11 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
> if (pcdev->icd)
> return -EBUSY;
>
> - ret = clk_prepare_enable(pcdev->clk_csi);
> + ret = clk_prepare_enable(pcdev->clk_csi_ahb);
> + if (ret < 0)
> + return ret;
> +
> + ret = clk_prepare_enable(pcdev->clk_csi_per);
> if (ret < 0)
> return ret;
>
> @@ -1725,11 +1731,18 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
> goto exit;
> }
>
> - pcdev->clk_csi = devm_clk_get(&pdev->dev, "ahb");
> - if (IS_ERR(pcdev->clk_csi)) {
> - dev_err(&pdev->dev, "Could not get csi clock\n");
> - err = PTR_ERR(pcdev->clk_csi);
> - goto exit;
> + pcdev->clk_csi_ahb = devm_clk_get(&pdev->dev, "ahb");
> + if (IS_ERR(pcdev->clk_csi_ahb)) {
> + dev_err(&pdev->dev, "Could not get csi ahb clock\n");
> + err = PTR_ERR(pcdev->clk_csi_ahb);
> + goto exit;
> + }
> +
> + pcdev->clk_csi_per = devm_clk_get(&pdev->dev, "per");
> + if (IS_ERR(pcdev->clk_csi_per)) {
> + dev_err(&pdev->dev, "Could not get csi per clock\n");
> + err = PTR_ERR(pcdev->clk_csi_per);
> + goto exit_csi_ahb;
> }
>
> pcdev->pdata = pdev->dev.platform_data;
> @@ -1738,14 +1751,15 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
>
> pcdev->platform_flags = pcdev->pdata->flags;
>
> - rate = clk_round_rate(pcdev->clk_csi, pcdev->pdata->clk * 2);
> + rate = clk_round_rate(pcdev->clk_csi_per,
> + pcdev->pdata->clk * 2);
> if (rate <= 0) {
> err = -ENODEV;
> - goto exit;
> + goto exit_csi_per;
> }
> - err = clk_set_rate(pcdev->clk_csi, rate);
> + err = clk_set_rate(pcdev->clk_csi_per, rate);
> if (err < 0)
> - goto exit;
> + goto exit_csi_per;
> }
>
> INIT_LIST_HEAD(&pcdev->capture);
> @@ -1801,7 +1815,7 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
> goto exit_free_emma;
>
> dev_info(&pdev->dev, "MX2 Camera (CSI) driver probed, clock frequency: %ld\n",
> - clk_get_rate(pcdev->clk_csi));
> + clk_get_rate(pcdev->clk_csi_per));
>
> return 0;
>
> @@ -1812,6 +1826,10 @@ eallocctx:
> clk_disable_unprepare(pcdev->clk_emma_ipg);
> clk_disable_unprepare(pcdev->clk_emma_ahb);
> }
> +exit_csi_per:
> + clk_disable_unprepare(pcdev->clk_csi_per);
> +exit_csi_ahb:
> + clk_disable_unprepare(pcdev->clk_csi_ahb);
> exit:
> return err;
> }
> @@ -1831,6 +1849,9 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev)
> clk_disable_unprepare(pcdev->clk_emma_ahb);
> }
>
> + clk_disable_unprepare(pcdev->clk_csi_per);
> + clk_disable_unprepare(pcdev->clk_csi_ahb);
> +
> dev_info(&pdev->dev, "MX2 Camera driver unloaded\n");
>
> return 0;
> --
> 1.7.9.5
>
This patch doesn't fix the BUG it claims to, since I have it working
properly in our Visstrim M10 platform without it. Look:
soc-camera-pdrv soc-camera-pdrv.0: Probing soc-camera-pdrv.0
mx2-camera mx2-camera.0: Camera driver attached to camera 0
ov7670 0-0021: chip found @ 0x42 (imx-i2c)
[..]
mx2-camera mx2-camera.0: Camera driver detached from camera 0
mx2-camera mx2-camera.0: MX2 Camera (CSI) driver probed, clock
frequency: 66500000
Furthermore, it's not correct, since there isn't such "per" clock for
the CSI in 3.5 [1], 3.6 [2], linux-next-20121008[3], or
next-20121009[4].
[1] http://lxr.linux.no/#linux+v3.5/arch/arm/mach-imx/clk-imx27.c#L226
[2] http://lxr.linux.no/#linux+v3.6/arch/arm/mach-imx/clk-imx27.c#L226
[3] http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=blob;f=arch/arm/mach-imx/clk-imx27.c;h=3b6b640eed247ea1b7848c7a7fa01801f0190cde;hb=cc925138a0dd9ae388135bb3cf11ee1729f9c4e9#l226
[4] http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=blob;f=arch/arm/mach-imx/clk-imx27.c;h=3b6b640eed247ea1b7848c7a7fa01801f0190cde;hb=b066f61482c7eac44e656499426a3c56d29c32ed#l226
Regards.
--
Javier Martin
Vista Silicon S.L.
CDTUC - FASE C - Oficina S-345
Avda de los Castros s/n
39005- Santander. Cantabria. Spain
+34 942 25 32 60
www.vista-silicon.com
^ permalink raw reply
* Booting vanilla kernel on the beaglebone
From: Richard Cochran @ 2012-10-09 11:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <79CD15C6BA57404B839C016229A409A83EB39685@DBDE01.ent.ti.com>
On Tue, Oct 09, 2012 at 05:57:22AM +0000, Hiremath, Vaibhav wrote:
> On Tue, Oct 09, 2012 at 00:46:57, Richard Cochran wrote:
> > 2. Can you post your .config?
> >
>
> I use omap2plus_defconfig + CONFIG_ARM_APPENDED_DTB + CONFIG_ARM_ATAG_DTB_COMPAT and nothing more.
^
-----------------------------------------+ ???
But in the u-boot console example you post, you load the dtb into
memory.
Confused,
Richard
^ permalink raw reply
* [PATCH 11/11] nand: Increase the ecc placement locations to 640
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349778820.git.vipin.kumar@st.com>
Few devices like H27UBG8T2CTR have a writesize/oobsize of 8KB/640B.
This means that the maximum oobsize has gone up to 640 bytes and consequently
the maximum ecc placement locations have also gone up to 640.
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
include/linux/mtd/mtd.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 81d61e7..f9ac289 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -98,7 +98,7 @@ struct mtd_oob_ops {
};
#define MTD_MAX_OOBFREE_ENTRIES_LARGE 32
-#define MTD_MAX_ECCPOS_ENTRIES_LARGE 448
+#define MTD_MAX_ECCPOS_ENTRIES_LARGE 640
/*
* Internal ECC layout control structure. For historical reasons, there is a
* similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained
--
1.7.11.4
^ permalink raw reply related
* [PATCH 10/11] fsmc/nand: Add sw bch support for ecc calculation/correction
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349778820.git.vipin.kumar@st.com>
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
.../devicetree/bindings/mtd/fsmc-nand.txt | 2 +
drivers/mtd/nand/fsmc_nand.c | 156 +++++++++++++--------
include/linux/mtd/fsmc.h | 3 +
3 files changed, 106 insertions(+), 55 deletions(-)
diff --git a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
index 598bca2..dcf513b 100644
--- a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
@@ -30,6 +30,8 @@ Optional properties:
- st,rb-gpios: When the st,ready-busy is defined as "rb-gpio", a gpio
pin number is defined in this property
+- nand-sw-ecc: boolean indicating whether s/w ecc is supported
+
Example:
fsmc: flash at d1800000 {
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 762cf83..ff84468 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -946,6 +946,9 @@ static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
} else
pdata->rbpin.use_pin = FSMC_RB_WAIT;
+ if (of_property_read_bool(np, "nand-sw-ecc"))
+ pdata->sw_ecc = true;
+
return 0;
}
#else
@@ -972,6 +975,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
dma_cap_mask_t mask;
int ret = 0;
u32 pid, bank;
+ uint oobeccsize, m;
int i;
if (np) {
@@ -1104,9 +1108,24 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
nand->cmd_ctrl = fsmc_cmd_ctrl;
nand->chip_delay = 30;
- nand->ecc.mode = NAND_ECC_HW;
- nand->ecc.hwctl = fsmc_enable_hwecc;
- nand->ecc.size = 512;
+ if (pdata->sw_ecc) {
+ nand->ecc.mode = NAND_ECC_SOFT_BCH;
+ /*
+ * The recent devices require n-bit correctibility in x bytes.
+ * The values of n and x varies as below
+ * n - 1 to 100
+ * x - 512 to 1K
+ * TODO: For now, take x = 1K for all sw bch mathematics. Think
+ * of a better way to handle other device dependent
+ * requirements. May be it should come from board dts files
+ */
+ nand->ecc.size = 1024;
+ } else {
+ nand->ecc.mode = NAND_ECC_HW;
+ nand->ecc.hwctl = fsmc_enable_hwecc;
+ nand->ecc.size = 512;
+ }
+
nand->options = pdata->options;
nand->select_chip = fsmc_select_chip;
nand->badblockbits = 7;
@@ -1165,17 +1184,19 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
nand->options & NAND_BUSWIDTH_16,
host->dev_timings, host->rbpin);
- if (AMBA_REV_BITS(host->pid) >= 8) {
- nand->ecc.read_page = fsmc_read_page_hwecc;
- nand->ecc.calculate = fsmc_read_hwecc_ecc4;
- nand->ecc.correct = fsmc_bch8_correct_data;
- nand->ecc.bytes = 13;
- nand->ecc.strength = 8;
- } else {
- nand->ecc.calculate = fsmc_read_hwecc_ecc1;
- nand->ecc.correct = nand_correct_data;
- nand->ecc.bytes = 3;
- nand->ecc.strength = 1;
+ if (nand->ecc.mode != NAND_ECC_SOFT_BCH) {
+ if (AMBA_REV_BITS(host->pid) >= 8) {
+ nand->ecc.read_page = fsmc_read_page_hwecc;
+ nand->ecc.calculate = fsmc_read_hwecc_ecc4;
+ nand->ecc.correct = fsmc_bch8_correct_data;
+ nand->ecc.bytes = 13;
+ nand->ecc.strength = 8;
+ } else {
+ nand->ecc.calculate = fsmc_read_hwecc_ecc1;
+ nand->ecc.correct = nand_correct_data;
+ nand->ecc.bytes = 3;
+ nand->ecc.strength = 1;
+ }
}
/*
@@ -1187,48 +1208,73 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
goto err_scan_ident;
}
- if (AMBA_REV_BITS(host->pid) >= 8) {
- switch (host->mtd.oobsize) {
- case 16:
- nand->ecc.layout = &fsmc_ecc4_16_layout;
- host->ecc_place = &fsmc_ecc4_sp_place;
- break;
- case 64:
- nand->ecc.layout = &fsmc_ecc4_64_layout;
- host->ecc_place = &fsmc_ecc4_lp_place;
- break;
- case 128:
- nand->ecc.layout = &fsmc_ecc4_128_layout;
- host->ecc_place = &fsmc_ecc4_lp_place;
- break;
- case 224:
- nand->ecc.layout = &fsmc_ecc4_224_layout;
- host->ecc_place = &fsmc_ecc4_lp_place;
- break;
- case 256:
- nand->ecc.layout = &fsmc_ecc4_256_layout;
- host->ecc_place = &fsmc_ecc4_lp_place;
- break;
- default:
- printk(KERN_WARNING "No oob scheme defined for "
- "oobsize %d\n", mtd->oobsize);
- BUG();
- }
+ if (nand->ecc.mode == NAND_ECC_SOFT_BCH) {
+ /*
+ * Initialize the ecc bytes and strength dynamically based on eccsize
+ * and writesize.
+ *
+ * Parameters @eccsize and @eccbytes are used to compute BCH parameters
+ * m (Galois field order) and t (error correction capability). @eccbytes
+ * should be equal to the number of bytes required to store m*t bits,
+ * where m is such that 2^m-1 > @eccsize*8.
+ *
+ * Example: to configure 4 bit correction per 512 bytes, you should pass
+ * @eccsize = 512 (thus, m=13 is the smallest integer such that 2^m-1 >
+ * 512*8) @eccbytes = 7 (7 bytes are required to store m*t = 13*4 = 52
+ * bits)
+ *
+ * Note: 2 bytes of oob are considered reserved for bad block marking
+ */
+ m = fls(1 + 8 * nand->ecc.size);
+ oobeccsize = ((host->mtd.oobsize - 2) * \
+ nand->ecc.size) / host->mtd.writesize;
+ nand->ecc.bytes = (oobeccsize / m) * m;
+ nand->ecc.strength = (nand->ecc.bytes * 8) / m;
+ nand->ecc.layout = NULL;
} else {
- switch (host->mtd.oobsize) {
- case 16:
- nand->ecc.layout = &fsmc_ecc1_16_layout;
- break;
- case 64:
- nand->ecc.layout = &fsmc_ecc1_64_layout;
- break;
- case 128:
- nand->ecc.layout = &fsmc_ecc1_128_layout;
- break;
- default:
- printk(KERN_WARNING "No oob scheme defined for "
- "oobsize %d\n", mtd->oobsize);
- BUG();
+ if (AMBA_REV_BITS(host->pid) >= 8) {
+ switch (host->mtd.oobsize) {
+ case 16:
+ nand->ecc.layout = &fsmc_ecc4_16_layout;
+ host->ecc_place = &fsmc_ecc4_sp_place;
+ break;
+ case 64:
+ nand->ecc.layout = &fsmc_ecc4_64_layout;
+ host->ecc_place = &fsmc_ecc4_lp_place;
+ break;
+ case 128:
+ nand->ecc.layout = &fsmc_ecc4_128_layout;
+ host->ecc_place = &fsmc_ecc4_lp_place;
+ break;
+ case 224:
+ nand->ecc.layout = &fsmc_ecc4_224_layout;
+ host->ecc_place = &fsmc_ecc4_lp_place;
+ break;
+ case 256:
+ nand->ecc.layout = &fsmc_ecc4_256_layout;
+ host->ecc_place = &fsmc_ecc4_lp_place;
+ break;
+ default:
+ printk(KERN_WARNING "No oob scheme defined for "
+ "oobsize %d\n", mtd->oobsize);
+ BUG();
+ }
+ } else {
+ switch (host->mtd.oobsize) {
+ case 16:
+ nand->ecc.layout = &fsmc_ecc1_16_layout;
+ break;
+ case 64:
+ nand->ecc.layout = &fsmc_ecc1_64_layout;
+ break;
+ case 128:
+ nand->ecc.layout = &fsmc_ecc1_128_layout;
+ break;
+ default:
+ printk(KERN_WARNING "No oob scheme defined for "
+ "oobsize %d\n", mtd->oobsize);
+ BUG();
+ }
}
}
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h
index eed22a1..07eee6e 100644
--- a/include/linux/mtd/fsmc.h
+++ b/include/linux/mtd/fsmc.h
@@ -176,6 +176,9 @@ struct fsmc_nand_platform_data {
/* priv structures for dma accesses */
void *read_dma_priv;
void *write_dma_priv;
+
+ /* whether s/w ecc is supported */
+ bool sw_ecc;
};
extern int __init fsmc_nor_init(struct platform_device *pdev,
--
1.7.11.4
^ permalink raw reply related
* [PATCH 09/11] fsmc/nand:FIX: replace change_bit routine
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349778820.git.vipin.kumar@st.com>
change_bit routine accepts only ulong pointers as buffer, so an unaligned char
pointer passed to change_bit may lead to a crash.
Fix this bug by accessing the buffer as char pointer.
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
drivers/mtd/nand/fsmc_nand.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index f48ee60..762cf83 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -859,7 +859,9 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
change_bit(1, (unsigned long *)&err_idx[i]);
if (err_idx[i] < chip->ecc.size * 8) {
- change_bit(err_idx[i], (unsigned long *)dat);
+ uint8_t *p = dat + err_idx[i] / 8;
+ *p = *p ^ (1 << (err_idx[i] % 8));
+
i++;
}
}
--
1.7.11.4
^ permalink raw reply related
* [PATCH 08/11] fsmc/nand: Use relaxed variants of io accessors
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349778820.git.vipin.kumar@st.com>
Use relaxed variants of readl/writel accessors. readl/writel io accessors use
explicit dsb instruction which causes stalls in the processor core resulting
several cycles of delay for each access
Use relaxed variants where ever possible. This also results in an improved
read/write performance.
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
drivers/mtd/nand/fsmc_nand.c | 54 ++++++++++++++++++++++++--------------------
1 file changed, 29 insertions(+), 25 deletions(-)
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 8de6dcf..f48ee60 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -400,13 +400,13 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
pc |= FSMC_ENABLE;
else
pc &= ~FSMC_ENABLE;
- writel(pc, FSMC_NAND_REG(regs, bank, PC));
+ writel_relaxed(pc, FSMC_NAND_REG(regs, bank, PC));
}
mb();
if (cmd != NAND_CMD_NONE)
- writeb(cmd, this->IO_ADDR_W);
+ writeb_relaxed(cmd, this->IO_ADDR_W);
}
/*
@@ -433,14 +433,18 @@ static void fsmc_nand_setup(void __iomem *regs, uint32_t bank, uint32_t busw,
tset = (timings->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT;
if (busw)
- writel(value | FSMC_DEVWID_16, FSMC_NAND_REG(regs, bank, PC));
+ writel_relaxed(value | FSMC_DEVWID_16,
+ FSMC_NAND_REG(regs, bank, PC));
else
- writel(value | FSMC_DEVWID_8, FSMC_NAND_REG(regs, bank, PC));
+ writel_relaxed(value | FSMC_DEVWID_8,
+ FSMC_NAND_REG(regs, bank, PC));
- writel(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar,
+ writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar,
FSMC_NAND_REG(regs, bank, PC));
- writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, COMM));
- writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, ATTRIB));
+ writel_relaxed(thiz | thold | twait | tset,
+ FSMC_NAND_REG(regs, bank, COMM));
+ writel_relaxed(thiz | thold | twait | tset,
+ FSMC_NAND_REG(regs, bank, ATTRIB));
}
/*
@@ -453,11 +457,11 @@ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
void __iomem *regs = host->regs_va;
uint32_t bank = host->bank;
- writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256,
+ writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256,
FSMC_NAND_REG(regs, bank, PC));
- writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN,
+ writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN,
FSMC_NAND_REG(regs, bank, PC));
- writel(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN,
+ writel_relaxed(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN,
FSMC_NAND_REG(regs, bank, PC));
}
@@ -477,7 +481,7 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT;
do {
- if (readl(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY)
+ if (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY)
break;
else
cond_resched();
@@ -488,25 +492,25 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
return -ETIMEDOUT;
}
- ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1));
+ ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
ecc[0] = (uint8_t) (ecc_tmp >> 0);
ecc[1] = (uint8_t) (ecc_tmp >> 8);
ecc[2] = (uint8_t) (ecc_tmp >> 16);
ecc[3] = (uint8_t) (ecc_tmp >> 24);
- ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC2));
+ ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
ecc[4] = (uint8_t) (ecc_tmp >> 0);
ecc[5] = (uint8_t) (ecc_tmp >> 8);
ecc[6] = (uint8_t) (ecc_tmp >> 16);
ecc[7] = (uint8_t) (ecc_tmp >> 24);
- ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC3));
+ ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
ecc[8] = (uint8_t) (ecc_tmp >> 0);
ecc[9] = (uint8_t) (ecc_tmp >> 8);
ecc[10] = (uint8_t) (ecc_tmp >> 16);
ecc[11] = (uint8_t) (ecc_tmp >> 24);
- ecc_tmp = readl(FSMC_NAND_REG(regs, bank, STS));
+ ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
ecc[12] = (uint8_t) (ecc_tmp >> 16);
return 0;
@@ -526,7 +530,7 @@ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
uint32_t bank = host->bank;
uint32_t ecc_tmp;
- ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1));
+ ecc_tmp = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
ecc[0] = (uint8_t) (ecc_tmp >> 0);
ecc[1] = (uint8_t) (ecc_tmp >> 8);
ecc[2] = (uint8_t) (ecc_tmp >> 16);
@@ -635,10 +639,10 @@ static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
uint32_t *p = (uint32_t *)buf;
len = len >> 2;
for (i = 0; i < len; i++)
- writel(p[i], chip->IO_ADDR_W);
+ writel_relaxed(p[i], chip->IO_ADDR_W);
} else {
for (i = 0; i < len; i++)
- writeb(buf[i], chip->IO_ADDR_W);
+ writeb_relaxed(buf[i], chip->IO_ADDR_W);
}
}
@@ -658,10 +662,10 @@ static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
uint32_t *p = (uint32_t *)buf;
len = len >> 2;
for (i = 0; i < len; i++)
- p[i] = readl(chip->IO_ADDR_R);
+ p[i] = readl_relaxed(chip->IO_ADDR_R);
} else {
for (i = 0; i < len; i++)
- buf[i] = readb(chip->IO_ADDR_R);
+ buf[i] = readb_relaxed(chip->IO_ADDR_R);
}
}
@@ -792,7 +796,7 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
uint32_t num_err, i;
uint32_t ecc1, ecc2, ecc3, ecc4;
- num_err = (readl(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF;
+ num_err = (readl_relaxed(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF;
/* no bit flipping */
if (likely(num_err == 0))
@@ -835,10 +839,10 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
* uint64_t array and error offset indexes are populated in err_idx
* array
*/
- ecc1 = readl(FSMC_NAND_REG(regs, bank, ECC1));
- ecc2 = readl(FSMC_NAND_REG(regs, bank, ECC2));
- ecc3 = readl(FSMC_NAND_REG(regs, bank, ECC3));
- ecc4 = readl(FSMC_NAND_REG(regs, bank, STS));
+ ecc1 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC1));
+ ecc2 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC2));
+ ecc3 = readl_relaxed(FSMC_NAND_REG(regs, bank, ECC3));
+ ecc4 = readl_relaxed(FSMC_NAND_REG(regs, bank, STS));
err_idx[0] = (ecc1 >> 0) & 0x1FFF;
err_idx[1] = (ecc1 >> 13) & 0x1FFF;
--
1.7.11.4
^ permalink raw reply related
* [PATCH 07/11] fsmc/nand: Provide contiguous buffers to dma
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349778820.git.vipin.kumar@st.com>
read_buf/write_buf callbacks should be able to accept a user space memory
address (virtually contiguous memory) as buffer pointer.
This patch allocates a logically contiguous memory area which is use for dma
xfers during read and write accesses.
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
drivers/mtd/nand/fsmc_nand.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 4b29a64..8de6dcf 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -323,6 +323,7 @@ struct fsmc_nand_data {
struct dma_chan *read_dma_chan;
struct dma_chan *write_dma_chan;
struct completion dma_access_complete;
+ void *dma_buf;
/* Recieved from plat data */
struct fsmc_rbpin *rbpin;
@@ -675,7 +676,8 @@ static void fsmc_read_buf_dma(struct mtd_info *mtd, uint8_t *buf, int len)
struct fsmc_nand_data *host;
host = container_of(mtd, struct fsmc_nand_data, mtd);
- dma_xfer(host, buf, len, DMA_FROM_DEVICE);
+ dma_xfer(host, host->dma_buf, len, DMA_FROM_DEVICE);
+ memcpy(buf, (const void *)host->dma_buf, len);
}
/*
@@ -690,7 +692,8 @@ static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
struct fsmc_nand_data *host;
host = container_of(mtd, struct fsmc_nand_data, mtd);
- dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
+ memcpy(host->dma_buf, buf, len);
+ dma_xfer(host, host->dma_buf, len, DMA_TO_DEVICE);
}
/*
@@ -1133,6 +1136,13 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Unable to get write dma channel\n");
goto err_req_write_chnl;
}
+
+ host->dma_buf = kmalloc(NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE,
+ GFP_KERNEL);
+ if (!host->dma_buf) {
+ dev_err(&pdev->dev, "failed to allocate dma buffer\n");
+ goto err_req_dma_buf;
+ }
nand->read_buf = fsmc_read_buf_dma;
nand->write_buf = fsmc_write_buf_dma;
break;
@@ -1246,6 +1256,9 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
err_probe:
err_scan_ident:
if (host->mode == USE_DMA_ACCESS)
+ kfree(host->dma_buf);
+err_req_dma_buf:
+ if (host->mode == USE_DMA_ACCESS)
dma_release_channel(host->write_dma_chan);
err_req_write_chnl:
if (host->mode == USE_DMA_ACCESS)
--
1.7.11.4
^ permalink raw reply related
* [PATCH 06/11] fsmc/nand: Modify the wait to uninterruptible
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349778820.git.vipin.kumar@st.com>
Interruptible wait caused trouble in fsmc hardware state machine if the
application was killed abruptly. To make fsmc operation safe turn wait in to
un-interruptible.
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
drivers/mtd/nand/fsmc_nand.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index eaffd3b..4b29a64 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -607,7 +607,7 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len,
dma_async_issue_pending(chan);
ret =
- wait_for_completion_interruptible_timeout(&host->dma_access_complete,
+ wait_for_completion_timeout(&host->dma_access_complete,
msecs_to_jiffies(3000));
if (ret <= 0) {
chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
--
1.7.11.4
^ permalink raw reply related
* [PATCH 05/11] fsmc: Implement ready/busy through gpio pin
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349778820.git.vipin.kumar@st.com>
The NAND devices have a ready/busy (active low) output which is connected to the
FSMC controller FSMC_RnB pin
The CPU can work in following two ways
* CPU keeps waiting for a ready response and it halts until it receives a ready
response from NAND device. This halts the ldr instruction in between and in
effect holds the CPU down for a number of cycles. During this period, CPU
can't even service interrupts. This behavior is enabled via WAIT_ON bit of
FSMC controller
* CPU merely issues the command and does not wait for response. The NAND device
is later probed for being ready by reading the NAND_RnB signal
Until now, WAIT_ON was enabled by default. This patch implements reading the
device ready state through a gpio. The gpio number is passed via DT and this
patch also adds a corresponding binding for fsmc
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
.../devicetree/bindings/mtd/fsmc-nand.txt | 5 ++
drivers/mtd/nand/fsmc_nand.c | 54 +++++++++++++++++++---
include/linux/mtd/fsmc.h | 11 +++++
3 files changed, 64 insertions(+), 6 deletions(-)
diff --git a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
index 6a7fc43..598bca2 100644
--- a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
@@ -25,6 +25,11 @@ Optional properties:
period of hclk ie a number 4 in thold with hclk = 166MHz means that
thold = (1000 / 166) * 4 ns = 24.09ns
+- st,ready-busy: Should contain either of "rb-gpio" or "rb-wait". When
+ this property is not defined, the default is to use rb-wait.
+- st,rb-gpios: When the st,ready-busy is defined as "rb-gpio", a gpio
+ pin number is defined in this property
+
Example:
fsmc: flash at d1800000 {
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index f3d69b3..eaffd3b 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -22,6 +22,7 @@
#include <linux/dma-direction.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
+#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/resource.h>
@@ -32,6 +33,7 @@
#include <linux/mtd/nand_ecc.h>
#include <linux/platform_device.h>
#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/mtd/partitions.h>
#include <linux/io.h>
#include <linux/slab.h>
@@ -289,6 +291,7 @@ static struct fsmc_eccplace fsmc_ecc4_sp_place = {
* @write_dma_chan: DMA channel for write access to NAND
* @dma_access_complete: Completion structure
*
+ * @rb_pin: Ready/Busy data
* @dev_timings: Timings to be programmed in controller
* @partitions: Partition info for a NAND Flash
* @nr_partitions: Total number of partition of a NAND flash
@@ -322,6 +325,7 @@ struct fsmc_nand_data {
struct completion dma_access_complete;
/* Recieved from plat data */
+ struct fsmc_rbpin *rbpin;
struct fsmc_nand_timings *dev_timings;
struct mtd_partition *partitions;
unsigned int nr_partitions;
@@ -410,12 +414,16 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
* This routine initializes timing parameters related to NAND memory access in
* FSMC registers
*/
-static void fsmc_nand_setup(void __iomem *regs, uint32_t bank,
- uint32_t busw, struct fsmc_nand_timings *timings)
+static void fsmc_nand_setup(void __iomem *regs, uint32_t bank, uint32_t busw,
+ struct fsmc_nand_timings *timings,
+ struct fsmc_rbpin *rbpin)
{
- uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON;
+ uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE;
uint32_t tclr, tar, thiz, thold, twait, tset;
+ if (!rbpin || (rbpin->use_pin == FSMC_RB_WAIT))
+ value |= FSMC_WAITON;
+
tclr = (timings->tclr & FSMC_TCLR_MASK) << FSMC_TCLR_SHIFT;
tar = (timings->tar & FSMC_TAR_MASK) << FSMC_TAR_SHIFT;
thiz = (timings->thiz & FSMC_THIZ_MASK) << FSMC_THIZ_SHIFT;
@@ -857,6 +865,14 @@ static bool filter(struct dma_chan *chan, void *slave)
return true;
}
+static int fsmc_dev_ready(struct mtd_info *mtd)
+{
+ struct fsmc_nand_data *host = container_of(mtd,
+ struct fsmc_nand_data, mtd);
+
+ return !!gpio_get_value(host->rbpin->gpio_pin);
+}
+
#ifdef CONFIG_OF
static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
struct device_node *np)
@@ -870,7 +886,9 @@ static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
.twait = FSMC_TWAIT_6,
.tset = FSMC_TSET_0,
};
+ const char *rb;
u32 val;
+ enum of_gpio_flags flags;
/* Set default NAND width to 8 bits */
pdata->width = 8;
@@ -911,6 +929,14 @@ static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
sizeof(default_timings));
}
+ if (!of_property_read_string(np, "st,ready-busy", &rb) &&
+ !strcmp(rb, "rb-gpio")) {
+ pdata->rbpin.use_pin = FSMC_RB_GPIO;
+ pdata->rbpin.gpio_pin =
+ of_get_named_gpio_flags(np, "st,rb-gpios", 0, &flags);
+ } else
+ pdata->rbpin.use_pin = FSMC_RB_WAIT;
+
return 0;
}
#else
@@ -1049,6 +1075,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
host->nr_partitions = pdata->nr_partitions;
host->dev = &pdev->dev;
host->dev_timings = &pdata->nand_timings;
+ host->rbpin = &pdata->rbpin;
+
host->mode = pdata->mode;
host->max_banks = pdata->max_banks;
@@ -1074,6 +1102,18 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
nand->select_chip = fsmc_select_chip;
nand->badblockbits = 7;
+ if (host->rbpin->use_pin != FSMC_RB_WAIT)
+ nand->dev_ready = fsmc_dev_ready;
+
+ if (host->rbpin->use_pin == FSMC_RB_GPIO) {
+ ret = gpio_request(host->rbpin->gpio_pin, "fsmc-rb");
+ if (ret < 0) {
+ dev_err(&pdev->dev, "gpio request fail: %d\n",
+ host->rbpin->gpio_pin);
+ goto err_gpio_req;
+ }
+ }
+
if (pdata->width == FSMC_NAND_BW16)
nand->options |= NAND_BUSWIDTH_16;
@@ -1107,7 +1147,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
for (bank = 0; bank < host->max_banks; bank++)
fsmc_nand_setup(host->regs_va, bank,
nand->options & NAND_BUSWIDTH_16,
- host->dev_timings);
+ host->dev_timings, host->rbpin);
if (AMBA_REV_BITS(host->pid) >= 8) {
nand->ecc.read_page = fsmc_read_page_hwecc;
@@ -1211,6 +1251,9 @@ err_req_write_chnl:
if (host->mode == USE_DMA_ACCESS)
dma_release_channel(host->read_dma_chan);
err_req_read_chnl:
+ if (host->rbpin->use_pin == FSMC_RB_GPIO)
+ gpio_free(host->rbpin->gpio_pin);
+err_gpio_req:
clk_disable_unprepare(host->clk);
err_clk_prepare_enable:
clk_put(host->clk);
@@ -1260,8 +1303,7 @@ static int fsmc_nand_resume(struct device *dev)
for (bank = 0; bank < host->max_banks; bank++)
fsmc_nand_setup(host->regs_va, bank,
host->nand.options & NAND_BUSWIDTH_16,
- host->dev_timings);
-
+ host->dev_timings, host->rbpin);
}
return 0;
}
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h
index 4fbdce4..eed22a1 100644
--- a/include/linux/mtd/fsmc.h
+++ b/include/linux/mtd/fsmc.h
@@ -130,6 +130,16 @@ struct fsmc_nand_timings {
uint8_t tset;
};
+enum rbpin {
+ FSMC_RB_WAIT = 0,
+ FSMC_RB_GPIO,
+};
+
+struct fsmc_rbpin {
+ enum rbpin use_pin;
+ uint32_t gpio_pin;
+};
+
enum access_mode {
USE_DMA_ACCESS = 1,
USE_WORD_ACCESS,
@@ -149,6 +159,7 @@ enum access_mode {
*/
struct fsmc_nand_platform_data {
struct fsmc_nand_timings nand_timings;
+ struct fsmc_rbpin rbpin;
struct mtd_partition *partitions;
unsigned int nr_partitions;
unsigned int options;
--
1.7.11.4
^ permalink raw reply related
* [PATCH 04/11] fsmc/nand: Accept nand timing parameters via DT
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349778820.git.vipin.kumar@st.com>
Add support to accept nand timing parameters via device tree
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
.../devicetree/bindings/mtd/fsmc-nand.txt | 20 ++++++++
drivers/mtd/nand/fsmc_nand.c | 59 ++++++++++++++--------
include/linux/mtd/fsmc.h | 2 +-
3 files changed, 59 insertions(+), 22 deletions(-)
diff --git a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
index 29d1a2f..6a7fc43 100644
--- a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
@@ -13,6 +13,18 @@ Optional properties:
defaults to 1 byte
- nand-skip-bbtscan: Indicates the the BBT scanning should be skipped
+- nand-timings-enabled: Indicates if the timing parameters are passed
+ via DT
+- nand-timings,tclr:
+- nand-timings,tar:
+- nand-timings,thiz:
+- nand-timings,thold:
+- nand-timings,twait:
+- nand-timings,tset: All these timing parameters come from the actual
+ nand device specification. Each of this represents a number of time
+ period of hclk ie a number 4 in thold with hclk = 166MHz means that
+ thold = (1000 / 166) * 4 ns = 24.09ns
+
Example:
fsmc: flash at d1800000 {
@@ -26,6 +38,14 @@ Example:
st,cle-off = <0x10000>;
maxbanks = <1>;
+ nand-timings-enabled;
+ nand-timings,tclr = <1>;
+ nand-timings,tar = <1>;
+ nand-timings,thiz = <1>;
+ nand-timings,thold = <4>;
+ nand-timings,twait = <6>;
+ nand-timings,tset = <0>;
+
bank-width = <1>;
nand-skip-bbtscan;
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index fc6a044..f3d69b3 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -415,27 +415,13 @@ static void fsmc_nand_setup(void __iomem *regs, uint32_t bank,
{
uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON;
uint32_t tclr, tar, thiz, thold, twait, tset;
- struct fsmc_nand_timings *tims;
- struct fsmc_nand_timings default_timings = {
- .tclr = FSMC_TCLR_1,
- .tar = FSMC_TAR_1,
- .thiz = FSMC_THIZ_1,
- .thold = FSMC_THOLD_4,
- .twait = FSMC_TWAIT_6,
- .tset = FSMC_TSET_0,
- };
-
- if (timings)
- tims = timings;
- else
- tims = &default_timings;
- tclr = (tims->tclr & FSMC_TCLR_MASK) << FSMC_TCLR_SHIFT;
- tar = (tims->tar & FSMC_TAR_MASK) << FSMC_TAR_SHIFT;
- thiz = (tims->thiz & FSMC_THIZ_MASK) << FSMC_THIZ_SHIFT;
- thold = (tims->thold & FSMC_THOLD_MASK) << FSMC_THOLD_SHIFT;
- twait = (tims->twait & FSMC_TWAIT_MASK) << FSMC_TWAIT_SHIFT;
- tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT;
+ tclr = (timings->tclr & FSMC_TCLR_MASK) << FSMC_TCLR_SHIFT;
+ tar = (timings->tar & FSMC_TAR_MASK) << FSMC_TAR_SHIFT;
+ thiz = (timings->thiz & FSMC_THIZ_MASK) << FSMC_THIZ_SHIFT;
+ thold = (timings->thold & FSMC_THOLD_MASK) << FSMC_THOLD_SHIFT;
+ twait = (timings->twait & FSMC_TWAIT_MASK) << FSMC_TWAIT_SHIFT;
+ tset = (timings->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT;
if (busw)
writel(value | FSMC_DEVWID_16, FSMC_NAND_REG(regs, bank, PC));
@@ -876,6 +862,14 @@ static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
struct device_node *np)
{
struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct fsmc_nand_timings default_timings = {
+ .tclr = FSMC_TCLR_1,
+ .tar = FSMC_TAR_1,
+ .thiz = FSMC_THIZ_1,
+ .thold = FSMC_THOLD_4,
+ .twait = FSMC_TWAIT_6,
+ .tset = FSMC_TSET_0,
+ };
u32 val;
/* Set default NAND width to 8 bits */
@@ -894,6 +888,29 @@ static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
pdata->options = NAND_SKIP_BBTSCAN;
of_property_read_u32(np, "maxbanks", &pdata->max_banks);
+ if (of_property_read_bool(np, "nand-timings-enabled")) {
+ of_property_read_u32(np, "nand-timings,tclr", &val);
+ pdata->nand_timings.tclr = (uint8_t)val;
+
+ of_property_read_u32(np, "nand-timings,tar", &val);
+ pdata->nand_timings.tar = (uint8_t)val;
+
+ of_property_read_u32(np, "nand-timings,thiz", &val);
+ pdata->nand_timings.thiz = (uint8_t)val;
+
+ of_property_read_u32(np, "nand-timings,thold", &val);
+ pdata->nand_timings.thold = (uint8_t)val;
+
+ of_property_read_u32(np, "nand-timings,twait", &val);
+ pdata->nand_timings.twait = (uint8_t)val;
+
+ of_property_read_u32(np, "nand-timings,tset", &val);
+ pdata->nand_timings.tset = (uint8_t)val;
+ } else {
+ memcpy(&pdata->nand_timings, &default_timings,
+ sizeof(default_timings));
+ }
+
return 0;
}
#else
@@ -1031,7 +1048,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
host->partitions = pdata->partitions;
host->nr_partitions = pdata->nr_partitions;
host->dev = &pdev->dev;
- host->dev_timings = pdata->nand_timings;
+ host->dev_timings = &pdata->nand_timings;
host->mode = pdata->mode;
host->max_banks = pdata->max_banks;
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h
index f0ab734..4fbdce4 100644
--- a/include/linux/mtd/fsmc.h
+++ b/include/linux/mtd/fsmc.h
@@ -148,7 +148,7 @@ enum access_mode {
* this may be set to NULL
*/
struct fsmc_nand_platform_data {
- struct fsmc_nand_timings *nand_timings;
+ struct fsmc_nand_timings nand_timings;
struct mtd_partition *partitions;
unsigned int nr_partitions;
unsigned int options;
--
1.7.11.4
^ permalink raw reply related
* [PATCH 03/11] fsmc/nand: Support multiple banks connected to controller
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349778820.git.vipin.kumar@st.com>
Support up to max_banks number of banks in fsmc driver.
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
.../devicetree/bindings/mtd/fsmc-nand.txt | 2 ++
arch/arm/boot/dts/spear300.dtsi | 1 +
arch/arm/boot/dts/spear310.dtsi | 1 +
arch/arm/boot/dts/spear320.dtsi | 1 +
arch/arm/boot/dts/spear600.dtsi | 1 +
arch/arm/mach-u300/core.c | 1 +
drivers/mtd/nand/fsmc_nand.c | 26 +++++++++++++++-------
include/linux/mtd/fsmc.h | 2 +-
8 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
index e2c663b..29d1a2f 100644
--- a/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/fsmc-nand.txt
@@ -6,6 +6,7 @@ Required properties:
- reg-names: Should contain the reg names "fsmc_regs" and "nand_data"
- st,ale-off : Chip specific offset to ALE
- st,cle-off : Chip specific offset to CLE
+- maxbanks: Number of banks supported by SoC
Optional properties:
- bank-width : Width (in bytes) of the device. If not present, the width
@@ -23,6 +24,7 @@ Example:
reg-names = "fsmc_regs", "nand_data";
st,ale-off = <0x20000>;
st,cle-off = <0x10000>;
+ maxbanks = <1>;
bank-width = <1>;
nand-skip-bbtscan;
diff --git a/arch/arm/boot/dts/spear300.dtsi b/arch/arm/boot/dts/spear300.dtsi
index ed3627c..19e2328 100644
--- a/arch/arm/boot/dts/spear300.dtsi
+++ b/arch/arm/boot/dts/spear300.dtsi
@@ -42,6 +42,7 @@
reg-names = "fsmc_regs", "nand_data";
st,ale-off = <0x20000>;
st,cle-off = <0x10000>;
+ maxbanks = <1>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi
index 62fc4fb..0272afb3 100644
--- a/arch/arm/boot/dts/spear310.dtsi
+++ b/arch/arm/boot/dts/spear310.dtsi
@@ -36,6 +36,7 @@
reg-names = "fsmc_regs", "nand_data";
st,ale-off = <0x10000>;
st,cle-off = <0x20000>;
+ maxbanks = <1>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi
index 1f49d69..69fe50d 100644
--- a/arch/arm/boot/dts/spear320.dtsi
+++ b/arch/arm/boot/dts/spear320.dtsi
@@ -42,6 +42,7 @@
reg-names = "fsmc_regs", "nand_data";
st,ale-off = <0x20000>;
st,cle-off = <0x10000>;
+ maxbanks = <1>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/spear600.dtsi b/arch/arm/boot/dts/spear600.dtsi
index a3c36e4..6ed57c8 100644
--- a/arch/arm/boot/dts/spear600.dtsi
+++ b/arch/arm/boot/dts/spear600.dtsi
@@ -71,6 +71,7 @@
reg-names = "fsmc_regs", "nand_data";
st,ale-off = <0x20000>;
st,cle-off = <0x10000>;
+ maxbanks = <1>;
status = "disabled";
};
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 03acf18..5ea9f71 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -1546,6 +1546,7 @@ static struct fsmc_nand_platform_data nand_platform_data = {
.width = FSMC_NAND_BW8,
.ale_off = PLAT_NAND_ALE,
.cle_off = PLAT_NAND_CLE,
+ .max_banks = 1,
};
static struct platform_device nand_device = {
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index bd89580..fc6a044 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -298,6 +298,7 @@ static struct fsmc_eccplace fsmc_ecc4_sp_place = {
* - Word access (CPU)
* - None (Use driver default ie bus width specific
* CPU access)
+ * @max_banks: Maximum number of banks supported
* @select_chip: Select a particular bank
*
* @data_pa: NAND Physical port for Data
@@ -325,6 +326,7 @@ struct fsmc_nand_data {
struct mtd_partition *partitions;
unsigned int nr_partitions;
enum access_mode mode;
+ uint32_t max_banks;
void (*select_chip)(uint32_t bank, uint32_t busw);
/* Virtual/Physical addresses for CPU/DMA access */
@@ -343,6 +345,7 @@ static void fsmc_select_chip(struct mtd_info *mtd, int chipnr)
host = container_of(mtd, struct fsmc_nand_data, mtd);
+ host->bank = chipnr;
switch (chipnr) {
case -1:
chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
@@ -889,6 +892,7 @@ static int __devinit fsmc_nand_probe_config_dt(struct platform_device *pdev,
of_property_read_u32(np, "st,cle-off", &pdata->cle_off);
if (of_get_property(np, "nand-skip-bbtscan", NULL))
pdata->options = NAND_SKIP_BBTSCAN;
+ of_property_read_u32(np, "maxbanks", &pdata->max_banks);
return 0;
}
@@ -915,7 +919,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
struct resource *res;
dma_cap_mask_t mask;
int ret = 0;
- u32 pid;
+ u32 pid, bank;
int i;
if (np) {
@@ -1023,13 +1027,13 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
AMBA_PART_BITS(pid), AMBA_MANF_BITS(pid),
AMBA_REV_BITS(pid), AMBA_CONFIG_BITS(pid));
- host->bank = pdata->bank;
host->select_chip = pdata->select_bank;
host->partitions = pdata->partitions;
host->nr_partitions = pdata->nr_partitions;
host->dev = &pdev->dev;
host->dev_timings = pdata->nand_timings;
host->mode = pdata->mode;
+ host->max_banks = pdata->max_banks;
if (host->mode == USE_DMA_ACCESS)
init_completion(&host->dma_access_complete);
@@ -1083,9 +1087,10 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
break;
}
- fsmc_nand_setup(host->regs_va, host->bank,
- nand->options & NAND_BUSWIDTH_16,
- host->dev_timings);
+ for (bank = 0; bank < host->max_banks; bank++)
+ fsmc_nand_setup(host->regs_va, bank,
+ nand->options & NAND_BUSWIDTH_16,
+ host->dev_timings);
if (AMBA_REV_BITS(host->pid) >= 8) {
nand->ecc.read_page = fsmc_read_page_hwecc;
@@ -1230,11 +1235,16 @@ static int fsmc_nand_suspend(struct device *dev)
static int fsmc_nand_resume(struct device *dev)
{
struct fsmc_nand_data *host = dev_get_drvdata(dev);
+ uint32_t bank;
+
if (host) {
clk_prepare_enable(host->clk);
- fsmc_nand_setup(host->regs_va, host->bank,
- host->nand.options & NAND_BUSWIDTH_16,
- host->dev_timings);
+
+ for (bank = 0; bank < host->max_banks; bank++)
+ fsmc_nand_setup(host->regs_va, bank,
+ host->nand.options & NAND_BUSWIDTH_16,
+ host->dev_timings);
+
}
return 0;
}
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h
index b200292..f0ab734 100644
--- a/include/linux/mtd/fsmc.h
+++ b/include/linux/mtd/fsmc.h
@@ -153,7 +153,7 @@ struct fsmc_nand_platform_data {
unsigned int nr_partitions;
unsigned int options;
unsigned int width;
- unsigned int bank;
+ unsigned int max_banks;
/* CLE, ALE offsets */
unsigned int cle_off;
--
1.7.11.4
^ permalink raw reply related
* [PATCH 02/11] fsmc/nand: Rearrange the fsmc_nand_data structure and update comments
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349778820.git.vipin.kumar@st.com>
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
drivers/mtd/nand/fsmc_nand.c | 51 ++++++++++++++++++++++++++------------------
1 file changed, 30 insertions(+), 21 deletions(-)
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index e96d7d1..bd89580 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -278,52 +278,61 @@ static struct fsmc_eccplace fsmc_ecc4_sp_place = {
* struct fsmc_nand_data - structure for FSMC NAND device state
*
* @pid: Part ID on the AMBA PrimeCell format
- * @mtd: MTD info for a NAND flash.
- * @nand: Chip related info for a NAND flash.
- * @partitions: Partition info for a NAND Flash.
- * @nr_partitions: Total number of partition of a NAND flash.
- *
- * @ecc_place: ECC placing locations in oobfree type format.
- * @bank: Bank number for probed device.
- * @clk: Clock structure for FSMC.
+ * @mtd: MTD info for a NAND flash
+ * @nand: Chip related info for a NAND flash
+ * @dev: Device structure pointer
+ * @clk: Clock structure for FSMC
+ * @ecc_place: ECC placing locations in oobfree type format
+ * @bank: Bank number for probed device
*
* @read_dma_chan: DMA channel for read access
* @write_dma_chan: DMA channel for write access to NAND
* @dma_access_complete: Completion structure
*
- * @data_pa: NAND Physical port for Data.
- * @data_va: NAND port for Data.
- * @cmd_va: NAND port for Command.
- * @addr_va: NAND port for Address.
- * @regs_va: FSMC regs base address.
+ * @dev_timings: Timings to be programmed in controller
+ * @partitions: Partition info for a NAND Flash
+ * @nr_partitions: Total number of partition of a NAND flash
+ * @mode: Defines the NAND device access mode
+ * Can be one of:
+ * - DMA access
+ * - Word access (CPU)
+ * - None (Use driver default ie bus width specific
+ * CPU access)
+ * @select_chip: Select a particular bank
+ *
+ * @data_pa: NAND Physical port for Data
+ * @data_va: NAND port for Data
+ * @cmd_va: NAND port for Command
+ * @addr_va: NAND port for Address
+ * @regs_va: FSMC regs base address
*/
struct fsmc_nand_data {
u32 pid;
struct mtd_info mtd;
struct nand_chip nand;
- struct mtd_partition *partitions;
- unsigned int nr_partitions;
-
- struct fsmc_eccplace *ecc_place;
- unsigned int bank;
struct device *dev;
- enum access_mode mode;
struct clk *clk;
+ struct fsmc_eccplace *ecc_place;
+ unsigned int bank;
/* DMA related objects */
struct dma_chan *read_dma_chan;
struct dma_chan *write_dma_chan;
struct completion dma_access_complete;
+ /* Recieved from plat data */
struct fsmc_nand_timings *dev_timings;
+ struct mtd_partition *partitions;
+ unsigned int nr_partitions;
+ enum access_mode mode;
+ void (*select_chip)(uint32_t bank, uint32_t busw);
+ /* Virtual/Physical addresses for CPU/DMA access */
dma_addr_t data_pa;
void __iomem *data_va;
void __iomem *cmd_va;
void __iomem *addr_va;
void __iomem *regs_va;
-
- void (*select_chip)(uint32_t bank, uint32_t busw);
};
/* Assert CS signal based on chipnr */
--
1.7.11.4
^ permalink raw reply related
* [PATCH 01/11] fsmc/nand:FIX: Change the type for regs to void __iomem *
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1349778820.git.vipin.kumar@st.com>
Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
drivers/mtd/nand/fsmc_nand.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 38d2624..e96d7d1 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -361,7 +361,7 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
struct nand_chip *this = mtd->priv;
struct fsmc_nand_data *host = container_of(mtd,
struct fsmc_nand_data, mtd);
- void *__iomem *regs = host->regs_va;
+ void __iomem *regs = host->regs_va;
unsigned int bank = host->bank;
if (ctrl & NAND_CTRL_CHANGE) {
--
1.7.11.4
^ permalink raw reply related
* [PATCH 00/11] mtd/nand: fsmc driver updates
From: Vipin Kumar @ 2012-10-09 10:44 UTC (permalink / raw)
To: linux-arm-kernel
This patch-set contains several fixes and a few enhancements in fsmc driver.
Modifications include
- General enhancements
* Add ready/busy support through a GPIO pin
* Add software bch support
* Increase ecc loactions to 640
* Support multiple banks
* Use relaxed io accessors for increased throughput
- Enhance DT support
* Add timing parameters
- Several fixes
* Fix the type for regs
* Replace change_bit routine to handle unaligned addresses
* Provide contiguous buffers for DMA operation
Vipin Kumar (11):
fsmc/nand:FIX: Change the type for regs to void __iomem *
fsmc/nand: Rearrange the fsmc_nand_data structure and update comments
fsmc/nand: Support multiple banks connected to controller
fsmc/nand: Accept nand timing parameters via DT
fsmc: Implement ready/busy through gpio pin
fsmc/nand: Modify the wait to uninterruptible
fsmc/nand: Provide contiguous buffers to dma
fsmc/nand: Use relaxed variants of io accessors
fsmc/nand:FIX: replace change_bit routine
fsmc/nand: Add sw bch support for ecc calculation/correction
nand: Increase the ecc placement locations to 640
.../devicetree/bindings/mtd/fsmc-nand.txt | 29 ++
arch/arm/boot/dts/spear300.dtsi | 1 +
arch/arm/boot/dts/spear310.dtsi | 1 +
arch/arm/boot/dts/spear320.dtsi | 1 +
arch/arm/boot/dts/spear600.dtsi | 1 +
arch/arm/mach-u300/core.c | 1 +
drivers/mtd/nand/fsmc_nand.c | 419 ++++++++++++++-------
include/linux/mtd/fsmc.h | 18 +-
include/linux/mtd/mtd.h | 2 +-
9 files changed, 332 insertions(+), 141 deletions(-)
--
1.7.11.4
^ permalink raw reply
* [PATCH] ARM: dts: exynos4210-trats: Split memory into 4 sections
From: Tomasz Figa @ 2012-10-09 10:39 UTC (permalink / raw)
To: linux-arm-kernel
Since the maximum section size on mach-exynos is set to 256MiB, boards
with memory configuration defined using sections bigger than 256MiB will
fail to boot with a kernel panic.
This patch modifies the dts file of Samsung Trats board to define four
sections of 256MiB instead of two of 512MiB to fix the boot problem.
Signed-off-by: Tomasz Figa <t.figa@samsung.com>
---
arch/arm/boot/dts/exynos4210-trats.dts | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index 73567b8..a21511c 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -20,8 +20,10 @@
compatible = "samsung,trats", "samsung,exynos4210";
memory {
- reg = <0x40000000 0x20000000
- 0x60000000 0x20000000>;
+ reg = <0x40000000 0x10000000
+ 0x50000000 0x10000000
+ 0x60000000 0x10000000
+ 0x70000000 0x10000000>;
};
chosen {
--
1.7.12
^ permalink raw reply related
* [PATCH] Add McSPI devices found in AM33xx SoC to dtsi
From: Philip, Avinash @ 2012-10-09 10:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAAek22HhtFc-1XOFrQC8DKZ9VdKyuShE_G_j4581WL15JTNJXg@mail.gmail.com>
On Tue, Oct 09, 2012 at 10:40:58, Phil Pokorny wrote:
> We're using the BeagleBone for a project and we need the SPI devices
> available and configured with all available chip selects.
>
> Please accept the following patch to add these to the base .dtsi file
> so they can then be enabled in the beaglebone specific .dts with
> minimal fuss.
Patch for adding MCSPI in am33xx.dtsi already been sent by me.
https://lkml.org/lkml/2012/9/18/32
Thanks
Avinash
>
^ permalink raw reply
* [PATCH] ARM: integrator_cp: fix build failure
From: Linus Walleij @ 2012-10-09 10:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349631760-21350-1-git-send-email-olof@lixom.net>
On Sun, Oct 7, 2012 at 7:42 PM, Olof Johansson <olof@lixom.net> wrote:
> arch/arm/mach-integrator/integrator_cp.c:272:32: error: 'of_aliases'
> undeclared (first use in this function)
>
> Move the OF-only timer init under #ifdef CONFIG_OF, just like
> integrator_ap has it.
>
> Signed-off-by: Olof Johansson <olof@lixom.net>
My mistake.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Thanks Olof!
Linus Walleij
^ permalink raw reply
* [PATCH v2 2/2] mtd: sh_flctl: Add device tree support
From: Bastian Hecht @ 2012-10-09 9:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1349776729-9311-1-git-send-email-hechtb@gmail.com>
The flctl can now be probed via device tree setup in addition to the
existing platform data way.
SoC specific setup data is set in the .data member of the OF match, so
kept within the driver itself, while board/user specific setup - like
partitioning - is taken from the device tree.
Actual configuration is added for the SoC sh7372.
Signed-off-by: Bastian Hecht <hechtb@gmail.com>
---
v2: added dmas and dma-names fields to the bindings. These are not used yet
but are added for completing the bindings and will be needed later.
.../devicetree/bindings/mtd/flctl-nand.txt | 49 +++++++++++
drivers/mtd/nand/sh_flctl.c | 92 ++++++++++++++++++--
2 files changed, 134 insertions(+), 7 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mtd/flctl-nand.txt
diff --git a/Documentation/devicetree/bindings/mtd/flctl-nand.txt b/Documentation/devicetree/bindings/mtd/flctl-nand.txt
new file mode 100644
index 0000000..427f46d
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/flctl-nand.txt
@@ -0,0 +1,49 @@
+FLCTL NAND controller
+
+Required properties:
+- compatible : "renesas,shmobile-flctl-sh7372"
+- reg : Address range of the FLCTL
+- interrupts : flste IRQ number
+- nand-bus-width : bus width to NAND chip
+
+Optional properties:
+- dmas: DMA specifier(s)
+- dma-names: name for each DMA specifier. Valid names are
+ "data_tx", "data_rx", "ecc_tx", "ecc_rx"
+
+The DMA fields are not used yet in the driver but are listed here for
+completing the bindings.
+
+The device tree may optionally contain sub-nodes describing partitions of the
+address space. See partition.txt for more detail.
+
+Example:
+
+ flctl at e6a30000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "renesas,shmobile-flctl-sh7372";
+ reg = <0xe6a30000 0x100>;
+ interrupts = <0x0d80>;
+
+ nand-bus-width = <16>;
+
+ dmas = <&dmac 1 /* data_tx */
+ &dmac 2;> /* data_rx */
+ dma-names = "data_tx", "data_rx";
+
+ system at 0 {
+ label = "system";
+ reg = <0x0 0x8000000>;
+ };
+
+ userdata at 8000000 {
+ label = "userdata";
+ reg = <0x8000000 0x10000000>;
+ };
+
+ cache at 18000000 {
+ label = "cache";
+ reg = <0x18000000 0x8000000>;
+ };
+ };
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index 1105fbb..02ff9d1 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -29,6 +29,9 @@
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_mtd.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/sh_dma.h>
@@ -1021,6 +1024,73 @@ static irqreturn_t flctl_handle_flste(int irq, void *dev_id)
return IRQ_HANDLED;
}
+#ifdef CONFIG_OF
+struct flctl_soc_config {
+ unsigned long flcmncr_val;
+ unsigned has_hwecc:1;
+ unsigned use_holden:1;
+};
+
+static struct flctl_soc_config flctl_sh7372_config = {
+ .flcmncr_val = CLK_16B_12L_4H | TYPESEL_SET | SHBUSSEL,
+ .has_hwecc = 1,
+ .use_holden = 1,
+};
+
+static const struct of_device_id of_flctl_match[] = {
+ { .compatible = "renesas,shmobile-flctl-sh7372",
+ .data = &flctl_sh7372_config },
+ {},
+};
+MODULE_DEVICE_TABLE(of, of_flctl_match);
+
+static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
+{
+ const struct of_device_id *match;
+ struct flctl_soc_config *config;
+ struct sh_flctl_platform_data *pdata;
+ struct device_node *dn = dev->of_node;
+ int ret;
+
+ match = of_match_device(of_flctl_match, dev);
+ if (match)
+ config = (struct flctl_soc_config *)match->data;
+ else {
+ dev_err(dev, "%s: no OF configuration attached\n", __func__);
+ return NULL;
+ }
+
+ pdata = devm_kzalloc(dev, sizeof(struct sh_flctl_platform_data),
+ GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev, "%s: failed to allocate config data\n", __func__);
+ return NULL;
+ }
+
+ /* set SoC specific options */
+ pdata->flcmncr_val = config->flcmncr_val;
+ pdata->has_hwecc = config->has_hwecc;
+ pdata->use_holden = config->use_holden;
+
+ /* parse user defined options */
+ ret = of_get_nand_bus_width(dn);
+ if (ret == 16)
+ pdata->flcmncr_val |= SEL_16BIT;
+ else if (ret != 8) {
+ dev_err(dev, "%s: invalid bus width\n", __func__);
+ return NULL;
+ }
+
+ return pdata;
+}
+#else /* CONFIG_OF */
+#define of_flctl_match NULL
+static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
+{
+ return NULL;
+}
+#endif /* CONFIG_OF */
+
static int __devinit flctl_probe(struct platform_device *pdev)
{
struct resource *res;
@@ -1030,12 +1100,7 @@ static int __devinit flctl_probe(struct platform_device *pdev)
struct sh_flctl_platform_data *pdata;
int ret = -ENXIO;
int irq;
-
- pdata = pdev->dev.platform_data;
- if (pdata == NULL) {
- dev_err(&pdev->dev, "no platform data defined\n");
- return -EINVAL;
- }
+ struct mtd_part_parser_data ppdata = {};
flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
if (!flctl) {
@@ -1067,6 +1132,16 @@ static int __devinit flctl_probe(struct platform_device *pdev)
goto err_flste;
}
+ if (pdev->dev.of_node)
+ pdata = flctl_parse_dt(&pdev->dev);
+ else
+ pdata = pdev->dev.platform_data;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "no setup data defined\n");
+ return -EINVAL;
+ }
+
platform_set_drvdata(pdev, flctl);
flctl_mtd = &flctl->mtd;
nand = &flctl->chip;
@@ -1109,7 +1184,9 @@ static int __devinit flctl_probe(struct platform_device *pdev)
if (ret)
goto err_chip;
- mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts);
+ ppdata.of_node = pdev->dev.of_node;
+ ret = mtd_device_parse_register(flctl_mtd, NULL, &ppdata, pdata->parts,
+ pdata->nr_parts);
return 0;
@@ -1143,6 +1220,7 @@ static struct platform_driver flctl_driver = {
.driver = {
.name = "sh_flctl",
.owner = THIS_MODULE,
+ .of_match_table = of_flctl_match,
},
};
--
1.7.5.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox