From: Tony Lindgren <tony@atomide.com>
To: Dirk Behme <dirk.behme@googlemail.com>
Cc: linux-omap-open-source@linux.omap.com
Subject: Re: [PATCH] Basic N800 support
Date: Fri, 26 Jan 2007 13:31:27 -0800 [thread overview]
Message-ID: <20070126213126.GH29286@atomide.com> (raw)
In-Reply-To: <45B1BEE7.2000603@googlemail.com>
[-- Attachment #1: Type: text/plain, Size: 446 bytes --]
* Dirk Behme <dirk.behme@googlemail.com> [070119 23:04]:
> Tony Lindgren wrote:
> >Here's a quick patch of N800 support against the current git tree
>
> The following patches fix some minor warnings for
> n800_defconfig compilation. Apply them on top of
> patch-n800-add-minimal and patch-n800-pm-changes.
Cool. I've split up and pushed the N800 core support.
Following two patches are still needed to compile and
mount root.
Regards,
Tony
[-- Attachment #2: 01-onenand.patch --]
[-- Type: text/x-diff, Size: 17049 bytes --]
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -29,6 +29,13 @@
help
Support for OneNAND flash via platform device driver.
+config MTD_ONENAND_OMAP2
+ tristate "OneNAND on OMAP2 support"
+ depends on MTD_ONENAND && ARCH_OMAP2
+ help
+ Support for a OneNAND flash device connected to an OMAP2 CPU
+ via the GPMC memory controller.
+
config MTD_ONENAND_OTP
bool "OneNAND OTP Support"
depends on MTD_ONENAND
--- a/drivers/mtd/onenand/Makefile
+++ b/drivers/mtd/onenand/Makefile
@@ -7,5 +7,6 @@
# Board specific.
obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o
+obj-$(CONFIG_MTD_ONENAND_OMAP2) += omap2.o
onenand-objs = onenand_base.o onenand_bbt.o
+++ b/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -0,0 +1,545 @@
+/*
+ * linux/drivers/mtd/onenand/omap2.c
+ *
+ * OneNAND driver for OMAP2
+ *
+ * Copyright (C) 2005-2006 Nokia Corporation
+ *
+ * Author: Jarkko Lavinen <jarkko.lavinen@nokia.com> and Juha Yrjola
+ * IRQ and DMA support written by Timo Teras
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/mach/flash.h>
+#include <asm/arch/gpmc.h>
+#include <asm/arch/onenand.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/gpmc.h>
+#include <asm/arch/pm.h>
+
+#include <linux/dma-mapping.h>
+#include <asm/dma-mapping.h>
+#include <asm/arch/dma.h>
+
+#include <asm/arch/board.h>
+
+#define ONENAND_IO_SIZE SZ_128K
+
+struct omap2_onenand {
+ struct platform_device *pdev;
+ int gpmc_cs;
+ unsigned long phys_base;
+ int gpio_irq;
+ struct mtd_info mtd;
+ struct mtd_partition *parts;
+ struct onenand_chip onenand;
+ struct completion irq_done;
+ struct completion dma_done;
+ int dma_channel;
+};
+
+static unsigned short omap2_onenand_readw(void __iomem *addr)
+{
+ return readw(addr);
+}
+
+static void omap2_onenand_writew(unsigned short value, void __iomem *addr)
+{
+ writew(value, addr);
+}
+
+static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
+{
+ struct omap2_onenand *info = data;
+
+ complete(&info->dma_done);
+}
+
+static irqreturn_t omap2_onenand_interrupt(int irq, void *dev_id)
+{
+ struct omap2_onenand *info = dev_id;
+
+ complete(&info->irq_done);
+
+ return IRQ_HANDLED;
+}
+
+static int omap2_onenand_wait(struct mtd_info *mtd, int state)
+{
+ struct omap2_onenand *info = container_of(mtd, struct omap2_onenand, mtd);
+ struct onenand_chip *this = mtd->priv;
+ unsigned int interrupt = 0;
+ unsigned int ctrl, ecc;
+ unsigned long timeout;
+ u32 syscfg;
+
+ if (state == FL_RESETING) {
+ udelay(1);
+ return 0;
+ }
+
+ if (state != FL_READING) {
+ /* Turn interrupts on */
+ syscfg = omap2_onenand_readw(info->onenand.base + ONENAND_REG_SYS_CFG1);
+ syscfg |= ONENAND_SYS_CFG1_IOBE;
+ omap2_onenand_writew(syscfg, info->onenand.base + ONENAND_REG_SYS_CFG1);
+
+ INIT_COMPLETION(info->irq_done);
+ if (!omap_get_gpio_datain(info->gpio_irq)) {
+ wait_for_completion_timeout(&info->irq_done,
+ msecs_to_jiffies(20));
+ }
+ } else {
+ /* Turn interrupts off */
+ syscfg = omap2_onenand_readw(info->onenand.base + ONENAND_REG_SYS_CFG1);
+ syscfg &= ~ONENAND_SYS_CFG1_IOBE;
+ omap2_onenand_writew(syscfg, info->onenand.base + ONENAND_REG_SYS_CFG1);
+
+ timeout = jiffies + msecs_to_jiffies(20);
+ while (time_before(jiffies, timeout)) {
+ if (omap2_onenand_readw(info->onenand.base + ONENAND_REG_INTERRUPT) &
+ ONENAND_INT_MASTER)
+ break;
+ }
+ }
+
+ /* To get correct interrupt status in timeout case */
+ interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
+ ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
+
+ if (ctrl & ONENAND_CTRL_ERROR) {
+ /* It maybe occur at initial bad block */
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl);
+ /* Clear other interrupt bits for preventing ECC error */
+ interrupt &= ONENAND_INT_MASTER;
+ }
+
+ if (ctrl & ONENAND_CTRL_LOCK) {
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl);
+ return -EACCES;
+ }
+
+ if (interrupt & ONENAND_INT_READ) {
+ ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);
+ if (ecc & ONENAND_ECC_2BIT_ALL) {
+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc);
+ return -EBADMSG;
+ }
+ }
+
+ return 0;
+}
+
+static inline int omap2_onenand_bufferram_offset(struct mtd_info *mtd, int area)
+{
+ struct onenand_chip *this = mtd->priv;
+
+ if (ONENAND_CURRENT_BUFFERRAM(this)) {
+ if (area == ONENAND_DATARAM)
+ return mtd->writesize;
+ if (area == ONENAND_SPARERAM)
+ return mtd->oobsize;
+ }
+
+ return 0;
+}
+
+static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset,
+ size_t count)
+{
+ struct omap2_onenand *info = container_of(mtd, struct omap2_onenand, mtd);
+ struct onenand_chip *this = mtd->priv;
+ dma_addr_t dma_src, dma_dst;
+ int bram_offset;
+
+ bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
+ if ((info->dma_channel < 0) || ((void *) buffer >= (void *) high_memory) ||
+ (bram_offset & 3) || (((unsigned int) buffer) & 3) ||
+ (count < 1024) || (count & 3)) {
+ memcpy(buffer, (void *)(this->base + bram_offset), count);
+ return 0;
+ }
+
+ dma_src = info->phys_base + bram_offset;
+ dma_dst = dma_map_single(&info->pdev->dev, buffer, count, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dma_dst)) {
+ dev_err(&info->pdev->dev,
+ "Couldn't DMA map a %d byte buffer\n",
+ count);
+ return -1;
+ }
+
+ omap_set_dma_transfer_params(info->dma_channel, OMAP_DMA_DATA_TYPE_S32,
+ count / 4, 1, 0, 0, 0);
+ omap_set_dma_src_params(info->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_src, 0, 0);
+ omap_set_dma_dest_params(info->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_dst, 0, 0);
+
+ INIT_COMPLETION(info->dma_done);
+ omap2_block_sleep();
+ omap_start_dma(info->dma_channel);
+ wait_for_completion(&info->dma_done);
+ omap2_allow_sleep();
+
+ dma_unmap_single(&info->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
+
+ return 0;
+}
+
+static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
+ const unsigned char *buffer, int offset,
+ size_t count)
+{
+ struct omap2_onenand *info = container_of(mtd, struct omap2_onenand, mtd);
+ struct onenand_chip *this = mtd->priv;
+ dma_addr_t dma_src, dma_dst;
+ int bram_offset;
+
+ bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
+ if ((info->dma_channel < 0) || ((void *) buffer >= (void *) high_memory) ||
+ (bram_offset & 3) || (((unsigned int) buffer) & 3) ||
+ (count < 1024) || (count & 3)) {
+ memcpy((void *)(this->base + bram_offset), buffer, count);
+ return 0;
+ }
+
+ dma_src = dma_map_single(&info->pdev->dev, (void *) buffer, count,
+ DMA_TO_DEVICE);
+ dma_dst = info->phys_base + bram_offset;
+ if (dma_mapping_error(dma_dst)) {
+ dev_err(&info->pdev->dev,
+ "Couldn't DMA map a %d byte buffer\n",
+ count);
+ return -1;
+ }
+
+ omap_set_dma_transfer_params(info->dma_channel, OMAP_DMA_DATA_TYPE_S16,
+ count / 2, 1, 0, 0, 0);
+ omap_set_dma_src_params(info->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_src, 0, 0);
+ omap_set_dma_dest_params(info->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+ dma_dst, 0, 0);
+
+ INIT_COMPLETION(info->dma_done);
+ omap_start_dma(info->dma_channel);
+ wait_for_completion(&info->dma_done);
+
+ dma_unmap_single(&info->pdev->dev, dma_dst, count, DMA_TO_DEVICE);
+
+ return 0;
+}
+
+static int omap2_onenand_set_async_mode(struct omap2_onenand *info)
+{
+ struct gpmc_timings t;
+
+ memset(&t, 0, sizeof(t));
+ t.sync_clk = 0;
+ t.cs_on = 0;
+ t.adv_on = gpmc_round_ns_to_ticks(1);
+
+ /* FIXME: Get timings from platform data */
+ /* Read */
+ t.adv_rd_off = t.adv_on + gpmc_round_ns_to_ticks(12);
+ t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1);
+ t.access = t.oe_on + gpmc_round_ns_to_ticks(35);
+ t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
+ t.cs_rd_off = t.oe_off;
+ t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(15);
+
+ /* Write */
+ t.adv_wr_off = t.adv_on + gpmc_round_ns_to_ticks(12);
+ t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(1);
+ t.we_off = t.we_on + gpmc_round_ns_to_ticks(30);
+ t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(1);
+ t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(15);
+
+ /* Configure GPMC for asynchronous read */
+ gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG1,
+ GPMC_CONFIG1_READTYPE_ASYNC |
+ GPMC_CONFIG1_DEVICESIZE_16 |
+ GPMC_CONFIG1_DEVICETYPE_NOR |
+ GPMC_CONFIG1_MUXADDDATA);
+
+ return gpmc_cs_set_timings(info->gpmc_cs, &t);
+}
+
+static int omap2_onenand_set_sync_mode(struct omap2_onenand *info)
+{
+ const int min_gpmc_clk_period = 18;
+ struct gpmc_timings t;
+ int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency, cs;
+ u32 reg;
+
+ cs = info->gpmc_cs;
+ tick_ns = gpmc_round_ns_to_ticks(1);
+ div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period);
+ gpmc_clk_ns = div * tick_ns;
+ if (gpmc_clk_ns >= 24)
+ latency = 3;
+ else
+ latency = 4;
+
+ /* Configure OneNAND for sync read */
+ reg = omap2_onenand_readw(info->onenand.base + ONENAND_REG_SYS_CFG1);
+ reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9));
+ reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) |
+ ONENAND_SYS_CFG1_SYNC_READ |
+ ONENAND_SYS_CFG1_BL_16;
+ omap2_onenand_writew(reg, info->onenand.base + ONENAND_REG_SYS_CFG1);
+
+ /* FIXME: Get timings from platform data */
+ /* Set syncronous read timings */
+ memset(&t, 0, sizeof(t));
+ t.sync_clk = min_gpmc_clk_period;
+ t.cs_on = 0;
+ t.adv_on = gpmc_round_ns_to_ticks(7);
+ fclk_offset_ns = t.adv_on + gpmc_round_ns_to_ticks(7);
+ fclk_offset = fclk_offset_ns / gpmc_round_ns_to_ticks(1);
+ t.page_burst_access = gpmc_clk_ns;
+
+ /* Read */
+ t.adv_rd_off = fclk_offset_ns + gpmc_round_ns_to_ticks(7);
+ t.oe_on = t.adv_rd_off;
+ t.access = fclk_offset_ns + (latency + 1) * gpmc_clk_ns;
+ t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
+ t.cs_rd_off = t.oe_off;
+ t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(17);
+
+ /* Write */
+ t.adv_wr_off = t.adv_on + gpmc_round_ns_to_ticks(12);
+ t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(1);
+ t.we_off = t.we_on + gpmc_round_ns_to_ticks(40);
+ t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(1);
+ t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(1);
+
+ /* Configure GPMC for synchronous read */
+ fclk_offset %= div;
+ gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
+ GPMC_CONFIG1_WRAPBURST_SUPP |
+ GPMC_CONFIG1_READMULTIPLE_SUPP |
+ GPMC_CONFIG1_READTYPE_SYNC |
+ GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
+ GPMC_CONFIG1_PAGE_LEN(2) |
+ GPMC_CONFIG1_WAIT_READ_MON |
+ GPMC_CONFIG1_WAIT_PIN_SEL(0) |
+ GPMC_CONFIG1_DEVICESIZE_16 |
+ GPMC_CONFIG1_DEVICETYPE_NOR |
+ GPMC_CONFIG1_MUXADDDATA);
+
+ return gpmc_cs_set_timings(cs, &t);
+}
+
+static int __devinit omap2_onenand_probe(struct platform_device *pdev)
+{
+ struct omap_onenand_platform_data *pdata;
+ struct omap2_onenand *info;
+ int r;
+
+ pdata = pdev->dev.platform_data;
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "platform data missing\n");
+ return -ENODEV;
+ }
+
+ info = kzalloc(sizeof(struct omap2_onenand), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ init_completion(&info->irq_done);
+ init_completion(&info->dma_done);
+ info->gpmc_cs = pdata->cs;
+ info->gpio_irq = pdata->gpio_irq;
+
+ r = gpmc_cs_request(info->gpmc_cs, ONENAND_IO_SIZE, &info->phys_base);
+ if (r < 0) {
+ dev_err(&pdev->dev, "Cannot request GPMC CS\n");
+ goto err_kfree;
+ }
+
+ if (request_mem_region(info->phys_base, ONENAND_IO_SIZE,
+ pdev->dev.driver->name) == NULL) {
+ dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, size: 0x%x\n",
+ info->phys_base, ONENAND_IO_SIZE);
+ r = -EBUSY;
+ goto err_free_cs;
+ }
+ info->onenand.base = ioremap(info->phys_base, ONENAND_IO_SIZE);
+ if (info->onenand.base == NULL) {
+ r = -ENOMEM;
+ goto err_release_mem_region;
+ }
+
+ /* Force OneNAND to async mode */
+ omap2_onenand_writew(ONENAND_SYS_CFG1_BRL_4 | ONENAND_SYS_CFG1_RDY |
+ ONENAND_SYS_CFG1_INT, info->onenand.base + ONENAND_REG_SYS_CFG1);
+
+ /* Set async timings in GPMC */
+ if (omap2_onenand_set_async_mode(info) < 0) {
+ dev_err(&pdev->dev, "Unable to set async mode\n");
+ r = -EINVAL;
+ goto err_iounmap;
+ }
+
+ if ((r = omap_request_gpio(info->gpio_irq)) < 0) {
+ dev_err(&pdev->dev, "Failed to request GPIO%d for OneNAND\n",
+ info->gpio_irq);
+ goto err_iounmap;
+ }
+ omap_set_gpio_direction(info->gpio_irq, 1);
+
+ if ((r = request_irq(OMAP_GPIO_IRQ(info->gpio_irq),
+ omap2_onenand_interrupt, IRQF_TRIGGER_RISING,
+ pdev->dev.driver->name, info)) < 0)
+ goto err_release_gpio;
+
+ r = omap_request_dma(0, pdev->dev.driver->name,
+ omap2_onenand_dma_cb, (void *) info,
+ &info->dma_channel);
+ if (r == 0) {
+ omap_set_dma_write_mode(info->dma_channel, OMAP_DMA_WRITE_NON_POSTED);
+ omap_set_dma_src_data_pack(info->dma_channel, 1);
+ omap_set_dma_src_burst_mode(info->dma_channel, OMAP_DMA_DATA_BURST_8);
+ omap_set_dma_dest_data_pack(info->dma_channel, 1);
+ omap_set_dma_dest_burst_mode(info->dma_channel, OMAP_DMA_DATA_BURST_8);
+ } else {
+ dev_info(&pdev->dev,
+ "failed to allocate DMA for OneNAND, using PIO instead\n");
+ info->dma_channel = -1;
+ }
+
+ dev_info(&pdev->dev, "initializing on CS%d, phys base 0x%08lx, virtual base %p\n",
+ info->gpmc_cs, info->phys_base, info->onenand.base);
+
+ info->pdev = pdev;
+ info->mtd.name = pdev->dev.bus_id;
+ info->mtd.priv = &info->onenand;
+ info->mtd.owner = THIS_MODULE;
+ info->onenand.wait = omap2_onenand_wait;
+ info->onenand.read_bufferram = omap2_onenand_read_bufferram;
+ info->onenand.write_bufferram = omap2_onenand_write_bufferram;
+
+ if ((r = onenand_scan(&info->mtd, 1)) < 0)
+ goto err_release_dma;
+
+ if (omap2_onenand_set_sync_mode(info) < 0) {
+ dev_err(&pdev->dev, "Unable to set sync mode\n");
+ r = -EINVAL;
+ goto err_release_onenand;
+ }
+
+#ifdef CONFIG_MTD_PARTITIONS
+ if (pdata->parts != NULL)
+ r = add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
+ else
+#endif
+ r = add_mtd_device(&info->mtd);
+ if (r < 0)
+ goto err_release_onenand;
+
+ platform_set_drvdata(pdev, info);
+
+ return 0;
+
+err_release_onenand:
+ onenand_release(&info->mtd);
+err_release_dma:
+ if (info->dma_channel != -1)
+ omap_free_dma(info->dma_channel);
+ free_irq(OMAP_GPIO_IRQ(info->gpio_irq), info);
+err_release_gpio:
+ omap_free_gpio(info->gpio_irq);
+err_iounmap:
+ iounmap(info->onenand.base);
+err_release_mem_region:
+ release_mem_region(info->phys_base, ONENAND_IO_SIZE);
+err_free_cs:
+ gpmc_cs_free(info->gpmc_cs);
+err_kfree:
+ kfree(info);
+
+ return r;
+}
+
+static int __devexit omap2_onenand_remove(struct platform_device *pdev)
+{
+ struct omap2_onenand *info = dev_get_drvdata(&pdev->dev);
+
+ BUG_ON(info == NULL);
+
+#ifdef CONFIG_MTD_PARTITIONS
+ if (info->parts)
+ del_mtd_partitions(&info->mtd);
+ else
+ del_mtd_device(&info->mtd);
+#else
+ del_mtd_device(&info->mtd);
+#endif
+
+ onenand_release(&info->mtd);
+ if (info->dma_channel != -1)
+ omap_free_dma(info->dma_channel);
+ platform_set_drvdata(pdev, NULL);
+ free_irq(OMAP_GPIO_IRQ(info->gpio_irq), info);
+ omap_free_gpio(info->gpio_irq);
+ iounmap(info->onenand.base);
+ release_mem_region(info->phys_base, ONENAND_IO_SIZE);
+ kfree(info);
+
+ return 0;
+}
+
+static struct platform_driver omap2_onenand_driver = {
+ .probe = omap2_onenand_probe,
+ .remove = omap2_onenand_remove,
+ .driver = {
+ .name = "omap2-onenand",
+ .owner = THIS_MODULE,
+ },
+};
+
+MODULE_ALIAS(DRIVER_NAME);
+
+static int __init omap2_onenand_init(void)
+{
+ printk(KERN_INFO "OMAP2 OneNAND driver initializing\n");
+ return platform_driver_register(&omap2_onenand_driver);
+}
+
+static void __exit omap2_onenand_exit(void)
+{
+ platform_driver_unregister(&omap2_onenand_driver);
+}
+
+module_init(omap2_onenand_init);
+module_exit(omap2_onenand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>");
+MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2");
[-- Attachment #3: 02-mach-types-hack.patch --]
[-- Type: text/x-diff, Size: 351 bytes --]
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -767,6 +767,7 @@
e330 MACH_E330 E330 753
rt3000 MACH_RT3000 RT3000 754
nokia770 MACH_NOKIA770 NOKIA770 755
+nokia_n800 MACH_NOKIA_N800 NOKIA_N800 5555
pnx0106 MACH_PNX0106 PNX0106 756
hx21xx MACH_HX21XX HX21XX 757
faraday MACH_FARADAY FARADAY 758
[-- Attachment #4: Type: text/plain, Size: 0 bytes --]
next prev parent reply other threads:[~2007-01-26 21:31 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-01-19 20:57 [PATCH] Basic N800 support Tony Lindgren
2007-01-20 7:04 ` Dirk Behme
2007-01-26 21:31 ` Tony Lindgren [this message]
2007-01-27 7:24 ` Dirk Behme
2007-01-29 7:13 ` Jarkko Nikula
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070126213126.GH29286@atomide.com \
--to=tony@atomide.com \
--cc=dirk.behme@googlemail.com \
--cc=linux-omap-open-source@linux.omap.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.