From 3ab8f2a2e7011c5e83363b42950757e46ef06824 Mon Sep 17 00:00:00 2001 From: Roy Zang Date: Mon, 18 Oct 2010 15:22:31 +0800 Subject: P4080/eLBC: Make Freescale elbc interrupt common to elbc devices Move Freescale elbc interrupt from nand driver to elbc driver. Then all elbc devices can use the interrupt instead of ONLY nand. For former nand driver, it had the two functions: 1. detecting nand flash partitions; 2. registering elbc interrupt. Now, second function is removed to fsl_lbc.c. Signed-off-by: Lan Chunhe-B25806 Signed-off-by: Roy Zang Reviewed-by: Anton Vorontsov Cc: Wood Scott-B07421 Signed-off-by: David Woodhouse --- arch/powerpc/include/asm/fsl_lbc.h | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/include') diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h index 1b5a21041f9b..06a11124dde1 100644 --- a/arch/powerpc/include/asm/fsl_lbc.h +++ b/arch/powerpc/include/asm/fsl_lbc.h @@ -1,9 +1,10 @@ /* Freescale Local Bus Controller * - * Copyright (c) 2006-2007 Freescale Semiconductor + * Copyright © 2006-2007, 2010 Freescale Semiconductor * * Authors: Nick Spence , * Scott Wood + * Jack Lan * * 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 @@ -26,6 +27,8 @@ #include #include #include +#include +#include struct fsl_lbc_bank { __be32 br; /**< Base Register */ @@ -125,13 +128,23 @@ struct fsl_lbc_regs { #define LTESR_ATMW 0x00800000 #define LTESR_ATMR 0x00400000 #define LTESR_CS 0x00080000 +#define LTESR_UPM 0x00000002 #define LTESR_CC 0x00000001 #define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC) +#define LTESR_MASK (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \ + | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \ + | LTESR_CC) +#define LTESR_CLEAR 0xFFFFFFFF +#define LTECCR_CLEAR 0xFFFFFFFF +#define LTESR_STATUS LTESR_MASK +#define LTEIR_ENABLE LTESR_MASK +#define LTEDR_ENABLE 0x00000000 __be32 ltedr; /**< Transfer Error Disable Register */ __be32 lteir; /**< Transfer Error Interrupt Register */ __be32 lteatr; /**< Transfer Error Attributes Register */ __be32 ltear; /**< Transfer Error Address Register */ - u8 res6[0xC]; + __be32 lteccr; /**< Transfer Error ECC Register */ + u8 res6[0x8]; __be32 lbcr; /**< Configuration Register */ #define LBCR_LDIS 0x80000000 #define LBCR_LDIS_SHIFT 31 @@ -265,7 +278,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm) cpu_relax(); } +/* overview of the fsl lbc controller */ + +struct fsl_lbc_ctrl { + /* device info */ + struct device *dev; + struct fsl_lbc_regs __iomem *regs; + int irq; + wait_queue_head_t irq_wait; + spinlock_t lock; + void *nand; + + /* status read from LTESR by irq handler */ + unsigned int irq_status; +}; + extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar); +extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev; #endif /* __ASM_FSL_LBC_H */ -- cgit From 0b824d2b10eacd496c608a7c41a046862d48563b Mon Sep 17 00:00:00 2001 From: Lan Chunhe-B25806 Date: Mon, 18 Oct 2010 15:22:32 +0800 Subject: P4080/mtd: Fix the freescale lbc issue with 36bit mode When system uses 36bit physical address, res.start is 36bit physical address. But the function of in_be32 returns 32bit physical address. Then both of them compared each other is wrong. So by converting the address of res.start into the right format fixes this issue. Signed-off-by: Lan Chunhe-B25806 Signed-off-by: Roy Zang Reviewed-by: Anton Vorontsov Signed-off-by: David Woodhouse --- arch/powerpc/include/asm/fsl_lbc.h | 1 + arch/powerpc/sysdev/fsl_lbc.c | 23 ++++++++++++++++++++++- drivers/mtd/nand/fsl_elbc_nand.c | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/include') diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h index 06a11124dde1..5c1bf3466749 100644 --- a/arch/powerpc/include/asm/fsl_lbc.h +++ b/arch/powerpc/include/asm/fsl_lbc.h @@ -248,6 +248,7 @@ struct fsl_upm { int width; }; +extern u32 fsl_lbc_addr(phys_addr_t addr_base); extern int fsl_lbc_find(phys_addr_t addr_base); extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm); diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c index 91c9c53b1845..4fcb5a4e60dd 100644 --- a/arch/powerpc/sysdev/fsl_lbc.c +++ b/arch/powerpc/sysdev/fsl_lbc.c @@ -33,6 +33,27 @@ static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev; EXPORT_SYMBOL(fsl_lbc_ctrl_dev); +/** + * fsl_lbc_addr - convert the base address + * @addr_base: base address of the memory bank + * + * This function converts a base address of lbc into the right format for the + * BR register. If the SOC has eLBC then it returns 32bit physical address + * else it convers a 34bit local bus physical address to correct format of + * 32bit address for BR register (Example: MPC8641). + */ +u32 fsl_lbc_addr(phys_addr_t addr_base) +{ + struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node; + u32 addr = addr_base & 0xffff8000; + + if (of_device_is_compatible(np, "fsl,elbc")) + return addr; + + return addr | ((addr_base & 0x300000000ull) >> 19); +} +EXPORT_SYMBOL(fsl_lbc_addr); + /** * fsl_lbc_find - find Localbus bank * @addr_base: base address of the memory bank @@ -55,7 +76,7 @@ int fsl_lbc_find(phys_addr_t addr_base) __be32 br = in_be32(&lbc->bank[i].br); __be32 or = in_be32(&lbc->bank[i].or); - if (br & BR_V && (br & or & BR_BA) == addr_base) + if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base)) return i; } diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index cd8de29e38cc..c141b07b25d1 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -868,7 +868,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev) (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM && (in_be32(&lbc->bank[bank].br) & in_be32(&lbc->bank[bank].or) & BR_BA) - == res.start) + == fsl_lbc_addr(res.start)) break; if (bank >= MAX_BANKS) { -- cgit