Hi all,this patch adds support for RAM chips connected to the Local Plus Bus of a MPC5200B in 16-bit mode. As no single byte write accesses are allowed by the bus in this mode, a byte write has to be split into a word read - modify - write sequence (mpc52xx_memcpy2lpb16, as fix/extension for memcpy_toio; note that memcpy_fromio *does* work just fine). It has been tested in conjunction with Wolfram Sang's mtd-ram [1] and Sascha Hauer's jffs unaligned access [2] patches on 2.6.29.1, with a Renesas static RAM connected in 16-bit "Large Flash" mode.
[1] <http://lists.ozlabs.org/pipermail/linuxppc-dev/2009-June/072794.html>
[2] <http://article.gmane.org/gmane.linux.drivers.mtd/21521> Signed-off-by: Albrecht Dreß <albrecht.dr...@arcor.de> Cc: Grant Likely <grant.lik...@secretlab.ca> Cc: David Woodhouse <dw...@infradead.org> Cc: linuxppc-...@ozlabs.org ---diff -u linux-2.6.29.1.orig/arch/powerpc/platforms/52xx/mpc52xx_common.c linux-2.6.29.1/arch/powerpc/platforms/52xx/mpc52xx_common.c --- linux-2.6.29.1.orig/arch/powerpc/platforms/52xx/mpc52xx_common.c 2009-04-02 22:55:27.000000000 +0200 +++ linux-2.6.29.1/arch/powerpc/platforms/52xx/mpc52xx_common.c 2009-06-09 21:16:22.000000000 +0200
@@ -225,3 +225,59 @@ while (1); } + +/**+ * mpc52xx_memcpy2lpb16: copy data to the Local Plus Bus in 16-bit mode which
+ * doesn't allow byte accesses + */ +void +mpc52xx_memcpy2lpb16(volatile void __iomem *dest, const void *src, + unsigned long n) +{ + void *vdest = (void __force *) dest; + + __asm__ __volatile__ ("sync" : : : "memory"); + + if (((unsigned long) vdest & 1) != 0) { + u8 buf[2]; + + *(u16 *)buf = *((volatile u16 *)(vdest - 1)); + buf[1] = *((u8 *)src); + *((volatile u16 *)(vdest - 1)) = *(u16 *)buf; + src++; + vdest++; + n--; + } + + /* looks weird, but helps the optimiser... */ + if (n >= 4) { + unsigned long chunks = n >> 2; + volatile u32 * _dst = (volatile u32 *)(vdest - 4); + volatile u32 * _src = (volatile u32 *)(src - 4); + + vdest += chunks << 2; + src += chunks << 2; + do { + *++_dst = *++_src; + } while (--chunks); + n &= 3; + } + + if (n >= 2) { + *((volatile u16 *)vdest) = *((volatile u16 *)src); + src += 2; + vdest += 2; + n -= 2; + } + + if (n > 0) { + u8 buf[2]; + + *(u16 *)buf = *((volatile u16 *)vdest); + buf[0] = *((u8 *)src); + *((volatile u16 *)vdest) = *(u16 *)buf; + } + + __asm__ __volatile__ ("sync" : : : "memory"); +} +EXPORT_SYMBOL(mpc52xx_memcpy2lpb16);diff -u linux-2.6.29.1.orig/arch/powerpc/include/asm/mpc52xx.h linux-2.6.29.1/arch/powerpc/include/asm/mpc52xx.h --- linux-2.6.29.1.orig/arch/powerpc/include/asm/mpc52xx.h 2009-04-02 22:55:27.000000000 +0200 +++ linux-2.6.29.1/arch/powerpc/include/asm/mpc52xx.h 2009-06-09 21:14:31.000000000 +0200
@@ -274,6 +274,8 @@ extern void mpc52xx_map_common_devices(void); extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv); extern void mpc52xx_restart(char *cmd);+extern void mpc52xx_memcpy2lpb16(volatile void __iomem *dest, const void *src,
+ unsigned long n); /* mpc52xx_pic.c */ extern void mpc52xx_init_irq(void);diff -u linux-2.6.29.1.orig/include/linux/mtd/map.h linux-2.6.29.1/include/linux/mtd/map.h --- linux-2.6.29.1.orig/include/linux/mtd/map.h 2009-04-02 22:55:27.000000000 +0200 +++ linux-2.6.29.1/include/linux/mtd/map.h 2009-06-08 14:28:05.000000000 +0200
@@ -13,6 +13,9 @@ #include <asm/unaligned.h> #include <asm/system.h> #include <asm/io.h> +#ifdef CONFIG_PPC_MPC52xx +#include <asm/mpc52xx.h> +#endif #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1 #define map_bankwidth(map) 1 @@ -417,6 +420,11 @@static inline void inline_map_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
{ +#ifdef CONFIG_PPC_MPC52xx + if (map->bankwidth == 2) + mpc52xx_memcpy2lpb16(map->virt + to, from, len); + else +#endif memcpy_toio(map->virt + to, from, len); }
pgpVaj8YdBwdW.pgp
Description: PGP signature
_______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev