--- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -260,6 +260,12 @@ Support for parsing CFE image tag and creating MTD partitions on Broadcom BCM63xx boards. +config MTD_LANTIQ + bool "Lantiq SoC NOR support" + depends on LANTIQ && MTD_PARTITIONS + help + Support for NOR flsh chips on Lantiq SoC + config MTD_DILNETPC tristate "CFI Flash device mapped on DIL/Net PC" depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -59,3 +59,4 @@ obj-$(CONFIG_MTD_VMU) += vmu-flash.o obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o +obj-$(CONFIG_MTD_LANTIQ) += lantiq.o --- /dev/null +++ b/drivers/mtd/maps/lantiq.c @@ -0,0 +1,173 @@ +/* + * 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. + * + * Copyright (C) 2004 Liu Peng Infineon IFAP DC COM CPE + * Copyright (C) 2010 John Crispin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_SOC_LANTIQ_XWAY +#include +#endif + +static map_word +lq_read16(struct map_info *map, unsigned long adr) +{ + unsigned long flags; + map_word temp; + spin_lock_irqsave(&ebu_lock, flags); + adr ^= 2; + temp.x[0] = *((__u16 *)(map->virt + adr)); + spin_unlock_irqrestore(&ebu_lock, flags); + return temp; +} + +static void +lq_write16(struct map_info *map, map_word d, unsigned long adr) +{ + unsigned long flags; + spin_lock_irqsave(&ebu_lock, flags); + adr ^= 2; + *((__u16 *)(map->virt + adr)) = d.x[0]; + spin_unlock_irqrestore(&ebu_lock, flags); +} + +void +lq_copy_from(struct map_info *map, void *to, + unsigned long from, ssize_t len) +{ + unsigned char *p; + unsigned char *to_8; + unsigned long flags; + spin_lock_irqsave(&ebu_lock, flags); + from = (unsigned long)(from + map->virt); + p = (unsigned char *) from; + to_8 = (unsigned char *) to; + while (len--) + *to_8++ = *p++; + spin_unlock_irqrestore(&ebu_lock, flags); +} + +void +lq_copy_to(struct map_info *map, unsigned long to, + const void *from, ssize_t len) +{ + unsigned char *p = (unsigned char *)from; + unsigned char *to_8; + unsigned long flags; + spin_lock_irqsave(&ebu_lock, flags); + to += (unsigned long) map->virt; + to_8 = (unsigned char *)to; + while (len--) + *p++ = *to_8++; + spin_unlock_irqrestore(&ebu_lock, flags); +} + +static const char *part_probe_types[] = { "cmdlinepart", NULL }; + +static struct map_info lq_map = { + .name = "lq_nor", + .bankwidth = 2, + .read = lq_read16, + .write = lq_write16, + .copy_from = lq_copy_from, + .copy_to = lq_copy_to, +}; + +static int +lq_mtd_probe(struct platform_device *pdev) +{ + struct physmap_flash_data *lq_mtd_data = + (struct physmap_flash_data*) dev_get_platdata(&pdev->dev); + struct mtd_info *lq_mtd = NULL; + struct mtd_partition *parts = NULL; + struct resource *res = 0; + int nr_parts = 0; + +#ifdef CONFIG_SOC_LANTIQ_XWAY + lq_w32(lq_r32(LQ_EBU_BUSCON0) & ~EBU_WRDIS, LQ_EBU_BUSCON0); +#endif + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if(!res) + { + dev_err(&pdev->dev, "failed to get memory resource"); + return -ENOENT; + } + res = request_mem_region(res->start, resource_size(res), + dev_name(&pdev->dev)); + if(!res) + { + dev_err(&pdev->dev, "failed to request mem resource"); + return -EBUSY; + } + + lq_map.phys = res->start; + lq_map.size = resource_size(res); + lq_map.virt = ioremap_nocache(lq_map.phys, lq_map.size); + + if (!lq_map.virt ) { + dev_err(&pdev->dev, "failed to ioremap!\n"); + return -EIO; + } + + lq_mtd = (struct mtd_info *) do_map_probe("cfi_probe", &lq_map); + if (!lq_mtd) { + iounmap(lq_map.virt); + dev_err(&pdev->dev, "probing failed\n"); + return -ENXIO; + } + + lq_mtd->owner = THIS_MODULE; + + nr_parts = parse_mtd_partitions(lq_mtd, part_probe_types, &parts, 0); + if (nr_parts > 0) { + dev_info(&pdev->dev, "using %d partitions from cmdline", nr_parts); + } else { + nr_parts = lq_mtd_data->nr_parts; + parts = lq_mtd_data->parts; + } + + add_mtd_partitions(lq_mtd, parts, nr_parts); + return 0; +} + +static struct platform_driver lq_mtd_driver = { + .probe = lq_mtd_probe, + .driver = { + .name = "lq_nor", + .owner = THIS_MODULE, + }, +}; + +int __init +init_lq_mtd(void) +{ + int ret = platform_driver_register(&lq_mtd_driver); + if (ret) + printk(KERN_INFO "lq_nor: error registering platfom driver"); + return ret; +} + +module_init(init_lq_mtd); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("Lantiq SoC NOR"); --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -40,7 +40,11 @@ /* #define CMDSET0001_DISABLE_WRITE_SUSPEND */ // debugging, turns off buffer write mode if set to 1 -#define FORCE_WORD_WRITE 0 +#ifdef CONFIG_LANTIQ +# define FORCE_WORD_WRITE 1 +#else +# define FORCE_WORD_WRITE 0 +#endif /* Intel chips */ #define I82802AB 0x00ad @@ -1493,6 +1497,9 @@ int ret=0; adr += chip->start; +#ifdef CONFIG_LANTIQ + adr ^= 2; +#endif switch (mode) { case FL_WRITING: --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -39,7 +39,11 @@ #include #define AMD_BOOTLOC_BUG -#define FORCE_WORD_WRITE 0 +#ifdef CONFIG_LANTIQ +# define FORCE_WORD_WRITE 1 +#else +# define FORCE_WORD_WRITE 0 +#endif #define MAX_WORD_RETRIES 3 @@ -1167,6 +1171,10 @@ adr += chip->start; +#ifdef CONFIG_LANTIQ + adr ^= 2; +#endif + mutex_lock(&chip->mutex); ret = get_chip(map, chip, adr, FL_WRITING); if (ret) {