* Re: [patch 08/16] powerpc: remove EMBEDDED6xx Kconfig entry
From: Wolfgang Denk @ 2006-11-04 2:07 UTC (permalink / raw)
To: Olof Johansson; +Cc: paulus, linuxppc-dev
In-Reply-To: <20061103174948.34a5afe4@localhost.localdomain>
In message <20061103174948.34a5afe4@localhost.localdomain> you wrote:
>
> Might not be. I don't know what AMCC use for their eval boards, if it's
> u-boot or PIBS or something else.
There is a working U-Boot configuration for all AMCC eval boards
(including downloadable binary images). So if you want, you can use
U-Boot on all these boards.
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
It is impractical for the standard to attempt to constrain the
behavior of code that does not obey the constraints of the standard.
- Doug Gwyn
^ permalink raw reply
* [PATCH/RFC] Hookable IO operations #2
From: Benjamin Herrenschmidt @ 2006-11-04 8:01 UTC (permalink / raw)
To: linuxppc-dev list
[This is version 2 of the patch. Based on Arnd's comments, I've
simplified the macro usage. I've also hooked in the PIO stream
operations and added a ppc_md. hook for ioremap. It now switches
to the generic iomap implementation when CONFIG_PPC_INDIRECT_IO
is set so ioread/write & friends are also handled now ]
This patch reworks the way iSeries hooks on PCI IO operations (both MMIO
and PIO) and provides a generic way for other platforms to do so (we
have need to do that for various other platforms).
While reworking the IO ops, I ended up doing some spring cleaning in
io.h and eeh.h which I might want to split into 2 or 3 patches (among
others, eeh.h had a lot of useless stuff in it) and I sitll need to do
hooks for the insw/insl/... versions of the ops, along with handling the
iomap case (probably by falling back to lib/iomap.c when INDIRECT_PCI_IO
is set).
A side effect is that EEH for PIO should work now (it used to pass IO
ports down to the eeh address check functions which is bogus).
Since I need that to fix some issues with Cell fairly urgently, I plan
to push that to 2.6.20 when the merge window opens, so please comment
asap :)
Oh, also, in the long run, I might also make EEH use the hooks instead
of wrapping at the toplevel, which would make things even cleaner and
relegate EEH completely in platforms/iseries, but we have to measure the
performance impact there (though it's really only on MMIO reads)
iSeries boots with that patch. Note that iSeries lacks an implementation
for the PIO stream operations. I will do that later. One thing I want to
do is to add a hookable implementation of MMIO stream ops and have the
PIO ones be based on that, like other PIO ops.
Not for merge yet, so no signed-off-yet... Diffstat is pretty nice
overall. Still removing more than I'm adding :-)
arch/powerpc/Kconfig | 10
arch/powerpc/kernel/Makefile | 6
arch/powerpc/kernel/pci_64.c | 2
arch/powerpc/kernel/setup_64.c | 7
arch/powerpc/mm/pgtable_64.c | 46 +-
arch/powerpc/platforms/iseries/pci.c | 358 +++++----------------
arch/powerpc/platforms/iseries/setup.c | 12
include/asm-powerpc/eeh.h | 91 -----
include/asm-powerpc/io-defs.h | 37 ++
include/asm-powerpc/io.h | 557
+++++++++++++++++----------------
include/asm-powerpc/machdep.h | 4
11 files changed, 491 insertions(+), 639 deletions(-)
Index: linux-cell/include/asm-powerpc/io.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/io.h 2006-11-04 15:24:57.000000000 +1100
+++ linux-cell/include/asm-powerpc/io.h 2006-11-04 18:24:43.000000000 +1100
@@ -31,57 +31,120 @@
#define SLOW_DOWN_IO
+/*
+ *
+ * Low level MMIO accessors
+ *
+ * This provides the non-bus specific accessors to MMIO. Those are PowerPC
+ * specific and thus shouldn't be used in generic code. The accessors
+ * provided here are:
+ *
+ * in_8, in_le16, in_be16, in_le32, in_be32, in_le64, in_be64
+ * out_8, out_le16, out_be16, out_le32, out_be32, out_le64, out_be64
+ * _insb, _insw_ns, _insl_ns, _outsb, _outsw_ns, _outsl_ns
+ *
+ * Those operate directly on a kernel virtual address. Note that the prototype
+ * for the out_* accessors has the arguments in opposite order from the usual
+ * linux PCI accessors. Unlike those, they take the address first and the value
+ * next.
+ *
+ * Note: I might drop the _ns suffix on the stream operations soon as it is
+ * simply normal for stream operations to not swap in the first place.
+ *
+ */
+
+#define DEF_MMIO_IN(name, type, insn) \
+static inline type name(const volatile type __iomem *addr) \
+{ \
+ type ret; \
+ __asm__ __volatile__("sync;" insn ";twi 0,%0,0;isync" \
+ : "=r" (ret) : "r" (addr), "m" (*addr)); \
+ return ret; \
+}
+
+#define DEF_MMIO_OUT(name, type, insn) \
+static inline void name(volatile type __iomem *addr, type val) \
+{ \
+ __asm__ __volatile__("sync;" insn \
+ : "=m" (*addr) : "r" (val), "r" (addr)); \
+ get_paca()->io_sync = 1; \
+}
+
+
+#define DEF_MMIO_IN_BE(name, size, insn) \
+ DEF_MMIO_IN(name, u##size, __stringify(insn)"%U2%X2 %0,%2")
+#define DEF_MMIO_IN_LE(name, size, insn) \
+ DEF_MMIO_IN(name, u##size, __stringify(insn)" %0,0,%1")
+
+#define DEF_MMIO_OUT_BE(name, size, insn) \
+ DEF_MMIO_OUT(name, u##size, __stringify(insn)"%U0%X0 %1,%0")
+#define DEF_MMIO_OUT_LE(name, size, insn) \
+ DEF_MMIO_OUT(name, u##size, __stringify(insn)" %1,0,%2")
+
+DEF_MMIO_IN_BE(in_8, 8, lbz);
+DEF_MMIO_IN_BE(in_be16, 16, lhz);
+DEF_MMIO_IN_BE(in_be32, 32, lwz);
+DEF_MMIO_IN_BE(in_be64, 64, ld);
+DEF_MMIO_IN_LE(in_le16, 16, lhbrx);
+DEF_MMIO_IN_LE(in_le32, 32, lwbrx);
+
+DEF_MMIO_OUT_BE(out_8, 8, stb);
+DEF_MMIO_OUT_BE(out_be16, 16, sth);
+DEF_MMIO_OUT_BE(out_be32, 32, stw);
+DEF_MMIO_OUT_BE(out_be64, 64, std);
+DEF_MMIO_OUT_LE(out_le16, 16, sthbrx);
+DEF_MMIO_OUT_LE(out_le32, 32, stwbrx);
+
+/* There is no asm instructions for 64 bits reverse loads and stores */
+static inline u64 in_le64(const volatile u64 __iomem *addr)
+{
+ return le64_to_cpu(in_le64(addr));
+}
+
+static inline void out_le64(volatile u64 __iomem *addr, u64 val)
+{
+ out_le64(addr, cpu_to_le64(val));
+}
+
+/*
+ * Low level IO stream instructions are defined out of line for now
+ */
+extern void _insb(volatile u8 __iomem *port, void *buf, long count);
+extern void _outsb(volatile u8 __iomem *port, const void *buf, long count);
+extern void _insw_ns(volatile u16 __iomem *port, void *buf, long count);
+extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count);
+extern void _insl_ns(volatile u32 __iomem *port, void *buf, long count);
+extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count);
+
+/* _ns suffix is historical, just define the non-ns version as equivalent
+ * until I've cleaned up the assembly
+ */
+#define _insw _insw_ns
+#define _outsw _outsw_ns
+#define _insl _insl_ns
+#define _outsl _outsl_ns
+
+/*
+ *
+ * PCI and standard ISA accessors
+ *
+ * Those are globally defined linux accessors for devices on PCI or ISA
+ * busses. They follow the Linux defined semantics. The current implementation
+ * for PowerPC is as close as possible to the x86 version of these, and thus
+ * provides fairly heavy weight barriers for the non-raw versions
+ *
+ * In addition, they support a hook mecanism when CONFIG_PPC_INDIRECT_IO
+ * allowing the platform to provide its own implementation of some or all
+ * of the accessors.
+ */
+
extern unsigned long isa_io_base;
extern unsigned long pci_io_base;
-#ifdef CONFIG_PPC_ISERIES
-extern int in_8(const volatile unsigned char __iomem *addr);
-extern void out_8(volatile unsigned char __iomem *addr, int val);
-extern int in_le16(const volatile unsigned short __iomem *addr);
-extern int in_be16(const volatile unsigned short __iomem *addr);
-extern void out_le16(volatile unsigned short __iomem *addr, int val);
-extern void out_be16(volatile unsigned short __iomem *addr, int val);
-extern unsigned in_le32(const volatile unsigned __iomem *addr);
-extern unsigned in_be32(const volatile unsigned __iomem *addr);
-extern void out_le32(volatile unsigned __iomem *addr, int val);
-extern void out_be32(volatile unsigned __iomem *addr, int val);
-extern unsigned long in_le64(const volatile unsigned long __iomem *addr);
-extern unsigned long in_be64(const volatile unsigned long __iomem *addr);
-extern void out_le64(volatile unsigned long __iomem *addr, unsigned long val);
-extern void out_be64(volatile unsigned long __iomem *addr, unsigned long val);
-
-extern unsigned char __raw_readb(const volatile void __iomem *addr);
-extern unsigned short __raw_readw(const volatile void __iomem *addr);
-extern unsigned int __raw_readl(const volatile void __iomem *addr);
-extern unsigned long __raw_readq(const volatile void __iomem *addr);
-extern void __raw_writeb(unsigned char v, volatile void __iomem *addr);
-extern void __raw_writew(unsigned short v, volatile void __iomem *addr);
-extern void __raw_writel(unsigned int v, volatile void __iomem *addr);
-extern void __raw_writeq(unsigned long v, volatile void __iomem *addr);
-
-extern void memset_io(volatile void __iomem *addr, int c, unsigned long n);
-extern void memcpy_fromio(void *dest, const volatile void __iomem *src,
- unsigned long n);
-extern void memcpy_toio(volatile void __iomem *dest, const void *src,
- unsigned long n);
-
-#else /* CONFIG_PPC_ISERIES */
-
-#define in_8(addr) __in_8((addr))
-#define out_8(addr, val) __out_8((addr), (val))
-#define in_le16(addr) __in_le16((addr))
-#define in_be16(addr) __in_be16((addr))
-#define out_le16(addr, val) __out_le16((addr), (val))
-#define out_be16(addr, val) __out_be16((addr), (val))
-#define in_le32(addr) __in_le32((addr))
-#define in_be32(addr) __in_be32((addr))
-#define out_le32(addr, val) __out_le32((addr), (val))
-#define out_be32(addr, val) __out_be32((addr), (val))
-#define in_le64(addr) __in_le64((addr))
-#define in_be64(addr) __in_be64((addr))
-#define out_le64(addr, val) __out_le64((addr), (val))
-#define out_be64(addr, val) __out_be64((addr), (val))
+/*
+ * Non ordered and non-swapping "raw" accessors
+ */
static inline unsigned char __raw_readb(const volatile void __iomem *addr)
{
@@ -115,52 +178,132 @@
{
*(volatile unsigned long __force *)addr = v;
}
-#define memset_io(a,b,c) eeh_memset_io((a),(b),(c))
-#define memcpy_fromio(a,b,c) eeh_memcpy_fromio((a),(b),(c))
-#define memcpy_toio(a,b,c) eeh_memcpy_toio((a),(b),(c))
-
-#endif /* CONFIG_PPC_ISERIES */
-
-/*
- * The insw/outsw/insl/outsl macros don't do byte-swapping.
- * They are only used in practice for transferring buffers which
- * are arrays of bytes, and byte-swapping is not appropriate in
- * that case. - paulus */
-#define insb(port, buf, ns) eeh_insb((port), (buf), (ns))
-#define insw(port, buf, ns) eeh_insw_ns((port), (buf), (ns))
-#define insl(port, buf, nl) eeh_insl_ns((port), (buf), (nl))
-
-#define outsb(port, buf, ns) _outsb((u8 __iomem *)((port)+pci_io_base), (buf), (ns))
-#define outsw(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns))
-#define outsl(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl))
-
-#define readb(addr) eeh_readb(addr)
-#define readw(addr) eeh_readw(addr)
-#define readl(addr) eeh_readl(addr)
-#define readq(addr) eeh_readq(addr)
-#define writeb(data, addr) eeh_writeb((data), (addr))
-#define writew(data, addr) eeh_writew((data), (addr))
-#define writel(data, addr) eeh_writel((data), (addr))
-#define writeq(data, addr) eeh_writeq((data), (addr))
-#define inb(port) eeh_inb((unsigned long)port)
-#define outb(val, port) eeh_outb(val, (unsigned long)port)
-#define inw(port) eeh_inw((unsigned long)port)
-#define outw(val, port) eeh_outw(val, (unsigned long)port)
-#define inl(port) eeh_inl((unsigned long)port)
-#define outl(val, port) eeh_outl(val, (unsigned long)port)
+
+/*
+ *
+ * PCI PIO and MMIO accessors.
+ *
+ */
+
+#include <asm/eeh.h>
+
+/* Shortcut to the MMIO argument pointer */
+#define PCI_IO_ADDR volatile void __iomem *
+
+/* The "__do_*" operations below provide the actual "base" implementation
+ * for each of the defined acccessor. Some of them use the out_* functions
+ * directly, some of them still use EEH, though we might change that in the
+ * future. Those macros below provide the necessary argument swapping and
+ * handling of the IO base for PIO.
+ *
+ * They are themselves used by the macros that define the actual accessors
+ */
+#define __do_writeb(val, addr) out_8(addr, val)
+#define __do_writew(val, addr) out_le16(addr, val)
+#define __do_writel(val, addr) out_le32(addr, val)
+#define __do_writeq(val, addr) out_le64(addr, val)
+#define __do_readb(addr) eeh_readb(addr)
+#define __do_readw(addr) eeh_readw(addr)
+#define __do_readl(addr) eeh_readl(addr)
+#define __do_readq(addr) eeh_readq(addr)
+
+#define __do_outb(val, port) writeb(val,(PCI_IO_ADDR)pci_io_base+port);
+#define __do_outw(val, port) writew(val,(PCI_IO_ADDR)pci_io_base+port);
+#define __do_outl(val, port) writel(val,(PCI_IO_ADDR)pci_io_base+port);
+#define __do_inb(port) readb((PCI_IO_ADDR)pci_io_base + port);
+#define __do_inw(port) readw((PCI_IO_ADDR)pci_io_base + port);
+#define __do_inl(port) readl((PCI_IO_ADDR)pci_io_base + port);
+
+/* Ideally, we should define the IO stream operations based on MMIO versions
+ * like we do for base IO operations. That would make them automagically work
+ * on iSeries.
+ */
+#define __do_insb(port, b, n) eeh_insb((port), (b), (n))
+#define __do_insw(port, b, n) eeh_insw_ns((port), (b), (n))
+#define __do_insl(port, b, n) eeh_insl_ns((port), (b), (n))
+
+#define __do_outsb(p, b, n) _outsb((PCI_IO_ADDR)pci_io_base+(p),(b),(n))
+#define __do_outsw(p, b, n) _outsw((PCI_IO_ADDR)pci_io_base+(p),(b),(n))
+#define __do_outsl(p, b, n) _outsl((PCI_IO_ADDR)pci_io_base+(p),(b),(n))
+
+#define __do_memset_io(addr, c, n) eeh_memset_io(addr, c, n)
+#define __do_memcpy_fromio(dst, src, n) eeh_memcpy_fromio(dst, src, n)
+#define __do_memcpy_toio(dst, src, n) eeh_memcpy_toio(dst, src, n)
+
+#ifdef CONFIG_PPC_INDIRECT_IO
+#define DEF_PCI_HOOK(x) x
+#else
+#define DEF_PCI_HOOK(x) NULL
+#endif
+
+/* Structure containing all the hooks */
+extern struct ppc_pci_io {
+
+#define DEF_PCI_AC_RET(name, ret, at, al) ret (*name) at;
+#define DEF_PCI_AC_NORET(name, at, al) void (*name) at;
+
+#include <asm/io-defs.h>
+
+#undef DEF_PCI_AC_RET
+#undef DEF_PCI_AC_NORET
+
+} ppc_pci_io;
+
+/* The inline wrappers */
+#define DEF_PCI_AC_RET(name, ret, at, al) \
+static inline ret name at \
+{ \
+ if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL) \
+ return ppc_pci_io.name al; \
+ return __do_##name al; \
+}
+
+#define DEF_PCI_AC_NORET(name, at, al) \
+static inline void name at \
+{ \
+ if (DEF_PCI_HOOK(ppc_pci_io.name) != NULL) \
+ ppc_pci_io.name al; \
+ else \
+ __do_##name al; \
+}
+
+#include <asm/io-defs.h>
+
+#undef DEF_PCI_AC_RET
+#undef DEF_PCI_AC_NORET
+
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size) do { } while (0)
+#define dma_cache_wback(_start,_size) do { } while (0)
+#define dma_cache_wback_inv(_start,_size) do { } while (0)
+
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
+/*
+ * We don't do relaxed operations yet, at least not with this semantic
+ */
#define readb_relaxed(addr) readb(addr)
#define readw_relaxed(addr) readw(addr)
#define readl_relaxed(addr) readl(addr)
#define readq_relaxed(addr) readq(addr)
-extern void _insb(volatile u8 __iomem *port, void *buf, long count);
-extern void _outsb(volatile u8 __iomem *port, const void *buf, long count);
-extern void _insw_ns(volatile u16 __iomem *port, void *buf, long count);
-extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count);
-extern void _insl_ns(volatile u32 __iomem *port, void *buf, long count);
-extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count);
-
+/*
+ * Enforce synchronisation of stores vs. spin_unlock
+ * (this does it explicitely, though our implementation of spin_unlock
+ * does it implicitely too)
+ */
static inline void mmiowb(void)
{
unsigned long tmp;
@@ -170,6 +313,19 @@
: "memory");
}
+static inline void iosync(void)
+{
+ __asm__ __volatile__ ("sync" : : : "memory");
+}
+
+/* Enforce in-order execution of data I/O.
+ * No distinction between read/write on PPC; use eieio for all three.
+ */
+#define iobarrier_rw() eieio()
+#define iobarrier_r() eieio()
+#define iobarrier_w() eieio()
+
+
/*
* output pause versions need a delay at least for the
* w83c105 ide controller in a p610.
@@ -185,11 +341,6 @@
#define IO_SPACE_LIMIT ~(0UL)
-extern int __ioremap_explicit(unsigned long p_addr, unsigned long v_addr,
- unsigned long size, unsigned long flags);
-extern void __iomem *__ioremap(unsigned long address, unsigned long size,
- unsigned long flags);
-
/**
* ioremap - map bus memory into CPU space
* @address: bus address of the memory
@@ -200,14 +351,59 @@
* writew/writel functions and the other mmio helpers. The returned
* address is not guaranteed to be usable directly as a virtual
* address.
+ *
+ * We provide a few variations of it:
+ *
+ * * ioremap is the standard one and provides non-cacheable guarded mappings
+ * and can be hooked by the platform via ppc_md
+ *
+ * * ioremap_flags allows to specify the page flags as an argument and can
+ * also be hooked by the platform via ppc_md
+ *
+ * * ioremap_nocache is identical to ioremap
+ *
+ * * iounmap undoes such a mapping and can be hooked
+ *
+ * * __ioremap_explicit (and it's pending __iounmap_explicit) are low level
+ * functions to create hand-made mappings for use only by the PCI code
+ * and cannot currently be hooked.
+ *
+ * * __ioremap is the low level implementation used by ioremap and
+ * ioremap_flags and cannot be hooked (but can be used by a hook on one
+ * of the previous ones)
+ *
+ * * __iounmap, is the low level implementation used by iounmap and cannot
+ * be hooked (but can be used by a hook on iounmap)
+ *
*/
extern void __iomem *ioremap(unsigned long address, unsigned long size);
-
+extern void __iomem *ioremap_flags(unsigned long address, unsigned long size,
+ unsigned long flags);
#define ioremap_nocache(addr, size) ioremap((addr), (size))
-extern int iounmap_explicit(volatile void __iomem *addr, unsigned long size);
-extern void iounmap(volatile void __iomem *addr);
+extern void iounmap(void __iomem *addr);
+
+extern void __iomem *__ioremap(unsigned long address, unsigned long size,
+ unsigned long flags);
+extern void __iounmap(void __iomem *addr);
+
+extern int __ioremap_explicit(unsigned long p_addr, unsigned long v_addr,
+ unsigned long size, unsigned long flags);
+extern int __iounmap_explicit(void __iomem *start, unsigned long size);
+
extern void __iomem * reserve_phb_iospace(unsigned long size);
+
+/*
+ * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation
+ * which needs some additional definitions here. They basically allow PIO
+ * space overall to be 1Gb. This will work as long as we never try to use
+ * iomap to map MMIO below 1Gb which should be fine on ppc64
+ */
+#define HAVE_ARCH_PIO_SIZE 1
+#define PIO_OFFSET 0x00000000UL
+#define PIO_MASK 0x3fffffffUL
+#define PIO_RESERVED 0x40000000UL
+
/**
* virt_to_phys - map virtual addresses to physical
* @address: address to remap
@@ -254,177 +450,6 @@
*/
#define BIO_VMERGE_BOUNDARY 0
-static inline void iosync(void)
-{
- __asm__ __volatile__ ("sync" : : : "memory");
-}
-
-/* Enforce in-order execution of data I/O.
- * No distinction between read/write on PPC; use eieio for all three.
- */
-#define iobarrier_rw() eieio()
-#define iobarrier_r() eieio()
-#define iobarrier_w() eieio()
-
-/*
- * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
- * These routines do not perform EEH-related I/O address translation,
- * and should not be used directly by device drivers. Use inb/readb
- * instead.
- */
-static inline int __in_8(const volatile unsigned char __iomem *addr)
-{
- int ret;
-
- __asm__ __volatile__("sync; lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
- : "=r" (ret) : "m" (*addr));
- return ret;
-}
-
-static inline void __out_8(volatile unsigned char __iomem *addr, int val)
-{
- __asm__ __volatile__("sync; stb%U0%X0 %1,%0"
- : "=m" (*addr) : "r" (val));
- get_paca()->io_sync = 1;
-}
-
-static inline int __in_le16(const volatile unsigned short __iomem *addr)
-{
- int ret;
-
- __asm__ __volatile__("sync; lhbrx %0,0,%1; twi 0,%0,0; isync"
- : "=r" (ret) : "r" (addr), "m" (*addr));
- return ret;
-}
-
-static inline int __in_be16(const volatile unsigned short __iomem *addr)
-{
- int ret;
-
- __asm__ __volatile__("sync; lhz%U1%X1 %0,%1; twi 0,%0,0; isync"
- : "=r" (ret) : "m" (*addr));
- return ret;
-}
-
-static inline void __out_le16(volatile unsigned short __iomem *addr, int val)
-{
- __asm__ __volatile__("sync; sthbrx %1,0,%2"
- : "=m" (*addr) : "r" (val), "r" (addr));
- get_paca()->io_sync = 1;
-}
-
-static inline void __out_be16(volatile unsigned short __iomem *addr, int val)
-{
- __asm__ __volatile__("sync; sth%U0%X0 %1,%0"
- : "=m" (*addr) : "r" (val));
- get_paca()->io_sync = 1;
-}
-
-static inline unsigned __in_le32(const volatile unsigned __iomem *addr)
-{
- unsigned ret;
-
- __asm__ __volatile__("sync; lwbrx %0,0,%1; twi 0,%0,0; isync"
- : "=r" (ret) : "r" (addr), "m" (*addr));
- return ret;
-}
-
-static inline unsigned __in_be32(const volatile unsigned __iomem *addr)
-{
- unsigned ret;
-
- __asm__ __volatile__("sync; lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
- : "=r" (ret) : "m" (*addr));
- return ret;
-}
-
-static inline void __out_le32(volatile unsigned __iomem *addr, int val)
-{
- __asm__ __volatile__("sync; stwbrx %1,0,%2" : "=m" (*addr)
- : "r" (val), "r" (addr));
- get_paca()->io_sync = 1;
-}
-
-static inline void __out_be32(volatile unsigned __iomem *addr, int val)
-{
- __asm__ __volatile__("sync; stw%U0%X0 %1,%0"
- : "=m" (*addr) : "r" (val));
- get_paca()->io_sync = 1;
-}
-
-static inline unsigned long __in_le64(const volatile unsigned long __iomem *addr)
-{
- unsigned long tmp, ret;
-
- __asm__ __volatile__(
- "sync\n"
- "ld %1,0(%2)\n"
- "twi 0,%1,0\n"
- "isync\n"
- "rldimi %0,%1,5*8,1*8\n"
- "rldimi %0,%1,3*8,2*8\n"
- "rldimi %0,%1,1*8,3*8\n"
- "rldimi %0,%1,7*8,4*8\n"
- "rldicl %1,%1,32,0\n"
- "rlwimi %0,%1,8,8,31\n"
- "rlwimi %0,%1,24,16,23\n"
- : "=r" (ret) , "=r" (tmp) : "b" (addr) , "m" (*addr));
- return ret;
-}
-
-static inline unsigned long __in_be64(const volatile unsigned long __iomem *addr)
-{
- unsigned long ret;
-
- __asm__ __volatile__("sync; ld%U1%X1 %0,%1; twi 0,%0,0; isync"
- : "=r" (ret) : "m" (*addr));
- return ret;
-}
-
-static inline void __out_le64(volatile unsigned long __iomem *addr, unsigned long val)
-{
- unsigned long tmp;
-
- __asm__ __volatile__(
- "rldimi %0,%1,5*8,1*8\n"
- "rldimi %0,%1,3*8,2*8\n"
- "rldimi %0,%1,1*8,3*8\n"
- "rldimi %0,%1,7*8,4*8\n"
- "rldicl %1,%1,32,0\n"
- "rlwimi %0,%1,8,8,31\n"
- "rlwimi %0,%1,24,16,23\n"
- "sync\n"
- "std %0,0(%3)"
- : "=&r" (tmp) , "=&r" (val) : "1" (val) , "b" (addr) , "m" (*addr));
- get_paca()->io_sync = 1;
-}
-
-static inline void __out_be64(volatile unsigned long __iomem *addr, unsigned long val)
-{
- __asm__ __volatile__("sync; std%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
- get_paca()->io_sync = 1;
-}
-
-#include <asm/eeh.h>
-
-/* Nothing to do */
-
-#define dma_cache_inv(_start,_size) do { } while (0)
-#define dma_cache_wback(_start,_size) do { } while (0)
-#define dma_cache_wback_inv(_start,_size) do { } while (0)
-
-
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem
- * access
- */
-#define xlate_dev_mem_ptr(p) __va(p)
-
-/*
- * Convert a virtual cached pointer to an uncached pointer
- */
-#define xlate_dev_kmem_ptr(p) p
-
#endif /* __KERNEL__ */
#endif /* CONFIG_PPC64 */
Index: linux-cell/arch/powerpc/Kconfig
===================================================================
--- linux-cell.orig/arch/powerpc/Kconfig 2006-11-04 15:24:57.000000000 +1100
+++ linux-cell/arch/powerpc/Kconfig 2006-11-04 18:03:42.000000000 +1100
@@ -389,6 +389,7 @@
config PPC_ISERIES
bool "IBM Legacy iSeries"
depends on PPC_MULTIPLATFORM && PPC64
+ select PPC_INDIRECT_IO
config PPC_CHRP
bool "Common Hardware Reference Platform (CHRP) based machines"
@@ -534,6 +535,15 @@
bool
default n
+config PPC_INDIRECT_IO
+ bool
+ select GENERIC_IOMAP
+ default n
+
+config GENERIC_IOMAP
+ bool
+ default n
+
source "drivers/cpufreq/Kconfig"
config CPU_FREQ_PMAC
Index: linux-cell/arch/powerpc/kernel/setup_64.c
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/setup_64.c 2006-11-04 15:24:57.000000000 +1100
+++ linux-cell/arch/powerpc/kernel/setup_64.c 2006-11-04 17:36:34.000000000 +1100
@@ -599,3 +599,10 @@
}
}
#endif
+
+
+#ifdef CONFIG_PPC_INDIRECT_IO
+struct ppc_pci_io ppc_pci_io;
+EXPORT_SYMBOL(ppc_pci_io);
+#endif /* CONFIG_PPC_INDIRECT_IO */
+
Index: linux-cell/arch/powerpc/platforms/iseries/pci.c
===================================================================
--- linux-cell.orig/arch/powerpc/platforms/iseries/pci.c 2006-11-04 15:24:57.000000000 +1100
+++ linux-cell/arch/powerpc/platforms/iseries/pci.c 2006-11-04 18:00:45.000000000 +1100
@@ -156,53 +156,6 @@
}
/*
- * iSeries_pcibios_init
- *
- * Description:
- * This function checks for all possible system PCI host bridges that connect
- * PCI buses. The system hypervisor is queried as to the guest partition
- * ownership status. A pci_controller is built for any bus which is partially
- * owned or fully owned by this guest partition.
- */
-void iSeries_pcibios_init(void)
-{
- struct pci_controller *phb;
- struct device_node *root = of_find_node_by_path("/");
- struct device_node *node = NULL;
-
- if (root == NULL) {
- printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
- "of device tree\n");
- return;
- }
- while ((node = of_get_next_child(root, node)) != NULL) {
- HvBusNumber bus;
- const u32 *busp;
-
- if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
- continue;
-
- busp = get_property(node, "bus-range", NULL);
- if (busp == NULL)
- continue;
- bus = *busp;
- printk("bus %d appears to exist\n", bus);
- phb = pcibios_alloc_controller(node);
- if (phb == NULL)
- continue;
-
- phb->pci_mem_offset = phb->local_number = bus;
- phb->first_busno = bus;
- phb->last_busno = bus;
- phb->ops = &iSeries_pci_ops;
- }
-
- of_node_put(root);
-
- pci_devs_phb_init();
-}
-
-/*
* iSeries_pci_final_fixup(void)
*/
void __init iSeries_pci_final_fixup(void)
@@ -438,13 +391,9 @@
/*
* Read MM I/O Instructions for the iSeries
* On MM I/O error, all ones are returned and iSeries_pci_IoError is cal
- * else, data is returned in big Endian format.
- *
- * iSeries_Read_Byte = Read Byte ( 8 bit)
- * iSeries_Read_Word = Read Word (16 bit)
- * iSeries_Read_Long = Read Long (32 bit)
+ * else, data is returned in little Endian format.
*/
-static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
+static u8 iseries_readb(const volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
@@ -462,7 +411,8 @@
num_printed = 0;
}
if (num_printed++ < 10)
- printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress);
+ printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n",
+ IoAddress);
return 0xff;
}
do {
@@ -472,7 +422,7 @@
return (u8)ret.value;
}
-static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
+static u16 iseries_readw(const volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
@@ -490,7 +440,8 @@
num_printed = 0;
}
if (num_printed++ < 10)
- printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress);
+ printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n",
+ IoAddress);
return 0xffff;
}
do {
@@ -498,10 +449,10 @@
BarOffset, 0);
} while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
- return swab16((u16)ret.value);
+ return cpu_to_le16((u16)ret.value);
}
-static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
+static u32 iseries_readl(const volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
@@ -519,7 +470,8 @@
num_printed = 0;
}
if (num_printed++ < 10)
- printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress);
+ printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n",
+ IoAddress);
return 0xffffffff;
}
do {
@@ -527,17 +479,14 @@
BarOffset, 0);
} while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
- return swab32((u32)ret.value);
+ return cpu_to_le32((u32)ret.value);
}
/*
* Write MM I/O Instructions for the iSeries
*
- * iSeries_Write_Byte = Write Byte (8 bit)
- * iSeries_Write_Word = Write Word(16 bit)
- * iSeries_Write_Long = Write Long(32 bit)
*/
-static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
+static void iseries_writeb(u8 data, volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
@@ -563,7 +512,7 @@
} while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
}
-static void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
+static void iseries_writew(u16 data, volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
@@ -581,15 +530,16 @@
num_printed = 0;
}
if (num_printed++ < 10)
- printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress);
+ printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n",
+ IoAddress);
return;
}
do {
- rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
+ rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, le16_to_cpu(data), 0);
} while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
}
-static void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
+static void iseries_writel(u32 data, volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
@@ -607,231 +557,109 @@
num_printed = 0;
}
if (num_printed++ < 10)
- printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress);
+ printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n",
+ IoAddress);
return;
}
do {
- rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
+ rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, le32_to_cpu(data), 0);
} while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
}
-extern unsigned char __raw_readb(const volatile void __iomem *addr)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- return *(volatile unsigned char __force *)addr;
-}
-EXPORT_SYMBOL(__raw_readb);
-
-extern unsigned short __raw_readw(const volatile void __iomem *addr)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- return *(volatile unsigned short __force *)addr;
-}
-EXPORT_SYMBOL(__raw_readw);
-
-extern unsigned int __raw_readl(const volatile void __iomem *addr)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- return *(volatile unsigned int __force *)addr;
-}
-EXPORT_SYMBOL(__raw_readl);
-
-extern unsigned long __raw_readq(const volatile void __iomem *addr)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- return *(volatile unsigned long __force *)addr;
-}
-EXPORT_SYMBOL(__raw_readq);
-
-extern void __raw_writeb(unsigned char v, volatile void __iomem *addr)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- *(volatile unsigned char __force *)addr = v;
-}
-EXPORT_SYMBOL(__raw_writeb);
-
-extern void __raw_writew(unsigned short v, volatile void __iomem *addr)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- *(volatile unsigned short __force *)addr = v;
-}
-EXPORT_SYMBOL(__raw_writew);
-
-extern void __raw_writel(unsigned int v, volatile void __iomem *addr)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- *(volatile unsigned int __force *)addr = v;
-}
-EXPORT_SYMBOL(__raw_writel);
-
-extern void __raw_writeq(unsigned long v, volatile void __iomem *addr)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- *(volatile unsigned long __force *)addr = v;
-}
-EXPORT_SYMBOL(__raw_writeq);
-
-int in_8(const volatile unsigned char __iomem *addr)
+static void iseries_memset_io(volatile void __iomem *addr, int c, unsigned long n)
{
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- return iSeries_Read_Byte(addr);
- return __in_8(addr);
-}
-EXPORT_SYMBOL(in_8);
-
-void out_8(volatile unsigned char __iomem *addr, int val)
-{
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- iSeries_Write_Byte(val, addr);
- else
- __out_8(addr, val);
-}
-EXPORT_SYMBOL(out_8);
-
-int in_le16(const volatile unsigned short __iomem *addr)
-{
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- return iSeries_Read_Word(addr);
- return __in_le16(addr);
-}
-EXPORT_SYMBOL(in_le16);
-
-int in_be16(const volatile unsigned short __iomem *addr)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- return __in_be16(addr);
-}
-EXPORT_SYMBOL(in_be16);
-
-void out_le16(volatile unsigned short __iomem *addr, int val)
-{
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- iSeries_Write_Word(val, addr);
- else
- __out_le16(addr, val);
-}
-EXPORT_SYMBOL(out_le16);
-
-void out_be16(volatile unsigned short __iomem *addr, int val)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- __out_be16(addr, val);
-}
-EXPORT_SYMBOL(out_be16);
-
-unsigned in_le32(const volatile unsigned __iomem *addr)
-{
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- return iSeries_Read_Long(addr);
- return __in_le32(addr);
-}
-EXPORT_SYMBOL(in_le32);
-
-unsigned in_be32(const volatile unsigned __iomem *addr)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- return __in_be32(addr);
-}
-EXPORT_SYMBOL(in_be32);
+ volatile char __iomem *d = addr;
-void out_le32(volatile unsigned __iomem *addr, int val)
-{
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- iSeries_Write_Long(val, addr);
- else
- __out_le32(addr, val);
+ while (n-- > 0)
+ iseries_writeb(c, d++);
}
-EXPORT_SYMBOL(out_le32);
-void out_be32(volatile unsigned __iomem *addr, int val)
+static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,
+ unsigned long n)
{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
+ char *d = dest;
+ const volatile char __iomem *s = src;
- __out_be32(addr, val);
+ while (n-- > 0)
+ *d++ = iseries_readb(s++);
}
-EXPORT_SYMBOL(out_be32);
-unsigned long in_le64(const volatile unsigned long __iomem *addr)
+static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,
+ unsigned long n)
{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
+ const char *s = src;
+ volatile char __iomem *d = dest;
- return __in_le64(addr);
+ while (n-- > 0)
+ iseries_writeb(*s++, d++);
}
-EXPORT_SYMBOL(in_le64);
-unsigned long in_be64(const volatile unsigned long __iomem *addr)
+static void __init iseries_setup_io_access(void)
{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
-
- return __in_be64(addr);
+ /* Note that we only set the ones we support. The other ones
+ * are kept to their native implementation which will fault
+ * since we are giving them tokens that match non-mapped areas.
+ * This is as good behaviour as the BUG() we used to have
+ *
+ * We probably want to support the stream operations too though
+ */
+ ppc_pci_io.readb = iseries_readb;
+ ppc_pci_io.readw = iseries_readw;
+ ppc_pci_io.readl = iseries_readl;
+ ppc_pci_io.writeb = iseries_writeb;
+ ppc_pci_io.writew = iseries_writew;
+ ppc_pci_io.writel = iseries_writel;
+ ppc_pci_io.memset_io = iseries_memset_io;
+ ppc_pci_io.memcpy_fromio = iseries_memcpy_fromio;
+ ppc_pci_io.memcpy_toio = iseries_memcpy_toio;
}
-EXPORT_SYMBOL(in_be64);
-void out_le64(volatile unsigned long __iomem *addr, unsigned long val)
+/*
+ * iSeries_pcibios_init
+ *
+ * Description:
+ * This function checks for all possible system PCI host bridges that connect
+ * PCI buses. The system hypervisor is queried as to the guest partition
+ * ownership status. A pci_controller is built for any bus which is partially
+ * owned or fully owned by this guest partition.
+ */
+void __init iSeries_pcibios_init(void)
{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
+ struct pci_controller *phb;
+ struct device_node *root = of_find_node_by_path("/");
+ struct device_node *node = NULL;
- __out_le64(addr, val);
-}
-EXPORT_SYMBOL(out_le64);
+ iseries_setup_io_access();
-void out_be64(volatile unsigned long __iomem *addr, unsigned long val)
-{
- BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
+ if (root == NULL) {
+ printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
+ "of device tree\n");
+ return;
+ }
+ while ((node = of_get_next_child(root, node)) != NULL) {
+ HvBusNumber bus;
+ const u32 *busp;
- __out_be64(addr, val);
-}
-EXPORT_SYMBOL(out_be64);
+ if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
+ continue;
-void memset_io(volatile void __iomem *addr, int c, unsigned long n)
-{
- if (firmware_has_feature(FW_FEATURE_ISERIES)) {
- volatile char __iomem *d = addr;
+ busp = get_property(node, "bus-range", NULL);
+ if (busp == NULL)
+ continue;
+ bus = *busp;
+ printk("bus %d appears to exist\n", bus);
+ phb = pcibios_alloc_controller(node);
+ if (phb == NULL)
+ continue;
- while (n-- > 0) {
- iSeries_Write_Byte(c, d++);
- }
- } else
- eeh_memset_io(addr, c, n);
-}
-EXPORT_SYMBOL(memset_io);
+ phb->pci_mem_offset = phb->local_number = bus;
+ phb->first_busno = bus;
+ phb->last_busno = bus;
+ phb->ops = &iSeries_pci_ops;
+ }
-void memcpy_fromio(void *dest, const volatile void __iomem *src,
- unsigned long n)
-{
- if (firmware_has_feature(FW_FEATURE_ISERIES)) {
- char *d = dest;
- const volatile char __iomem *s = src;
+ of_node_put(root);
- while (n-- > 0) {
- *d++ = iSeries_Read_Byte(s++);
- }
- } else
- eeh_memcpy_fromio(dest, src, n);
+ pci_devs_phb_init();
}
-EXPORT_SYMBOL(memcpy_fromio);
-void memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n)
-{
- if (firmware_has_feature(FW_FEATURE_ISERIES)) {
- const char *s = src;
- volatile char __iomem *d = dest;
-
- while (n-- > 0) {
- iSeries_Write_Byte(*s++, d++);
- }
- } else
- eeh_memcpy_toio(dest, src, n);
-}
-EXPORT_SYMBOL(memcpy_toio);
Index: linux-cell/include/asm-powerpc/eeh.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/eeh.h 2006-11-04 15:24:57.000000000 +1100
+++ linux-cell/include/asm-powerpc/eeh.h 2006-11-04 18:01:20.000000000 +1100
@@ -120,10 +120,6 @@
return eeh_check_failure(addr, val);
return val;
}
-static inline void eeh_writeb(u8 val, volatile void __iomem *addr)
-{
- out_8(addr, val);
-}
static inline u16 eeh_readw(const volatile void __iomem *addr)
{
@@ -132,21 +128,6 @@
return eeh_check_failure(addr, val);
return val;
}
-static inline void eeh_writew(u16 val, volatile void __iomem *addr)
-{
- out_le16(addr, val);
-}
-static inline u16 eeh_raw_readw(const volatile void __iomem *addr)
-{
- u16 val = in_be16(addr);
- if (EEH_POSSIBLE_ERROR(val, u16))
- return eeh_check_failure(addr, val);
- return val;
-}
-static inline void eeh_raw_writew(u16 val, volatile void __iomem *addr) {
- volatile u16 __iomem *vaddr = (volatile u16 __iomem *) addr;
- out_be16(vaddr, val);
-}
static inline u32 eeh_readl(const volatile void __iomem *addr)
{
@@ -155,21 +136,6 @@
return eeh_check_failure(addr, val);
return val;
}
-static inline void eeh_writel(u32 val, volatile void __iomem *addr)
-{
- out_le32(addr, val);
-}
-static inline u32 eeh_raw_readl(const volatile void __iomem *addr)
-{
- u32 val = in_be32(addr);
- if (EEH_POSSIBLE_ERROR(val, u32))
- return eeh_check_failure(addr, val);
- return val;
-}
-static inline void eeh_raw_writel(u32 val, volatile void __iomem *addr)
-{
- out_be32(addr, val);
-}
static inline u64 eeh_readq(const volatile void __iomem *addr)
{
@@ -178,21 +144,6 @@
return eeh_check_failure(addr, val);
return val;
}
-static inline void eeh_writeq(u64 val, volatile void __iomem *addr)
-{
- out_le64(addr, val);
-}
-static inline u64 eeh_raw_readq(const volatile void __iomem *addr)
-{
- u64 val = in_be64(addr);
- if (EEH_POSSIBLE_ERROR(val, u64))
- return eeh_check_failure(addr, val);
- return val;
-}
-static inline void eeh_raw_writeq(u64 val, volatile void __iomem *addr)
-{
- out_be64(addr, val);
-}
#define EEH_CHECK_ALIGN(v,a) \
((((unsigned long)(v)) & ((a) - 1)) == 0)
@@ -292,48 +243,6 @@
#undef EEH_CHECK_ALIGN
-static inline u8 eeh_inb(unsigned long port)
-{
- u8 val;
- val = in_8((u8 __iomem *)(port+pci_io_base));
- if (EEH_POSSIBLE_ERROR(val, u8))
- return eeh_check_failure((void __iomem *)(port), val);
- return val;
-}
-
-static inline void eeh_outb(u8 val, unsigned long port)
-{
- out_8((u8 __iomem *)(port+pci_io_base), val);
-}
-
-static inline u16 eeh_inw(unsigned long port)
-{
- u16 val;
- val = in_le16((u16 __iomem *)(port+pci_io_base));
- if (EEH_POSSIBLE_ERROR(val, u16))
- return eeh_check_failure((void __iomem *)(port), val);
- return val;
-}
-
-static inline void eeh_outw(u16 val, unsigned long port)
-{
- out_le16((u16 __iomem *)(port+pci_io_base), val);
-}
-
-static inline u32 eeh_inl(unsigned long port)
-{
- u32 val;
- val = in_le32((u32 __iomem *)(port+pci_io_base));
- if (EEH_POSSIBLE_ERROR(val, u32))
- return eeh_check_failure((void __iomem *)(port), val);
- return val;
-}
-
-static inline void eeh_outl(u32 val, unsigned long port)
-{
- out_le32((u32 __iomem *)(port+pci_io_base), val);
-}
-
/* in-string eeh macros */
static inline void eeh_insb(unsigned long port, void * buf, int ns)
{
Index: linux-cell/arch/powerpc/kernel/Makefile
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/Makefile 2006-11-04 18:03:56.000000000 +1100
+++ linux-cell/arch/powerpc/kernel/Makefile 2006-11-04 18:05:27.000000000 +1100
@@ -63,7 +63,7 @@
module-$(CONFIG_PPC64) += module_64.o
obj-$(CONFIG_MODULES) += $(module-y)
-pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o iomap.o
+pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o
pci32-$(CONFIG_PPC32) := pci_32.o
obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y)
kexec-$(CONFIG_PPC64) := machine_kexec_64.o
@@ -72,6 +72,10 @@
obj-$(CONFIG_AUDIT) += audit.o
obj64-$(CONFIG_AUDIT) += compat_audit.o
+ifneq ($(CONFIG_PPC_INDIRECT_IO),y)
+pci64-$(CONFIG_PPC64) += iomap.o
+endif
+
ifeq ($(CONFIG_PPC_ISERIES),y)
$(obj)/head_64.o: $(obj)/lparmap.s
AFLAGS_head_64.o += -I$(obj)
Index: linux-cell/arch/powerpc/mm/pgtable_64.c
===================================================================
--- linux-cell.orig/arch/powerpc/mm/pgtable_64.c 2006-11-04 17:47:01.000000000 +1100
+++ linux-cell/arch/powerpc/mm/pgtable_64.c 2006-11-04 18:24:49.000000000 +1100
@@ -129,22 +129,12 @@
return (void __iomem *) (ea + (addr & ~PAGE_MASK));
}
-
-void __iomem *
-ioremap(unsigned long addr, unsigned long size)
-{
- return __ioremap(addr, size, _PAGE_NO_CACHE | _PAGE_GUARDED);
-}
-
void __iomem * __ioremap(unsigned long addr, unsigned long size,
unsigned long flags)
{
unsigned long pa, ea;
void __iomem *ret;
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- return (void __iomem *)addr;
-
/*
* Choose an address to map it to.
* Once the imalloc system is running, we use it.
@@ -178,6 +168,25 @@
return ret;
}
+
+void __iomem * ioremap(unsigned long addr, unsigned long size)
+{
+ unsigned long flags = _PAGE_NO_CACHE | _PAGE_GUARDED;
+
+ if (ppc_md.ioremap)
+ return ppc_md.ioremap(addr, size, flags);
+ return __ioremap(addr, size, flags);
+}
+
+void __iomem * ioremap_flags(unsigned long addr, unsigned long size,
+ unsigned long flags)
+{
+ if (ppc_md.ioremap)
+ return ppc_md.ioremap(addr, size, flags);
+ return __ioremap(addr, size, flags);
+}
+
+
#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK))
int __ioremap_explicit(unsigned long pa, unsigned long ea,
@@ -235,13 +244,10 @@
*
* XXX what about calls before mem_init_done (ie python_countermeasures())
*/
-void iounmap(volatile void __iomem *token)
+void __iounmap(void __iomem *token)
{
void *addr;
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- return;
-
if (!mem_init_done)
return;
@@ -250,6 +256,14 @@
im_free(addr);
}
+void iounmap(void __iomem *token)
+{
+ if (ppc_md.iounmap)
+ ppc_md.iounmap(token);
+ else
+ __iounmap(token);
+}
+
static int iounmap_subset_regions(unsigned long addr, unsigned long size)
{
struct vm_struct *area;
@@ -268,7 +282,7 @@
return 0;
}
-int iounmap_explicit(volatile void __iomem *start, unsigned long size)
+int __iounmap_explicit(void __iomem *start, unsigned long size)
{
struct vm_struct *area;
unsigned long addr;
@@ -303,8 +317,10 @@
}
EXPORT_SYMBOL(ioremap);
+EXPORT_SYMBOL(ioremap_flags);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(__iounmap);
void __iomem * reserve_phb_iospace(unsigned long size)
{
Index: linux-cell/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- linux-cell.orig/arch/powerpc/platforms/iseries/setup.c 2006-11-04 17:54:18.000000000 +1100
+++ linux-cell/arch/powerpc/platforms/iseries/setup.c 2006-11-04 18:10:36.000000000 +1100
@@ -649,6 +649,16 @@
void __init iSeries_init_IRQ(void) { }
#endif
+static void __iomem *iseries_ioremap(unsigned long address, unsigned long size,
+ unsigned long flags)
+{
+ return (void __iomem *)address;
+}
+
+static void iseries_iounmap(void __iomem *token)
+{
+}
+
/*
* iSeries has no legacy IO, anything calling this function has to
* fail or bad things will happen
@@ -687,6 +697,8 @@
.progress = iSeries_progress,
.probe = iseries_probe,
.check_legacy_ioport = iseries_check_legacy_ioport,
+ .ioremap = iseries_ioremap,
+ .iounmap = iseries_iounmap,
/* XXX Implement enable_pmcs for iSeries */
};
Index: linux-cell/include/asm-powerpc/io-defs.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-cell/include/asm-powerpc/io-defs.h 2006-11-04 18:15:53.000000000 +1100
@@ -0,0 +1,37 @@
+/* This file is meant to be include multiple times by other headers */
+
+DEF_PCI_AC_RET(readb, u8, (const PCI_IO_ADDR addr), (addr))
+DEF_PCI_AC_RET(readw, u16, (const PCI_IO_ADDR addr), (addr))
+DEF_PCI_AC_RET(readl, u32, (const PCI_IO_ADDR addr), (addr))
+DEF_PCI_AC_RET(readq, u64, (const PCI_IO_ADDR addr), (addr))
+DEF_PCI_AC_NORET(writeb, (u8 val, PCI_IO_ADDR addr), (val, addr))
+DEF_PCI_AC_NORET(writew, (u16 val, PCI_IO_ADDR addr), (val, addr))
+DEF_PCI_AC_NORET(writel, (u32 val, PCI_IO_ADDR addr), (val, addr))
+DEF_PCI_AC_NORET(writeq, (u64 val, PCI_IO_ADDR addr), (val, addr))
+
+DEF_PCI_AC_RET(inb, u8, (unsigned long port), (port))
+DEF_PCI_AC_RET(inw, u16, (unsigned long port), (port))
+DEF_PCI_AC_RET(inl, u32, (unsigned long port), (port))
+DEF_PCI_AC_NORET(outb, (u8 val, unsigned long port), (val, port))
+DEF_PCI_AC_NORET(outw, (u16 val, unsigned long port), (val, port))
+DEF_PCI_AC_NORET(outl, (u32 val, unsigned long port), (val, port))
+
+DEF_PCI_AC_NORET(insb, (unsigned long p, void *b, unsigned long c), \
+ (p, b, c))
+DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c), \
+ (p, b, c))
+DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c), \
+ (p, b, c))
+DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned long c), \
+ (p, b, c))
+DEF_PCI_AC_NORET(outsw, (unsigned long p, const void *b, unsigned long c), \
+ (p, b, c))
+DEF_PCI_AC_NORET(outsl, (unsigned long p, const void *b, unsigned long c), \
+ (p, b, c))
+
+DEF_PCI_AC_NORET(memset_io, (PCI_IO_ADDR a, int c, unsigned long n), \
+ (a, c, n))
+DEF_PCI_AC_NORET(memcpy_fromio,(void *d,const PCI_IO_ADDR s,unsigned long n), \
+ (d, s, n))
+DEF_PCI_AC_NORET(memcpy_toio,(PCI_IO_ADDR d,const void *s,unsigned long n), \
+ (d, s, n))
Index: linux-cell/include/asm-powerpc/machdep.h
===================================================================
--- linux-cell.orig/include/asm-powerpc/machdep.h 2006-11-04 17:43:47.000000000 +1100
+++ linux-cell/include/asm-powerpc/machdep.h 2006-11-04 17:57:24.000000000 +1100
@@ -87,6 +87,10 @@
void (*tce_flush)(struct iommu_table *tbl);
void (*pci_dma_dev_setup)(struct pci_dev *dev);
void (*pci_dma_bus_setup)(struct pci_bus *bus);
+
+ void __iomem * (*ioremap)(unsigned long addr, unsigned long size,
+ unsigned long flags);
+ void (*iounmap)(void __iomem *token);
#endif /* CONFIG_PPC64 */
int (*probe)(void);
Index: linux-cell/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-cell.orig/arch/powerpc/kernel/pci_64.c 2006-11-04 18:25:17.000000000 +1100
+++ linux-cell/arch/powerpc/kernel/pci_64.c 2006-11-04 18:25:19.000000000 +1100
@@ -1172,7 +1172,7 @@
if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
return 1;
- if (iounmap_explicit((void __iomem *) start_virt, size))
+ if (__iounmap_explicit((void __iomem *) start_virt, size))
return 1;
return 0;
^ permalink raw reply
* Booting without Uboot on 8548E
From: M Ptich @ 2006-11-04 8:52 UTC (permalink / raw)
To: linuxppc-dev
Documentation mentions that the only dependencies between 2.6 Kernel and
bootloader are:
1. 5 input parameters (bd_t pointer, start and end of command line, start
and end of ram disk)
2. bd_t pointer and command line must with within 16MB of Kernel
3. Initial TLB1 entry must have IPROT=1
Slowly, we are finding that this list is not complete. For example, address
calculation at the start of platform_init (r3 + ...) assumes that Kernel has
been initially loaded at 0-base virtual address.
And now we are stuck with apparently another dependency: our Kernel fails to
advance beyond time calibration because jiffies are not getting incremented,
so we are not getting timer interrupts. Is it true that Kernel relies on
EPIC timer set in Uboot ? If not - where the timer insterrupts are
configured ?
_________________________________________________________________
Try the next generation of search with Windows Live Search today!
http://imagine-windowslive.com/minisites/searchlaunch/?locale=en-us&source=hmtagline
^ permalink raw reply
* Re: Booting without Uboot on 8548E
From: Benjamin Herrenschmidt @ 2006-11-04 9:13 UTC (permalink / raw)
To: M Ptich; +Cc: linuxppc-dev
In-Reply-To: <BAY102-F21BB220054F2541A7614E4A9FD0@phx.gbl>
On Sat, 2006-11-04 at 08:52 +0000, M Ptich wrote:
> Documentation mentions that the only dependencies between 2.6 Kernel and
> bootloader are:
>
> 1. 5 input parameters (bd_t pointer, start and end of command line, start
> and end of ram disk)
> 2. bd_t pointer and command line must with within 16MB of Kernel
> 3. Initial TLB1 entry must have IPROT=1
This is for arch/ppc, which is sort-of deprecated. You should seriously
think about porting over to arch/powerpc instead.
> Slowly, we are finding that this list is not complete. For example, address
> calculation at the start of platform_init (r3 + ...) assumes that Kernel has
> been initially loaded at 0-base virtual address.
For which CPU core ? 6xx/7xx/7xxx/G2 cores don't assume such a thing,
the kernel can be loaded anywhere as long as the virtual and physical
addresses are the same.
> And now we are stuck with apparently another dependency: our Kernel fails to
> advance beyond time calibration because jiffies are not getting incremented,
> so we are not getting timer interrupts. Is it true that Kernel relies on
> EPIC timer set in Uboot ? If not - where the timer insterrupts are
> configured ?
I'm not familiar about which core family the 85xx is. Doesn't it use the
decrementer ?
Ben.
^ permalink raw reply
* Re: Booting without Uboot on 8548E
From: Benjamin Herrenschmidt @ 2006-11-04 9:19 UTC (permalink / raw)
To: M Ptich; +Cc: linuxppc-dev
In-Reply-To: <1162631621.28571.26.camel@localhost.localdomain>
> > Slowly, we are finding that this list is not complete. For example, address
> > calculation at the start of platform_init (r3 + ...) assumes that Kernel has
> > been initially loaded at 0-base virtual address.
>
> For which CPU core ? 6xx/7xx/7xxx/G2 cores don't assume such a thing,
> the kernel can be loaded anywhere as long as the virtual and physical
> addresses are the same.
I've checked and 85xx is some sort of BookE, so you'll have to wait for
the freescale folks here to help you..
(Note that it's unlikely that people will be motivated to help you
considering the rude tone of your initial email)
Ben.
^ permalink raw reply
* FSL vs. IBM BookE
From: Benjamin Herrenschmidt @ 2006-11-04 9:21 UTC (permalink / raw)
To: linuxppc-dev list; +Cc: Kumar Gala, Paul Mackerras
Out of curiosity... I noticed we have both head_44x.S and
head_fsl_booke.S, the later being a fork of the former with changed from
Kumar (and possibly others) to support E200 and E500.
How bad are the differences between those cores ? Would it be possible
to reconcile those and IBM 44x into a single processor family ? Or are
there some fundamental differences making that impossible ? (even with a
bit of CPU feature patching).
Also, I suppose we should rename head_4xx.S to head_40x.S no ?
Cheers,
Ben.
^ permalink raw reply
* Re: Booting without Uboot on 8548E
From: M Ptich @ 2006-11-04 9:28 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev
In-Reply-To: <1162631621.28571.26.camel@localhost.localdomain>
>You should seriously think about porting
>over to arch/powerpc instead.
8548E is E500v2 core. Our Kernel is from Freescale, it is using arch/ppc. I
am not sure how well (if at all) E500 is supported in the arch/powerpc from
the FSF ditribution.
>I'm not familiar about which core family the 85xx is. Doesn't it use the
>decrementer ?
Actually E500 could use Decrementer, with its Autoreload feature to get an
exact time tick. I did not think about it, will investigate.
M Ptich
>From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>To: M Ptich <ptich@hotmail.com>
>CC: linuxppc-dev@ozlabs.org
>Subject: Re: Booting without Uboot on 8548E
>Date: Sat, 04 Nov 2006 20:13:40 +1100
>MIME-Version: 1.0
>Received: from gate.crashing.org ([63.228.1.57]) by
>bay0-mc7-f7.bay0.hotmail.com with Microsoft SMTPSVC(6.0.3790.2444); Sat, 4
>Nov 2006 01:13:43 -0800
>Received: from [127.0.0.1] (localhost.localdomain [127.0.0.1])by
>gate.crashing.org (8.13.8/8.13.8) with ESMTP id kA49DeGf013357;Sat, 4 Nov
>2006 03:13:41 -0600
>X-Message-Info: LsUYwwHHNt3660MmjhEvYg2f34OAemlKtU9j2Z7TuGo=
>References: <BAY102-F21BB220054F2541A7614E4A9FD0@phx.gbl>
>X-Mailer: Evolution 2.8.1 Return-Path: benh@kernel.crashing.org
>X-OriginalArrivalTime: 04 Nov 2006 09:13:43.0980 (UTC)
>FILETIME=[86C386C0:01C6FFF1]
>
>On Sat, 2006-11-04 at 08:52 +0000, M Ptich wrote:
> > Documentation mentions that the only dependencies between 2.6 Kernel and
> > bootloader are:
> >
> > 1. 5 input parameters (bd_t pointer, start and end of command line,
>start
> > and end of ram disk)
> > 2. bd_t pointer and command line must with within 16MB of Kernel
> > 3. Initial TLB1 entry must have IPROT=1
>
>This is for arch/ppc, which is sort-of deprecated. You should seriously
>think about porting over to arch/powerpc instead.
>
> > Slowly, we are finding that this list is not complete. For example,
>address
> > calculation at the start of platform_init (r3 + ...) assumes that Kernel
>has
> > been initially loaded at 0-base virtual address.
>
>For which CPU core ? 6xx/7xx/7xxx/G2 cores don't assume such a thing,
>the kernel can be loaded anywhere as long as the virtual and physical
>addresses are the same.
>
> > And now we are stuck with apparently another dependency: our Kernel
>fails to
> > advance beyond time calibration because jiffies are not getting
>incremented,
> > so we are not getting timer interrupts. Is it true that Kernel relies on
> > EPIC timer set in Uboot ? If not - where the timer insterrupts are
> > configured ?
>
>I'm not familiar about which core family the 85xx is. Doesn't it use the
>decrementer ?
>
>Ben.
>
>
_________________________________________________________________
Get FREE company branded e-mail accounts and business Web site from
Microsoft Office Live
http://clk.atdmt.com/MRT/go/mcrssaub0050001411mrt/direct/01/
^ permalink raw reply
* Re: [PATCH/RFC] powerpc: Refactor 64 bits DMA operations
From: Christoph Hellwig @ 2006-11-04 13:21 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list
In-Reply-To: <1162588895.10630.112.camel@localhost.localdomain>
On Sat, Nov 04, 2006 at 08:21:34AM +1100, Benjamin Herrenschmidt wrote:
> This is also something I'll need in 2.6.20. Right now posted only for
> comments though. It's known to "miss" fixup of at least pasemi and maybe
> a few other things and I've not tested if I break 32 bits build yet :)
>
> This patch completely refactors DMA operations for 64 bits powerpc. 32 bits
> is untouched for now.
Can we please make 32bit use the same scheme for consistancy? It would
just plug in a set of dummy direct mapped ops, quite similar to what we
do in Cell (just without setting the magic bit)
^ permalink raw reply
* Re: minor progress with plb_temac v3.00a, EDK 8.2, & 2.6.18.1
From: robert corley @ 2006-11-04 15:02 UTC (permalink / raw)
To: Pradeep Sampath; +Cc: linux linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 9933 bytes --]
Pradeep;
Booting with a ramdisk is a matter of putting the appropriate image in the arch/ppc/boot/images directory (I obtained mine from the gsrd design files), adding the root=/dev/ram rw on the command-line boot options, making the .config changes for ram disk support and initrd usage, and issuing a make zImage.initrd command.
Beware when upgrading to 2.6.18.1 as you may have difficulties with the adapter.c you obtained previously. The adapter.c in EDK 8.2 is not as easy to find. Using the EDK to generate software components for linux will not expose the proper adapter.c. I had to use the path that Rick Moleres posted earlier to retrieve the adapter.c which I used for 2.6.18.1 and in my notes.
-cy
----- Original Message ----
From: Pradeep Sampath <pradeepsampath@yahoo.com>
To: robert corley <rdcorle@yahoo.com>
Sent: Thursday, November 2, 2006 7:57:25 PM
Subject: Re: minor progress with plb_temac v3.00a, EDK 8.2, & 2.6.18.1
This is great! I played around for a while with the Sysace CF driver patches and got it to work. Since you are booting with ramdisk image would you be kind enough to add more text on how to do that? I see that you are using UART Lite? Does it require any special setting for the boot logs to show up on the standard hyperterminal.
I am planning on rebuilding the whole system using EDK 8.2 and linux kernel 2.6.18.1.
-Pradeep
robert corley <rdcorle@yahoo.com> wrote:
For those interested, I have acheived some measure of success with the plb_temac driver.
I have attached a txt file of what I had to do to get it working under 2.6.18.1
I am using the plb_temac in DMA mode 3
Below you will see the boot dump.
For those able to help, can
anyone provide insight as to the failure of setting PHY link speed?
-cy
====================
----------------------------------------------------------------------
2.6.18.1 kernel with all patches
11/02/2006 15:30
plb_temac v3.00a
hard_temac v3.00b
loaded at: 00400000 009F1138
board data at: 009EF120 009EF138
relocated to: 004040B4 004040CC
zimage at: 00404EC7 0057C1F2
initrd at: 0057D000 009EE6FE
avail ram: 009F2000 04000000
Linux/PPC load: console=ttyUL0 single ip=192.168.1.100:192.168.1.144:192.168.1.1:255.255.255.0:nab:: ramdisk_size=4660000 root=/dev/ram rw
Uncompressing Linux...done.
Now booting the kernel
[ 0.000000] Linux version 2.6.18.1 (rdcorle@athena) (gcc version 3.4.2) #2 Thu Nov 2 21:56:32 UTC 2006
[ 0.000000] Xilinx ML403 Reference System (Virtex-4 FX)
[ 0.000000] Built 1 zonelists. Total pages: 16384
[ 0.000000] Kernel command line: console=ttyUL0 single
ip=192.168.1.100:192.168.1.144:192.168.1.1:255.255.255.0:nab:: ramdisk_size=4660000 root=/dev/ram rw
[ 0.000000] Xilinx INTC #0 at 0xD1000FC0 mapped to 0xFDFFFFC0
[ 0.000000] PID hash table entries: 512 (order: 9, 2048 bytes)
[ 0.000158] Console: colour dummy device 80x25
[ 0.000568] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
[ 0.001277] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.012895] Memory: 57060k available (2548k kernel code, 640k data, 96k init, 0k highmem)
[ 0.104378] Mount-cache hash table entries: 512
[ 0.106721] checking if image is initramfs...it isn't (no cpio magic); looks like an initrd
[ 2.414242] Freeing initrd memory: 4549k freed
[ 2.418712] NET: Registered protocol family 16
[ 2.427313] NET: Registered protocol family 2
[ 2.464244] IP route cache hash table entries: 512 (order: -1, 2048 bytes)
[ 2.465037] TCP established hash table entries: 2048 (order: 1, 8192 bytes)
[
2.465205] TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
[ 2.465296] TCP: Hash tables configured (established 2048 bind 1024)
[ 2.465324] TCP reno registered
[ 2.474633] NTFS driver 2.1.27 [Flags: R/O].
[ 2.475046] JFS: nTxBlock = 481, nTxLock = 3854
[ 2.477623] SGI XFS with no debug enabled
[ 2.479001] io scheduler noop registered
[ 2.479109] io scheduler anticipatory registered
[ 2.479197] io scheduler deadline registered
[ 2.479402] io scheduler cfq registered (default)
[ 2.517627] uartlite.0: ttyUL0 at MMIO 0xa0000000 (irq = 1) is a uartlite
[ 2.691029] RAMDISK driver initialized: 16 RAM disks of 4660000K size 1024 blocksize
[ 2.703933] loop: loaded (max 8 devices)
[ 2.709698] XTemac: using sgDMA mode.
[ 2.713493] XTemac: using TxDRE mode
[ 2.717081] XTemac: using RxDRE mode
[ 2.720678] XTemac: buffer descriptor size: 32768 (0x8000)
[ 2.726622] XTemac: (buffer_descriptor_init) phy: 0x580000, virt: 0xff100000,
size: 0x8000
[ 2.741073] eth0: Xilinx TEMAC #0 at 0x60000000 mapped to 0xC5050000, irq=0
[ 2.748080] eth0: XTemac id 1.0f, block id 5, type 8
[ 2.753636] mice: PS/2 mouse device common for all mice
[ 2.759529] TCP bic registered
[ 3.264317] eth0: XTemac: Options: 0xb8f2
[ 15.227339] eth0: XTemac: Not able to set the speed to 1000 (status: 0x148)
[ 25.200394] eth0: XTemac: Not able to set the speed to 100 (status: 0x148)
[ 35.173357] eth0: XTemac: Not able to set the speed to 10 (status: 0x148)
[ 35.180122] eth0: XTemac: could not negotiate speed
[ 35.187740] eth0: XTemac: Send Threshold = 16, Receive Threshold = 2
[ 35.194116] eth0: XTemac: Send Wait bound = 1, Receive Wait bound = 1
[ 36.205399] IP-Config: Complete:
[ 36.208459] device=eth0, addr=192.168.1.100, mask=255.255.255.0, gw=192.168.1.1,
[ 36.216339] host=nab, domain=, nis-domain=(none),
[ 36.221487] bootserver=192.168.1.144, rootserver=192.168.1.144, rootpath=
[
36.229826] RAMDISK: Compressed image found at block 0
[ 37.200498] eth0: XTemac: PHY Link carrier lost.
[ 39.097820] VFS: Mounted root (ext2 filesystem).
[ 39.102751] Freeing unused kernel memory: 96k init
[ 39.108356] ulite_startup: UART status = 0x0014
[ 39.124619] ulite_startup: UART status = 0x0014
[ 39.134313] ulite_startup: UART status = 0x0014
BusyBox v1.00-pre9 (2004.04.18-19:53+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.
-sh: can't access tty; job control turned off
steps for plb_temac drivers under EDK 8.2.02i (w/SP2.4+0)
Using plb_temac v3.00a & hard_temac v3.00b
Generate s/w libraries
1. copy or ftp the following files from C:\EDK\sw\ThirdParty\bsp\linux_2_6_v1_00_a\linux\
to the base directory of the linux source tree
USED:
arch\ppc\platforms\4xx\xparameters\xparameters.h
**
UNUSED
arch\ppc\platforms\4xx\virtex.c
arch\ppc\boot\simple\embed_config.c
include\linux\xilinx_devices.h
2. copy C:\EDK\sw\ThirdParty\bsp\linux_2_6_v1_00_a\drivers\temac_linux_2_6_v2_00_b\src\adapter.c to
../drivers/net/xilinx_temac/adapter.c
3. copy or ftp ..\linux\arch\ppc\platforms\xilinx_ocp => drivers/xilinx_edk
Note: Remove all old files first *except* Kconfig, xio.h
4. modify drivers/xilinx_edk/Makefile with the following to look like this:
# Linux file to EXPORT_SYMBOL all of the Xilinx entries.
obj-$(CONFIG_XILINX_EDK) += xilinx_syms.o
#
# # The Xilinx OS independent code.
xilinx_syms-objs := xbasic_types.o \
xdmav3.o xdmav3_intr.o xdmav3_selftest.o xdmav3_simple.o xdmav3_sg.o \
xipif_v1_23_b.o \
xpacket_fifo_l_v2_00_a.o xpacket_fifo_v2_00_a.o \
xversion.o
5. Modify your copied xparameters_ml403.h (see notes below) as follows:
add these lines after #define
XPAR_PLB_TEMAC_0_INCLUDE_RX_CSUM
#define XPAR_TEMAC_0_IPIF_RDFIFO_DEPTH XPAR_PLB_TEMAC_0_RXFIFO_DEPTH
#define XPAR_TEMAC_0_IPIF_WRFIFO_DEPTH XPAR_PLB_TEMAC_0_TXFIFO_DEPTH
#define XPAR_TEMAC_0_MAC_FIFO_DEPTH XPAR_PLB_TEMAC_0_MAC_FIFO_DEPTH
#define XPAR_TEMAC_0_TEMAC_DCR_HOST 0
#define XPAR_TEMAC_0_INCLUDE_DRE 1
6. (optional) modify arch/ppc/platforms/virtex.h to accomodate RX_CSUM XPAR
struct xtemac_platform_data {
#ifdef XPAR_TEMAC_0_INCLUDE_RX_CSUM
u8 tx_dre;
u8 rx_dre;
u8 tx_csum;
u8 rx_csum;
u8 phy_type;
#endif
u8 dma_mode;
u32 rx_pkt_fifo_depth;
u32 tx_pkt_fifo_depth;
u16 mac_fifo_depth;
u8 dcr_host;
u8 dre;
u8 mac_addr[6];
};
7. Modify ../drivers/net/xilinx_temac/adapter.c to remove #include and
add #include
add #include
____________________________________________________________________________________
NOTES:
1. Don't forget to copy EDK-generated xparameters.h to ../arch/ppc/platforms/4xx/xparameters/xparameters_ml403.h
=====================================================
Files in latest patch:
../drivers/net/xilinx_temac =
Makefile
adapter.c
xtemac.c
xtemac_control.c
xtemac_fifo.c
xtemac_intr.c
xtemac_intr_fifo.c
xtemac_intr_sgdma.c
xtemac_l.c
xtemac_sgdma.c
xtemac.h
xtemac_i.h
xtemac_l.h
Files in ..\linux\drivers\net\xilinx_temac => (** = new
files)
Makefile
adapter.c
xtemac.c
xtemac_control.c
xtemac_fifo.c
xtemac_g.c**
xtemac_intr.c
xtemac_intr_fifo.c
xtemac_intr_sgdma.c
xtemac_l.c
xtemac_selftest.c**
xtemac_sgdma.c
xtemac_sinit.c**
xtemac_stats.c**
xtemac.h
xtemac_i.h
xtemac_l.h
============================================================
Files in ../drivers/xilinx_edk =>
Kconfig
Makefile
xbasic_types.c
xdmav2.c
xdmav2_intr.c
xdmav2_sg.c
xdmav2_simple.c
xilinx_syms.c
xpacket_fifo_l_v2_00_a.c
xpacket_fifo_v2_00_a.c
xbasic_types.h
xdmabdv2.h
xdmav2.h
xdmav2_l.h
xio.h
xpacket_fifo_l_v2_00_a.h
xpacket_fifo_v2_00_a.h
xstatus.h
Files in
..\linux\arch\ppc\platforms\xilinx_ocp=>
Makefile
xbasic_types.c
xutil_memtest.c
xpacket_fifo_v2_00_a.c
xdmav3.c
xpacket_fifo_l_v2_00_a.c
xdmav3_intr.c
xipif_v1_23_b.c
xdmav3_selftest.c
xdmav3_sg.c
xdmav3_simple.c
xversion.c
xenv.h
xenv_none.h
xenv_vxworks.h
xdmav3_l.h
xipif_v1_23_b.h
xdmav3.h
xpacket_fifo_l_v2_00_a.h
xdmabdv3.h
xpacket_fifo_v2_00_a.h
xparameters_ml300.h
xstatus.h
xutil.h
xbasic_types.h
xenv_linux.h
xversion.h
_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded
[-- Attachment #2: Type: text/html, Size: 11213 bytes --]
^ permalink raw reply
* [PATCH] Add MPC52xx PIO/ATA support for arch/powerpc
From: Nicolas DET @ 2006-11-04 15:04 UTC (permalink / raw)
To: linuxppc-dev list; +Cc: akpm, sl, linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 260 bytes --]
This patch add MPC52xx ATA/PIO support.
It's based on a previous patch:
http://patchwork.ozlabs.org/linuxppc/patch?id=4364
But, it now use of_platform and a of_device_id to match the appropriate device.
Signed-off-by: Nicolas DET <nd@bplqn-gmbh.de>
[-- Attachment #2: archpower_mpc52xxide.patch --]
[-- Type: application/octet-stream, Size: 21682 bytes --]
diff -uprN a/drivers/ide/ppc/mpc52xx_ide.c b/drivers/ide/ppc/mpc52xx_ide.c
--- a/drivers/ide/ppc/mpc52xx_ide.c 1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/ide/ppc/mpc52xx_ide.c 2006-11-04 15:46:42.000000000 +0100
@@ -0,0 +1,428 @@
+/*
+ * drivers/ide/ppc/mpc52xx_ide.h
+ *
+ * Driver for the Freescale MPC52xx on-chip IDE interface
+ *
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#undef REALLY_SLOW_IO /* most systems can safely undef this */
+
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
+#include <asm/ppcboot.h>
+#include <asm/mpc52xx.h>
+
+#include "mpc52xx_ide.h"
+
+/* Private structures used by the driver */
+struct mpc52xx_ata_timings {
+ u32 pio1;
+ u32 pio2;
+ u32 mdma1;
+ u32 mdma2;
+ u32 udma1;
+ u32 udma2;
+ u32 udma3;
+ u32 udma4;
+ u32 udma5;
+ int using_udma;
+};
+
+struct mpc52xx_ide_priv {
+ unsigned int ipb_period; /* in ps */
+ struct mpc52xx_ata __iomem *ata_regs;
+ struct mpc52xx_ata_timings timings[2];
+ resource_size_t resmem_start;
+ size_t resmem_size;
+};
+
+/* ATAPI-4 PIO specs (arranged for the 5200, cfr User Manual) */
+/* numbers in ns, extrapolation done by code */
+static int ataspec_t0[5] = {600, 383, 240, 180, 120};
+static int ataspec_t1[5] = { 70, 50, 30, 30, 25};
+static int ataspec_t2_8[5] = {290, 290, 290, 80, 70};
+static int ataspec_t2_16[5] = {165, 125, 100, 80, 70};
+static int ataspec_t2i[5] = { 0, 0, 0, 70, 25};
+static int ataspec_t4[5] = { 30, 20, 15, 10, 10};
+static int ataspec_ta[5] = { 35, 35, 35, 35, 35};
+
+/* Helpers to compute timing parameters */
+#define CALC_CLK_VALUE_UP(c,v) (((v) + c - 1) / c)
+
+
+/* ======================================================================== */
+/* IDE Driver & Aux functions */
+/* ======================================================================== */
+
+static void
+mpc52xx_ide_apply_timing(
+ struct mpc52xx_ata __iomem *regs, struct mpc52xx_ata_timings *timing)
+{
+ out_be32(®s->pio1, timing->pio1);
+ out_be32(®s->pio2, timing->pio2);
+ out_be32(®s->mdma1, timing->mdma1);
+ out_be32(®s->mdma2, timing->mdma2);
+ out_be32(®s->udma1, timing->udma1);
+ out_be32(®s->udma2, timing->udma2);
+ out_be32(®s->udma3, timing->udma3);
+ out_be32(®s->udma4, timing->udma4);
+ out_be32(®s->udma5, timing->udma5);
+}
+
+static void
+mpc52xx_ide_compute_pio_timing(
+ struct mpc52xx_ata_timings *timing, unsigned int ipb_period, u8 pio)
+{
+ u32 t0, t2_8, t2_16, t2i, t4, t1, ta;
+
+ /* We add 1 as a 'margin' */
+ t0 = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t0[pio]);
+ t2_8 = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t2_8[pio]);
+ t2_16 = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t2_16[pio]);
+ t2i = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t2i[pio]);
+ t4 = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t4[pio]);
+ t1 = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_t1[pio]);
+ ta = 1 + CALC_CLK_VALUE_UP(ipb_period, 1000*ataspec_ta[pio]);
+
+ timing->pio1 = (t0 << 24) | (t2_8 << 16) | (t2_16 << 8) | (t2i);
+ timing->pio2 = (t4 << 24) | (t1 << 16) | (ta << 8);
+}
+
+
+static void
+mpc52xx_ide_tuneproc(ide_drive_t *drive, u8 pio)
+{
+ struct mpc52xx_ide_priv *priv = drive->hwif->hwif_data;
+ struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+ int w = drive->select.b.unit & 0x01;
+
+ pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
+
+ printk("%s: Setting PIO %d timings\n", drive->name, pio);
+
+ mpc52xx_ide_compute_pio_timing(&priv->timings[w], priv->ipb_period, pio);
+
+ if (drive->select.all == HWIF(drive)->INB(IDE_SELECT_REG))
+ mpc52xx_ide_apply_timing(regs, &priv->timings[w]);
+
+ /* Should we do it here or only in speedproc ? */
+ ide_config_drive_speed(drive, pio + XFER_PIO_0);
+}
+
+static int
+mpc52xx_ide_speedproc(ide_drive_t *drive, u8 speed)
+{
+ /* Configure PIO Mode */
+ if (speed >= XFER_PIO_0 && speed <= XFER_PIO_4) {
+ mpc52xx_ide_tuneproc(drive, speed - XFER_PIO_0);
+ return 0;
+ }
+
+ /* DMA settings currently unsupported */
+ printk(KERN_ERR
+ "mpc52xx-ide: speedproc called with unsupported mode %d\n",
+ speed);
+
+ return 1;
+}
+
+static void
+mpc52xx_ide_selectproc(ide_drive_t *drive)
+{
+ /* Change the PIO timings to the ones of the
+ currently selected drive */
+ struct mpc52xx_ide_priv *priv = drive->hwif->hwif_data;
+ struct mpc52xx_ata __iomem *regs = priv->ata_regs;
+
+ mpc52xx_ide_apply_timing(regs,
+ &priv->timings[drive->select.b.unit & 0x01]);
+}
+
+
+static int
+mpc52xx_ide_setup(
+ struct mpc52xx_ata __iomem *regs, struct mpc52xx_ide_priv *priv)
+{
+ /* Vars */
+ //extern bd_t __res;
+ //bd_t *bd = (bd_t *)&__res;
+ unsigned long ipb_freq = 133 *1000 *1000;
+ int tslot;
+
+ /* All sample code do this */
+ out_be32(®s->share_cnt, 0);
+
+ /* Configure & Reset host */
+ out_be32(®s->config,
+ MPC52xx_ATA_HOSTCONF_IE |
+ MPC52xx_ATA_HOSTCONF_IORDY |
+ MPC52xx_ATA_HOSTCONF_SMR |
+ MPC52xx_ATA_HOSTCONF_FR);
+ udelay(10);
+ out_be32(®s->config,
+ MPC52xx_ATA_HOSTCONF_IE |
+ MPC52xx_ATA_HOSTCONF_IORDY);
+
+ /* Get IPB bus period */
+ priv->ipb_period = 1000000000 / (ipb_freq /1000);
+
+ /* Try to set the time slot to around 1us = 1000000 ps */
+ tslot = CALC_CLK_VALUE_UP(priv->ipb_period, 1000000);
+ out_be32(®s->share_cnt, tslot << 16);
+
+ /* Init imings to PIO0 (safest) */
+ memset(priv->timings, 0x00, 2*sizeof(struct mpc52xx_ata_timings));
+
+ mpc52xx_ide_compute_pio_timing(&priv->timings[0], priv->ipb_period, 0);
+ mpc52xx_ide_compute_pio_timing(&priv->timings[1], priv->ipb_period, 0);
+
+ mpc52xx_ide_apply_timing(regs, &priv->timings[0]);
+
+ return 0;
+}
+
+static void
+mpc52xx_ide_setup_hwif_ports(hw_regs_t *hw, struct mpc52xx_ata __iomem *regs)
+{
+ /* It's MMIO and we handle all the io ops ourself, */
+ /* so theses address are really virtual addresses */
+ hw->io_ports[IDE_DATA_OFFSET] = (unsigned long) ®s->tf_data;
+ hw->io_ports[IDE_ERROR_OFFSET] = (unsigned long) ®s->tf_features;
+ hw->io_ports[IDE_NSECTOR_OFFSET] = (unsigned long) ®s->tf_sec_count;
+ hw->io_ports[IDE_SECTOR_OFFSET] = (unsigned long) ®s->tf_sec_num;
+ hw->io_ports[IDE_LCYL_OFFSET] = (unsigned long) ®s->tf_cyl_low;
+ hw->io_ports[IDE_HCYL_OFFSET] = (unsigned long) ®s->tf_cyl_high;
+ hw->io_ports[IDE_SELECT_OFFSET] = (unsigned long) ®s->tf_dev_head;
+ hw->io_ports[IDE_STATUS_OFFSET] = (unsigned long) ®s->tf_command;
+ hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long) ®s->tf_control;
+}
+
+
+/* ======================================================================== */
+/* OF Platform Driver */
+/* ======================================================================== */
+
+static int __devinit
+mpc52xx_ide_probe(struct of_device *op, const struct of_device_id *match)
+{
+ /* Vars */
+ ide_hwif_t *hwif;
+ int ret;
+ struct mpc52xx_ide_priv *priv;
+ struct mpc52xx_ata __iomem *ata_regs = NULL;
+ int ata_irq;
+ struct resource res_mem;
+ size_t res_mem_size;
+ int i, rv;
+
+ /* Get an empty slot */
+ for (i=0; i<MAX_HWIFS && ide_hwifs[i].io_ports[IDE_DATA_OFFSET]; i++);
+ if (i >= MAX_HWIFS) {
+ printk(KERN_ERR "mpc52xx-ide: No free hwif slot !\n");
+ return -ENOMEM;
+ }
+
+ hwif = &ide_hwifs[i];
+
+ /* Get the resources of this device */
+ ata_irq = irq_of_parse_and_map(op->node, 0);
+ if (ata_irq == NO_IRQ) {
+ printk(KERN_ERR "mpc52xx-ide: Invalid IRQ!\n");
+ return -EINVAL;
+ }
+ //res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+ if ((ret = of_address_to_resource(op->node, 0, &res_mem)) != 0)
+ {
+ printk(KERN_ERR "mpc52xx-ide: Can not find IO mem!\n");
+ return ret;
+ }
+
+ res_mem_size = res_mem.end - res_mem.start + 1;
+
+ if (!request_mem_region(res_mem.start, res_mem_size,
+ "mpc52xx-ide")) {
+ printk(KERN_ERR "mpc52xx-ide: Memory zone unavailable !\n");
+ return -EBUSY;
+ }
+
+ ata_regs = ioremap(res_mem.start, res_mem_size);
+ if (!ata_regs) {
+ printk(KERN_ERR
+ "mpc52xx-ide: Unable to ioremap ATA registers\n");
+ rv = -ENOMEM;
+ goto error;
+ }
+
+ /* Setup private structure */
+ priv = kmalloc(sizeof(struct mpc52xx_ide_priv), GFP_ATOMIC);
+ if (!priv) {
+ printk(KERN_ERR
+ "mpc52xx-ide: Can't allocate private structure !\n");
+ rv = -ENOMEM;
+ goto error;
+ }
+
+ priv->resmem_size = res_mem_size;
+ priv->resmem_start = res_mem.start;
+ priv->ata_regs = ata_regs;
+
+ /* Setup the ATA controller */
+ rv = mpc52xx_ide_setup(ata_regs, priv);
+ if (rv) {
+ printk(KERN_ERR "mpc52xx-ide: Controller setup failed !\n");
+ goto error;
+ }
+
+ /* Setup the hwif structure */
+ hwif->irq = ata_irq;
+ hwif->mmio = 2;
+ mpc52xx_ide_setup_hwif_iops(hwif);
+ mpc52xx_ide_setup_hwif_ports(&hwif->hw, ata_regs);
+ memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
+
+ hwif->atapi_dma = 0;
+ hwif->ultra_mask = 0x00;
+ hwif->mwdma_mask = 0x00;
+ hwif->swdma_mask = 0x00;
+ hwif->chipset = ide_forced;
+ hwif->tuneproc = mpc52xx_ide_tuneproc;
+ hwif->speedproc = mpc52xx_ide_speedproc;
+ hwif->selectproc = mpc52xx_ide_selectproc;
+ hwif->noprobe = 0;
+ hwif->hold = 1;
+ hwif->autodma = 0;
+ hwif->udma_four = 0;
+ hwif->no_lba48 = 1; /* FIXME ? Did some one test that ? */
+ hwif->no_lba48_dma = 1;
+
+ hwif->drives[0].unmask = 1;
+ hwif->drives[0].autotune = 0; /* default */
+ hwif->drives[0].autodma = hwif->autodma;
+ hwif->drives[0].no_io_32bit = 1; /* Anyone tried ? */
+
+ hwif->drives[1].unmask = 1;
+ hwif->drives[1].autotune = 0; /* default */
+ hwif->drives[1].autodma = hwif->autodma;
+ hwif->drives[1].no_io_32bit = 1; /* Anyone tried ? */
+
+ hwif->hwif_data = priv;
+ dev_set_drvdata(&op->dev, hwif);
+
+ /* Lauch probe */
+ probe_hwif_init(hwif);
+
+ /* We're good ! */
+ printk(KERN_INFO
+ "mpc52xx-ide: Setup successful for %s (mem=%08lx-%08lx irq=%d)\n",
+ hwif->name, (unsigned long) res_mem.start, (unsigned long) res_mem.end, ata_irq);
+
+ return 0;
+
+
+ /* Error path */
+error:
+ if (ata_regs)
+ iounmap(ata_regs);
+
+ release_mem_region(res_mem.start, res_mem_size);
+
+ return rv;
+}
+
+static int
+mpc52xx_ide_remove(struct of_device *op)
+{
+ ide_hwif_t *hwif = dev_get_drvdata(&op->dev);
+ struct mpc52xx_ide_priv *priv = hwif->hwif_data;
+
+ ide_unregister(hwif - ide_hwifs);
+
+ iounmap(priv->ata_regs);
+
+ release_mem_region(priv->resmem_start, priv->resmem_size);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int
+mpc52xx_ide_suspend(struct of_device *op, pm_message_t state)
+{
+ return 0; /* FIXME : What to do here ? */
+}
+
+static int
+mpc52xx_ide_resume(struct of_device *op)
+{
+ return 0; /* FIXME : What to do here ? */
+}
+#endif
+
+
+static struct of_device_id mpc52xx_ide_of_match[] = {
+ {
+ .name = "ata",
+ .compatible = "mpc5200-ata",
+ },
+ {
+ .name = "ata",
+ .compatible = "mpc52xx-ata",
+ },
+ {},
+};
+
+
+static struct of_platform_driver mpc52xx_ide_of_platform_driver = {
+ .name = "mpc52xx-ata",
+ .match_table = mpc52xx_ide_of_match,
+ .probe = mpc52xx_ide_probe,
+ .remove = mpc52xx_ide_remove,
+#ifdef CONFIG_PM
+ .suspend = mpc52xx_ide_suspend,
+ .resume = mpc52xx_ide_resume,
+#endif
+ .driver = {
+ .name = "mpc52xx-ata",
+ .owner = THIS_MODULE,
+ },
+};
+
+
+/* ======================================================================== */
+/* Module */
+/* ======================================================================== */
+
+static int __init
+mpc52xx_ide_init(void)
+{
+ printk(KERN_INFO "ide: MPC52xx IDE/ATA driver\n");
+ return of_register_driver(&mpc52xx_ide_of_platform_driver);
+}
+
+static void __exit
+mpc52xx_ide_exit(void)
+{
+ of_unregister_driver(&mpc52xx_ide_of_platform_driver);
+}
+
+module_init(mpc52xx_ide_init);
+module_exit(mpc52xx_ide_exit);
+
+MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
+MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA driver");
+MODULE_LICENSE("GPL");
+
diff -uprN a/drivers/ide/ppc/mpc52xx_ide.h b/drivers/ide/ppc/mpc52xx_ide.h
--- a/drivers/ide/ppc/mpc52xx_ide.h 1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/ide/ppc/mpc52xx_ide.h 2006-11-04 15:46:42.000000000 +0100
@@ -0,0 +1,127 @@
+/*
+ * drivers/ide/ppc/mpc52xx_ide.h
+ *
+ * Definitions for the Freescale MPC52xx on-chip IDE interface
+ *
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __MPC52xx_IDE_H__
+#define __MPC52xx_IDE_H__
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <asm/types.h>
+#include <asm/io.h>
+
+
+
+/* Bit definitions inside the registers */
+
+#define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */
+#define MPC52xx_ATA_HOSTCONF_FR 0x40000000UL /* FIFO Reset */
+#define MPC52xx_ATA_HOSTCONF_IE 0x02000000UL /* Enable interrupt in PIO */
+#define MPC52xx_ATA_HOSTCONF_IORDY 0x01000000UL /* Drive supports IORDY protocol */
+
+#define MPC52xx_ATA_HOSTSTAT_TIP 0x80000000UL /* Transaction in progress */
+#define MPC52xx_ATA_HOSTSTAT_UREP 0x40000000UL /* UDMA Read Extended Pause */
+#define MPC52xx_ATA_HOSTSTAT_RERR 0x02000000UL /* Read Error */
+#define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */
+
+#define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */
+
+#define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */
+#define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */
+#define MPC52xx_ATA_DMAMODE_UDMA 0x04 /* UDMA enabled */
+#define MPC52xx_ATA_DMAMODE_IE 0x08 /* Enable drive interrupt to CPU in DMA mode */
+#define MPC52xx_ATA_DMAMODE_FE 0x10 /* FIFO Flush enable in Rx mode */
+#define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */
+#define MPC52xx_ATA_DMAMODE_HUT 0x40 /* Host UDMA burst terminate */
+
+
+/* Structure of the hardware registers */
+struct mpc52xx_ata {
+
+ /* Host interface registers */
+ u32 config; /* ATA + 0x00 Host configuration */
+ u32 host_status; /* ATA + 0x04 Host controller status */
+ u32 pio1; /* ATA + 0x08 PIO Timing 1 */
+ u32 pio2; /* ATA + 0x0c PIO Timing 2 */
+ u32 mdma1; /* ATA + 0x10 MDMA Timing 1 */
+ u32 mdma2; /* ATA + 0x14 MDMA Timing 2 */
+ u32 udma1; /* ATA + 0x18 UDMA Timing 1 */
+ u32 udma2; /* ATA + 0x1c UDMA Timing 2 */
+ u32 udma3; /* ATA + 0x20 UDMA Timing 3 */
+ u32 udma4; /* ATA + 0x24 UDMA Timing 4 */
+ u32 udma5; /* ATA + 0x28 UDMA Timing 5 */
+ u32 share_cnt; /* ATA + 0x2c ATA share counter */
+ u32 reserved0[3];
+
+ /* FIFO registers */
+ u32 fifo_data; /* ATA + 0x3c */
+ u8 fifo_status_frame; /* ATA + 0x40 */
+ u8 fifo_status; /* ATA + 0x41 */
+ u16 reserved7[1];
+ u8 fifo_control; /* ATA + 0x44 */
+ u8 reserved8[5];
+ u16 fifo_alarm; /* ATA + 0x4a */
+ u16 reserved9;
+ u16 fifo_rdp; /* ATA + 0x4e */
+ u16 reserved10;
+ u16 fifo_wrp; /* ATA + 0x52 */
+ u16 reserved11;
+ u16 fifo_lfrdp; /* ATA + 0x56 */
+ u16 reserved12;
+ u16 fifo_lfwrp; /* ATA + 0x5a */
+
+ /* Drive TaskFile registers */
+ u8 tf_control; /* ATA + 0x5c TASKFILE Control/Alt Status */
+ u8 reserved13[3];
+ u16 tf_data; /* ATA + 0x60 TASKFILE Data */
+ u16 reserved14;
+ u8 tf_features; /* ATA + 0x64 TASKFILE Features/Error */
+ u8 reserved15[3];
+ u8 tf_sec_count; /* ATA + 0x68 TASKFILE Sector Count */
+ u8 reserved16[3];
+ u8 tf_sec_num; /* ATA + 0x6c TASKFILE Sector Number */
+ u8 reserved17[3];
+ u8 tf_cyl_low; /* ATA + 0x70 TASKFILE Cylinder Low */
+ u8 reserved18[3];
+ u8 tf_cyl_high; /* ATA + 0x74 TASKFILE Cylinder High */
+ u8 reserved19[3];
+ u8 tf_dev_head; /* ATA + 0x78 TASKFILE Device/Head */
+ u8 reserved20[3];
+ u8 tf_command; /* ATA + 0x7c TASKFILE Command/Status */
+ u8 dma_mode; /* ATA + 0x7d ATA Host DMA Mode configuration */
+ u8 reserved21[2];
+};
+
+
+/* Function definition */
+
+static inline void
+mpc52xx_ide_wait_tip_bit_clear(struct mpc52xx_ata __iomem *regs)
+{
+ int timeout = 1000;
+
+ while (in_be32(®s->host_status) & MPC52xx_ATA_HOSTSTAT_TIP)
+ if (timeout-- == 0) {
+ printk(KERN_ERR
+ "mpc52xx-ide: Timeout waiting for TIP clear\n");
+ break;
+ }
+ udelay(10); /* FIXME: Necessary ??? */
+}
+
+extern void mpc52xx_ide_setup_hwif_iops(ide_hwif_t *hwif);
+
+
+#endif /* __MPC52xx_IDE_H__ */
+
diff -uprN a/drivers/ide/ppc/mpc52xx_ide_iops.c b/drivers/ide/ppc/mpc52xx_ide_iops.c
--- a/drivers/ide/ppc/mpc52xx_ide_iops.c 1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/ide/ppc/mpc52xx_ide_iops.c 2006-11-04 15:46:42.000000000 +0100
@@ -0,0 +1,150 @@
+/*
+ * drivers/ide/ppc/mpc52xx_ide_iops.c
+ *
+ * Utility functions for MPC52xx on-chip IDE interface
+ *
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+
+#include "mpc52xx_ide.h"
+
+
+
+static u8
+mpc52xx_ide_inb(unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ return (u8) readb((void __iomem *) port);
+}
+
+static u16
+mpc52xx_ide_inw(unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ return (u16) readw((void __iomem *) port);
+}
+
+static void
+mpc52xx_ide_insw(unsigned long port, void *addr, u32 count)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ __ide_mm_insw((void __iomem *) port, addr, count);
+}
+
+static u32
+mpc52xx_ide_inl(unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ return (u32) readl((void __iomem *) port);
+}
+
+static void
+mpc52xx_ide_insl(unsigned long port, void *addr, u32 count)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ __ide_mm_insl((void __iomem *) port, addr, count);
+}
+
+static void
+mpc52xx_ide_outb(u8 value, unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ writeb(value, (void __iomem *) port);
+}
+
+static void
+mpc52xx_ide_outbsync(ide_drive_t *drive, u8 value, unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ writeb(value, (void __iomem *) port);
+}
+
+
+static void
+mpc52xx_ide_outw(u16 value, unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ writew(value, (void __iomem *) port);
+}
+
+static void
+mpc52xx_ide_outsw(unsigned long port, void *addr, u32 count)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ __ide_mm_outsw((void __iomem *) port, addr, count);
+}
+
+static void
+mpc52xx_ide_outl(u32 value, unsigned long port)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ writel(value, (void __iomem *) port);
+}
+
+static void
+mpc52xx_ide_outsl(unsigned long port, void *addr, u32 count)
+{
+ struct mpc52xx_ata __iomem *ata_regs =
+ (struct mpc52xx_ata __iomem *)(port & ~0xfful);
+
+ mpc52xx_ide_wait_tip_bit_clear(ata_regs);
+ __ide_mm_outsl((void __iomem *) port, addr, count);
+}
+
+
+void
+mpc52xx_ide_setup_hwif_iops(ide_hwif_t *hwif)
+{
+ hwif->OUTB = mpc52xx_ide_outb;
+ hwif->OUTBSYNC = mpc52xx_ide_outbsync;
+ hwif->OUTW = mpc52xx_ide_outw;
+ hwif->OUTL = mpc52xx_ide_outl;
+ hwif->OUTSW = mpc52xx_ide_outsw;
+ hwif->OUTSL = mpc52xx_ide_outsl;
+ hwif->INB = mpc52xx_ide_inb;
+ hwif->INW = mpc52xx_ide_inw;
+ hwif->INL = mpc52xx_ide_inl;
+ hwif->INSW = mpc52xx_ide_insw;
+ hwif->INSL = mpc52xx_ide_insl;
+}
+
--- a/drivers/ide/Kconfig 2006-11-04 15:29:27.000000000 +0100
+++ b/drivers/ide/Kconfig 2006-11-04 15:46:42.000000000 +0100
@@ -955,6 +955,10 @@ config IDE_EXT_DIRECT
endchoice
+config BLK_DEV_MPC52xx_IDE
+ tristate "MPC52xx Builtin IDE support"
+ depends on PPC_MPC52xx && IDE=y
+
# no isa -> no vlb
config IDE_CHIPSETS
bool "Other IDE chipset support"
--- a/drivers/ide/Makefile 2006-09-20 05:42:06.000000000 +0200
+++ b/drivers/ide/Makefile 2006-11-04 15:46:42.000000000 +0100
@@ -36,6 +36,7 @@ ide-core-$(CONFIG_BLK_DEV_Q40IDE) += leg
# built-in only drivers from ppc/
ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ppc/mpc8xx.o
ide-core-$(CONFIG_BLK_DEV_IDE_PMAC) += ppc/pmac.o
+ide-core-$(CONFIG_BLK_DEV_MPC52xx_IDE) += ppc/mpc52xx_ide.o ppc/mpc52xx_ide_iops.o
# built-in only drivers from h8300/
ide-core-$(CONFIG_H8300) += h8300/ide-h8300.o
^ permalink raw reply
* RE : minor progress with plb_temac v3.00a, EDK 8.2, & 2.6.18.1
From: robert corley @ 2006-11-04 15:08 UTC (permalink / raw)
To: alayrac; +Cc: linux linuxppc-embedded
Chris;=0A=0AI obtained the linux tree from kernels.org and patched it using=
the same patches you have.=0A=0AThe updated drivers for the TEMAC, however=
, I pulled from the EDK-generated files. My notes describe what files and =
from =0Awhere.=0A=0AI used David B.'s uartlite drivers to get the uartlite =
to work. There was some xparameters.h editing for that to work. I don't k=
now if he has posted his latest work or not.=0A=0AI use the following comma=
nd to patch:=0A=0Apatch -p 1 --backup --verbose <file> <patch file>=0A=0Awh=
ere <file> is the first file to patch as per the patch file and=0A<patch fi=
le> is self-explanatory=0A=0A-cy=0A=0A----- Original Message ----=0AFrom: a=
layrac <christophe.alayrac@cresitt.com>=0ATo: robert corley <rdcorle@yahoo.=
com>; linux linuxppc-embedded <linuxppc-embedded@ozlabs.org>=0ASent: Friday=
, November 3, 2006 8:39:23 AM=0ASubject: RE : minor progress with plb_temac=
v3.00a, EDK 8.2, & 2.6.18.1=0A=0AHi Robert,=0A=0AThanks for your contribut=
ion.=0AI would like to know where did you get the kernel source 2.6.18.1?=
=0A=0AI've tried from kernel.org, but then temac drivers is not included.=
=0AI've then download the temac patch from mvista at following address :=0A=
http://source.mvista.com/~ank/paulus-powerpc/20060309/temac.paulus-power=0A=
pc.20060309.tgz=0A=0AWhen I try to pacth the kernel with following command =
:=0A patch -i ppc32_xilinx_edk_temac.patch=0Athe process ask me the file=
to pacth.=0A=0AI've try to get the kernel source code from mvista with cg-=
clone=0Acommande from =0Acg-clone git://source.mvista.com/git/linux-xilinx-=
26.git =0A=0Aand patch command give same message.=0A=0AAny track to properl=
y applying patch?=0A=0AKinds regards=0A=0AChris=0A=0ACRESITT INDUSTRIE=0A12=
Rue de Blois, BP6744=0A45067 ORLEANS Cedex 2=0ATel : 02.38.49.45.59=0AFax =
:02.38.49.45.55=0AEmail : christophe.alayrac@cresitt.com =0AWeb : http://ww=
w.cresitt.com=0A=0A=0A<----> -----Message d'origine-----=0A<----> De : linu=
xppc-embedded-=0A<----> bounces+christophe.alayrac=3Dcresitt.com@ozlabs.org=
=0A[mailto:linuxppc-=0A<----> embedded-bounces+christophe.alayrac=3Dcresitt=
.com@ozlabs.org] De la=0A<----> part de robert corley=0A<----> Envoy=E9 : j=
eudi 2 novembre 2006 23:21=0A<----> =C0 : linux linuxppc-embedded=0A<----> =
Objet : minor progress with plb_temac v3.00a, EDK 8.2, & 2.6.18.1=0A<----> =
=0A<----> For those interested, I have acheived some measure of success=0Aw=
ith=0A<----> the plb_temac driver.=0A<----> =0A<----> I have attached a txt=
file of what I had to do to get it working=0A<----> under 2.6.18.1=0A<----=
> =0A<----> I am using the plb_temac in DMA mode 3=0A<----> =0A<----> Below=
you will see the boot dump.=0A<----> =0A<----> For those able to help, can=
anyone provide insight as to the=0Afailure=0A<----> of setting PHY link sp=
eed?=0A<----> =0A<----> -cy=0A<----> =0A<----> =0A<----> =0A<----> =3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A<---->=0A---------=
------------------------------------------------------------=0A<----> -=0A<=
----> 2.6.18.1 kernel with all patches=0A<----> 11/02/2006 15:30=0A<----=
> plb_temac v3.00a=0A<----> hard_temac v3.00b=0A<----> =0A<----> =0A<----> =
loaded at: 00400000 009F1138=0A<----> board data at: 009EF120 009EF138=
=0A<----> relocated to: 004040B4 004040CC=0A<----> zimage at: 00404EC7=
0057C1F2=0A<----> initrd at: 0057D000 009EE6FE=0A<----> avail ram: =
009F2000 04000000=0A<----> =0A<----> =0A<----> Linux/PPC load: console=3Dt=
tyUL0 single=0A<----> ip=3D192.168.1.100:192.168.1.144:192.168.1.1:255.255.=
255.0:nab::=0A<----> ramdisk_size=3D4660000 root=3D/dev/ram rw=0A<----> =0A=
<----> Uncompressing Linux...done.=0A<----> =0A<----> Now booting the kerne=
l=0A<----> =0A<----> [ 0.000000] Linux version 2.6.18.1 (rdcorle@athena)=
(gcc=0Aversion=0A<----> 3.4.2) #2 Thu Nov 2 21:56:32 UTC 2006=0A<----> [ =
0.000000] Xilinx ML403 Reference System (Virtex-4 FX)=0A<----> [ 0.000=
000] Built 1 zonelists. Total pages: 16384=0A<----> [ 0.000000] Kernel =
command line: console=3DttyUL0 single=0A<----> ip=3D192.168.1.100:192.168.1=
.144:192.168.1.1:255.255.255.0:nab::=0A<----> ramdisk_size=3D4660000 root=
=3D/dev/ram rw=0A<----> [ 0.000000] Xilinx INTC #0 at 0xD1000FC0 mapped =
to 0xFDFFFFC0=0A<----> [ 0.000000] PID hash table entries: 512 (order: 9=
, 2048 bytes)=0A<----> [ 0.000158] Console: colour dummy device 80x25=0A=
<----> [ 0.000568] Dentry cache hash table entries: 8192 (order: 3,=0A32=
768=0A<----> bytes)=0A<----> [ 0.001277] Inode-cache hash table entries:=
4096 (order: 2,=0A16384=0A<----> bytes)=0A<----> [ 0.012895] Memory: 57=
060k available (2548k kernel code, 640k=0A<----> data, 96k init, 0k highmem=
)=0A<----> [ 0.104378] Mount-cache hash table entries: 512=0A<----> [ =
0.106721] checking if image is initramfs...it isn't (no cpio=0A<----> magi=
c); looks like an initrd=0A<----> [ 2.414242] Freeing initrd memory: 454=
9k freed=0A<----> [ 2.418712] NET: Registered protocol family 16=0A<----=
> [ 2.427313] NET: Registered protocol family 2=0A<----> [ 2.464244] =
IP route cache hash table entries: 512 (order: -1,=0A<----> 2048 bytes)=0A<=
----> [ 2.465037] TCP established hash table entries: 2048 (order:=0A1,=
=0A<----> 8192 bytes)=0A<----> [ 2.465205] TCP bind hash table entries: =
1024 (order: 0, 4096=0A<----> bytes)=0A<----> [ 2.465296] TCP: Hash tabl=
es configured (established 2048 bind=0A<----> 1024)=0A<----> [ 2.465324]=
TCP reno registered=0A<----> [ 2.474633] NTFS driver 2.1.27 [Flags: R/O=
].=0A<----> [ 2.475046] JFS: nTxBlock =3D 481, nTxLock =3D 3854=0A<---->=
[ 2.477623] SGI XFS with no debug enabled=0A<----> [ 2.479001] io sc=
heduler noop registered=0A<----> [ 2.479109] io scheduler anticipatory r=
egistered=0A<----> [ 2.479197] io scheduler deadline registered=0A<---->=
[ 2.479402] io scheduler cfq registered (default)=0A<----> [ 2.51762=
7] uartlite.0: ttyUL0 at MMIO 0xa0000000 (irq =3D 1) is=0Aa=0A<----> uartli=
te=0A<----> [ 2.691029] RAMDISK driver initialized: 16 RAM disks of=0A46=
60000K=0A<----> size 1024 blocksize=0A<----> [ 2.703933] loop: loaded (m=
ax 8 devices)=0A<----> [ 2.709698] XTemac: using sgDMA mode.=0A<----> [ =
2.713493] XTemac: using TxDRE mode=0A<----> [ 2.717081] XTemac: using=
RxDRE mode=0A<----> [ 2.720678] XTemac: buffer descriptor size: 32768 (=
0x8000)=0A<----> [ 2.726622] XTemac: (buffer_descriptor_init) phy: 0x580=
000,=0Avirt:=0A<----> 0xff100000, size: 0x8000=0A<----> [ 2.741073] eth0=
: Xilinx TEMAC #0 at 0x60000000 mapped to=0A<----> 0xC5050000, irq=3D0=0A<-=
---> [ 2.748080] eth0: XTemac id 1.0f, block id 5, type 8=0A<----> [ =
2.753636] mice: PS/2 mouse device common for all mice=0A<----> [ 2.75952=
9] TCP bic registered=0A<----> [ 3.264317] eth0: XTemac: Options: 0xb8f2=
=0A<----> [ 15.227339] eth0: XTemac: Not able to set the speed to 1000=0A=
<----> (status: 0x148)=0A<----> [ 25.200394] eth0: XTemac: Not able to se=
t the speed to 100=0A<----> (status: 0x148)=0A<----> [ 35.173357] eth0: X=
Temac: Not able to set the speed to 10=0A(status:=0A<----> 0x148)=0A<----> =
[ 35.180122] eth0: XTemac: could not negotiate speed=0A<----> [ 35.1877=
40] eth0: XTemac: Send Threshold =3D 16, Receive=0AThreshold =3D=0A<----> 2=
=0A<----> [ 35.194116] eth0: XTemac: Send Wait bound =3D 1, Receive Wait=
=0Abound=0A<----> =3D 1=0A<----> [ 36.205399] IP-Config: Complete:=0A<---=
-> [ 36.208459] device=3Deth0, addr=3D192.168.1.100,=0A<----> mask=
=3D255.255.255.0, gw=3D192.168.1.1,=0A<----> [ 36.216339] host=3Dnab=
, domain=3D, nis-domain=3D(none),=0A<----> [ 36.221487] bootserver=
=3D192.168.1.144,=0A<----> rootserver=3D192.168.1.144, rootpath=3D=0A<---->=
[ 36.229826] RAMDISK: Compressed image found at block 0=0A<----> [ 37.=
200498] eth0: XTemac: PHY Link carrier lost.=0A<----> [ 39.097820] VFS: M=
ounted root (ext2 filesystem).=0A<----> [ 39.102751] Freeing unused kerne=
l memory: 96k init=0A<----> [ 39.108356] ulite_startup: UART status =3D 0=
x0014=0A<----> [ 39.124619] ulite_startup: UART status =3D 0x0014=0A<----=
> [ 39.134313] ulite_startup: UART status =3D 0x0014=0A<----> =0A<----> =
=0A<----> BusyBox v1.00-pre9 (2004.04.18-19:53+0000) Built-in shell (ash)=
=0A<----> Enter 'help' for a list of built-in commands.=0A<----> =0A<----> =
-sh: can't access tty; job control turned off=0A<----> =0A=0A=0A___________=
____________________________________=0ALinuxppc-embedded mailing list=0ALin=
uxppc-embedded@ozlabs.org=0Ahttps://ozlabs.org/mailman/listinfo/linuxppc-em=
bedded=0A=0A=0A
^ permalink raw reply
* Re: [PATCH/RFC] powerpc: Create PCI busses from of_platform
From: Segher Boessenkool @ 2006-11-04 15:40 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list
In-Reply-To: <1162589327.10630.125.camel@localhost.localdomain>
> +static struct of_device_id of_pci_phb_ids[] = {
> + { .type = "pci", },
> + { .type = "pcix", },
> + { .type = "pcie", },
> + { .type = "pciex", },
> + { .type = "ht", },
> + {}
> +};
> +
> +static struct of_platform_driver of_pci_phb_driver = {
> + .name = "of-pci",
> + .match_table = of_pci_phb_ids,
> + .probe = of_pci_phb_probe,
> + .driver = {
> + .multithread_probe = 1,
> + },
> +};
Shouldn't you also/only check for compatible=pci? Or maybe
that would give too much fallout from all the broken device
trees out there?
Segher
^ permalink raw reply
* Re: FSL vs. IBM BookE
From: Josh Boyer @ 2006-11-04 16:16 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, Paul Mackerras, Kumar Gala
In-Reply-To: <1162632114.28571.33.camel@localhost.localdomain>
On Sat, 2006-11-04 at 20:21 +1100, Benjamin Herrenschmidt wrote:
> Out of curiosity... I noticed we have both head_44x.S and
> head_fsl_booke.S, the later being a fork of the former with changed from
> Kumar (and possibly others) to support E200 and E500.
>
> How bad are the differences between those cores ? Would it be possible
> to reconcile those and IBM 44x into a single processor family ? Or are
> there some fundamental differences making that impossible ? (even with a
> bit of CPU feature patching).
I'm not sure. Maybe Kumar knows better since he made the changes to
head_fsl_booke.S. I believe FSL can do SMP and has an SPE and some
other HID registers that 44x does not have.
>
> Also, I suppose we should rename head_4xx.S to head_40x.S no ?
That would be fine with me. I can send a patch if you'd like.
josh
^ permalink raw reply
* Re: [PATCH/RFC] Hookable IO operations
From: Segher Boessenkool @ 2006-11-04 16:28 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list
In-Reply-To: <1162588367.10630.100.camel@localhost.localdomain>
> + * Those operate direction on a kernel virtual address. Note that
> the prototype
s/direction/directly/ ?
> + * for the out_* accessors has the arguments in opposite order
> from the usual
> + * linux PCI accessors. Unlike those, they take the address first
> and the value
> + * next.
Isn't that more confusing than useful?
> +#define DEF_MMIO_IN(name, type, insn) \
> +static inline type in_##name(const volatile type __iomem *addr) \
> +{ \
> + type ret; \
> + __asm__ __volatile__("sync;" insn ";twi 0,%0,0;isync" \
> + : "=r" (ret) : "r" (addr), "m" (*addr)); \
> + return ret; \
> +}
Drop the "inline" and you don't need any macro games anymore, and code
size drops, and it shouldn't be slower -- the I/O operation itself
dominates runtime (but testing is needed, of course).
You can also drop the "volatile" -- it has no effect.
"r"(addr) should probably be "b" (and you might want to lose the "m" --
it certainly won't have any bad effects if you decide to get rid of the
inline).
> +#define DEF_MMIO_IN_BE(pfx, size, insn) \
> + DEF_MMIO_IN(pfx##size, u##size, __stringify(insn)"%U2%X2 %0,%2")
> +#define DEF_MMIO_IN_LE(pfx, size, insn) \
> + DEF_MMIO_IN(pfx##size, u##size, __stringify(insn)" %0,0,%1")
... "r" is okay actually, no "b" needed (would be needed if addr was the
first arg -- which is very much preferred on most CPUs for performance
reasons).
> + * as EEH can use the new hook mecanism, provided it doesn't impact
s/mecanism/mechanism/ .
> + * performances too much
s/s//
> +#ifdef CONFIG_PPC_INDIRECT_IO
> +#define DEF_PCI_HOOK(x) x
> +#else
> +#define DEF_PCI_HOOK(x) NULL
> +#endif
> +
> +#define DEF_PCI_AC_IN_MMIO(ts) \
> +extern DEF_PCI_DT_##ts (*__ind_read##ts)(const volatile void
> __iomem * addr); \
> +static inline DEF_PCI_DT_##ts read##ts(const volatile void __iomem
> * addr) \
> +{ \
> + if (DEF_PCI_HOOK(__ind_read##ts) != NULL) \
> + return __ind_read##ts(addr); \
> + return eeh_read##ts(addr); \
> +}
You really went over the top with macros here. Luckily this will
disappear if you move EEH to use the hooks, too.
> +/* Enforce in-order execution of data I/O.
> + * No distinction between read/write on PPC; use eieio for all three.
> + */
It also prevents write gathering; if not, the _w version wouldn't
need eieio.
> +#define iobarrier_rw() eieio()
> +#define iobarrier_r() eieio()
> +#define iobarrier_w() eieio()
> +config PPC_INDIRECT_IO
I find this name a little confusing, it sounds too much like the
"PCI indirect I/O".
> -static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
> +static u8 iseries_readb(const volatile void __iomem *IoAddress)
Get rid of the caps in IoAddress too?
> - printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO
> address %p\n", IoAddress);
> + printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO
> address %p\n",
> + IoAddress);
Update the printk() to say the new function name.
> +void __init iSeries_pcibios_init(void)
Caps. There's a few more, can you remove them while you're
touching the code anyway please?
Segher
^ permalink raw reply
* Re: FSL vs. IBM BookE
From: Kumar Gala @ 2006-11-04 16:56 UTC (permalink / raw)
To: Josh Boyer; +Cc: Paul Mackerras, Kumar Gala, linuxppc-dev list
In-Reply-To: <1162657000.3139.108.camel@vader.jdub.homelinux.org>
On Nov 4, 2006, at 10:16 AM, Josh Boyer wrote:
> On Sat, 2006-11-04 at 20:21 +1100, Benjamin Herrenschmidt wrote:
>> Out of curiosity... I noticed we have both head_44x.S and
>> head_fsl_booke.S, the later being a fork of the former with
>> changed from
>> Kumar (and possibly others) to support E200 and E500.
>>
>> How bad are the differences between those cores ? Would it be
>> possible
>> to reconcile those and IBM 44x into a single processor family ? Or
>> are
>> there some fundamental differences making that impossible ? (even
>> with a
>> bit of CPU feature patching).
>
> I'm not sure. Maybe Kumar knows better since he made the changes to
> head_fsl_booke.S. I believe FSL can do SMP and has an SPE and some
> other HID registers that 44x does not have.
The big differences are in MMU architectures/programming models
between 44x and FSL Book-E. I tried to move as much common code into
macros between the two head_* files.
- kumar
^ permalink raw reply
* Has anyone 2.6 kernel with Xenomai and MPC5200 Lite running?
From: Matthias Fechner @ 2006-11-04 16:31 UTC (permalink / raw)
To: linuxppc-embedded
Hi,
I have here a MPC5200 Lite (IceCube/Freescale Lite 5200) and tried to
get Xenomai running.
If I use the 2.6 kernel from denx the board boots fine but I am not
able to patch the kernel with the adeos patch (adeos-patch is for
kernel 2.6.18) and the kernel from denx is 2.6.19rc4. I checked the
changes and they are to much for me to adapt it.
What I need now is a patch for kernel 2.6.18 to get all the MPC5200
stuff running (priority has the networkchip) or a adeos patch for the
denx kernel 2.6.19-rc4.
Can anyone help me here, please?
Best regards,
Matthias
--
"Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the universe trying to
produce bigger and better idiots. So far, the universe is winning." --
Rich Cook
^ permalink raw reply
* Re: Booting without Uboot on 8548E
From: Dan Malek @ 2006-11-04 17:22 UTC (permalink / raw)
To: M Ptich; +Cc: linuxppc-dev
In-Reply-To: <BAY102-F21BB220054F2541A7614E4A9FD0@phx.gbl>
On Nov 4, 2006, at 3:52 AM, M Ptich wrote:
> Documentation mentions that the only dependencies between 2.6
> Kernel and
> bootloader are:
>
> 1. 5 input parameters (bd_t pointer, start and end of command line,
> start
> and end of ram disk)
> 2. bd_t pointer and command line must with within 16MB of Kernel
> 3. Initial TLB1 entry must have IPROT=1
I don't know where these are "documented", but there are
many more dependencies. :-) Take a look at the cpu initialization
code from u-boot and you will notice how the TLB CAMs need
to be initialized with the various memory maps. All of the local
bus windows likewise need to be properly set up and match
the kernel configuration.
> And now we are stuck with apparently another dependency: our Kernel
> fails to
> advance beyond time calibration because jiffies are not getting
> incremented,
The time base needs to be enabled in HID0 prior to calling
the kernel.
All of these "dependencies" are typically things a boot rom is
going to also need for proper functioning. We just chose not
to do it again in the kernel. You are going to find more.
Thanks.
-- Dan
^ permalink raw reply
* Re: FSL vs. IBM BookE
From: Dan Malek @ 2006-11-04 17:24 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, Paul Mackerras, Kumar Gala
In-Reply-To: <1162632114.28571.33.camel@localhost.localdomain>
On Nov 4, 2006, at 4:21 AM, Benjamin Herrenschmidt wrote:
> How bad are the differences between those cores ?
They are getting more different as the product families
evolve. The common instruction paths are growing
smaller, and I think the amount of #ifdefs and patching
will make the code much more complex that just leaving
as it is.
> ... Would it be possible
> to reconcile those and IBM 44x into a single processor family ?
I don't think it's worth while. The amount of code isn't
that great and the differences outweigh the similarities.
> Also, I suppose we should rename head_4xx.S to head_40x.S no ?
Maybe, but we all know what they are :-)
Thanks.
-- Dan
^ permalink raw reply
* Kernel oops running 2.6.17 kernel on RPXlite DW involving DP memory in network initialization
From: Jim Heck @ 2006-11-04 19:09 UTC (permalink / raw)
To: linuxppc-embedded
I've been trying to get a 2.6.x kernel working with the RPXlite DW
system from Embedded Planet. I'm getting an oops in the initialization
of the network driver. I have done the basic crash analysis, and it
appears to have to do with the allocation of DP Ram for buffer
descriptors during initialization of the loopback device. The address
being allocated appears to cause a bus fault. I was hoping someone more
familiar with the 8xx network code (or the RPXlite specifically) might
recognize what's going on here. Find my analysis below.
Thanks for any help,
-Jim Heck
I'm using the GCC Powerpc cross compiler and tools from the ELDK 4.0
http://www.denx.de/wiki/DULG/ELDK
The kernel source code is stock 2.6.17 from kernel.org, with one
modification to the /arch/ppc/platforms/rpxlite.h file to remove the
bd_t struct definition and replace it with
#include <asm/ppcboot.h>
This was necessary to get it to work with u-boot.
I also tried the 2.6.15 source code in the ELDK, but had similar
symptoms (I debugged only the 2.6.17 code).
*****RPXLite DW Syslog
001c0e74: 6c3a2043 504d2064 72697665 72202452 l: CPM driver $R
001c0e84: 65766973 696f6e3a 20302e30 3220240a evision: 0.02 $.
001c0e94: 3c363e63 706d5f75 6172743a 20574152 <6>cpm_uart: WAR
001c0ea4: 4e494e47 3a206e6f 20554152 54206465 NING: no UART de
001c0eb4: 76696365 7320666f 756e6420 6f6e2070 vices found on p
001c0ec4: 6c617466 6f726d20 62757321 0a3c363e latform bus!.<6>
001c0ed4: 63706d5f 75617274 3a207468 65206472 cpm_uart: the dr
001c0ee4: 69766572 2077696c 6c206775 65737320 iver will guess
001c0ef4: 636f6e66 69677572 6174696f 6e2c2062 configuration, b
001c0f04: 75742074 68697320 6d6f6465 20697320 ut this mode is
001c0f14: 6e6f206c 6f6e6765 72207375 70706f72 no longer suppor
001c0f24: 7465642e 0a3c343e 52414d44 49534b20 ted..<4>RAMDISK
001c0f34: 64726976 65722069 6e697469 616c697a driver initializ
001c0f44: 65643a20 31362052 414d2064 69736b73 ed: 16 RAM disks
001c0f54: 206f6620 34303936 4b207369 7a652031 of 4096K size 1
001c0f64: 30323420 626c6f63 6b73697a 650a3c36 024 blocksize.<6
001c0f74: 3e6c6f6f 703a206c 6f616465 6420286d >loop: loaded (m
001c0f84: 61782038 20646576 69636573 290a3c34 ax 8 devices).<4
001c0f94: 3e4a4148 2041626f 75742074 6f20646d >JAH About to dm
001c0fa4: 615f616c 6c6f635f 636f6865 00000000 a_alloc_cohe....
001c0fb4: 00000000 00000000 00000000 00000000 ................
001c0fc4: 00000000 00000000 00000000 343e4a41 ............4>JA
001c0fd4: 48205265 7475726e 20666972 73742070 H Return first p
001c0fe4: 6167652e 20416464 72657373 20666631 age. Address ff1
001c0ff4: 30303030 300a3c34 3e4f6f70 733a206b 00000.<4>Oops: k
001c1004: 65726e65 6c206163 63657373 206f6620 ernel access of
001c1014: 62616420 61726561 2c207369 673a2031 bad area, sig: 1
001c1024: 31205b23 315d0a3c 343e4e49 503a2043 1 [#1].<4>NIP: C
001c1034: 30314237 38383820 4c523a20 00000000 01B7888 LR: ....
001c1044: 00000000 00000000 00000000 30303030 ............0000
001c1054: 30300a3c 343e5245 47533a20 63303238 00.<4>REGS: c028
001c1064: 62653930 20545241 503a2030 33303020 be90 TRAP: 0300
001c1074: 20204e6f 74207461 696e7465 64202028 Not tainted (
001c1084: 322e362e 31372d31 290a3c34 3e4d5352 2.6.17-1).<4>MSR
001c1094: 3a203030 30303930 3332203c 45452c4d : 00009032 <EE,M
001c10a4: 452c4952 2c44523e 20204352 3a203234 E,IR,DR> CR: 24
001c10b4: 30303230 32322020 5845523a 20343030 002022 XER: 400
001c10c4: 30443037 460a3c34 3e444152 3a203334 0D07F.<4>DAR: 34
001c10d4: 32303230 30302c20 44534953 523a2043 202000, DSISR: C
001c10e4: 32303030 3030300a 3c343e54 00000000 2000000.<4>T....
001c10f4: 00000000 00000000 00000000 00000000 ................
001c1104: 00000000 00000000 00000000 00000000 ................
001c1114: 00000000 00000000 00000000 47505230 ............GPR0
001c1124: 303a2043 30314237 38374320 43303238 0: C01B787C C028
001c1134: 42463430 20433032 38364145 00000000 BF40 C0286AE....
001c1144: 00000000 00000000 00000000 00000000 ................
001c1154: 00000000 00000000 00000000 00000000 ................
001c1164: 00000000 00000000 00000000 00000000 ................
001c1174: 00000000 00000000 00000000 00000000 ................
001c1184: 00000000 00000000 00000000 00000000 ................
001c1194: 00000000 00000000 00000000 00000000 ................
001c11a4: 00000000 00000000 00000000 30343030 ............0400
001c11b4: 30303030 20303038 30303030 30200a3c 0000 00800000 .<
001c11c4: 363e4750 5231363a 20303346 46463139 6>GPR16: 03FFF19
001c11d4: 30204646 46464646 46462030 30303030 0 FFFFFFFF 00000
001c11e4: 30303020 43303138 30303030 20433031 000 C0180000 C01
001c11f4: 38303030 30204641 32303041 32302046 80000 FA200A20 F
001c1204: 46464639 30303020 43303330 31453630 FFF9000 C0301E60
001c1214: 200a3c36 3e475052 32343a20 00000000 .<6>GPR24: ....
001c1224: 00000000 00000000 00000000 00000000 ................
001c1234: 00000000 00000000 00000000 44303020 ............D00
001c1244: 33343230 32303030 20433033 30314539 34202000 C0301E9
001c1254: 30204646 31303030 30302033 34323032 0 FF100000 34202
001c1264: 30303020 0a3c343e 43616c6c 20547261 000 .<4>Call Tra
001c1274: 63653a0a 3c343e5b 43303238 00000000 ce:.<4>[C028....
***** /arch/ppc/8xx_io/enet.c starting at line 841
bpd = cep->rx_bd_base;
k = 0;
/* JAH Add debug */
printk("JAH About to dma_alloc_coherent.\n");
for (i=0; i<CPM_ENET_RX_PAGES; i++) {
printk("JAH Start first page.\n");
/* Allocate a page.
*/
ba = (unsigned char *)dma_alloc_coherent(NULL, PAGE_SIZE,
&mem_addr, GFP_KERNEL);
printk("JAH Return first page. Address %08x\n", ba);
/* BUG: no check for failure */
/* Initialize the BD for every fragment in the page.
*/
for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
bdp->cbd_bufaddr = mem_addr;
cep->rx_vaddr[k++] = ba;
mem_addr += CPM_ENET_RX_FRSIZE;
ba += CPM_ENET_RX_FRSIZE;
bdp++;
}
}
/* JAH Add debug */
printk("JAH Finished dma_alloc_coherent.\n");
***** from stack stack and disassembly analysis, failure at line
bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
*****dissasembly
c01b783c: 4b e6 2c 0d bl c001a448 <printk>
c01b7840: 3b 20 00 00 li r25,0
c01b7844: 3e 60 c0 18 lis r19,-16360
c01b7848: 3e 80 c0 18 lis r20,-16360
c01b784c: 3a c0 90 00 li r22,-28672
c01b7850: 3b b7 00 30 addi r29,r23,48
c01b7854: 38 73 ef 6c addi r3,r19,-4244
c01b7858: 4b e6 2b f1 bl c001a448 <printk>
c01b785c: 38 81 00 08 addi r4,r1,8
c01b7860: 38 a0 00 d0 li r5,208
c01b7864: 38 60 10 00 li r3,4096
c01b7868: 4b e4 de 31 bl c0005698 <__dma_alloc_coherent>
c01b786c: 7c 64 1b 78 mr r4,r3
c01b7870: 7c 7e 1b 78 mr r30,r3
c01b7874: 38 74 ef 84 addi r3,r20,-4220
c01b7878: 4b e6 2b d1 bl c001a448 <printk>
c01b787c: 7f 9f e3 78 mr r31,r28
c01b7880: 39 7d 00 0c addi r11,r29,12
c01b7884: 39 40 00 00 li r10,0
c01b7888: b2 df 00 00 sth r22,0(r31)
c01b788c: 80 01 00 08 lwz r0,8(r1)
c01b7890: 2f 8a 00 01 cmpwi cr7,r10,1
c01b7894: 90 1f 00 04 stw r0,4(r31)
c01b7898: 93 cb 00 00 stw r30,0(r11)
c01b789c: 81 21 00 08 lwz r9,8(r1)
c01b78a0: 3b de 08 00 addi r30,r30,2048
c01b78a4: 39 29 08 00 addi r9,r9,2048
c01b78a8: 91 21 00 08 stw r9,8(r1)
c01b78ac: 3b ff 00 08 addi r31,r31,8
c01b78b0: 39 6b 00 04 addi r11,r11,4
c01b78b4: 39 4a 00 01 addi r10,r10,1
c01b78b8: 40 be ff d0 bne- cr7,c01b7888 <scc_enet_init+0x264>
*****failure based on NIP at c01b7888 in sth at c01b7888
*****value of r31 (bpd in source code) is 34202000
*****cep->rx_bd_base allocated in /arch/ppc/8xx_io/enet.c lines 751-753
/* Allocate space for the buffer descriptors in the DP ram.
* These are relative offsets in the DP ram address space.
* Initialize base addresses for the buffer descriptors.
*/
dp_offset = cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE, 8);
ep->sen_genscc.scc_rbase = dp_offset;
cep->rx_bd_base = cpm_dpram_addr(dp_offset);
dp_offset = cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE, 8);
ep->sen_genscc.scc_tbase = dp_offset;
cep->tx_bd_base = cpm_dpram_addr(dp_offset);
*****referring to commproc.c line 441
void *cpm_dpram_addr(uint offset)
{
return ((immap_t *)IMAP_ADDR)->im_cpm.cp_dpmem + offset;
}
EXPORT_SYMBOL(cpm_dpram_addr);
*****The memory at 0x34202000 doesn't map nicely...
u-boot>md 0x34202000 0x100
34202000:Bus Fault @ 0x03fe9ea0, fixup 0x00000000
Machine check in kernel mode.
Caused by (from msr): regs 03faea60 Unknown values in msr
NIP: 03FE9EA0 XER: 6000D07F LR: 03FE9E74 REGS: 03faea60 TRAP: 0200 DAR:
03FF9F0CMSR: 00009002 EE: 1 PR: 0 FP: 0 ME: 1 IR/DR: 00
GPR00: 03FE9E74 03FAEB50 00000000 00000000 03FAE9FC 00000010 00000001
00000030
GPR08: 00000001 FA202811 FA202808 FA200808 00000000 FFFFEFFD 04000000
04FD7000
GPR16: 03FFF190 FFFFFFFF 00000000 C0180000 03FAEB58 00000100 03FAEB58
03FAEB58
GPR24: 00000004 03FAEB58 00000400 00000010 34202000 03FAEF94 04000A80
00000000
Call backtrace:
machine check
U-Boot 1.1.5 (Oct 24 2006 - 14:28:06)
CPU: PPC823EZTnnB2 at 48 MHz: 16 kB I-Cache 8 kB D-Cache
Board: RPXlite_DW
DRAM: 64 MB
FLASH: 16 MB
In: serial
Out: serial
Err: serial
Net: SCC ETHERNET
Hit any key to stop autoboot: 0
u-boot>
^ permalink raw reply
* Re: [PATCH/RFC] powerpc: Refactor 64 bits DMA operations
From: Benjamin Herrenschmidt @ 2006-11-04 21:52 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linuxppc-dev list
In-Reply-To: <20061104132101.GA8704@lst.de>
On Sat, 2006-11-04 at 14:21 +0100, Christoph Hellwig wrote:
> On Sat, Nov 04, 2006 at 08:21:34AM +1100, Benjamin Herrenschmidt wrote:
> > This is also something I'll need in 2.6.20. Right now posted only for
> > comments though. It's known to "miss" fixup of at least pasemi and maybe
> > a few other things and I've not tested if I break 32 bits build yet :)
> >
> > This patch completely refactors DMA operations for 64 bits powerpc. 32 bits
> > is untouched for now.
>
> Can we please make 32bit use the same scheme for consistancy? It would
> just plug in a set of dummy direct mapped ops, quite similar to what we
> do in Cell (just without setting the magic bit)
dma_64.c has a set of generic direct ops that could be used for 32 bits
as well. It's just that in addition to fairly different PCI code, 32
bits code use a wider variety of bus types and platform devices and does
DMA from them. All those would need to be updated to get the device
extension with the dma ops pointers.
That's why right now, I prefer leaving 32 bits alone. I do plan to
converge 32 and 64 bits PCI code, don't worry about that :-) At which
point I'll also tackle that issue.
Right now, 64 bits DMA is different, I'm not making it more or less
different, just differently different :-). Merging 32 bits here is just
not something I can do for 2.6.20 timeframe.
Ben
^ permalink raw reply
* Re: [PATCH/RFC] powerpc: Create PCI busses from of_platform
From: Benjamin Herrenschmidt @ 2006-11-04 21:53 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev list
In-Reply-To: <A9F3AC31-AB61-4E39-86D7-B14B96B50B4D@kernel.crashing.org>
On Sat, 2006-11-04 at 16:40 +0100, Segher Boessenkool wrote:
> > +static struct of_device_id of_pci_phb_ids[] = {
> > + { .type = "pci", },
> > + { .type = "pcix", },
> > + { .type = "pcie", },
> > + { .type = "pciex", },
> > + { .type = "ht", },
> > + {}
> > +};
> > +
> > +static struct of_platform_driver of_pci_phb_driver = {
> > + .name = "of-pci",
> > + .match_table = of_pci_phb_ids,
> > + .probe = of_pci_phb_probe,
> > + .driver = {
> > + .multithread_probe = 1,
> > + },
> > +};
>
> Shouldn't you also/only check for compatible=pci? Or maybe
> that would give too much fallout from all the broken device
> trees out there?
We can add things when we need them. This mecanism is to be used by
platforms who register of_device's for the PHBs. Currently, this will
only happen with Cell, so I only need to deal with what's there (I could
even remove 'ht' from the list :-)
As more platforms want to use it, they can fine-tune the list and probe
function.
Ben.
^ permalink raw reply
* Re: [PATCH/RFC] powerpc: Add of_platform support for OHCI/Bigendian HC
From: Sylvain Munaut @ 2006-11-04 22:04 UTC (permalink / raw)
To: Nicolas DET; +Cc: linuxppc-embedded, sl, linuxppc-dev
In-Reply-To: <454A59CC.6070902@bplan-gmbh.de>
>
> ------------------------------------------------------------------------
> +
> +static struct of_device_id ohci_hcd_ppc_of_match_be[] = {
> + {
> + .name = "usb",
> + .compatible = "ohci-bigendian",
> + },
> + {
> + .name = "usb",
> + .compatible = "ohci-be",
> + },
> + {},
> +};
>
> +
> +static struct of_device_id ohci_hcd_ppc_of_match_le[] = {
> + {
> + .name = "usb",
> + .compatible = "ohci-littledian",
> + },
> + {
> + .name = "usb",
> + .compatible = "ohci-le",
> + },
> + {},
> +};
>
Isn't it possible to specify "options" in the device tree rather than
different names ?
(just a though ...)
It's just duplicating all that code doesn't look nice.
> +config USB_OHCI_HCD_PPC_OF
> + bool "OHCI support for PPC USB controller for OpenFirmware platform"
> + depends on USB_OHCI_HCD && PPC_OF
> + default y
> + select USB_OHCI_BIG_ENDIAN
> + select USB_OHCI_LITTLE_ENDIAN
> + ---help---
> + Enables support for the USB controller PowerPC OpenFirmware platform
> +
>
I know what benh said but do we really want to select both all the
times. That adds
quite an overhead to the accesses ...
> --- a/drivers/usb/host/ohci-hcd.c 2006-11-01 09:18:56.000000000 +0100
> +++ b/drivers/usb/host/ohci-hcd.c 2006-11-02 18:06:02.000000000 +0100
> @@ -930,6 +930,12 @@ MODULE_LICENSE ("GPL");
> #include "ohci-ppc-soc.c"
> #endif
>
> +#ifdef CONFIG_USB_OHCI_HCD_PPC_OF
> +#include "ohci-ppc-of.c"
> +#endif
> +
> +
> +
> #if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261)
> #include "ohci-at91.c"
> #endif
>
Don't add space for nothing. All the #if #endif are space by one empty
line, keep it that way.
You also missed the last #if #end
#if !(defined(CONFIG_PCI) \
|| defined(CONFIG_SA1111) \
|| defined(CONFIG_ARCH_S3C2410) \
|| defined(CONFIG_ARCH_OMAP) \
|| defined (CONFIG_ARCH_LH7A404) \
|| defined (CONFIG_PXA27x) \
|| defined (CONFIG_ARCH_EP93XX) \
|| defined (CONFIG_SOC_AU1X00) \
|| defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
|| defined (CONFIG_ARCH_AT91RM9200) \
|| defined (CONFIG_ARCH_AT91SAM9261) \
|| defined (CONFIG_ARCH_PNX4008) \
)
#error "missing bus glue for ohci-hcd"
#endif
You need to add a || defined(...) clause there.
Sylvain
^ permalink raw reply
* Re: [PATCH/RFC] Hookable IO operations
From: Benjamin Herrenschmidt @ 2006-11-04 22:05 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev list
In-Reply-To: <CE55E1AD-1553-442C-98FC-D348BC73E7A4@kernel.crashing.org>
On Sat, 2006-11-04 at 17:28 +0100, Segher Boessenkool wrote:
> > + * Those operate direction on a kernel virtual address. Note that
> > the prototype
>
> s/direction/directly/ ?
Thanks.
> > + * for the out_* accessors has the arguments in opposite order
> > from the usual
> > + * linux PCI accessors. Unlike those, they take the address first
> > and the value
> > + * next.
>
> Isn't that more confusing than useful?
That's how they have been singe day 1. I'm not about to change that and
go fix every bit of ppc code that uses them. At least not with this
patch.
> > +#define DEF_MMIO_IN(name, type, insn) \
> > +static inline type in_##name(const volatile type __iomem *addr) \
> > +{ \
> > + type ret; \
> > + __asm__ __volatile__("sync;" insn ";twi 0,%0,0;isync" \
> > + : "=r" (ret) : "r" (addr), "m" (*addr)); \
> > + return ret; \
> > +}
>
> Drop the "inline" and you don't need any macro games anymore, and code
> size drops, and it shouldn't be slower -- the I/O operation itself
> dominates runtime (but testing is needed, of course).
No, the low level accessors are staying inline and I don't see how that
would prevent macro games... Anyway that doesn't matter much at this
point. Note that I've posted a second version of the patch with simpler
macros.
> You can also drop the "volatile" -- it has no effect.
Well, it's possible, but I've never quite understood when and when not C
compilers need/want volatile or not in the case of IO accessors :-) It
seems to be the rule accross linux that those functions take volatile so
I will continue following it.
> "r"(addr) should probably be "b" (and you might want to lose the "m" --
> it certainly won't have any bad effects if you decide to get rid of the
> inline).
In which case should "r" be "b" ? Those macros are directly equivalent
to the previous code that was there and it didn't use "b". If you look
closely, depending on the type of operations(lbz,lhz,lwz etc.. vs.
lhbrz, lwbrx etc...), we use %1 or %2 for the address. In the former
case, we get more efficient code by letting gcc generate the right type
of instruction (update form, indexed form, ... using %U and %X) by using
and "m" input. For the later, we use "r" and we use it for rB which can
safely be r0 afaik so we don't need "b".
> > +#define DEF_MMIO_IN_BE(pfx, size, insn) \
> > + DEF_MMIO_IN(pfx##size, u##size, __stringify(insn)"%U2%X2 %0,%2")
> > +#define DEF_MMIO_IN_LE(pfx, size, insn) \
> > + DEF_MMIO_IN(pfx##size, u##size, __stringify(insn)" %0,0,%1")
>
> ... "r" is okay actually, no "b" needed (would be needed if addr was the
> first arg -- which is very much preferred on most CPUs for performance
> reasons).
Ah ? But how so ? I mean, there has to be a rB, there is no form of
these instructions (the LE ones) with only one argument. Thus there is
always a register specified as the second part of the address. So if I
was using "b" with rA, I would have to spill another register for rB and
put 0 in it. I fail to see how that would be an improvement, and I fail
to see how the processor implementation would go faster getting 2
registers to add together rather than one.
> > + * as EEH can use the new hook mecanism, provided it doesn't impact
>
> s/mecanism/mechanism/ .
Ok.
> > + * performances too much
>
> s/s//
Ok.
> > +#ifdef CONFIG_PPC_INDIRECT_IO
> > +#define DEF_PCI_HOOK(x) x
> > +#else
> > +#define DEF_PCI_HOOK(x) NULL
> > +#endif
> > +
> > +#define DEF_PCI_AC_IN_MMIO(ts) \
> > +extern DEF_PCI_DT_##ts (*__ind_read##ts)(const volatile void
> > __iomem * addr); \
> > +static inline DEF_PCI_DT_##ts read##ts(const volatile void __iomem
> > * addr) \
> > +{ \
> > + if (DEF_PCI_HOOK(__ind_read##ts) != NULL) \
> > + return __ind_read##ts(addr); \
> > + return eeh_read##ts(addr); \
> > +}
>
> You really went over the top with macros here. Luckily this will
> disappear if you move EEH to use the hooks, too.
Those macros won't disappear but I've simplified them significantly in
the patch #2 that I posted ysterday.
> > +/* Enforce in-order execution of data I/O.
> > + * No distinction between read/write on PPC; use eieio for all three.
> > + */
>
> It also prevents write gathering; if not, the _w version wouldn't
> need eieio.
That was there already, I haven't touched that comment. Maybe I
should...
> > +#define iobarrier_rw() eieio()
> > +#define iobarrier_r() eieio()
> > +#define iobarrier_w() eieio()
>
>
> > +config PPC_INDIRECT_IO
>
> I find this name a little confusing, it sounds too much like the
> "PCI indirect I/O".
Any better idea ?
> > -static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
> > +static u8 iseries_readb(const volatile void __iomem *IoAddress)
>
> Get rid of the caps in IoAddress too?
As I said to Arnd, I will do that in a separate patch as I sanitize a
bit the content of those functions. In fact, I originally changed those
names because I also had to change the prototype (some initial version
of the patch that wasn't posted). Since then, the prototype is back to
what it was, so I might just drop the name change completely from the
patch and do it all in a separate iseries cleanup patch.
> > - printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO
> > address %p\n", IoAddress);
> > + printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO
> > address %p\n",
> > + IoAddress);
>
> Update the printk() to say the new function name.
Yup. See above.
> > +void __init iSeries_pcibios_init(void)
>
> Caps. There's a few more, can you remove them while you're
> touching the code anyway please?
As I said, in a separate patch.
Thanks for your comments !
Cheers
Ben.
^ permalink raw reply
* Re: [PATCH/RFC] powerpc: Add of_platform support for OHCI/Bigendian HC
From: Benjamin Herrenschmidt @ 2006-11-04 22:15 UTC (permalink / raw)
To: Sylvain Munaut; +Cc: linuxppc-dev, linuxppc-embedded, sl
In-Reply-To: <454D0E58.4010100@246tNt.com>
On Sat, 2006-11-04 at 23:04 +0100, Sylvain Munaut wrote:
> Isn't it possible to specify "options" in the device tree rather than
> different names ?
> (just a though ...)
> It's just duplicating all that code doesn't look nice.
Well, he certainly doesn't need to different match lists.
He can just have both LE and BE in a single list and have probe()
routine go look at the property instead.
Ben.
> > +config USB_OHCI_HCD_PPC_OF
> > + bool "OHCI support for PPC USB controller for OpenFirmware platform"
> > + depends on USB_OHCI_HCD && PPC_OF
> > + default y
> > + select USB_OHCI_BIG_ENDIAN
> > + select USB_OHCI_LITTLE_ENDIAN
> > + ---help---
> > + Enables support for the USB controller PowerPC OpenFirmware platform
> > +
> >
> I know what benh said but do we really want to select both all the
> times. That adds
> quite an overhead to the accesses ...
What I said ws that I wanted them to be user-selectable options.
Ben.
^ permalink raw reply
* Re: [PATCH/RFC] Hookable IO operations
From: Segher Boessenkool @ 2006-11-04 22:33 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list
In-Reply-To: <1162677911.28571.55.camel@localhost.localdomain>
>>> + * for the out_* accessors has the arguments in opposite order
>>> from the usual
>>> + * linux PCI accessors. Unlike those, they take the address first
>>> and the value
>>> + * next.
>>
>> Isn't that more confusing than useful?
>
> That's how they have been singe day 1. I'm not about to change that
> and
> go fix every bit of ppc code that uses them. At least not with this
> patch.
Sure. By just reading the patch I couldn't tell whether this was
new (or a new comment) or not, without cross-referencing stuff :-)
>> Drop the "inline" and you don't need any macro games anymore, and
>> code
>> size drops, and it shouldn't be slower -- the I/O operation itself
>> dominates runtime (but testing is needed, of course).
>
> No, the low level accessors are staying inline and I don't see how
> that
> would prevent macro games... Anyway that doesn't matter much at this
> point.
It would be nice if someone could measure the difference between
inlined and non-inlined though, both in code size and actual
performance.
> Note that I've posted a second version of the patch with simpler
> macros.
Your mails show up in my mailbox really late, I'll look at the
new version.
>> You can also drop the "volatile" -- it has no effect.
>
> Well, it's possible, but I've never quite understood when and when
> not C
> compilers need/want volatile or not in the case of IO accessors :-)
"volatile" on a pointer only has effect at the point where that
pointer is dereferenced (at the C level, asm doesn't count).
"volatile" in a function prototype is meaningless; in a function
definition, it only does something _within_ that function, and
then only where the pointer is dereferenced. It's preferable
for clarity to cast the pointer to the volatile version of its
type _right at the dereference itself_.
> It
> seems to be the rule accross linux that those functions take
> volatile so
> I will continue following it.
... but then there's that, heh. I don't feel up to a bad-use-of-
volatile-crusade right now, so I won't ask you to either :-)
>> "r"(addr) should probably be "b" (and you might want to lose the
>> "m" --
>> it certainly won't have any bad effects if you decide to get rid
>> of the
>> inline).
>
> In which case should "r" be "b" ? Those macros are directly equivalent
> to the previous code that was there and it didn't use "b". If you look
> closely, depending on the type of operations(lbz,lhz,lwz etc.. vs.
> lhbrz, lwbrx etc...), we use %1 or %2 for the address. In the former
> case, we get more efficient code by letting gcc generate the right
> type
> of instruction (update form, indexed form, ... using %U and %X) by
> using
> and "m" input. For the later, we use "r" and we use it for rB which
> can
> safely be r0 afaik so we don't need "b".
>
>>> +#define DEF_MMIO_IN_BE(pfx, size, insn) \
>>> + DEF_MMIO_IN(pfx##size, u##size, __stringify(insn)"%U2%X2 %0,%2")
>>> +#define DEF_MMIO_IN_LE(pfx, size, insn) \
>>> + DEF_MMIO_IN(pfx##size, u##size, __stringify(insn)" %0,0,%1")
>>
>> ... "r" is okay actually, no "b" needed (would be needed if addr
>> was the
>> first arg -- which is very much preferred on most CPUs for
>> performance
>> reasons).
>
> Ah ? But how so ? I mean, there has to be a rB, there is no form of
> these instructions (the LE ones) with only one argument.
In load/store insns of the form
op rD,rA,rB
the rA needs to be "b" (i.e., GPR0 is disallowed) and rB can be "r".
Some CPUs want rA to be a "real" address itself, probably because of
how they do the storage address translation. I don't have details,
but see http://gcc.gnu.org/PR28690 . I can speculate but let's do
that in private, not on this mailing list :-)
> Thus there is
> always a register specified as the second part of the address. So if I
> was using "b" with rA, I would have to spill another register for
> rB and
> put 0 in it.
Quite true; just keep it as-is until you get complaints :-)
>>> +/* Enforce in-order execution of data I/O.
>>> + * No distinction between read/write on PPC; use eieio for all
>>> three.
>>> + */
>>
>> It also prevents write gathering; if not, the _w version wouldn't
>> need eieio.
>
> That was there already, I haven't touched that comment. Maybe I
> should...
Yes exactly.
>>> +config PPC_INDIRECT_IO
>>
>> I find this name a little confusing, it sounds too much like the
>> "PCI indirect I/O".
>
> Any better idea ?
Not sure really... PPC_HOOKED_IO?
>> Get rid of the caps in IoAddress too?
>
> As I said to Arnd, I will do that in a separate patch as I sanitize a
> bit the content of those functions.
Yeah I didn't see that reply yet. Great to hear you'll do this
cleanup, thanks!
And now to review #2, or did you send #3 already :-)
Segher
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox