diff -Nurd linux-2.6.24.orig/arch/arm/mach-hipox/hipox.c linux-2.6.24/arch/arm/mach-hipox/hipox.c --- linux-2.6.24.orig/arch/arm/mach-hipox/hipox.c 2011-05-03 17:05:00.000000000 +0200 +++ linux-2.6.24/arch/arm/mach-hipox/hipox.c 2011-05-03 17:05:40.000000000 +0200 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -170,6 +171,10 @@ // The spinlock exported to allow atomic use of GPIO register set spinlock_t hipox_gpio_spinlock; +// Mutex for NAND/NOR flash access +DEFINE_MUTEX(hipox_flash_mutex); +EXPORT_SYMBOL(hipox_flash_mutex); + // To hold LED inversion state int hipox_global_invert_leds = 0; #include diff -Nurd linux-2.6.24.orig/arch/arm/mach-hipox/Makefile linux-2.6.24/arch/arm/mach-hipox/Makefile --- linux-2.6.24.orig/arch/arm/mach-hipox/Makefile 2011-05-03 17:05:00.000000000 +0200 +++ linux-2.6.24/arch/arm/mach-hipox/Makefile 2011-05-03 17:05:40.000000000 +0200 @@ -4,7 +4,7 @@ # Object file lists. -obj-y := hipox.o irq.o time.o dma.o pci.o ahb_mon.o leon.o samba_reserve.o +obj-y := hipox.o irq.o time.o dma.o pci.o ahb_mon.o leon.o samba_reserve.o smc.o obj-$(CONFIG_SYNOPSYS_GMAC) += gmac.o diff -Nurd linux-2.6.24.orig/arch/arm/mach-hipox/smc.c linux-2.6.24/arch/arm/mach-hipox/smc.c --- linux-2.6.24.orig/arch/arm/mach-hipox/smc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24/arch/arm/mach-hipox/smc.c 2011-05-04 09:28:41.000000000 +0200 @@ -0,0 +1,74 @@ +/* + * linux/arch/arm/mach-hipox/smc.c + * + * Locking for OXE810 Static Memory Controller + * + * 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. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +static ktime_t request_pci_timestamp = {0}; +/* + * Request PCI_ARB to grant access to the STATIC core. + */ +void hipox_smc_request_pci_ad_31_0(void) +{ + unsigned maxtries = 10; /* wait for maxtries jiffies at maximum */ + + /* set PCI_ARB request bit in Sysctrl_PCI_Ctrl1 */ + writel(readl(SYS_CTRL_PCI_CTRL1) | (1UL << SYSCTL_PCI_CTRL1_SYSPCI_STATIC_REQ), SYS_CTRL_PCI_CTRL1); + + /* check if STATIC core has been granted access to the PCI bus + and can use PCI_AD[31:0] pins */ + for (;maxtries > 0; maxtries--) + { + if (readl(SYS_CTRL_PCI_STAT) & (1UL << SYSCTL_PCI_STAT_SYSPCI_STATIC_GNT)) + break; + udelay(10); + } + + /* check for timeout granting access */ + if (!(readl(SYS_CTRL_PCI_STAT) & (1UL << SYSCTL_PCI_STAT_SYSPCI_STATIC_GNT))) + printk(KERN_WARNING "%s: timeout requesting access to PCI bus for static memory interface\n", __func__); + + request_pci_timestamp = ktime_get(); +} + +/* + * Release access to PCI bus. + */ +void hipox_smc_release_pci_ad_31_0(void) +{ + const s64 timeout = 400; /* us */ + s64 delta = ktime_us_delta(ktime_get(), request_pci_timestamp); + + /* set PCI_ARB request bit in Sysctrl_PCI_Ctrl1 */ + writel(readl(SYS_CTRL_PCI_CTRL1) & ~(1UL << SYSCTL_PCI_CTRL1_SYSPCI_STATIC_REQ), SYS_CTRL_PCI_CTRL1); + + if (delta > timeout) + { + printk(KERN_WARNING "%s: static memory interface blocked PCI bus for %llu us\n", __func__, delta); + } +} + +EXPORT_SYMBOL(hipox_smc_request_pci_ad_31_0); +EXPORT_SYMBOL(hipox_smc_release_pci_ad_31_0); diff -Nurd linux-2.6.24.orig/drivers/mtd/chips/cfi_cmdset_0002.c linux-2.6.24/drivers/mtd/chips/cfi_cmdset_0002.c --- linux-2.6.24.orig/drivers/mtd/chips/cfi_cmdset_0002.c 2011-05-03 17:04:58.000000000 +0200 +++ linux-2.6.24/drivers/mtd/chips/cfi_cmdset_0002.c 2011-05-03 17:05:40.000000000 +0200 @@ -46,11 +46,14 @@ #define MANUFACTURER_AMD 0x0001 #define MANUFACTURER_ATMEL 0x001F +#define MANUFACTURER_AMIC 0x0037 #define MANUFACTURER_SST 0x00BF #define SST49LF004B 0x0060 #define SST49LF040B 0x0050 #define SST49LF008A 0x005a #define AT49BV6416 0x00d6 +#define AT49BV163DT 0x01c2 +#define A29L160AT 0x22c4 static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); @@ -157,6 +160,13 @@ } #endif +#if defined (CONFIG_ARCH_HIPOX) +static void fixup_hipox(struct mtd_info *mtd, void *param) +{ + printk(KERN_NOTICE "%s: Hipox NOR-flash detected.\n", __func__); +} +#endif /* CONFIG_ARCH_HIPOX */ + static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) { struct map_info *map = mtd->priv; @@ -226,6 +236,10 @@ { CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, }, { CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, }, { CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, }, +#if defined (CONFIG_ARCH_HIPOX) + { CFI_MFR_ATMEL, AT49BV163DT, fixup_hipox, NULL, }, + { CFI_MFR_AMIC, A29L160AT, fixup_hipox, NULL, }, +#endif /* CONFIG_ARCH_HIPOX */ #if !FORCE_WORD_WRITE { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, #endif diff -Nurd linux-2.6.24.orig/drivers/mtd/maps/physmap.c linux-2.6.24/drivers/mtd/maps/physmap.c --- linux-2.6.24.orig/drivers/mtd/maps/physmap.c 2011-05-03 17:04:58.000000000 +0200 +++ linux-2.6.24/drivers/mtd/maps/physmap.c 2011-05-03 17:05:40.000000000 +0200 @@ -18,11 +18,13 @@ #include #include #include +#include #include #include #include #if defined (CONFIG_ARCH_HIPOX) +#include #include /* timing for NOR flash */ #define STATIC_BUS_FLASH_CONFIG 0x4f1f3f0d /* fast ASIC settings, 70ns */ @@ -78,6 +80,64 @@ return 0; } +#if defined (CONFIG_ARCH_HIPOX) +static map_word __xipram physmap_hipox_read(struct map_info *map, unsigned long ofs) +{ + map_word ret; + + // printk("%s:%d would wait for hipox_flash_mutex\n", __func__, __LINE__); + mutex_lock(&hipox_flash_mutex); + hipox_smc_request_pci_ad_31_0(); + + ret = inline_map_read(map, ofs); + + hipox_smc_release_pci_ad_31_0(); + mutex_unlock(&hipox_flash_mutex); + // printk("%s:%d hipox_flash_mutex unlocked\n", __func__, __LINE__); + + return ret; +} + +static void __xipram physmap_hipox_write(struct map_info *map, const map_word datum, unsigned long ofs) +{ + // printk("%s:%d would wait for hipox_flash_mutex\n", __func__, __LINE__); + mutex_lock(&hipox_flash_mutex); + hipox_smc_request_pci_ad_31_0(); + + inline_map_write(map, datum, ofs); + + hipox_smc_release_pci_ad_31_0(); + mutex_unlock(&hipox_flash_mutex); + // printk("%s:%d hipox_flash_mutex unlocked\n", __func__, __LINE__); +} + +static void __xipram physmap_hipox_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + // printk("%s:%d would wait for hipox_flash_mutex\n", __func__, __LINE__); + mutex_lock(&hipox_flash_mutex); + hipox_smc_request_pci_ad_31_0(); + + inline_map_copy_from(map, to, from, len); + + hipox_smc_release_pci_ad_31_0(); + mutex_unlock(&hipox_flash_mutex); + // printk("%s:%d hipox_flash_mutex unlocked\n", __func__, __LINE__); +} + +static void __xipram physmap_hipox_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + // printk("%s:%d would wait for hipox_flash_mutex\n", __func__, __LINE__); + mutex_lock(&hipox_flash_mutex); + hipox_smc_request_pci_ad_31_0(); + + inline_map_copy_to(map, to, from, len); + + hipox_smc_release_pci_ad_31_0(); + mutex_unlock(&hipox_flash_mutex); + // printk("%s:%d hipox_flash_mutex unlocked\n", __func__, __LINE__); +} +#endif /* CONFIG_ARCH_HIPOX */ + static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL }; #ifdef CONFIG_MTD_PARTITIONS static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; @@ -95,8 +155,8 @@ return -ENODEV; #if defined (CONFIG_ARCH_HIPOX) -/* init timing for static memory controller */ - writel(STATIC_BUS_FLASH_CONFIG, STATIC_CONTROL_BANK0); + /* init timing for static memory controller */ + writel(STATIC_BUS_FLASH_CONFIG, STATIC_CONTROL_BANK0); #endif /* CONFIG_ARCH_HIPOX */ printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n", @@ -134,6 +194,12 @@ } simple_map_init(&info->map); +#if defined (CONFIG_ARCH_HIPOX) + info->map.read = physmap_hipox_read; + info->map.write = physmap_hipox_write; + info->map.copy_from = physmap_hipox_copy_from; + info->map.copy_to = physmap_hipox_copy_to; +#endif /* CONFIG_ARCH_HIPOX */ probe_type = rom_probe_types; for (; info->mtd == NULL && *probe_type != NULL; probe_type++) diff -Nurd linux-2.6.24.orig/drivers/mtd/nand/hipox_nand.c linux-2.6.24/drivers/mtd/nand/hipox_nand.c --- linux-2.6.24.orig/drivers/mtd/nand/hipox_nand.c 2011-05-03 17:04:58.000000000 +0200 +++ linux-2.6.24/drivers/mtd/nand/hipox_nand.c 2011-05-03 17:05:40.000000000 +0200 @@ -21,9 +21,10 @@ #include #include #include -#include +#include #include #include +#include #include #include @@ -59,50 +60,6 @@ }; #endif -static unsigned int timestamp = 0; -/* - * Request PCI_ARB to grant access to the STATIC core. - */ -static void request_bus(void) -{ - unsigned maxtries = 10; /* wait for maxtries jiffies at maximum */ - - /* set PCI_ARB request bit in Sysctrl_PCI_Ctrl1 */ - writel(readl(SYS_CTRL_PCI_CTRL1) | (1UL << SYSCTL_PCI_CTRL1_SYSPCI_STATIC_REQ), SYS_CTRL_PCI_CTRL1); - - /* check if STATIC core has been granted access to the PCI bus - and can use PCI_AD[31:0] pins */ - for (;maxtries > 0; maxtries--) - { - if (readl(SYS_CTRL_PCI_STAT) & (1UL << SYSCTL_PCI_STAT_SYSPCI_STATIC_GNT)) - break; - udelay(10); - } - - /* check for timeout granting access */ - if (!(readl(SYS_CTRL_PCI_STAT) & (1UL << SYSCTL_PCI_STAT_SYSPCI_STATIC_GNT))) - printk(KERN_WARNING "%s: timeout requesting access to PCI bus for static memory interface\n", __func__); - - timestamp = jiffies_to_msecs(get_jiffies_64()); -} - -/* - * Release access to PCI bus. - */ -static void release_bus(void) -{ - const unsigned int timeout = 100; /* ms */ - unsigned int delta = jiffies_to_msecs(get_jiffies_64()) - timestamp; - - /* set PCI_ARB request bit in Sysctrl_PCI_Ctrl1 */ - writel(readl(SYS_CTRL_PCI_CTRL1) & ~(1UL << SYSCTL_PCI_CTRL1_SYSPCI_STATIC_REQ), SYS_CTRL_PCI_CTRL1); - - if (delta > timeout) - { - printk(KERN_WARNING "%s: static memory interface blocked PCI bus for %u ms\n", __func__, delta); - } -} - /* * Hardware specific access to control-lines */ @@ -111,14 +68,26 @@ struct nand_chip *this = mtd->priv; if (ctrl & NAND_CTRL_CHANGE) { - unsigned long IO_ADDR_W = (unsigned long) this->IO_ADDR_W; - - IO_ADDR_W = CONFIG_SYS_NAND_BASE; + unsigned long IO_ADDR_W = CONFIG_SYS_NAND_BASE; if (ctrl & NAND_NCE) - writel(0x20000000, GPIO_A_OUTPUT_CLEAR); /* assert CS-NAND */ + { + if (0x20000000 & readl(GPIO_A_OUTPUT_VALUE)) + { + // printk("%s:%d would wait for hipox_flash_mutex\n", __func__, __LINE__); + mutex_lock(&hipox_flash_mutex); + writel(0x20000000, GPIO_A_OUTPUT_CLEAR); /* assert CS-NAND */ + } + } else - writel(0x20000000, GPIO_A_OUTPUT_SET); /* deassert CS-NAND */ + { + if (!(0x20000000 & readl(GPIO_A_OUTPUT_VALUE))) + { + writel(0x20000000, GPIO_A_OUTPUT_SET); /* deassert CS-NAND */ + mutex_unlock(&hipox_flash_mutex); + // printk("%s:%d hipox_flash_mutex unlocked\n", __func__, __LINE__); + } + } if (ctrl & NAND_CLE) IO_ADDR_W = CONFIG_SYS_NAND_COMMAND_LATCH; @@ -130,9 +99,9 @@ if (cmd != NAND_CMD_NONE) { - request_bus(); + hipox_smc_request_pci_ad_31_0(); writeb(cmd, this->IO_ADDR_W); - release_bus(); + hipox_smc_release_pci_ad_31_0(); } } @@ -146,9 +115,9 @@ { struct nand_chip *chip = mtd->priv; uint8_t res; - request_bus(); + hipox_smc_request_pci_ad_31_0(); res = readb(chip->IO_ADDR_R); - release_bus(); + hipox_smc_release_pci_ad_31_0(); return res; } @@ -163,9 +132,9 @@ { struct nand_chip *chip = mtd->priv; u16 res; - request_bus(); + hipox_smc_request_pci_ad_31_0(); res = readw(chip->IO_ADDR_R); - release_bus(); + hipox_smc_release_pci_ad_31_0(); return res; } @@ -182,10 +151,10 @@ int i; struct nand_chip *chip = mtd->priv; - request_bus(); + hipox_smc_request_pci_ad_31_0(); for (i = 0; i < len; i++) buf[i] = readb(chip->IO_ADDR_R); - release_bus(); + hipox_smc_release_pci_ad_31_0(); } /** @@ -201,10 +170,10 @@ int i; struct nand_chip *chip = mtd->priv; - request_bus(); + hipox_smc_request_pci_ad_31_0(); for (i = 0; i < len; i++) writeb(buf[i], chip->IO_ADDR_W); - release_bus(); + hipox_smc_release_pci_ad_31_0(); } /** @@ -221,16 +190,16 @@ int ret = 0; struct nand_chip *chip = mtd->priv; - request_bus(); + hipox_smc_request_pci_ad_31_0(); for (i = 0; i < len; i++) { if (buf[i] != readb(chip->IO_ADDR_R)) { - ret = 0; + ret = -EFAULT; break; } } - release_bus(); + hipox_smc_release_pci_ad_31_0(); return ret; } @@ -271,7 +240,7 @@ memset(hipox_nand_mtd, 0, sizeof(struct mtd_info)); memset(this, 0, sizeof(struct nand_chip)); - // assert CS-NAND + // init (deassert) CS-NAND writel(0x20000000, GPIO_A_OUTPUT_SET); writel(0x20000000, GPIO_A_OUTPUT_ENABLE_SET); @@ -283,6 +252,7 @@ writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_0) & ~0x20000000, SYS_CTRL_GPIO_TERTSEL_CTRL_0); + // assert CS-NAND writel(0x20000000, GPIO_A_OUTPUT_CLEAR); // reset NAND unit diff -Nurd linux-2.6.24.orig/include/asm-arm/arch-hipox/smc.h linux-2.6.24/include/asm-arm/arch-hipox/smc.h --- linux-2.6.24.orig/include/asm-arm/arch-hipox/smc.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.24/include/asm-arm/arch-hipox/smc.h 2011-05-03 17:05:40.000000000 +0200 @@ -0,0 +1,28 @@ +/* linux/include/asm-arm/arch-hipox/smc.h + * + * 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. + */ + +#ifndef __ASM_ARCH_SMC_H +#define __ASM_ARCH_SMC_H + +#include + +/* + * Mutex used for exclusive NAD vs. NOR access + */ +extern struct mutex hipox_flash_mutex; + +/* + * Request PCI_ARB to grant access to the STATIC core. + */ +void hipox_smc_request_pci_ad_31_0(void); + +/* + * Release access to PCI bus. + */ +void hipox_smc_release_pci_ad_31_0(void); + +#endif // __ASM_ARCH_SMC_H diff -Nurd linux-2.6.24.orig/include/asm-arm/arch-hipox/system.h linux-2.6.24/include/asm-arm/arch-hipox/system.h --- linux-2.6.24.orig/include/asm-arm/arch-hipox/system.h 2011-05-03 17:05:01.000000000 +0200 +++ linux-2.6.24/include/asm-arm/arch-hipox/system.h 2011-05-03 17:05:40.000000000 +0200 @@ -8,6 +8,7 @@ #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H +#include #include #include diff -Nurd linux-2.6.24.orig/include/linux/mtd/cfi.h linux-2.6.24/include/linux/mtd/cfi.h --- linux-2.6.24.orig/include/linux/mtd/cfi.h 2011-05-03 17:05:01.000000000 +0200 +++ linux-2.6.24/include/linux/mtd/cfi.h 2011-05-03 17:05:40.000000000 +0200 @@ -486,6 +486,7 @@ #define CFI_MFR_AMD 0x0001 #define CFI_MFR_ATMEL 0x001F +#define CFI_MFR_AMIC 0x0037 #define CFI_MFR_ST 0x0020 /* STMicroelectronics */ void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups);