* [PATCH v2 00/26] Add support for the Ingenic JZ4740 System-on-a-Chip
@ 2010-06-19 5:08 Lars-Peter Clausen
2010-06-19 5:08 ` [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver Lars-Peter Clausen
2010-06-20 9:26 ` [PATCH v2 00/26] Add support for the Ingenic JZ4740 System-on-a-Chip Thomas Bogendoerfer
0 siblings, 2 replies; 12+ messages in thread
From: Lars-Peter Clausen @ 2010-06-19 5:08 UTC (permalink / raw)
To: Ralf Baechle
Cc: linux-mips, Paul Gortmaker, Lars-Peter Clausen, Mark Brown,
Samuel Ortiz, alsa-devel, Alessandro Zummo, Greg Kroah-Hartman,
linux-mmc, linux-kernel, lm-sensors, David Brownell, linux-mtd,
linux-fbdev, Anton Vorontsov, rtc-linux, Andrew Morton,
David Woodhouse, linux-usb, Liam Girdwood
Foreword:
Ralf suggested that it might be a good idea in order to allow for reasonable
testing and to avoid build failures due to two-way dependencies in different
parts of the kernel, that he applies all the patches once they have been acked
by their respective maintainers, feeds them into -next and eventually sends the
whole series to Linus. One exception will be the ASoC patches which will, due to
major changes in the ASoC subsystem, go through the ASoC tree.
So if you are a maintainer for one of the subsystem touched by this series and
would rather see the patch going through your tree (given the patch is ok)
please tell.
This patch series adds support for the Ingenic JZ4740 System-on-a-Chip.
The JZ4740 has a mostly MIPS32 compatible core (no on cpu timers) and many on
chip peripherals like RTC, NAND, MMC, OHCI, UDC, ADC, I2C, SPI, AC97, I2S, I2S
Codec, UART and LCD controller.
The JZ4740 is mostly used in eBooks, PMPs and hand-held consoles.
This series contains patches for the Qi Ben NanoNote clamshell device as the
inital supported device.
Changes since v1:
There have been some minor changes since v1, mostly code cleanup and some
functional changes. One bigger change is that there is now a MFD driver for
the ADC core which does IRQ demultiplexing for the ADC unit and synchronizes
access to shared registers between the different users of the ADC core.
The patch adding a defconfig for the Qi LB60 has been dropped.
A detailed list of changes is present in each patch.
- Lars
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Anton Vorontsov <cbouatmailru@gmail.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Liam Girdwood <lrg@slimlogic.co.uk>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Paul Gortmaker <p_gortmaker@yahoo.com>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: alsa-devel@alsa-project.org
Cc: linux-fbdev@vger.kernel.org
Cc: linux-mmc@vger.kernel.org
Cc: linux-mtd@lists.infradead.org
Cc: linux-usb@vger.kernel.org
Cc: lm-sensors@lm-sensors.org
Cc: rtc-linux@googlegroups.com
Lars-Peter Clausen (26):
MIPS: Add base support for Ingenic JZ4740 System-on-a-Chip
MIPS: jz4740: Add IRQ handler code
MIPS: JZ4740: Add clock API support.
MIPS: JZ4740: Add timer support
MIPS: JZ4740: Add clocksource/clockevent support.
MIPS: JZ4740: Add power-management and system reset support
MIPS: JZ4740: Add setup code
MIPS: JZ4740: Add gpio support
MIPS: JZ4740: Add DMA support.
MIPS: JZ4740: Add PWM support
MIPS: JZ4740: Add serial support
MIPS: JZ4740: Add prom support
MIPS: JZ4740: Add platform devices
MIPS: JZ4740: Add Kbuild files
RTC: Add JZ4740 RTC driver
fbdev: Add JZ4740 framebuffer driver
MTD: Nand: Add JZ4740 NAND driver
MMC: Add JZ4740 mmc driver
USB: Add JZ4740 ohci support
alsa: ASoC: Add JZ4740 codec driver
alsa: ASoC: Add JZ4740 ASoC support
MFD: Add JZ4740 ADC driver
hwmon: Add JZ4740 ADC driver
power: Add JZ4740 battery driver.
MIPS: JZ4740: Add qi_lb60 board support
alsa: ASoC: JZ4740: Add qi_lb60 board driver
arch/mips/Kbuild.platforms | 1 +
arch/mips/Kconfig | 13 +
arch/mips/include/asm/bootinfo.h | 6 +
arch/mips/include/asm/cpu.h | 9 +-
arch/mips/include/asm/mach-jz4740/base.h | 26 +
arch/mips/include/asm/mach-jz4740/clock.h | 28 +
arch/mips/include/asm/mach-jz4740/dma.h | 90 +++
arch/mips/include/asm/mach-jz4740/gpio.h | 398 +++++++++++
arch/mips/include/asm/mach-jz4740/irq.h | 57 ++
arch/mips/include/asm/mach-jz4740/platform.h | 36 +
arch/mips/include/asm/mach-jz4740/timer.h | 22 +
arch/mips/include/asm/mach-jz4740/war.h | 25 +
arch/mips/jz4740/Kconfig | 12 +
arch/mips/jz4740/Makefile | 20 +
arch/mips/jz4740/Platform | 5 +
arch/mips/jz4740/board-qi_lb60.c | 483 +++++++++++++
arch/mips/jz4740/clock-debugfs.c | 109 +++
arch/mips/jz4740/clock.c | 920 ++++++++++++++++++++++++
arch/mips/jz4740/clock.h | 76 ++
arch/mips/jz4740/dma.c | 289 ++++++++
arch/mips/jz4740/gpio.c | 601 ++++++++++++++++
arch/mips/jz4740/irq.c | 169 +++++
arch/mips/jz4740/irq.h | 21 +
arch/mips/jz4740/platform.c | 284 ++++++++
arch/mips/jz4740/pm.c | 56 ++
arch/mips/jz4740/prom.c | 68 ++
arch/mips/jz4740/pwm.c | 169 +++++
arch/mips/jz4740/reset.c | 79 ++
arch/mips/jz4740/reset.h | 7 +
arch/mips/jz4740/serial.c | 33 +
arch/mips/jz4740/serial.h | 21 +
arch/mips/jz4740/setup.c | 29 +
arch/mips/jz4740/time.c | 144 ++++
arch/mips/jz4740/timer.c | 48 ++
arch/mips/jz4740/timer.h | 136 ++++
arch/mips/kernel/cpu-probe.c | 20 +
arch/mips/mm/tlbex.c | 5 +
drivers/hwmon/Kconfig | 11 +
drivers/hwmon/Makefile | 1 +
drivers/hwmon/jz4740-hwmon.c | 206 ++++++
drivers/mfd/Kconfig | 8 +
drivers/mfd/Makefile | 1 +
drivers/mfd/jz4740-adc.c | 392 ++++++++++
drivers/mmc/host/Kconfig | 8 +
drivers/mmc/host/Makefile | 1 +
drivers/mmc/host/jz4740_mmc.c | 993 ++++++++++++++++++++++++++
drivers/mtd/nand/Kconfig | 6 +
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/jz4740_nand.c | 474 ++++++++++++
drivers/power/Kconfig | 11 +
drivers/power/Makefile | 1 +
drivers/power/jz4740-battery.c | 445 ++++++++++++
drivers/rtc/Kconfig | 11 +
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-jz4740.c | 341 +++++++++
drivers/usb/Kconfig | 1 +
drivers/usb/host/ohci-hcd.c | 5 +
drivers/usb/host/ohci-jz4740.c | 276 +++++++
drivers/video/Kconfig | 9 +
drivers/video/Makefile | 1 +
drivers/video/jz4740_fb.c | 817 +++++++++++++++++++++
include/linux/jz4740-adc.h | 32 +
include/linux/jz4740_fb.h | 58 ++
include/linux/mmc/jz4740_mmc.h | 15 +
include/linux/mtd/jz4740_nand.h | 34 +
include/linux/power/jz4740-battery.h | 24 +
sound/soc/Kconfig | 1 +
sound/soc/Makefile | 1 +
sound/soc/codecs/Kconfig | 4 +
sound/soc/codecs/Makefile | 2 +
sound/soc/codecs/jz4740-codec.c | 514 +++++++++++++
sound/soc/codecs/jz4740-codec.h | 20 +
sound/soc/jz4740/Kconfig | 23 +
sound/soc/jz4740/Makefile | 13 +
sound/soc/jz4740/jz4740-i2s.c | 540 ++++++++++++++
sound/soc/jz4740/jz4740-i2s.h | 18 +
sound/soc/jz4740/jz4740-pcm.c | 373 ++++++++++
sound/soc/jz4740/jz4740-pcm.h | 22 +
sound/soc/jz4740/qi_lb60.c | 167 +++++
79 files changed, 10396 insertions(+), 1 deletions(-)
create mode 100644 arch/mips/include/asm/mach-jz4740/base.h
create mode 100644 arch/mips/include/asm/mach-jz4740/clock.h
create mode 100644 arch/mips/include/asm/mach-jz4740/dma.h
create mode 100644 arch/mips/include/asm/mach-jz4740/gpio.h
create mode 100644 arch/mips/include/asm/mach-jz4740/irq.h
create mode 100644 arch/mips/include/asm/mach-jz4740/platform.h
create mode 100644 arch/mips/include/asm/mach-jz4740/timer.h
create mode 100644 arch/mips/include/asm/mach-jz4740/war.h
create mode 100644 arch/mips/jz4740/Kconfig
create mode 100644 arch/mips/jz4740/Makefile
create mode 100644 arch/mips/jz4740/Platform
create mode 100644 arch/mips/jz4740/board-qi_lb60.c
create mode 100644 arch/mips/jz4740/clock-debugfs.c
create mode 100644 arch/mips/jz4740/clock.c
create mode 100644 arch/mips/jz4740/clock.h
create mode 100644 arch/mips/jz4740/dma.c
create mode 100644 arch/mips/jz4740/gpio.c
create mode 100644 arch/mips/jz4740/irq.c
create mode 100644 arch/mips/jz4740/irq.h
create mode 100644 arch/mips/jz4740/platform.c
create mode 100644 arch/mips/jz4740/pm.c
create mode 100644 arch/mips/jz4740/prom.c
create mode 100644 arch/mips/jz4740/pwm.c
create mode 100644 arch/mips/jz4740/reset.c
create mode 100644 arch/mips/jz4740/reset.h
create mode 100644 arch/mips/jz4740/serial.c
create mode 100644 arch/mips/jz4740/serial.h
create mode 100644 arch/mips/jz4740/setup.c
create mode 100644 arch/mips/jz4740/time.c
create mode 100644 arch/mips/jz4740/timer.c
create mode 100644 arch/mips/jz4740/timer.h
create mode 100644 drivers/hwmon/jz4740-hwmon.c
create mode 100644 drivers/mfd/jz4740-adc.c
create mode 100644 drivers/mmc/host/jz4740_mmc.c
create mode 100644 drivers/mtd/nand/jz4740_nand.c
create mode 100644 drivers/power/jz4740-battery.c
create mode 100644 drivers/rtc/rtc-jz4740.c
create mode 100644 drivers/usb/host/ohci-jz4740.c
create mode 100644 drivers/video/jz4740_fb.c
create mode 100644 include/linux/jz4740-adc.h
create mode 100644 include/linux/jz4740_fb.h
create mode 100644 include/linux/mmc/jz4740_mmc.h
create mode 100644 include/linux/mtd/jz4740_nand.h
create mode 100644 include/linux/power/jz4740-battery.h
create mode 100644 sound/soc/codecs/jz4740-codec.c
create mode 100644 sound/soc/codecs/jz4740-codec.h
create mode 100644 sound/soc/jz4740/Kconfig
create mode 100644 sound/soc/jz4740/Makefile
create mode 100644 sound/soc/jz4740/jz4740-i2s.c
create mode 100644 sound/soc/jz4740/jz4740-i2s.h
create mode 100644 sound/soc/jz4740/jz4740-pcm.c
create mode 100644 sound/soc/jz4740/jz4740-pcm.h
create mode 100644 sound/soc/jz4740/qi_lb60.c
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver
2010-06-19 5:08 [PATCH v2 00/26] Add support for the Ingenic JZ4740 System-on-a-Chip Lars-Peter Clausen
@ 2010-06-19 5:08 ` Lars-Peter Clausen
2010-07-08 6:06 ` Artem Bityutskiy
2010-07-17 12:15 ` [PATCH v3] " Lars-Peter Clausen
2010-06-20 9:26 ` [PATCH v2 00/26] Add support for the Ingenic JZ4740 System-on-a-Chip Thomas Bogendoerfer
1 sibling, 2 replies; 12+ messages in thread
From: Lars-Peter Clausen @ 2010-06-19 5:08 UTC (permalink / raw)
To: Ralf Baechle
Cc: linux-mips, Lars-Peter Clausen, David Woodhouse, linux-kernel,
linux-mtd
This patch adds support for the NAND controller on JZ4740 SoCs.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: linux-mtd@lists.infradead.org
---
Changes since v1
- JZ4740: Remove debug macro
- Fix platform driver remove callback
- Add custom nand read/write callback since we need to support more then 64 ecc
bytes
---
drivers/mtd/nand/Kconfig | 6 +
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/jz4740_nand.c | 474 +++++++++++++++++++++++++++++++++++++++
include/linux/mtd/jz4740_nand.h | 34 +++
4 files changed, 515 insertions(+), 0 deletions(-)
create mode 100644 drivers/mtd/nand/jz4740_nand.c
create mode 100644 include/linux/mtd/jz4740_nand.h
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index ffc3720..362d177 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -526,4 +526,10 @@ config MTD_NAND_NUC900
This enables the driver for the NAND Flash on evaluation board based
on w90p910 / NUC9xx.
+config MTD_NAND_JZ4740
+ tristate "Support for JZ4740 SoC NAND controller"
+ depends on MACH_JZ4740
+ help
+ Enables support for NAND Flash on JZ4740 SoC based boards.
+
endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index e8ab884..ac83dcd 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -46,5 +46,6 @@ obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o
obj-$(CONFIG_MTD_NAND_BCM_UMI) += bcm_umi_nand.o nand_bcm_umi.o
obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o
obj-$(CONFIG_MTD_NAND_RICOH) += r852.o
+obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
new file mode 100644
index 0000000..8c55f8a
--- /dev/null
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 SoC NAND controller driver
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/mtd/jz4740_nand.h>
+#include <linux/gpio.h>
+
+#define JZ_REG_NAND_CTRL 0x50
+#define JZ_REG_NAND_ECC_CTRL 0x100
+#define JZ_REG_NAND_DATA 0x104
+#define JZ_REG_NAND_PAR0 0x108
+#define JZ_REG_NAND_PAR1 0x10C
+#define JZ_REG_NAND_PAR2 0x110
+#define JZ_REG_NAND_IRQ_STAT 0x114
+#define JZ_REG_NAND_IRQ_CTRL 0x118
+#define JZ_REG_NAND_ERR(x) (0x11C + (x << 2))
+
+#define JZ_NAND_ECC_CTRL_PAR_READY BIT(4)
+#define JZ_NAND_ECC_CTRL_ENCODING BIT(3)
+#define JZ_NAND_ECC_CTRL_RS BIT(2)
+#define JZ_NAND_ECC_CTRL_RESET BIT(1)
+#define JZ_NAND_ECC_CTRL_ENABLE BIT(0)
+
+#define JZ_NAND_STATUS_ERR_COUNT (BIT(31) | BIT(30) | BIT(29))
+#define JZ_NAND_STATUS_PAD_FINISH BIT(4)
+#define JZ_NAND_STATUS_DEC_FINISH BIT(3)
+#define JZ_NAND_STATUS_ENC_FINISH BIT(2)
+#define JZ_NAND_STATUS_UNCOR_ERROR BIT(1)
+#define JZ_NAND_STATUS_ERROR BIT(0)
+
+#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT(x << 1)
+#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT((x << 1) + 1)
+
+#define JZ_NAND_DATA_ADDR ((void __iomem *)0xB8000000)
+#define JZ_NAND_CMD_ADDR (JZ_NAND_DATA_ADDR + 0x8000)
+#define JZ_NAND_ADDR_ADDR (JZ_NAND_DATA_ADDR + 0x10000)
+
+struct jz_nand {
+ struct mtd_info mtd;
+ struct nand_chip chip;
+ void __iomem *base;
+ struct resource *mem;
+
+ struct jz_nand_platform_data *pdata;
+ bool is_reading;
+};
+
+static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
+{
+ return container_of(mtd, struct jz_nand, mtd);
+}
+
+static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
+{
+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
+ struct nand_chip *chip = mtd->priv;
+ uint32_t reg;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
+ if (ctrl & NAND_ALE)
+ chip->IO_ADDR_W = JZ_NAND_ADDR_ADDR;
+ else if (ctrl & NAND_CLE)
+ chip->IO_ADDR_W = JZ_NAND_CMD_ADDR;
+ else
+ chip->IO_ADDR_W = JZ_NAND_DATA_ADDR;
+
+ reg = readl(nand->base + JZ_REG_NAND_CTRL);
+ if (ctrl & NAND_NCE)
+ reg |= JZ_NAND_CTRL_ASSERT_CHIP(0);
+ else
+ reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0);
+ writel(reg, nand->base + JZ_REG_NAND_CTRL);
+ }
+ if (dat != NAND_CMD_NONE)
+ writeb(dat, chip->IO_ADDR_W);
+}
+
+static int jz_nand_dev_ready(struct mtd_info *mtd)
+{
+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
+ return gpio_get_value_cansleep(nand->pdata->busy_gpio);
+}
+
+static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
+{
+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
+ uint32_t reg;
+
+ writel(0, nand->base + JZ_REG_NAND_IRQ_STAT);
+ reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+
+ reg |= JZ_NAND_ECC_CTRL_RESET;
+ reg |= JZ_NAND_ECC_CTRL_ENABLE;
+ reg |= JZ_NAND_ECC_CTRL_RS;
+
+ switch (mode) {
+ case NAND_ECC_READ:
+ reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
+ nand->is_reading = true;
+ break;
+ case NAND_ECC_WRITE:
+ reg |= JZ_NAND_ECC_CTRL_ENCODING;
+ nand->is_reading = false;
+ break;
+ default:
+ break;
+ }
+
+ writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+}
+
+static int jz_nand_calculate_ecc_rs(struct mtd_info *mtd, const uint8_t *dat,
+ uint8_t *ecc_code)
+{
+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
+ uint32_t reg, status;
+ int i;
+ static uint8_t empty_block_ecc[] = {0xcd, 0x9d, 0x90, 0x58, 0xf4,
+ 0x8b, 0xff, 0xb7, 0x6f};
+
+ if (nand->is_reading)
+ return 0;
+
+ do {
+ status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
+ } while (!(status & JZ_NAND_STATUS_ENC_FINISH));
+
+ reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+ reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
+ writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+ for (i = 0; i < 9; ++i)
+ ecc_code[i] = readb(nand->base + JZ_REG_NAND_PAR0 + i);
+
+ /* If the written data is completly 0xff, we also want to write 0xff as
+ * ecc, otherwise we will get in trouble when doing subpage writes. */
+ if (memcmp(ecc_code, empty_block_ecc, 9) == 0)
+ memset(ecc_code, 0xff, 9);
+
+ return 0;
+}
+
+static void correct_data(uint8_t *dat, int index, int mask)
+{
+ int offset = index & 0x7;
+ uint16_t data;
+
+ index += (index >> 3);
+
+ data = dat[index];
+ data |= dat[index+1] << 8;
+
+ mask ^= (data >> offset) & 0x1ff;
+ data &= ~(0x1ff << offset);
+ data |= (mask << offset);
+
+ dat[index] = data & 0xff;
+ dat[index+1] = (data >> 8) & 0xff;
+}
+
+static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
+ uint8_t *read_ecc, uint8_t *calc_ecc)
+{
+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
+ int i, error_count, index;
+ uint32_t reg, status, error;
+ uint32_t t;
+
+ t = read_ecc[0];
+
+ if (t == 0xff) {
+ for (i = 1; i < 9; ++i)
+ t &= read_ecc[i];
+
+ t &= dat[0];
+ t &= dat[nand->chip.ecc.size / 2];
+ t &= dat[nand->chip.ecc.size - 1];
+
+ if (t == 0xff) {
+ for (i = 1; i < nand->chip.ecc.size - 1; ++i)
+ t &= dat[i];
+ if (t == 0xff)
+ return 0;
+ }
+ }
+
+ for (i = 0; i < 9; ++i)
+ writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i);
+
+ reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+ reg |= JZ_NAND_ECC_CTRL_PAR_READY;
+ writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+ do {
+ status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
+ } while (!(status & JZ_NAND_STATUS_DEC_FINISH));
+
+ reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+ reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
+ writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+ if (status & JZ_NAND_STATUS_ERROR) {
+ if (status & JZ_NAND_STATUS_UNCOR_ERROR)
+ return -1;
+
+ error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29;
+
+ for (i = 0; i < error_count; ++i) {
+ error = readl(nand->base + JZ_REG_NAND_ERR(i));
+ index = ((error >> 16) & 0x1ff) - 1;
+ if (index >= 0 && index < 512)
+ correct_data(dat, index, error & 0x1ff);
+ }
+
+ return error_count;
+ }
+
+ return 0;
+}
+
+
+/* Copy paste of nand_read_page_hwecc_oob_first except for different eccpos
+ * handling. The ecc area is for 4k chips 72 bytes long and thus does not fit
+ * into the eccpos array. */
+static int jz_nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
+ struct nand_chip *chip, uint8_t *buf, int page)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ uint8_t *p = buf;
+ unsigned int ecc_offset = chip->page_shift;
+
+ /* Read the OOB area first */
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+
+ for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ int stat;
+
+ chip->ecc.hwctl(mtd, NAND_ECC_READ);
+ chip->read_buf(mtd, p, eccsize);
+
+ stat = chip->ecc.correct(mtd, p, &chip->oob_poi[i], NULL);
+ if (stat < 0)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
+ }
+ return 0;
+}
+
+/* Copy-and-paste of nand_write_page_hwecc with different eccpos handling. */
+static void jz_nand_write_page_hwecc(struct mtd_info *mtd,
+ struct nand_chip *chip, const uint8_t *buf)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ const uint8_t *p = buf;
+ unsigned int ecc_offset = chip->page_shift;
+
+ for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+ chip->write_buf(mtd, p, eccsize);
+ chip->ecc.calculate(mtd, p, &chip->oob_poi[i]);
+ }
+
+ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+static const char *part_probes[] = {"cmdline", NULL};
+#endif
+
+static int __devinit jz_nand_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct jz_nand *nand;
+ struct nand_chip *chip;
+ struct mtd_info *mtd;
+ struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+#ifdef CONFIG_MTD_PARTITIONS
+ struct mtd_partition *partition_info;
+ int num_partitions = 0;
+#endif
+
+ nand = kzalloc(sizeof(*nand), GFP_KERNEL);
+ if (!nand) {
+ dev_err(&pdev->dev, "Failed to allocate device structure.\n");
+ return -ENOMEM;
+ }
+
+ nand->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!nand->mem) {
+ dev_err(&pdev->dev, "Failed to get platform mmio memory\n");
+ ret = -ENOENT;
+ goto err_free;
+ }
+
+ nand->mem = request_mem_region(nand->mem->start,
+ resource_size(nand->mem), pdev->name);
+ if (!nand->mem) {
+ dev_err(&pdev->dev, "Failed to request mmio memory region\n");
+ ret = -EBUSY;
+ goto err_free;
+ }
+
+ nand->base = ioremap(nand->mem->start, resource_size(nand->mem));
+ if (!nand->base) {
+ dev_err(&pdev->dev, "Failed to ioremap mmio memory region\n");
+ ret = -EBUSY;
+ goto err_release_mem;
+ }
+
+ if (pdata && gpio_is_valid(pdata->busy_gpio)) {
+ ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to request busy gpio %d: %d\n",
+ pdata->busy_gpio, ret);
+ goto err_iounmap;
+ }
+ }
+
+ mtd = &nand->mtd;
+ chip = &nand->chip;
+ mtd->priv = chip;
+ mtd->owner = THIS_MODULE;
+ mtd->name = "jz4740-nand";
+
+ chip->ecc.hwctl = jz_nand_hwctl;
+ chip->ecc.calculate = jz_nand_calculate_ecc_rs;
+ chip->ecc.correct = jz_nand_correct_ecc_rs;
+ chip->ecc.mode = NAND_ECC_HW_OOB_FIRST;
+ chip->ecc.size = 512;
+ chip->ecc.bytes = 9;
+
+ chip->ecc.read_page = jz_nand_read_page_hwecc_oob_first;
+ chip->ecc.write_page = jz_nand_write_page_hwecc;
+
+ if (pdata)
+ chip->ecc.layout = pdata->ecc_layout;
+
+ chip->chip_delay = 50;
+ chip->cmd_ctrl = jz_nand_cmd_ctrl;
+
+ if (pdata && gpio_is_valid(pdata->busy_gpio))
+ chip->dev_ready = jz_nand_dev_ready;
+
+ chip->IO_ADDR_R = JZ_NAND_DATA_ADDR;
+ chip->IO_ADDR_W = JZ_NAND_DATA_ADDR;
+
+ nand->pdata = pdata;
+ platform_set_drvdata(pdev, nand);
+
+ ret = nand_scan_ident(mtd, 1, NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to scan nand\n");
+ goto err_gpio_free;
+ }
+
+ if (pdata && pdata->ident_callback) {
+ pdata->ident_callback(pdev, chip, &pdata->partitions,
+ &pdata->num_partitions);
+ }
+
+ ret = nand_scan_tail(mtd);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to scan nand\n");
+ goto err_gpio_free;
+ }
+
+#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ num_partitions = parse_mtd_partitions(mtd, part_probes,
+ &partition_info, 0);
+#endif
+ if (num_partitions <= 0 && pdata) {
+ num_partitions = pdata->num_partitions;
+ partition_info = pdata->partitions;
+ }
+
+ if (num_partitions > 0)
+ ret = add_mtd_partitions(mtd, partition_info, num_partitions);
+ else
+#endif
+ ret = add_mtd_device(mtd);
+
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to add mtd device\n");
+ goto err_nand_release;
+ }
+
+ dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n");
+
+ return 0;
+err_nand_release:
+ nand_release(&nand->mtd);
+err_gpio_free:
+ platform_set_drvdata(pdev, NULL);
+ gpio_free(pdata->busy_gpio);
+err_iounmap:
+ iounmap(nand->base);
+err_release_mem:
+ release_mem_region(nand->mem->start, resource_size(nand->mem));
+err_free:
+ kfree(nand);
+ return ret;
+}
+
+static int __devexit jz_nand_remove(struct platform_device *pdev)
+{
+ struct jz_nand *nand = platform_get_drvdata(pdev);
+
+ nand_release(&nand->mtd);
+
+ iounmap(nand->base);
+ release_mem_region(nand->mem->start, resource_size(nand->mem));
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(nand);
+
+ return 0;
+}
+
+struct platform_driver jz_nand_driver = {
+ .probe = jz_nand_probe,
+ .remove = __devexit_p(jz_nand_remove),
+ .driver = {
+ .name = "jz4740-nand",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init jz_nand_init(void)
+{
+ return platform_driver_register(&jz_nand_driver);
+}
+module_init(jz_nand_init);
+
+static void __exit jz_nand_exit(void)
+{
+ platform_driver_unregister(&jz_nand_driver);
+}
+module_exit(jz_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("NAND controller driver for JZ4740 SoC");
+MODULE_ALIAS("platform:jz4740-nand");
diff --git a/include/linux/mtd/jz4740_nand.h b/include/linux/mtd/jz4740_nand.h
new file mode 100644
index 0000000..379f9b6
--- /dev/null
+++ b/include/linux/mtd/jz4740_nand.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 SoC NAND controller driver
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __JZ_NAND_H__
+#define __JZ_NAND_H__
+
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+struct jz_nand_platform_data {
+ int num_partitions;
+ struct mtd_partition *partitions;
+
+ struct nand_ecclayout *ecc_layout;
+
+ unsigned int busy_gpio;
+
+ void (*ident_callback)(struct platform_device *, struct nand_chip *,
+ struct mtd_partition **, int *num_partitions);
+};
+
+#endif
--
1.5.6.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v2 00/26] Add support for the Ingenic JZ4740 System-on-a-Chip
2010-06-19 5:08 [PATCH v2 00/26] Add support for the Ingenic JZ4740 System-on-a-Chip Lars-Peter Clausen
2010-06-19 5:08 ` [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver Lars-Peter Clausen
@ 2010-06-20 9:26 ` Thomas Bogendoerfer
2010-06-21 2:56 ` Xiangfu Liu
1 sibling, 1 reply; 12+ messages in thread
From: Thomas Bogendoerfer @ 2010-06-20 9:26 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: linux-mips, Paul Gortmaker, David Brownell, Mark Brown,
Samuel Ortiz, alsa-devel, Alessandro Zummo, Greg Kroah-Hartman,
linux-mmc, linux-kernel, Ralf Baechle, lm-sensors, linux-usb,
linux-mtd, linux-fbdev, Anton Vorontsov, rtc-linux, Andrew Morton,
David Woodhouse, Liam Girdwood
On Sat, Jun 19, 2010 at 07:08:05AM +0200, Lars-Peter Clausen wrote:
> This patch series adds support for the Ingenic JZ4740 System-on-a-Chip.
great stuff. I have a JZ4730 based netbook, for which I started magling
the provided sources quite some time ago, but I didn't reach the
point of submitting patches... there are a lot of common stuff between
JZ4730 and JZ4740 so IMHO it would be a good thing not to nail
everthing to JZ4740 namewise. It might also a good idea to select
something like arch/mips/jzrisc as base directory, put the
factored out code there and add JZ4730/JZ4740 in either seperate
files or directories.
Thomas.
--
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea. [ RFC1925, 2.3 ]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 00/26] Add support for the Ingenic JZ4740 System-on-a-Chip
2010-06-20 9:26 ` [PATCH v2 00/26] Add support for the Ingenic JZ4740 System-on-a-Chip Thomas Bogendoerfer
@ 2010-06-21 2:56 ` Xiangfu Liu
0 siblings, 0 replies; 12+ messages in thread
From: Xiangfu Liu @ 2010-06-21 2:56 UTC (permalink / raw)
To: Thomas Bogendoerfer
Cc: linux-mips, Paul Gortmaker, Lars-Peter Clausen, Mark Brown,
Samuel Ortiz, alsa-devel, Alessandro Zummo, Greg Kroah-Hartman,
linux-mmc, linux-kernel, Ralf Baechle, lm-sensors, David Brownell,
linux-mtd, linux-fbdev, Anton Vorontsov, rtc-linux, Andrew Morton,
David Woodhouse, linux-usb, Liam Girdwood
On 06/20/2010 05:26 PM, Thomas Bogendoerfer wrote:
> great stuff. I have a JZ4730 based netbook, for which I started magling
> the provided sources quite some time ago, but I didn't reach the
> point of submitting patches... there are a lot of common stuff between
> JZ4730 and JZ4740 so IMHO it would be a good thing not to nail
> everthing to JZ4740 namewise. It might also a good idea to select
> something like arch/mips/jzrisc as base directory, put the
Hi Thomas
I would advice "xburst" instead jzrisc. because the Ingenic call
their cpu "XBurst" series. like: XBurst JZ4740, XBurst JZ4750 ...
> factored out code there and add JZ4730/JZ4740 in either seperate
> files or directories.
--
Best Regards
Xiangfu Liu
http://www.openmobilefree.net
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver
2010-06-19 5:08 ` [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver Lars-Peter Clausen
@ 2010-07-08 6:06 ` Artem Bityutskiy
2010-07-08 13:20 ` Lars-Peter Clausen
2010-07-17 12:15 ` [PATCH v3] " Lars-Peter Clausen
1 sibling, 1 reply; 12+ messages in thread
From: Artem Bityutskiy @ 2010-07-08 6:06 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: linux-mips, linux-mtd, David Woodhouse, linux-kernel,
Ralf Baechle
On Sat, 2010-06-19 at 07:08 +0200, Lars-Peter Clausen wrote:
> diff --git a/include/linux/mtd/jz4740_nand.h b/include/linux/mtd/jz4740_nand.h
> new file mode 100644
> index 0000000..379f9b6
> --- /dev/null
> +++ b/include/linux/mtd/jz4740_nand.h
> @@ -0,0 +1,34 @@
> +/*
> + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
> + * JZ4740 SoC NAND controller driver
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + */
> +
> +#ifndef __JZ_NAND_H__
> +#define __JZ_NAND_H__
> +
> +#include <linux/mtd/nand.h>
> +#include <linux/mtd/partitions.h>
> +
> +struct jz_nand_platform_data {
> + int num_partitions;
> + struct mtd_partition *partitions;
> +
> + struct nand_ecclayout *ecc_layout;
> +
> + unsigned int busy_gpio;
> +
> + void (*ident_callback)(struct platform_device *, struct nand_chip *,
> + struct mtd_partition **, int *num_partitions);
> +};
> +
> +#endif
Do you really have to add your platform data strucutre to
"inlculde/mtd" ? That is quite global namespace, and ideally only things
like user-space interface and "public" interface of the MTD subsystem
should live there.
Can you keep this somewhere in mips architecture directory?
--
Best Regards,
Artem Bityutskiy (Артём Битюцкий)
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver
2010-07-08 13:20 ` Lars-Peter Clausen
@ 2010-07-08 13:19 ` Artem Bityutskiy
2010-07-08 14:02 ` Lars-Peter Clausen
0 siblings, 1 reply; 12+ messages in thread
From: Artem Bityutskiy @ 2010-07-08 13:19 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: linux-mips, linux-mtd, David Woodhouse, linux-kernel,
Ralf Baechle
On Thu, 2010-07-08 at 15:20 +0200, Lars-Peter Clausen wrote:
> On the other hand I'm wondering where on would put headers for non platform specific
> drivers?
If we are talking about MTD, then drivers/mtd ?
--
Best Regards,
Artem Bityutskiy (Артём Битюцкий)
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver
2010-07-08 6:06 ` Artem Bityutskiy
@ 2010-07-08 13:20 ` Lars-Peter Clausen
2010-07-08 13:19 ` Artem Bityutskiy
0 siblings, 1 reply; 12+ messages in thread
From: Lars-Peter Clausen @ 2010-07-08 13:20 UTC (permalink / raw)
To: dedekind1
Cc: linux-mips, linux-mtd, David Woodhouse, linux-kernel,
Ralf Baechle
Artem Bityutskiy wrote:
> On Sat, 2010-06-19 at 07:08 +0200, Lars-Peter Clausen wrote:
>> diff --git a/include/linux/mtd/jz4740_nand.h b/include/linux/mtd/jz4740_nand.h
>> new file mode 100644
>> index 0000000..379f9b6
>> --- /dev/null
>> +++ b/include/linux/mtd/jz4740_nand.h
>> @@ -0,0 +1,34 @@
>> +/*
>> + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
>> + * JZ4740 SoC NAND controller driver
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License as published by the
>> + * Free Software Foundation; either version 2 of the License, or (at your
>> + * option) any later version.
>> + *
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, write to the Free Software Foundation, Inc.,
>> + * 675 Mass Ave, Cambridge, MA 02139, USA.
>> + *
>> + */
>> +
>> +#ifndef __JZ_NAND_H__
>> +#define __JZ_NAND_H__
>> +
>> +#include <linux/mtd/nand.h>
>> +#include <linux/mtd/partitions.h>
>> +
>> +struct jz_nand_platform_data {
>> + int num_partitions;
>> + struct mtd_partition *partitions;
>> +
>> + struct nand_ecclayout *ecc_layout;
>> +
>> + unsigned int busy_gpio;
>> +
>> + void (*ident_callback)(struct platform_device *, struct nand_chip *,
>> + struct mtd_partition **, int *num_partitions);
>> +};
>> +
>> +#endif
>
> Do you really have to add your platform data strucutre to
> "inlculde/mtd" ? That is quite global namespace, and ideally only things
> like user-space interface and "public" interface of the MTD subsystem
> should live there.
>
> Can you keep this somewhere in mips architecture directory?
Hi
Hm, ok, I see. I'll move it to arch/mips/include/asm/mach-jz4740/ then.
But I guess I should move the headers for all the other jz4740 driver to the same
directory as well.
On the other hand I'm wondering where on would put headers for non platform specific
drivers?
- Lars
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver
2010-07-08 13:19 ` Artem Bityutskiy
@ 2010-07-08 14:02 ` Lars-Peter Clausen
2010-07-08 14:14 ` Artem Bityutskiy
0 siblings, 1 reply; 12+ messages in thread
From: Lars-Peter Clausen @ 2010-07-08 14:02 UTC (permalink / raw)
To: dedekind1
Cc: linux-mips, linux-mtd, David Woodhouse, linux-kernel,
Ralf Baechle
Artem Bityutskiy wrote:
> On Thu, 2010-07-08 at 15:20 +0200, Lars-Peter Clausen wrote:
>> On the other hand I'm wondering where on would put headers for non platform specific
>> drivers?
>
> If we are talking about MTD, then drivers/mtd ?
>
No, what I meant was header defining platform data structs and such.
And what I wanted to get at is an answer to why driver header files are put in
different directories while the driver files themselves are all keep in the same
directory. (drivers of the same subsystem that is)
- Lars
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver
2010-07-08 14:02 ` Lars-Peter Clausen
@ 2010-07-08 14:14 ` Artem Bityutskiy
0 siblings, 0 replies; 12+ messages in thread
From: Artem Bityutskiy @ 2010-07-08 14:14 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: linux-mips, linux-mtd, David Woodhouse, linux-kernel,
Ralf Baechle
On Thu, 2010-07-08 at 16:02 +0200, Lars-Peter Clausen wrote:
> Artem Bityutskiy wrote:
> > On Thu, 2010-07-08 at 15:20 +0200, Lars-Peter Clausen wrote:
> >> On the other hand I'm wondering where on would put headers for non platform specific
> >> drivers?
> >
> > If we are talking about MTD, then drivers/mtd ?
> >
> No, what I meant was header defining platform data structs and such.
> And what I wanted to get at is an answer to why driver header files are put in
> different directories while the driver files themselves are all keep in the same
> directory. (drivers of the same subsystem that is)
To be frank I do not know, I did not look at the whole picture, just at
the MTD part :-)
--
Best Regards,
Artem Bityutskiy (Артём Битюцкий)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v3] MTD: Nand: Add JZ4740 NAND driver
2010-06-19 5:08 ` [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver Lars-Peter Clausen
2010-07-08 6:06 ` Artem Bityutskiy
@ 2010-07-17 12:15 ` Lars-Peter Clausen
2010-07-18 16:54 ` Artem Bityutskiy
1 sibling, 1 reply; 12+ messages in thread
From: Lars-Peter Clausen @ 2010-07-17 12:15 UTC (permalink / raw)
To: Ralf Baechle
Cc: linux-mips, Lars-Peter Clausen, David Woodhouse, linux-kernel,
linux-mtd
This patch adds support for the NAND controller on JZ4740 SoCs.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: linux-mtd@lists.infradead.org
--
Changes since v1
- JZ4740: Remove debug macro
- Fix platform driver remove callback
- Add custom nand read/write callback since we need to support more then 64 ecc
bytes
Changes since v2
- Fix potential deadlock that can happen when the hardware is broken
- Move include file from include/linux/mtd/ to arch/mips/include/asm/mach-jz4740/
- {Enable,Disable} NAND-chip in {probe,remove}
- Supply memory bank address through platform resource
---
arch/mips/include/asm/mach-jz4740/jz4740_nand.h | 34 ++
drivers/mtd/nand/Kconfig | 6 +
drivers/mtd/nand/Makefile | 1 +
drivers/mtd/nand/jz4740_nand.c | 516 +++++++++++++++++++++++
4 files changed, 557 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/include/asm/mach-jz4740/jz4740_nand.h
create mode 100644 drivers/mtd/nand/jz4740_nand.c
diff --git a/arch/mips/include/asm/mach-jz4740/jz4740_nand.h b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
new file mode 100644
index 0000000..bb5b9a4
--- /dev/null
+++ b/arch/mips/include/asm/mach-jz4740/jz4740_nand.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 SoC NAND controller driver
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __ASM_MACH_JZ4740_JZ4740_NAND_H__
+#define __ASM_MACH_JZ4740_JZ4740_NAND_H__
+
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+struct jz_nand_platform_data {
+ int num_partitions;
+ struct mtd_partition *partitions;
+
+ struct nand_ecclayout *ecc_layout;
+
+ unsigned int busy_gpio;
+
+ void (*ident_callback)(struct platform_device *, struct nand_chip *,
+ struct mtd_partition **, int *num_partitions);
+};
+
+#endif
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index ffc3720..362d177 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -526,4 +526,10 @@ config MTD_NAND_NUC900
This enables the driver for the NAND Flash on evaluation board based
on w90p910 / NUC9xx.
+config MTD_NAND_JZ4740
+ tristate "Support for JZ4740 SoC NAND controller"
+ depends on MACH_JZ4740
+ help
+ Enables support for NAND Flash on JZ4740 SoC based boards.
+
endif # MTD_NAND
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index e8ab884..ac83dcd 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -46,5 +46,6 @@ obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o
obj-$(CONFIG_MTD_NAND_BCM_UMI) += bcm_umi_nand.o nand_bcm_umi.o
obj-$(CONFIG_MTD_NAND_MPC5121_NFC) += mpc5121_nfc.o
obj-$(CONFIG_MTD_NAND_RICOH) += r852.o
+obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o
nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
new file mode 100644
index 0000000..67343fc
--- /dev/null
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
+ * JZ4740 SoC NAND controller driver
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/gpio.h>
+
+#include <asm/mach-jz4740/jz4740_nand.h>
+
+#define JZ_REG_NAND_CTRL 0x50
+#define JZ_REG_NAND_ECC_CTRL 0x100
+#define JZ_REG_NAND_DATA 0x104
+#define JZ_REG_NAND_PAR0 0x108
+#define JZ_REG_NAND_PAR1 0x10C
+#define JZ_REG_NAND_PAR2 0x110
+#define JZ_REG_NAND_IRQ_STAT 0x114
+#define JZ_REG_NAND_IRQ_CTRL 0x118
+#define JZ_REG_NAND_ERR(x) (0x11C + ((x) << 2))
+
+#define JZ_NAND_ECC_CTRL_PAR_READY BIT(4)
+#define JZ_NAND_ECC_CTRL_ENCODING BIT(3)
+#define JZ_NAND_ECC_CTRL_RS BIT(2)
+#define JZ_NAND_ECC_CTRL_RESET BIT(1)
+#define JZ_NAND_ECC_CTRL_ENABLE BIT(0)
+
+#define JZ_NAND_STATUS_ERR_COUNT (BIT(31) | BIT(30) | BIT(29))
+#define JZ_NAND_STATUS_PAD_FINISH BIT(4)
+#define JZ_NAND_STATUS_DEC_FINISH BIT(3)
+#define JZ_NAND_STATUS_ENC_FINISH BIT(2)
+#define JZ_NAND_STATUS_UNCOR_ERROR BIT(1)
+#define JZ_NAND_STATUS_ERROR BIT(0)
+
+#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1)
+#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1)
+
+#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
+#define JZ_NAND_MEM_CMD_OFFSET 0x08000
+
+struct jz_nand {
+ struct mtd_info mtd;
+ struct nand_chip chip;
+ void __iomem *base;
+ struct resource *mem;
+
+ void __iomem *bank_base;
+ struct resource *bank_mem;
+
+ struct jz_nand_platform_data *pdata;
+ bool is_reading;
+};
+
+static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
+{
+ return container_of(mtd, struct jz_nand, mtd);
+}
+
+static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
+{
+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
+ struct nand_chip *chip = mtd->priv;
+ uint32_t reg;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
+ if (ctrl & NAND_ALE)
+ chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_ADDR_OFFSET;
+ else if (ctrl & NAND_CLE)
+ chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_CMD_OFFSET;
+ else
+ chip->IO_ADDR_W = nand->bank_base;
+
+ reg = readl(nand->base + JZ_REG_NAND_CTRL);
+ if (ctrl & NAND_NCE)
+ reg |= JZ_NAND_CTRL_ASSERT_CHIP(0);
+ else
+ reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0);
+ writel(reg, nand->base + JZ_REG_NAND_CTRL);
+ }
+ if (dat != NAND_CMD_NONE)
+ writeb(dat, chip->IO_ADDR_W);
+}
+
+static int jz_nand_dev_ready(struct mtd_info *mtd)
+{
+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
+ return gpio_get_value_cansleep(nand->pdata->busy_gpio);
+}
+
+static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
+{
+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
+ uint32_t reg;
+
+ writel(0, nand->base + JZ_REG_NAND_IRQ_STAT);
+ reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+
+ reg |= JZ_NAND_ECC_CTRL_RESET;
+ reg |= JZ_NAND_ECC_CTRL_ENABLE;
+ reg |= JZ_NAND_ECC_CTRL_RS;
+
+ switch (mode) {
+ case NAND_ECC_READ:
+ reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
+ nand->is_reading = true;
+ break;
+ case NAND_ECC_WRITE:
+ reg |= JZ_NAND_ECC_CTRL_ENCODING;
+ nand->is_reading = false;
+ break;
+ default:
+ break;
+ }
+
+ writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+}
+
+static int jz_nand_calculate_ecc_rs(struct mtd_info *mtd, const uint8_t *dat,
+ uint8_t *ecc_code)
+{
+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
+ uint32_t reg, status;
+ int i;
+ unsigned int timeout = 1000;
+ static uint8_t empty_block_ecc[] = {0xcd, 0x9d, 0x90, 0x58, 0xf4,
+ 0x8b, 0xff, 0xb7, 0x6f};
+
+ if (nand->is_reading)
+ return 0;
+
+ do {
+ status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
+ } while (!(status & JZ_NAND_STATUS_ENC_FINISH) && --timeout);
+
+ if (timeout == 0)
+ return -1;
+
+ reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+ reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
+ writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+ for (i = 0; i < 9; ++i)
+ ecc_code[i] = readb(nand->base + JZ_REG_NAND_PAR0 + i);
+
+ /* If the written data is completly 0xff, we also want to write 0xff as
+ * ecc, otherwise we will get in trouble when doing subpage writes. */
+ if (memcmp(ecc_code, empty_block_ecc, 9) == 0)
+ memset(ecc_code, 0xff, 9);
+
+ return 0;
+}
+
+static void jz_nand_correct_data(uint8_t *dat, int index, int mask)
+{
+ int offset = index & 0x7;
+ uint16_t data;
+
+ index += (index >> 3);
+
+ data = dat[index];
+ data |= dat[index+1] << 8;
+
+ mask ^= (data >> offset) & 0x1ff;
+ data &= ~(0x1ff << offset);
+ data |= (mask << offset);
+
+ dat[index] = data & 0xff;
+ dat[index+1] = (data >> 8) & 0xff;
+}
+
+static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
+ uint8_t *read_ecc, uint8_t *calc_ecc)
+{
+ struct jz_nand *nand = mtd_to_jz_nand(mtd);
+ int i, error_count, index;
+ uint32_t reg, status, error;
+ uint32_t t;
+ unsigned int timeout = 1000;
+
+ t = read_ecc[0];
+
+ if (t == 0xff) {
+ for (i = 1; i < 9; ++i)
+ t &= read_ecc[i];
+
+ t &= dat[0];
+ t &= dat[nand->chip.ecc.size / 2];
+ t &= dat[nand->chip.ecc.size - 1];
+
+ if (t == 0xff) {
+ for (i = 1; i < nand->chip.ecc.size - 1; ++i)
+ t &= dat[i];
+ if (t == 0xff)
+ return 0;
+ }
+ }
+
+ for (i = 0; i < 9; ++i)
+ writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i);
+
+ reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+ reg |= JZ_NAND_ECC_CTRL_PAR_READY;
+ writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+ do {
+ status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
+ } while (!(status & JZ_NAND_STATUS_DEC_FINISH) && --timeout);
+
+ if (timeout == 0)
+ return -1;
+
+ reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
+ reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
+ writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
+
+ if (status & JZ_NAND_STATUS_ERROR) {
+ if (status & JZ_NAND_STATUS_UNCOR_ERROR)
+ return -1;
+
+ error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29;
+
+ for (i = 0; i < error_count; ++i) {
+ error = readl(nand->base + JZ_REG_NAND_ERR(i));
+ index = ((error >> 16) & 0x1ff) - 1;
+ if (index >= 0 && index < 512)
+ jz_nand_correct_data(dat, index, error & 0x1ff);
+ }
+
+ return error_count;
+ }
+
+ return 0;
+}
+
+
+/* Copy paste of nand_read_page_hwecc_oob_first except for different eccpos
+ * handling. The ecc area is for 4k chips 72 bytes long and thus does not fit
+ * into the eccpos array. */
+static int jz_nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
+ struct nand_chip *chip, uint8_t *buf, int page)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ uint8_t *p = buf;
+ unsigned int ecc_offset = chip->page_shift;
+
+ /* Read the OOB area first */
+ chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+ chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+
+ for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ int stat;
+
+ chip->ecc.hwctl(mtd, NAND_ECC_READ);
+ chip->read_buf(mtd, p, eccsize);
+
+ stat = chip->ecc.correct(mtd, p, &chip->oob_poi[i], NULL);
+ if (stat < 0)
+ mtd->ecc_stats.failed++;
+ else
+ mtd->ecc_stats.corrected += stat;
+ }
+ return 0;
+}
+
+/* Copy-and-paste of nand_write_page_hwecc with different eccpos handling. */
+static void jz_nand_write_page_hwecc(struct mtd_info *mtd,
+ struct nand_chip *chip, const uint8_t *buf)
+{
+ int i, eccsize = chip->ecc.size;
+ int eccbytes = chip->ecc.bytes;
+ int eccsteps = chip->ecc.steps;
+ const uint8_t *p = buf;
+ unsigned int ecc_offset = chip->page_shift;
+
+ for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+ chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+ chip->write_buf(mtd, p, eccsize);
+ chip->ecc.calculate(mtd, p, &chip->oob_poi[i]);
+ }
+
+ chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
+
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+static const char *part_probes[] = {"cmdline", NULL};
+#endif
+
+static int jz_nand_ioremap_resource(struct platform_device *pdev,
+ const char *name, struct resource **res, void __iomem **base)
+{
+ int ret;
+
+ *res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
+ if (!*res) {
+ dev_err(&pdev->dev, "Failed to get platform %s memory\n", name);
+ ret = -ENXIO;
+ goto err;
+ }
+
+ *res = request_mem_region((*res)->start, resource_size(*res),
+ pdev->name);
+ if (!*res) {
+ dev_err(&pdev->dev, "Failed to request %s memory region\n", name);
+ ret = -EBUSY;
+ goto err;
+ }
+
+ *base = ioremap((*res)->start, resource_size(*res));
+ if (!*base) {
+ dev_err(&pdev->dev, "Failed to ioremap %s memory region\n", name);
+ ret = -EBUSY;
+ goto err_release_mem;
+ }
+
+ return 0;
+
+err_release_mem:
+ release_mem_region((*res)->start, resource_size(*res));
+err:
+ *res = NULL;
+ *base = NULL;
+ return ret;
+}
+
+static int __devinit jz_nand_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct jz_nand *nand;
+ struct nand_chip *chip;
+ struct mtd_info *mtd;
+ struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
+#ifdef CONFIG_MTD_PARTITIONS
+ struct mtd_partition *partition_info;
+ int num_partitions = 0;
+#endif
+
+ nand = kzalloc(sizeof(*nand), GFP_KERNEL);
+ if (!nand) {
+ dev_err(&pdev->dev, "Failed to allocate device structure.\n");
+ return -ENOMEM;
+ }
+
+ ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base);
+ if (ret)
+ goto err_free;
+ ret = jz_nand_ioremap_resource(pdev, "bank", &nand->bank_mem,
+ &nand->bank_base);
+ if (ret)
+ goto err_iounmap_mmio;
+
+ if (pdata && gpio_is_valid(pdata->busy_gpio)) {
+ ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to request busy gpio %d: %d\n",
+ pdata->busy_gpio, ret);
+ goto err_iounmap_mem;
+ }
+ }
+
+ mtd = &nand->mtd;
+ chip = &nand->chip;
+ mtd->priv = chip;
+ mtd->owner = THIS_MODULE;
+ mtd->name = "jz4740-nand";
+
+ chip->ecc.hwctl = jz_nand_hwctl;
+ chip->ecc.calculate = jz_nand_calculate_ecc_rs;
+ chip->ecc.correct = jz_nand_correct_ecc_rs;
+ chip->ecc.mode = NAND_ECC_HW_OOB_FIRST;
+ chip->ecc.size = 512;
+ chip->ecc.bytes = 9;
+
+ chip->ecc.read_page = jz_nand_read_page_hwecc_oob_first;
+ chip->ecc.write_page = jz_nand_write_page_hwecc;
+
+ if (pdata)
+ chip->ecc.layout = pdata->ecc_layout;
+
+ chip->chip_delay = 50;
+ chip->cmd_ctrl = jz_nand_cmd_ctrl;
+
+ if (pdata && gpio_is_valid(pdata->busy_gpio))
+ chip->dev_ready = jz_nand_dev_ready;
+
+ chip->IO_ADDR_R = nand->bank_base;
+ chip->IO_ADDR_W = nand->bank_base;
+
+ nand->pdata = pdata;
+ platform_set_drvdata(pdev, nand);
+
+ writel(JZ_NAND_CTRL_ENABLE_CHIP(0), nand->base + JZ_REG_NAND_CTRL);
+
+ ret = nand_scan_ident(mtd, 1, NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to scan nand\n");
+ goto err_gpio_free;
+ }
+
+ if (pdata && pdata->ident_callback) {
+ pdata->ident_callback(pdev, chip, &pdata->partitions,
+ &pdata->num_partitions);
+ }
+
+ ret = nand_scan_tail(mtd);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to scan nand\n");
+ goto err_gpio_free;
+ }
+
+#ifdef CONFIG_MTD_PARTITIONS
+#ifdef CONFIG_MTD_CMDLINE_PARTS
+ num_partitions = parse_mtd_partitions(mtd, part_probes,
+ &partition_info, 0);
+#endif
+ if (num_partitions <= 0 && pdata) {
+ num_partitions = pdata->num_partitions;
+ partition_info = pdata->partitions;
+ }
+
+ if (num_partitions > 0)
+ ret = add_mtd_partitions(mtd, partition_info, num_partitions);
+ else
+#endif
+ ret = add_mtd_device(mtd);
+
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to add mtd device\n");
+ goto err_nand_release;
+ }
+
+ dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n");
+
+ return 0;
+
+err_nand_release:
+ nand_release(&nand->mtd);
+err_gpio_free:
+ platform_set_drvdata(pdev, NULL);
+ gpio_free(pdata->busy_gpio);
+err_iounmap_mem:
+ iounmap(nand->bank_base);
+err_iounmap_mmio:
+ iounmap(nand->base);
+err_free:
+ kfree(nand);
+ return ret;
+}
+
+static int __devexit jz_nand_remove(struct platform_device *pdev)
+{
+ struct jz_nand *nand = platform_get_drvdata(pdev);
+
+ nand_release(&nand->mtd);
+
+ /* Deassert and disable all chips */
+ writel(0, nand->base + JZ_REG_NAND_CTRL);
+
+ iounmap(nand->bank_base);
+ release_mem_region(nand->bank_mem->start, resource_size(nand->bank_mem));
+ iounmap(nand->base);
+ release_mem_region(nand->mem->start, resource_size(nand->mem));
+
+ platform_set_drvdata(pdev, NULL);
+ kfree(nand);
+
+ return 0;
+}
+
+struct platform_driver jz_nand_driver = {
+ .probe = jz_nand_probe,
+ .remove = __devexit_p(jz_nand_remove),
+ .driver = {
+ .name = "jz4740-nand",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init jz_nand_init(void)
+{
+ return platform_driver_register(&jz_nand_driver);
+}
+module_init(jz_nand_init);
+
+static void __exit jz_nand_exit(void)
+{
+ platform_driver_unregister(&jz_nand_driver);
+}
+module_exit(jz_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("NAND controller driver for JZ4740 SoC");
+MODULE_ALIAS("platform:jz4740-nand");
--
1.5.6.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v3] MTD: Nand: Add JZ4740 NAND driver
2010-07-17 12:15 ` [PATCH v3] " Lars-Peter Clausen
@ 2010-07-18 16:54 ` Artem Bityutskiy
2010-07-18 17:02 ` Lars-Peter Clausen
0 siblings, 1 reply; 12+ messages in thread
From: Artem Bityutskiy @ 2010-07-18 16:54 UTC (permalink / raw)
To: Lars-Peter Clausen
Cc: linux-mips, linux-mtd, David Woodhouse, linux-kernel,
Ralf Baechle
On Sat, 2010-07-17 at 14:15 +0200, Lars-Peter Clausen wrote:
> This patch adds support for the NAND controller on JZ4740 SoCs.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> Cc: David Woodhouse <dwmw2@infradead.org>
> Cc: linux-mtd@lists.infradead.org
>
Do you expect this patch to go in via the MTD tree? I guess it might be
better if it was MIPS tree?
--
Best Regards,
Artem Bityutskiy (Артём Битюцкий)
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3] MTD: Nand: Add JZ4740 NAND driver
2010-07-18 16:54 ` Artem Bityutskiy
@ 2010-07-18 17:02 ` Lars-Peter Clausen
0 siblings, 0 replies; 12+ messages in thread
From: Lars-Peter Clausen @ 2010-07-18 17:02 UTC (permalink / raw)
To: dedekind1
Cc: linux-mips, linux-mtd, David Woodhouse, linux-kernel,
Ralf Baechle
Artem Bityutskiy wrote:
> On Sat, 2010-07-17 at 14:15 +0200, Lars-Peter Clausen wrote:
>> This patch adds support for the NAND controller on JZ4740 SoCs.
>>
>> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
>> Cc: David Woodhouse <dwmw2@infradead.org>
>> Cc: linux-mtd@lists.infradead.org
>>
>
> Do you expect this patch to go in via the MTD tree? I guess it might be
> better if it was MIPS tree?
Hi
Yes, letting it go through the MIPS tree is the plan.
- Lars
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2010-07-18 17:02 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-19 5:08 [PATCH v2 00/26] Add support for the Ingenic JZ4740 System-on-a-Chip Lars-Peter Clausen
2010-06-19 5:08 ` [PATCH v2 17/26] MTD: Nand: Add JZ4740 NAND driver Lars-Peter Clausen
2010-07-08 6:06 ` Artem Bityutskiy
2010-07-08 13:20 ` Lars-Peter Clausen
2010-07-08 13:19 ` Artem Bityutskiy
2010-07-08 14:02 ` Lars-Peter Clausen
2010-07-08 14:14 ` Artem Bityutskiy
2010-07-17 12:15 ` [PATCH v3] " Lars-Peter Clausen
2010-07-18 16:54 ` Artem Bityutskiy
2010-07-18 17:02 ` Lars-Peter Clausen
2010-06-20 9:26 ` [PATCH v2 00/26] Add support for the Ingenic JZ4740 System-on-a-Chip Thomas Bogendoerfer
2010-06-21 2:56 ` Xiangfu Liu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).