linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/5] [POWERPC] 8xx: platform-specific mmu updates
       [not found] <20061114012504.17455.13833.stgit@localhost.localdomain>
@ 2006-11-14  1:28 ` Vitaly Bordug
  2006-11-14  1:28 ` [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port Vitaly Bordug
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: Vitaly Bordug @ 2006-11-14  1:28 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev


This is just a straight port of the same done in arch/ppc
by Marcelo Tosatti. One used to be
[PATCH] ppc32 8xx: update_mmu_cache() needs unconditional tlbie,
commit eb07d964b4491d1bb5864cd3d7e7633ccdda9a53

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---

 arch/powerpc/mm/mem.c |   20 ++++++++++----------
 1 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index d1c0758..c85eda6 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -490,19 +490,19 @@ #endif
 	    !cpu_has_feature(CPU_FTR_NOEXECUTE) &&
 	    pfn_valid(pfn)) {
 		struct page *page = pfn_to_page(pfn);
+#ifdef CONFIG_8xx
+		/* On 8xx, cache control instructions (particularly
+		 * "dcbst" from flush_dcache_icache) fault as write
+		 * operation if there is an unpopulated TLB entry
+		 * for the address in question. To workaround that,
+		 * we invalidate the TLB here, thus avoiding dcbst
+		 * misbehaviour.
+		 */
+		_tlbie(address);
+#endif
 		if (!PageReserved(page)
 		    && !test_bit(PG_arch_1, &page->flags)) {
 			if (vma->vm_mm == current->active_mm) {
-#ifdef CONFIG_8xx
-			/* On 8xx, cache control instructions (particularly 
-		 	 * "dcbst" from flush_dcache_icache) fault as write 
-			 * operation if there is an unpopulated TLB entry 
-			 * for the address in question. To workaround that, 
-			 * we invalidate the TLB here, thus avoiding dcbst 
-			 * misbehaviour.
-			 */
-				_tlbie(address);
-#endif
 				__flush_dcache_icache((void *) address);
 			} else
 				flush_dcache_icache_page(page);

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port
       [not found] <20061114012504.17455.13833.stgit@localhost.localdomain>
  2006-11-14  1:28 ` [PATCH 1/5] [POWERPC] 8xx: platform-specific mmu updates Vitaly Bordug
@ 2006-11-14  1:28 ` Vitaly Bordug
  2006-11-15 18:23   ` Christoph Hellwig
  2006-11-17  8:00   ` Christoph Hellwig
  2006-11-14  1:28 ` [PATCH 3/5] [POWERPC] 8xx: platform-related changes to the fsl_soc.c Vitaly Bordug
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 17+ messages in thread
From: Vitaly Bordug @ 2006-11-14  1:28 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev


Including support for non-coherent cache, some mm-related things +
relevant field in Kconfig and Makefiles. Also included rheap.o compilaiton
if 8xx is defined.

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---

 arch/powerpc/Kconfig              |   11 +
 arch/powerpc/kernel/Makefile      |    1 
 arch/powerpc/kernel/dma-mapping.c |  442 +++++++++++++++++++++++++++++++++++++
 arch/powerpc/lib/Makefile         |    1 
 arch/powerpc/mm/fault.c           |   99 ++++++++
 5 files changed, 552 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 1d71aff..42c2b6b 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -158,6 +158,11 @@ config PPC_86xx
 	help
 	  The Freescale E600 SoCs have 74xx cores.
 
+config PPC_8xx
+	bool "Freescale 8xx"
+	select FSL_SOC
+	select 8xx
+
 config 40x
 	bool "AMCC 40x"
 	select PPC_DCR_NATIVE
@@ -166,8 +171,6 @@ config 44x
 	bool "AMCC 44x"
 	select PPC_DCR_NATIVE
 
-config 8xx
-	bool "Freescale 8xx"
 
 config E200
 	bool "Freescale e200"
@@ -196,6 +199,10 @@ config 6xx
 	bool
 
 # this is temp to handle compat with arch=ppc
+config 8xx
+	bool
+
+# this is temp to handle compat with arch=ppc
 config 83xx
 	bool
 
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index f9ce5d7..98111ee 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -61,6 +61,7 @@ obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_s
 
 module-$(CONFIG_PPC64)		+= module_64.o
 obj-$(CONFIG_MODULES)		+= $(module-y)
+obj-$(CONFIG_NOT_COHERENT_CACHE)	+= dma-mapping.o
 
 pci64-$(CONFIG_PPC64)		+= pci_64.o pci_dn.o
 pci32-$(CONFIG_PPC32)		:= pci_32.o
diff --git a/arch/powerpc/kernel/dma-mapping.c b/arch/powerpc/kernel/dma-mapping.c
new file mode 100644
index 0000000..10fec73
--- /dev/null
+++ b/arch/powerpc/kernel/dma-mapping.c
@@ -0,0 +1,442 @@
+/*
+ *  PowerPC version derived from arch/arm/mm/consistent.c
+ *    Copyright (C) 2001 Dan Malek (dmalek@jlc.net)
+ *
+ *  Copyright (C) 2000 Russell King
+ *
+ * Consistent memory allocators.  Used for DMA devices that want to
+ * share uncached memory with the processor core.  The function return
+ * is the virtual address and 'dma_handle' is the physical address.
+ * Mostly stolen from the ARM port, with some changes for PowerPC.
+ *						-- Dan
+ *
+ * Reorganized to get rid of the arch-specific consistent_* functions
+ * and provide non-coherent implementations for the DMA API. -Matt
+ *
+ * Added in_interrupt() safe dma_alloc_coherent()/dma_free_coherent()
+ * implementation. This is pulled straight from ARM and barely
+ * modified. -Matt
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/stddef.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/dma-mapping.h>
+#include <linux/hardirq.h>
+
+#include <asm/pgalloc.h>
+#include <asm/prom.h>
+#include <asm/io.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/uaccess.h>
+#include <asm/smp.h>
+#include <asm/machdep.h>
+
+int map_page(unsigned long va, phys_addr_t pa, int flags);
+
+#include <asm/tlbflush.h>
+
+/*
+ * This address range defaults to a value that is safe for all
+ * platforms which currently set CONFIG_NOT_COHERENT_CACHE. It
+ * can be further configured for specific applications under
+ * the "Advanced Setup" menu. -Matt
+ */
+#define CONSISTENT_BASE	(CONFIG_CONSISTENT_START)
+#define CONSISTENT_END	(CONFIG_CONSISTENT_START + CONFIG_CONSISTENT_SIZE)
+#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
+
+/*
+ * This is the page table (2MB) covering uncached, DMA consistent allocations
+ */
+static pte_t *consistent_pte;
+static DEFINE_SPINLOCK(consistent_lock);
+
+/*
+ * VM region handling support.
+ *
+ * This should become something generic, handling VM region allocations for
+ * vmalloc and similar (ioremap, module space, etc).
+ *
+ * I envisage vmalloc()'s supporting vm_struct becoming:
+ *
+ *  struct vm_struct {
+ *    struct vm_region	region;
+ *    unsigned long	flags;
+ *    struct page	**pages;
+ *    unsigned int	nr_pages;
+ *    unsigned long	phys_addr;
+ *  };
+ *
+ * get_vm_area() would then call vm_region_alloc with an appropriate
+ * struct vm_region head (eg):
+ *
+ *  struct vm_region vmalloc_head = {
+ *	.vm_list	= LIST_HEAD_INIT(vmalloc_head.vm_list),
+ *	.vm_start	= VMALLOC_START,
+ *	.vm_end		= VMALLOC_END,
+ *  };
+ *
+ * However, vmalloc_head.vm_start is variable (typically, it is dependent on
+ * the amount of RAM found at boot time.)  I would imagine that get_vm_area()
+ * would have to initialise this each time prior to calling vm_region_alloc().
+ */
+struct vm_region {
+	struct list_head	vm_list;
+	unsigned long		vm_start;
+	unsigned long		vm_end;
+};
+
+static struct vm_region consistent_head = {
+	.vm_list	= LIST_HEAD_INIT(consistent_head.vm_list),
+	.vm_start	= CONSISTENT_BASE,
+	.vm_end		= CONSISTENT_END,
+};
+
+static struct vm_region *
+vm_region_alloc(struct vm_region *head, size_t size, gfp_t gfp)
+{
+	unsigned long addr = head->vm_start, end = head->vm_end - size;
+	unsigned long flags;
+	struct vm_region *c, *new;
+
+	new = kmalloc(sizeof(struct vm_region), gfp);
+	if (!new)
+		goto out;
+
+	spin_lock_irqsave(&consistent_lock, flags);
+
+	list_for_each_entry(c, &head->vm_list, vm_list) {
+		if ((addr + size) < addr)
+			goto nospc;
+		if ((addr + size) <= c->vm_start)
+			goto found;
+		addr = c->vm_end;
+		if (addr > end)
+			goto nospc;
+	}
+
+ found:
+	/*
+	 * Insert this entry _before_ the one we found.
+	 */
+	list_add_tail(&new->vm_list, &c->vm_list);
+	new->vm_start = addr;
+	new->vm_end = addr + size;
+
+	spin_unlock_irqrestore(&consistent_lock, flags);
+	return new;
+
+ nospc:
+	spin_unlock_irqrestore(&consistent_lock, flags);
+	kfree(new);
+ out:
+	return NULL;
+}
+
+static struct vm_region *vm_region_find(struct vm_region *head, unsigned long addr)
+{
+	struct vm_region *c;
+
+	list_for_each_entry(c, &head->vm_list, vm_list) {
+		if (c->vm_start == addr)
+			goto out;
+	}
+	c = NULL;
+ out:
+	return c;
+}
+
+/*
+ * Allocate DMA-coherent memory space and return both the kernel remapped
+ * virtual and bus address for that space.
+ */
+void *
+__dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t gfp)
+{
+	struct page *page;
+	struct vm_region *c;
+	unsigned long order;
+	u64 mask = 0x00ffffff, limit; /* ISA default */
+
+	if (!consistent_pte) {
+		printk(KERN_ERR "%s: not initialised\n", __func__);
+		dump_stack();
+		return NULL;
+	}
+
+	size = PAGE_ALIGN(size);
+	limit = (mask + 1) & ~mask;
+	if ((limit && size >= limit) || size >= (CONSISTENT_END - CONSISTENT_BASE)) {
+		printk(KERN_WARNING "coherent allocation too big (requested %#x mask %#Lx)\n",
+		       size, mask);
+		return NULL;
+	}
+
+	order = get_order(size);
+
+	if (mask != 0xffffffff)
+		gfp |= GFP_DMA;
+
+	page = alloc_pages(gfp, order);
+	if (!page)
+		goto no_page;
+
+	/*
+	 * Invalidate any data that might be lurking in the
+	 * kernel direct-mapped region for device DMA.
+	 */
+	{
+		unsigned long kaddr = (unsigned long)page_address(page);
+		memset(page_address(page), 0, size);
+		flush_dcache_range(kaddr, kaddr + size);
+	}
+
+	/*
+	 * Allocate a virtual address in the consistent mapping region.
+	 */
+	c = vm_region_alloc(&consistent_head, size,
+			    gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
+	if (c) {
+		unsigned long vaddr = c->vm_start;
+		pte_t *pte = consistent_pte + CONSISTENT_OFFSET(vaddr);
+		struct page *end = page + (1 << order);
+
+		split_page(page, order);
+
+		/*
+		 * Set the "dma handle"
+		 */
+		*handle = page_to_bus(page);
+
+		do {
+			BUG_ON(!pte_none(*pte));
+
+			SetPageReserved(page);
+			set_pte_at(&init_mm, vaddr,
+				   pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
+			page++;
+			pte++;
+			vaddr += PAGE_SIZE;
+		} while (size -= PAGE_SIZE);
+
+		/*
+		 * Free the otherwise unused pages.
+		 */
+		while (page < end) {
+			__free_page(page);
+			page++;
+		}
+
+		return (void *)c->vm_start;
+	}
+
+	if (page)
+		__free_pages(page, order);
+ no_page:
+	return NULL;
+}
+EXPORT_SYMBOL(__dma_alloc_coherent);
+
+/*
+ * free a page as defined by the above mapping.
+ */
+void __dma_free_coherent(size_t size, void *vaddr)
+{
+	struct vm_region *c;
+	unsigned long flags, addr;
+	pte_t *ptep;
+
+	size = PAGE_ALIGN(size);
+
+	spin_lock_irqsave(&consistent_lock, flags);
+
+	c = vm_region_find(&consistent_head, (unsigned long)vaddr);
+	if (!c)
+		goto no_area;
+
+	if ((c->vm_end - c->vm_start) != size) {
+		printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
+		       __func__, c->vm_end - c->vm_start, size);
+		dump_stack();
+		size = c->vm_end - c->vm_start;
+	}
+
+	ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+	addr = c->vm_start;
+	do {
+		pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
+		unsigned long pfn;
+
+		ptep++;
+		addr += PAGE_SIZE;
+
+		if (!pte_none(pte) && pte_present(pte)) {
+			pfn = pte_pfn(pte);
+
+			if (pfn_valid(pfn)) {
+				struct page *page = pfn_to_page(pfn);
+				ClearPageReserved(page);
+
+				__free_page(page);
+				continue;
+			}
+		}
+
+		printk(KERN_CRIT "%s: bad page in kernel page table\n",
+		       __func__);
+	} while (size -= PAGE_SIZE);
+
+	flush_tlb_kernel_range(c->vm_start, c->vm_end);
+
+	list_del(&c->vm_list);
+
+	spin_unlock_irqrestore(&consistent_lock, flags);
+
+	kfree(c);
+	return;
+
+ no_area:
+	spin_unlock_irqrestore(&consistent_lock, flags);
+	printk(KERN_ERR "%s: trying to free invalid coherent area: %p\n",
+	       __func__, vaddr);
+	dump_stack();
+}
+EXPORT_SYMBOL(__dma_free_coherent);
+
+/*
+ * Initialise the consistent memory allocation.
+ */
+static int __init dma_alloc_init(void)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	int ret = 0;
+
+	do {
+		pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
+		pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
+		if (!pmd) {
+			printk(KERN_ERR "%s: no pmd tables\n", __func__);
+			ret = -ENOMEM;
+			break;
+		}
+		WARN_ON(!pmd_none(*pmd));
+
+		pte = pte_alloc_kernel(pmd, CONSISTENT_BASE);
+		if (!pte) {
+			printk(KERN_ERR "%s: no pte tables\n", __func__);
+			ret = -ENOMEM;
+			break;
+		}
+
+		consistent_pte = pte;
+	} while (0);
+
+	return ret;
+}
+
+core_initcall(dma_alloc_init);
+
+/*
+ * make an area consistent.
+ */
+void __dma_sync(void *vaddr, size_t size, int direction)
+{
+	unsigned long start = (unsigned long)vaddr;
+	unsigned long end   = start + size;
+
+	switch (direction) {
+	case DMA_NONE:
+		BUG();
+	case DMA_FROM_DEVICE:	/* invalidate only */
+		invalidate_dcache_range(start, end);
+		break;
+	case DMA_TO_DEVICE:		/* writeback only */
+		clean_dcache_range(start, end);
+		break;
+	case DMA_BIDIRECTIONAL:	/* writeback and invalidate */
+		flush_dcache_range(start, end);
+		break;
+	}
+}
+EXPORT_SYMBOL(__dma_sync);
+
+#ifdef CONFIG_HIGHMEM
+/*
+ * __dma_sync_page() implementation for systems using highmem.
+ * In this case, each page of a buffer must be kmapped/kunmapped
+ * in order to have a virtual address for __dma_sync(). This must
+ * not sleep so kmap_atomic()/kunmap_atomic() are used.
+ *
+ * Note: yes, it is possible and correct to have a buffer extend
+ * beyond the first page.
+ */
+static inline void __dma_sync_page_highmem(struct page *page,
+		unsigned long offset, size_t size, int direction)
+{
+	size_t seg_size = min((size_t)(PAGE_SIZE - offset), size);
+	size_t cur_size = seg_size;
+	unsigned long flags, start, seg_offset = offset;
+	int nr_segs = 1 + ((size - seg_size) + PAGE_SIZE - 1)/PAGE_SIZE;
+	int seg_nr = 0;
+
+	local_irq_save(flags);
+
+	do {
+		start = (unsigned long)kmap_atomic(page + seg_nr,
+				KM_PPC_SYNC_PAGE) + seg_offset;
+
+		/* Sync this buffer segment */
+		__dma_sync((void *)start, seg_size, direction);
+		kunmap_atomic((void *)start, KM_PPC_SYNC_PAGE);
+		seg_nr++;
+
+		/* Calculate next buffer segment size */
+		seg_size = min((size_t)PAGE_SIZE, size - cur_size);
+
+		/* Add the segment size to our running total */
+		cur_size += seg_size;
+		seg_offset = 0;
+	} while (seg_nr < nr_segs);
+
+	local_irq_restore(flags);
+}
+#endif /* CONFIG_HIGHMEM */
+
+/*
+ * __dma_sync_page makes memory consistent. identical to __dma_sync, but
+ * takes a struct page instead of a virtual address
+ */
+void __dma_sync_page(struct page *page, unsigned long offset,
+	size_t size, int direction)
+{
+#ifdef CONFIG_HIGHMEM
+	__dma_sync_page_highmem(page, offset, size, direction);
+#else
+	unsigned long start = (unsigned long)page_address(page) + offset;
+	__dma_sync((void *)start, size, direction);
+#endif
+}
+EXPORT_SYMBOL(__dma_sync_page);
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index a0360ae..ad5c30b 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -24,5 +24,6 @@ endif
 
 # Temporary hack until we have migrated to asm-powerpc
 ifeq ($(CONFIG_PPC_MERGE),y)
+obj-$(CONFIG_8xx)	+= rheap.o
 obj-$(CONFIG_CPM2)	+= rheap.o
 endif
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 03aeb3a..539917f 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -447,3 +447,102 @@ void bad_page_fault(struct pt_regs *regs
 
 	die("Kernel access of bad area", regs, sig);
 }
+
+#ifdef CONFIG_8xx
+
+/* The pgtable.h claims some functions generically exist, but I
+ * can't find them......
+ */
+pte_t *va_to_pte(unsigned long address)
+{
+	pgd_t *dir;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	if (address < TASK_SIZE)
+		return NULL;
+
+	dir = pgd_offset(&init_mm, address);
+	if (dir) {
+		pmd = pmd_offset(dir, address & PAGE_MASK);
+		if (pmd && pmd_present(*pmd)) {
+			pte = pte_offset_kernel(pmd, address & PAGE_MASK);
+			if (pte && pte_present(*pte))
+				return(pte);
+		}
+	}
+	return NULL;
+}
+
+unsigned long va_to_phys(unsigned long address)
+{
+	pte_t *pte;
+
+	pte = va_to_pte(address);
+	if (pte)
+		return(((unsigned long)(pte_val(*pte)) & PAGE_MASK) | (address & ~(PAGE_MASK)));
+	return (0);
+}
+
+void
+print_8xx_pte(struct mm_struct *mm, unsigned long addr)
+{
+        pgd_t * pgd;
+        pmd_t * pmd;
+        pte_t * pte;
+
+        printk(" pte @ 0x%8lx: ", addr);
+        pgd = pgd_offset(mm, addr & PAGE_MASK);
+        if (pgd) {
+                pmd = pmd_offset(pgd, addr & PAGE_MASK);
+                if (pmd && pmd_present(*pmd)) {
+                        pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
+                        if (pte) {
+                                printk(" (0x%08lx)->(0x%08lx)->0x%08lx\n",
+                                        (long)pgd, (long)pte, (long)pte_val(*pte));
+#define pp ((long)pte_val(*pte))
+				printk(" RPN: %05lx PP: %lx SPS: %lx SH: %lx "
+				       "CI: %lx v: %lx\n",
+				       pp>>12,    /* rpn */
+				       (pp>>10)&3, /* pp */
+				       (pp>>3)&1, /* small */
+				       (pp>>2)&1, /* shared */
+				       (pp>>1)&1, /* cache inhibit */
+				       pp&1       /* valid */
+				       );
+#undef pp
+                        }
+                        else {
+                                printk("no pte\n");
+                        }
+                }
+                else {
+                        printk("no pmd\n");
+                }
+        }
+        else {
+                printk("no pgd\n");
+        }
+}
+
+int
+get_8xx_pte(struct mm_struct *mm, unsigned long addr)
+{
+        pgd_t * pgd;
+        pmd_t * pmd;
+        pte_t * pte;
+        int     retval = 0;
+
+        pgd = pgd_offset(mm, addr & PAGE_MASK);
+        if (pgd) {
+                pmd = pmd_offset(pgd, addr & PAGE_MASK);
+                if (pmd && pmd_present(*pmd)) {
+                        pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
+                        if (pte) {
+				retval = (int)pte_val(*pte);
+                        }
+                }
+        }
+        return(retval);
+}
+#endif /* CONFIG_8xx */

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 3/5] [POWERPC] 8xx: platform-related changes to the fsl_soc.c
       [not found] <20061114012504.17455.13833.stgit@localhost.localdomain>
  2006-11-14  1:28 ` [PATCH 1/5] [POWERPC] 8xx: platform-specific mmu updates Vitaly Bordug
  2006-11-14  1:28 ` [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port Vitaly Bordug
@ 2006-11-14  1:28 ` Vitaly Bordug
  2006-11-14  2:21   ` Benjamin Herrenschmidt
  2006-11-14  1:28 ` [PATCH 4/5] [POWERPC] 8xx: powerpc port of core CPM, CPM PIC, etc Vitaly Bordug
  2006-11-14  1:28 ` [PATCH 5/5] [POWERPC] 8xx: Add mpc885ads support and common mpc8xx Vitaly Bordug
  4 siblings, 1 reply; 17+ messages in thread
From: Vitaly Bordug @ 2006-11-14  1:28 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev


Added 8xx SoC peripherials: fec for Ethernet and smc for UARTs.
Ordinary routines to extract values from the device tree and insert respective
platform devices

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---

 arch/powerpc/sysdev/fsl_soc.c |  270 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 269 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index ad31e56..61aa8d4 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -39,6 +39,8 @@ #include <asm/cpm2.h>
 
 extern void init_fcc_ioports(struct fs_platform_info*);
 extern void init_scc_ioports(struct fs_uart_platform_info*);
+extern void init_fec_ioports(struct fs_platform_info*);
+extern void init_smc_ioports(struct fs_uart_platform_info*);
 static phys_addr_t immrbase = -1;
 
 phys_addr_t get_immrbase(void)
@@ -63,7 +65,7 @@ phys_addr_t get_immrbase(void)
 
 EXPORT_SYMBOL(get_immrbase);
 
-#ifdef CONFIG_CPM2
+#if defined(CONFIG_CPM2) || defined(CONFIG_8xx)
 
 static u32 brgfreq = -1;
 
@@ -792,3 +794,269 @@ err:
 
 arch_initcall(cpm_uart_of_init);
 #endif /* CONFIG_CPM2 */
+
+#ifdef CONFIG_8xx
+
+static int __init fs_enet_mdio_of_init(void)
+{
+	struct device_node *np;
+	unsigned int i;
+	struct platform_device *mdio_dev;
+	struct resource res;
+	int ret;
+
+	for (np = NULL, i = 0;
+	     (np = of_find_compatible_node(np, "mdio", "fs_enet")) != NULL;
+	     i++) {
+		struct fs_mii_fec_platform_info mdio_data;
+
+		memset(&res, 0, sizeof(res));
+		memset(&mdio_data, 0, sizeof(mdio_data));
+
+		ret = of_address_to_resource(np, 0, &res);
+		if (ret)
+			goto err;
+
+		mdio_dev =
+		    platform_device_register_simple("fsl-cpm-fec-mdio",
+						    res.start, &res, 1);
+		if (IS_ERR(mdio_dev)) {
+			ret = PTR_ERR(mdio_dev);
+			goto err;
+		}
+
+		mdio_data.mii_speed = ((((ppc_proc_freq + 4999999) / 2500000) / 2) & 0x3F) << 1;
+
+		ret =
+		    platform_device_add_data(mdio_dev, &mdio_data,
+					     sizeof(struct fs_mii_fec_platform_info));
+		if (ret)
+			goto unreg;
+	}
+	return 0;
+
+unreg:
+	platform_device_unregister(mdio_dev);
+err:
+	return ret;
+}
+
+arch_initcall(fs_enet_mdio_of_init);
+
+static const char *enet_regs = "regs";
+static const char *enet_pram = "pram";
+static const char *enet_irq = "interrupt";
+static char bus_id[9][BUS_ID_SIZE];
+
+static int __init fs_enet_of_init(void)
+{
+	struct device_node *np;
+	unsigned int i;
+	struct platform_device *fs_enet_dev = NULL;
+	struct resource res;
+	int ret;
+
+	for (np = NULL, i = 0;
+	     (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
+	     i++) {
+		struct resource r[4];
+		struct device_node *phy, *mdio;
+		struct fs_platform_info fs_enet_data;
+		unsigned int *id, *phy_addr;
+		void *mac_addr;
+		phandle *ph;
+		char *model;
+
+		memset(r, 0, sizeof(r));
+		memset(&fs_enet_data, 0, sizeof(fs_enet_data));
+
+		model = (char *)get_property(np, "model", NULL);
+		if (model == NULL) {
+			ret = -ENODEV;
+			goto unreg;
+		}
+
+		id = (u32 *) get_property(np, "device-id", NULL);
+		fs_enet_data.fs_no = *id;
+
+		if (platform_device_skip(model, *id))
+			continue;
+
+		ret = of_address_to_resource(np, 0, &r[0]);
+		if (ret)
+			goto err;
+		r[0].name = enet_regs;
+
+		mac_addr = (void *)get_property(np, "mac-address", NULL);
+		memcpy(fs_enet_data.macaddr, mac_addr, 6);
+
+		ph = (phandle *) get_property(np, "phy-handle", NULL);
+		phy = of_find_node_by_phandle(*ph);
+
+		if (phy != NULL) {
+			phy_addr = (u32 *) get_property(phy, "reg", NULL);
+			fs_enet_data.phy_addr = *phy_addr;
+			fs_enet_data.has_phy = 1;
+		}
+
+
+		model = (char*)get_property(np, "model", NULL);
+		strcpy(fs_enet_data.fs_type, model);
+
+		mdio = of_get_parent(phy);
+                ret = of_address_to_resource(mdio, 0, &res);
+                if (ret) {
+                        of_node_put(phy);
+                        of_node_put(mdio);
+                        goto unreg;
+                }
+
+		if (strstr(model, "FEC")) {
+//			int fec_index = fs_get_fec_index(*id);
+			r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
+			r[1].flags = IORESOURCE_IRQ;
+			r[1].name = enet_irq;
+
+			fs_enet_dev =
+				    platform_device_register_simple("fsl-cpm-fec", i, &r[0], 2);
+
+			if (IS_ERR(fs_enet_dev)) {
+				ret = PTR_ERR(fs_enet_dev);
+				goto err;
+			}
+
+			fs_enet_data.rx_ring = 128;
+			fs_enet_data.tx_ring = 16;
+			fs_enet_data.rx_copybreak = 240;
+			fs_enet_data.use_napi = 1;
+			fs_enet_data.napi_weight = 17;
+
+			snprintf((char*)&bus_id[(*id)], BUS_ID_SIZE, "%x:%02x",
+							(u32)res.start, fs_enet_data.phy_addr);
+			fs_enet_data.bus_id = (char*)&bus_id[(*id)];
+			fs_enet_data.init_ioports = init_fec_ioports;
+		}
+		if (strstr(model, "SCC")) {
+			ret = of_address_to_resource(np, 1, &r[1]);
+			if (ret)
+				goto err;
+			r[1].name = enet_pram;
+
+			r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
+			r[2].flags = IORESOURCE_IRQ;
+			r[2].name = enet_irq;
+
+			fs_enet_dev =
+				    platform_device_register_simple("fsl-cpm-scc", i, &r[0], 3);
+
+			if (IS_ERR(fs_enet_dev)) {
+				ret = PTR_ERR(fs_enet_dev);
+				goto err;
+			}
+
+			fs_enet_data.rx_ring = 64;
+			fs_enet_data.tx_ring = 8;
+			fs_enet_data.rx_copybreak = 240;
+			fs_enet_data.use_napi = 1;
+			fs_enet_data.napi_weight = 17;
+
+			snprintf((char*)&bus_id[(*id)], BUS_ID_SIZE, "%s", "fixed@10:1");
+                        fs_enet_data.bus_id = (char*)&bus_id[(*id)];
+			fs_enet_data.init_ioports = init_scc_ioports;
+		}
+
+		of_node_put(phy);
+		of_node_put(mdio);
+
+		ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
+					     sizeof(struct
+						    fs_platform_info));
+		if (ret) {
+			goto unreg;
+		}
+	}
+	return 0;
+
+unreg:
+	platform_device_unregister(fs_enet_dev);
+err:
+	return ret;
+}
+
+arch_initcall(fs_enet_of_init);
+
+
+static const char *smc_regs = "regs";
+static const char *smc_pram = "pram";
+
+static int __init cpm_smc_uart_of_init(void)
+{
+	struct device_node *np;
+	unsigned int i;
+	struct platform_device *cpm_uart_dev;
+	int ret;
+
+	for (np = NULL, i = 0;
+	     (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
+	     i++) {
+		struct resource r[3];
+		struct fs_uart_platform_info cpm_uart_data;
+		int *id;
+		char *model;
+
+		memset(r, 0, sizeof(r));
+		memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
+
+		ret = of_address_to_resource(np, 0, &r[0]);
+		if (ret)
+			goto err;
+
+		r[0].name = smc_regs;
+
+		ret = of_address_to_resource(np, 1, &r[1]);
+		if (ret)
+			goto err;
+		r[1].name = smc_pram;
+
+		r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
+		r[2].flags = IORESOURCE_IRQ;
+
+		cpm_uart_dev =
+		    platform_device_register_simple("fsl-cpm-smc:uart", i, &r[0], 3);
+
+		if (IS_ERR(cpm_uart_dev)) {
+			ret = PTR_ERR(cpm_uart_dev);
+			goto err;
+		}
+
+		model = (char*)get_property(np, "model", NULL);
+		strcpy(cpm_uart_data.fs_type, model);
+
+		id = (int*)get_property(np, "device-id", NULL);
+		cpm_uart_data.fs_no = *id;
+		cpm_uart_data.uart_clk = ppc_proc_freq;
+
+		cpm_uart_data.tx_num_fifo = 4;
+		cpm_uart_data.tx_buf_size = 32;
+		cpm_uart_data.rx_num_fifo = 4;
+		cpm_uart_data.rx_buf_size = 32;
+
+		ret =
+		    platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
+					     sizeof(struct
+						    fs_uart_platform_info));
+		if (ret)
+			goto unreg;
+	}
+
+	return 0;
+
+unreg:
+	platform_device_unregister(cpm_uart_dev);
+err:
+	return ret;
+}
+
+arch_initcall(cpm_smc_uart_of_init);
+
+#endif /* CONFIG_8xx */

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 4/5] [POWERPC] 8xx: powerpc port of core CPM, CPM PIC, etc.
       [not found] <20061114012504.17455.13833.stgit@localhost.localdomain>
                   ` (2 preceding siblings ...)
  2006-11-14  1:28 ` [PATCH 3/5] [POWERPC] 8xx: platform-related changes to the fsl_soc.c Vitaly Bordug
@ 2006-11-14  1:28 ` Vitaly Bordug
  2006-11-14  2:44   ` Benjamin Herrenschmidt
  2006-11-14  1:28 ` [PATCH 5/5] [POWERPC] 8xx: Add mpc885ads support and common mpc8xx Vitaly Bordug
  4 siblings, 1 reply; 17+ messages in thread
From: Vitaly Bordug @ 2006-11-14  1:28 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev


This covers common CPM access functions, CPM interrupt controller code,
micropatch and a few compatibility things to kee the same driver base
working with arch/ppc.

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---

 arch/powerpc/sysdev/Makefile     |    3 
 arch/powerpc/sysdev/commproc.c   |  426 ++++++++++++++++++++++
 arch/powerpc/sysdev/micropatch.c |  743 ++++++++++++++++++++++++++++++++++++++
 arch/powerpc/sysdev/mpc8xx_pic.c |  209 +++++++++++
 arch/powerpc/sysdev/mpc8xx_pic.h |   12 +
 include/asm-powerpc/fs_pd.h      |   44 ++
 include/asm-powerpc/mpc8xx.h     |   38 ++
 7 files changed, 1465 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 8ba11ab..ab6b06e 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -22,3 +22,6 @@ # Temporary hack until we have migrated 
 ifeq ($(ARCH),powerpc)
 obj-$(CONFIG_CPM2)		+= cpm2_common.o cpm2_pic.o
 endif
+
+obj-$(CONFIG_8xx)		+= mpc8xx_pic.o commproc.o
+obj-$(CONFIG_UCODE_PATCH)	+= micropatch.o
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c
new file mode 100644
index 0000000..6fc0c9e
--- /dev/null
+++ b/arch/powerpc/sysdev/commproc.c
@@ -0,0 +1,426 @@
+/*
+ * General Purpose functions for the global management of the
+ * Communication Processor Module.
+ * Copyright (c) 1997 Dan error_act (dmalek@jlc.net)
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space.  The allocator for that is here.  When the communication
+ * process is reset, we reclaim the memory available.  There is
+ * currently no deallocator for this memory.
+ * The amount of space available is platform dependent.  On the
+ * MBX, the EPPC software loads additional microcode into the
+ * communication processor, and uses some of the DP ram for this
+ * purpose.  Current, the first 512 bytes and the last 256 bytes of
+ * memory are used.  Right now I am conservative and only use the
+ * memory that can never be used for microcode.  If there are
+ * applications that require more DP ram, we can expand the boundaries
+ * but then we have to be careful of any downloaded microcode.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <asm/mpc8xx.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/8xx_immap.h>
+#include <asm/commproc.h>
+#include <asm/io.h>
+#include <asm/tlbflush.h>
+#include <asm/rheap.h>
+#include <asm/prom.h>
+
+#include <asm/fs_pd.h>
+
+#define CPM_MAP_SIZE    (0x4000)
+
+static void m8xx_cpm_dpinit(void);
+static	uint	host_buffer;	/* One page of host buffer */
+static	uint	host_end;	/* end + 1 */
+cpm8xx_t	*cpmp;		/* Pointer to comm processor space */
+cpic8xx_t	*cpic_reg;
+
+static struct device_node *cpm_pic_node;
+static struct irq_host *cpm_pic_host;
+
+static void cpm_mask_irq(unsigned int irq)
+{
+        unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
+
+	clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
+}
+
+static void cpm_unmask_irq(unsigned int irq)
+{
+        unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
+
+	setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
+}
+
+static void cpm_mask_and_ack(unsigned int irq)
+{
+	/* We do not need to do anything here. */
+}
+
+static void cpm_end_irq(unsigned int irq)
+{
+        unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
+
+	out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec));
+}
+
+static struct irq_chip cpm_pic = {
+	.typename = " CPM PIC ",
+	.enable = cpm_unmask_irq,
+	.disable = cpm_mask_irq,
+	.unmask = cpm_unmask_irq,
+	.mask_ack = cpm_mask_and_ack,
+	.end = cpm_end_irq,
+};
+
+int cpm_get_irq()
+{
+	int cpm_vec;
+
+	/* Get the vector by setting the ACK bit and then reading
+	 * the register.
+	 */
+	out_be16(&cpic_reg->cpic_civr, 1);
+	cpm_vec = in_be16(&cpic_reg->cpic_civr);
+	cpm_vec >>= 11;
+
+	return irq_linear_revmap(cpm_pic_host, cpm_vec);
+}
+
+static int cpm_pic_host_match(struct irq_host *h, struct device_node *node)
+{
+	return cpm_pic_node == NULL || cpm_pic_node == node;
+}
+
+static int cpm_pic_host_map(struct irq_host *h, unsigned int virq,
+			  irq_hw_number_t hw)
+{
+	pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw);
+
+	get_irq_desc(virq)->status |= IRQ_LEVEL;
+	set_irq_chip_and_handler(virq, &cpm_pic, handle_level_irq);
+	return 0;
+}
+
+static void cpm_host_unmap(struct irq_host *h, unsigned int virq)
+{
+	/* Make sure irq is masked in hardware */
+	cpm_mask_irq(virq);
+
+	/* remove chip and handler */
+	set_irq_chip_and_handler(virq, NULL, NULL);
+}
+
+static int cpm_pic_host_xlate(struct irq_host *h, struct device_node *ct,
+			    u32 *intspec, unsigned int intsize,
+			    irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+{
+	static unsigned char map_cpm_senses[4] = {
+		IRQ_TYPE_LEVEL_LOW,
+		IRQ_TYPE_LEVEL_HIGH,
+		IRQ_TYPE_EDGE_FALLING,
+		IRQ_TYPE_EDGE_RISING,
+	};
+
+	*out_hwirq = intspec[0];
+	if (intsize > 1 && intspec[1] < 4)
+		*out_flags = map_cpm_senses[intspec[1]];
+	else
+		*out_flags = IRQ_TYPE_NONE;
+
+	return 0;
+}
+
+/* The CPM can generate the error interrupt when there is a race condition
+ * between generating and masking interrupts.  All we have to do is ACK it
+ * and return.  This is a no-op function so we don't need any special
+ * tests in the interrupt handler.
+ */
+static	irqreturn_t cpm_error_interrupt(int irq, void *dev)
+{
+	return IRQ_HANDLED;
+}
+
+static struct irqaction cpm_error_irqaction = {
+	.handler = cpm_error_interrupt,
+	.mask = CPU_MASK_NONE,
+	.name = "error",
+};
+
+static struct irq_host_ops cpm_pic_host_ops = {
+	.match = cpm_pic_host_match,
+	.map = cpm_pic_host_map,
+	.unmap = cpm_host_unmap,
+	.xlate = cpm_pic_host_xlate,
+};
+
+unsigned int cpm_pic_init(void)
+{
+	struct device_node *np = NULL;
+	struct resource res;
+	unsigned int sirq = NO_IRQ, hwirq, eirq;
+	int ret;
+
+	pr_debug("cpm_pic_init\n");
+
+	np = of_find_compatible_node(NULL, "cpm-pic", "CPM");
+	if (np == NULL) {
+		printk(KERN_ERR "CPM PIC init: can not find cpm-pic node\n");
+                return sirq;
+	}
+	ret = of_address_to_resource(np, 0, &res);
+	if (ret)
+		return sirq;
+
+	cpic_reg = (void *)ioremap(res.start, res.end - res.start + 1);
+	if (cpic_reg == NULL)
+		return sirq;
+
+	sirq = irq_of_parse_and_map(np, 0);
+
+	/* Initialize the CPM interrupt controller. */
+	hwirq = (unsigned int)irq_map[sirq].hwirq;
+	out_be32(&cpic_reg->cpic_cicr,
+	    (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
+		((hwirq/2) << 13) | CICR_HP_MASK);
+
+	out_be32(&cpic_reg->cpic_cimr, 0);
+
+	/* create a legacy host */
+	if (np)
+		cpm_pic_node = of_node_get(np);
+
+	cpm_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &cpm_pic_host_ops, 64);
+	if (cpm_pic_host == NULL) {
+		printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
+		sirq = NO_IRQ;
+                return sirq;
+	}
+
+	/* Install our own error handler. */
+	np = of_find_node_by_type(NULL, "cpm");
+	eirq= irq_of_parse_and_map(np, 0);
+	if (setup_irq(eirq, &cpm_error_irqaction))
+		printk(KERN_ERR "Could not allocate CPM error IRQ!");
+
+	setbits32(&cpic_reg->cpic_cicr, CICR_IEN);
+
+	return sirq;
+}
+
+void cpm_reset(void)
+{
+	cpm8xx_t	*commproc;
+	sysconf8xx_t    *siu_conf;
+
+	commproc = (cpm8xx_t *)ioremap(CPM_MAP_ADDR, CPM_MAP_SIZE);
+
+#ifdef CONFIG_UCODE_PATCH
+	/* Perform a reset.
+	*/
+	out_be16(&commproc->cp_cpcr,  CPM_CR_RST | CPM_CR_FLG);
+
+	/* Wait for it.
+	*/
+	while (in_be16(&commproc->cp_cpcr) & CPM_CR_FLG);
+
+	cpm_load_patch(commproc);
+#endif
+
+	/* Set SDMA Bus Request priority 5.
+	 * On 860T, this also enables FEC priority 6.  I am not sure
+	 * this is what we realy want for some applications, but the
+	 * manual recommends it.
+	 * Bit 25, FAM can also be set to use FEC aggressive mode (860T).
+	 */
+	siu_conf = (sysconf8xx_t*)immr_map(im_siu_conf);
+	out_be32(&siu_conf->sc_sdcr, 1);
+	immr_unmap(siu_conf);
+
+	/* Reclaim the DP memory for our use. */
+	m8xx_cpm_dpinit();
+
+	/* Tell everyone where the comm processor resides.
+	*/
+	cpmp = commproc;
+}
+
+/* We used to do this earlier, but have to postpone as long as possible
+ * to ensure the kernel VM is now running.
+ */
+static void
+alloc_host_memory(void)
+{
+	dma_addr_t	physaddr;
+
+	/* Set the host page for allocation.
+	*/
+	host_buffer = (uint)dma_alloc_coherent(NULL, PAGE_SIZE, &physaddr,
+			GFP_KERNEL);
+	host_end = host_buffer + PAGE_SIZE;
+}
+
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+m8xx_cpm_hostalloc(uint size)
+{
+	uint	retloc;
+
+	if (host_buffer == 0)
+		alloc_host_memory();
+
+	if ((host_buffer + size) >= host_end)
+		return(0);
+
+	retloc = host_buffer;
+	host_buffer += size;
+
+	return(retloc);
+}
+
+/* Set a baud rate generator.  This needs lots of work.  There are
+ * four BRGs, any of which can be wired to any channel.
+ * The internal baud rate clock is the system clock divided by 16.
+ * This assumes the baudrate is 16x oversampled by the uart.
+ */
+#define BRG_INT_CLK		(get_brgfreq())
+#define BRG_UART_CLK		(BRG_INT_CLK/16)
+#define BRG_UART_CLK_DIV16	(BRG_UART_CLK/16)
+
+void
+cpm_setbrg(uint brg, uint rate)
+{
+	volatile uint	*bp;
+
+	/* This is good enough to get SMCs running.....
+	*/
+	bp = (uint *)&cpmp->cp_brgc1;
+	bp += brg;
+	/* The BRG has a 12-bit counter.  For really slow baud rates (or
+	 * really fast processors), we may have to further divide by 16.
+	 */
+	if (((BRG_UART_CLK / rate) - 1) < 4096)
+		*bp = (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN;
+	else
+		*bp = (((BRG_UART_CLK_DIV16 / rate) - 1) << 1) |
+						CPM_BRG_EN | CPM_BRG_DIV16;
+}
+
+/*
+ * dpalloc / dpfree bits.
+ */
+static spinlock_t cpm_dpmem_lock;
+/*
+ * 16 blocks should be enough to satisfy all requests
+ * until the memory subsystem goes up...
+ */
+static rh_block_t cpm_boot_dpmem_rh_block[16];
+static rh_info_t cpm_dpmem_info;
+
+#define CPM_DPMEM_ALIGNMENT	8
+static u8* dpram_vbase;
+static uint dpram_pbase;
+
+void m8xx_cpm_dpinit(void)
+{
+	spin_lock_init(&cpm_dpmem_lock);
+
+	dpram_vbase = immr_map_size(im_cpm.cp_dpmem, CPM_DATAONLY_BASE + CPM_DATAONLY_SIZE);
+	dpram_pbase = (uint)&((immap_t *)IMAP_ADDR)->im_cpm.cp_dpmem;
+
+	/* Initialize the info header */
+	rh_init(&cpm_dpmem_info, CPM_DPMEM_ALIGNMENT,
+			sizeof(cpm_boot_dpmem_rh_block) /
+			sizeof(cpm_boot_dpmem_rh_block[0]),
+			cpm_boot_dpmem_rh_block);
+
+	/*
+	 * Attach the usable dpmem area.
+	 * XXX: This is actually crap.  CPM_DATAONLY_BASE and
+	 * CPM_DATAONLY_SIZE are a subset of the available dparm.  It varies
+	 * with the processor and the microcode patches applied / activated.
+	 * But the following should be at least safe.
+	 */
+	rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
+}
+
+/*
+ * Allocate the requested size worth of DP memory.
+ * This function returns an offset into the DPRAM area.
+ * Use cpm_dpram_addr() to get the virtual address of the area.
+ */
+uint cpm_dpalloc(uint size, uint align)
+{
+	void *start;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+	cpm_dpmem_info.alignment = align;
+	start = rh_alloc(&cpm_dpmem_info, size, "commproc");
+	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+	return (uint)start;
+}
+EXPORT_SYMBOL(cpm_dpalloc);
+
+int cpm_dpfree(uint offset)
+{
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+	ret = rh_free(&cpm_dpmem_info, (void *)offset);
+	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(cpm_dpfree);
+
+uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
+{
+	void *start;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cpm_dpmem_lock, flags);
+	cpm_dpmem_info.alignment = align;
+	start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
+	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
+
+	return (uint)start;
+}
+EXPORT_SYMBOL(cpm_dpalloc_fixed);
+
+void cpm_dpdump(void)
+{
+	rh_dump(&cpm_dpmem_info);
+}
+EXPORT_SYMBOL(cpm_dpdump);
+
+void *cpm_dpram_addr(uint offset)
+{
+	return (void *)(dpram_vbase + offset);
+}
+EXPORT_SYMBOL(cpm_dpram_addr);
+
+uint cpm_dpram_phys(u8* addr)
+{
+	return (dpram_pbase + (uint)(addr - dpram_vbase));
+}
+EXPORT_SYMBOL(cpm_dpram_addr);
diff --git a/arch/powerpc/sysdev/micropatch.c b/arch/powerpc/sysdev/micropatch.c
new file mode 100644
index 0000000..712b10a
--- /dev/null
+++ b/arch/powerpc/sysdev/micropatch.c
@@ -0,0 +1,743 @@
+
+/* Microcode patches for the CPM as supplied by Motorola.
+ * This is the one for IIC/SPI.  There is a newer one that
+ * also relocates SMC2, but this would require additional changes
+ * to uart.c, so I am holding off on that for a moment.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/mpc8xx.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/8xx_immap.h>
+#include <asm/commproc.h>
+
+/*
+ * I2C/SPI relocation patch arrays.
+ */
+
+#ifdef CONFIG_I2C_SPI_UCODE_PATCH
+
+uint patch_2000[] = {
+	0x7FFFEFD9,
+	0x3FFD0000,
+	0x7FFB49F7,
+	0x7FF90000,
+	0x5FEFADF7,
+	0x5F89ADF7,
+	0x5FEFAFF7,
+	0x5F89AFF7,
+	0x3A9CFBC8,
+	0xE7C0EDF0,
+	0x77C1E1BB,
+	0xF4DC7F1D,
+	0xABAD932F,
+	0x4E08FDCF,
+	0x6E0FAFF8,
+	0x7CCF76CF,
+	0xFD1FF9CF,
+	0xABF88DC6,
+	0xAB5679F7,
+	0xB0937383,
+	0xDFCE79F7,
+	0xB091E6BB,
+	0xE5BBE74F,
+	0xB3FA6F0F,
+	0x6FFB76CE,
+	0xEE0DF9CF,
+	0x2BFBEFEF,
+	0xCFEEF9CF,
+	0x76CEAD24,
+	0x90B2DF9A,
+	0x7FDDD0BF,
+	0x4BF847FD,
+	0x7CCF76CE,
+	0xCFEF7E1F,
+	0x7F1D7DFD,
+	0xF0B6EF71,
+	0x7FC177C1,
+	0xFBC86079,
+	0xE722FBC8,
+	0x5FFFDFFF,
+	0x5FB2FFFB,
+	0xFBC8F3C8,
+	0x94A67F01,
+	0x7F1D5F39,
+	0xAFE85F5E,
+	0xFFDFDF96,
+	0xCB9FAF7D,
+	0x5FC1AFED,
+	0x8C1C5FC1,
+	0xAFDD5FC3,
+	0xDF9A7EFD,
+	0xB0B25FB2,
+	0xFFFEABAD,
+	0x5FB2FFFE,
+	0x5FCE600B,
+	0xE6BB600B,
+	0x5FCEDFC6,
+	0x27FBEFDF,
+	0x5FC8CFDE,
+	0x3A9CE7C0,
+	0xEDF0F3C8,
+	0x7F0154CD,
+	0x7F1D2D3D,
+	0x363A7570,
+	0x7E0AF1CE,
+	0x37EF2E68,
+	0x7FEE10EC,
+	0xADF8EFDE,
+	0xCFEAE52F,
+	0x7D0FE12B,
+	0xF1CE5F65,
+	0x7E0A4DF8,
+	0xCFEA5F72,
+	0x7D0BEFEE,
+	0xCFEA5F74,
+	0xE522EFDE,
+	0x5F74CFDA,
+	0x0B627385,
+	0xDF627E0A,
+	0x30D8145B,
+	0xBFFFF3C8,
+	0x5FFFDFFF,
+	0xA7F85F5E,
+	0xBFFE7F7D,
+	0x10D31450,
+	0x5F36BFFF,
+	0xAF785F5E,
+	0xBFFDA7F8,
+	0x5F36BFFE,
+	0x77FD30C0,
+	0x4E08FDCF,
+	0xE5FF6E0F,
+	0xAFF87E1F,
+	0x7E0FFD1F,
+	0xF1CF5F1B,
+	0xABF80D5E,
+	0x5F5EFFEF,
+	0x79F730A2,
+	0xAFDD5F34,
+	0x47F85F34,
+	0xAFED7FDD,
+	0x50B24978,
+	0x47FD7F1D,
+	0x7DFD70AD,
+	0xEF717EC1,
+	0x6BA47F01,
+	0x2D267EFD,
+	0x30DE5F5E,
+	0xFFFD5F5E,
+	0xFFEF5F5E,
+	0xFFDF0CA0,
+	0xAFED0A9E,
+	0xAFDD0C3A,
+	0x5F3AAFBD,
+	0x7FBDB082,
+	0x5F8247F8
+};
+
+uint patch_2f00[] = {
+	0x3E303430,
+	0x34343737,
+	0xABF7BF9B,
+	0x994B4FBD,
+	0xBD599493,
+	0x349FFF37,
+	0xFB9B177D,
+	0xD9936956,
+	0xBBFDD697,
+	0xBDD2FD11,
+	0x31DB9BB3,
+	0x63139637,
+	0x93733693,
+	0x193137F7,
+	0x331737AF,
+	0x7BB9B999,
+	0xBB197957,
+	0x7FDFD3D5,
+	0x73B773F7,
+	0x37933B99,
+	0x1D115316,
+	0x99315315,
+	0x31694BF4,
+	0xFBDBD359,
+	0x31497353,
+	0x76956D69,
+	0x7B9D9693,
+	0x13131979,
+	0x79376935
+};
+#endif
+
+/*
+ * I2C/SPI/SMC1 relocation patch arrays.
+ */
+
+#ifdef CONFIG_I2C_SPI_SMC1_UCODE_PATCH
+
+uint patch_2000[] = {
+	0x3fff0000,
+	0x3ffd0000,
+	0x3ffb0000,
+	0x3ff90000,
+	0x5f13eff8,
+	0x5eb5eff8,
+	0x5f88adf7,
+	0x5fefadf7,
+	0x3a9cfbc8,
+	0x77cae1bb,
+	0xf4de7fad,
+	0xabae9330,
+	0x4e08fdcf,
+	0x6e0faff8,
+	0x7ccf76cf,
+	0xfdaff9cf,
+	0xabf88dc8,
+	0xab5879f7,
+	0xb0925d8d,
+	0xdfd079f7,
+	0xb090e6bb,
+	0xe5bbe74f,
+	0x9e046f0f,
+	0x6ffb76ce,
+	0xee0cf9cf,
+	0x2bfbefef,
+	0xcfeef9cf,
+	0x76cead23,
+	0x90b3df99,
+	0x7fddd0c1,
+	0x4bf847fd,
+	0x7ccf76ce,
+	0xcfef77ca,
+	0x7eaf7fad,
+	0x7dfdf0b7,
+	0xef7a7fca,
+	0x77cafbc8,
+	0x6079e722,
+	0xfbc85fff,
+	0xdfff5fb3,
+	0xfffbfbc8,
+	0xf3c894a5,
+	0xe7c9edf9,
+	0x7f9a7fad,
+	0x5f36afe8,
+	0x5f5bffdf,
+	0xdf95cb9e,
+	0xaf7d5fc3,
+	0xafed8c1b,
+	0x5fc3afdd,
+	0x5fc5df99,
+	0x7efdb0b3,
+	0x5fb3fffe,
+	0xabae5fb3,
+	0xfffe5fd0,
+	0x600be6bb,
+	0x600b5fd0,
+	0xdfc827fb,
+	0xefdf5fca,
+	0xcfde3a9c,
+	0xe7c9edf9,
+	0xf3c87f9e,
+	0x54ca7fed,
+	0x2d3a3637,
+	0x756f7e9a,
+	0xf1ce37ef,
+	0x2e677fee,
+	0x10ebadf8,
+	0xefdecfea,
+	0xe52f7d9f,
+	0xe12bf1ce,
+	0x5f647e9a,
+	0x4df8cfea,
+	0x5f717d9b,
+	0xefeecfea,
+	0x5f73e522,
+	0xefde5f73,
+	0xcfda0b61,
+	0x5d8fdf61,
+	0xe7c9edf9,
+	0x7e9a30d5,
+	0x1458bfff,
+	0xf3c85fff,
+	0xdfffa7f8,
+	0x5f5bbffe,
+	0x7f7d10d0,
+	0x144d5f33,
+	0xbfffaf78,
+	0x5f5bbffd,
+	0xa7f85f33,
+	0xbffe77fd,
+	0x30bd4e08,
+	0xfdcfe5ff,
+	0x6e0faff8,
+	0x7eef7e9f,
+	0xfdeff1cf,
+	0x5f17abf8,
+	0x0d5b5f5b,
+	0xffef79f7,
+	0x309eafdd,
+	0x5f3147f8,
+	0x5f31afed,
+	0x7fdd50af,
+	0x497847fd,
+	0x7f9e7fed,
+	0x7dfd70a9,
+	0xef7e7ece,
+	0x6ba07f9e,
+	0x2d227efd,
+	0x30db5f5b,
+	0xfffd5f5b,
+	0xffef5f5b,
+	0xffdf0c9c,
+	0xafed0a9a,
+	0xafdd0c37,
+	0x5f37afbd,
+	0x7fbdb081,
+	0x5f8147f8,
+	0x3a11e710,
+	0xedf0ccdd,
+	0xf3186d0a,
+	0x7f0e5f06,
+	0x7fedbb38,
+	0x3afe7468,
+	0x7fedf4fc,
+	0x8ffbb951,
+	0xb85f77fd,
+	0xb0df5ddd,
+	0xdefe7fed,
+	0x90e1e74d,
+	0x6f0dcbf7,
+	0xe7decfed,
+	0xcb74cfed,
+	0xcfeddf6d,
+	0x91714f74,
+	0x5dd2deef,
+	0x9e04e7df,
+	0xefbb6ffb,
+	0xe7ef7f0e,
+	0x9e097fed,
+	0xebdbeffa,
+	0xeb54affb,
+	0x7fea90d7,
+	0x7e0cf0c3,
+	0xbffff318,
+	0x5fffdfff,
+	0xac59efea,
+	0x7fce1ee5,
+	0xe2ff5ee1,
+	0xaffbe2ff,
+	0x5ee3affb,
+	0xf9cc7d0f,
+	0xaef8770f,
+	0x7d0fb0c6,
+	0xeffbbfff,
+	0xcfef5ede,
+	0x7d0fbfff,
+	0x5ede4cf8,
+	0x7fddd0bf,
+	0x49f847fd,
+	0x7efdf0bb,
+	0x7fedfffd,
+	0x7dfdf0b7,
+	0xef7e7e1e,
+	0x5ede7f0e,
+	0x3a11e710,
+	0xedf0ccab,
+	0xfb18ad2e,
+	0x1ea9bbb8,
+	0x74283b7e,
+	0x73c2e4bb,
+	0x2ada4fb8,
+	0xdc21e4bb,
+	0xb2a1ffbf,
+	0x5e2c43f8,
+	0xfc87e1bb,
+	0xe74ffd91,
+	0x6f0f4fe8,
+	0xc7ba32e2,
+	0xf396efeb,
+	0x600b4f78,
+	0xe5bb760b,
+	0x53acaef8,
+	0x4ef88b0e,
+	0xcfef9e09,
+	0xabf8751f,
+	0xefef5bac,
+	0x741f4fe8,
+	0x751e760d,
+	0x7fdbf081,
+	0x741cafce,
+	0xefcc7fce,
+	0x751e70ac,
+	0x741ce7bb,
+	0x3372cfed,
+	0xafdbefeb,
+	0xe5bb760b,
+	0x53f2aef8,
+	0xafe8e7eb,
+	0x4bf8771e,
+	0x7e247fed,
+	0x4fcbe2cc,
+	0x7fbc30a9,
+	0x7b0f7a0f,
+	0x34d577fd,
+	0x308b5db7,
+	0xde553e5f,
+	0xaf78741f,
+	0x741f30f0,
+	0xcfef5e2c,
+	0x741f3eac,
+	0xafb8771e,
+	0x5e677fed,
+	0x0bd3e2cc,
+	0x741ccfec,
+	0xe5ca53cd,
+	0x6fcb4f74,
+	0x5dadde4b,
+	0x2ab63d38,
+	0x4bb3de30,
+	0x751f741c,
+	0x6c42effa,
+	0xefea7fce,
+	0x6ffc30be,
+	0xefec3fca,
+	0x30b3de2e,
+	0xadf85d9e,
+	0xaf7daefd,
+	0x5d9ede2e,
+	0x5d9eafdd,
+	0x761f10ac,
+	0x1da07efd,
+	0x30adfffe,
+	0x4908fb18,
+	0x5fffdfff,
+	0xafbb709b,
+	0x4ef85e67,
+	0xadf814ad,
+	0x7a0f70ad,
+	0xcfef50ad,
+	0x7a0fde30,
+	0x5da0afed,
+	0x3c12780f,
+	0xefef780f,
+	0xefef790f,
+	0xa7f85e0f,
+	0xffef790f,
+	0xefef790f,
+	0x14adde2e,
+	0x5d9eadfd,
+	0x5e2dfffb,
+	0xe79addfd,
+	0xeff96079,
+	0x607ae79a,
+	0xddfceff9,
+	0x60795dff,
+	0x607acfef,
+	0xefefefdf,
+	0xefbfef7f,
+	0xeeffedff,
+	0xebffe7ff,
+	0xafefafdf,
+	0xafbfaf7f,
+	0xaeffadff,
+	0xabffa7ff,
+	0x6fef6fdf,
+	0x6fbf6f7f,
+	0x6eff6dff,
+	0x6bff67ff,
+	0x2fef2fdf,
+	0x2fbf2f7f,
+	0x2eff2dff,
+	0x2bff27ff,
+	0x4e08fd1f,
+	0xe5ff6e0f,
+	0xaff87eef,
+	0x7e0ffdef,
+	0xf11f6079,
+	0xabf8f542,
+	0x7e0af11c,
+	0x37cfae3a,
+	0x7fec90be,
+	0xadf8efdc,
+	0xcfeae52f,
+	0x7d0fe12b,
+	0xf11c6079,
+	0x7e0a4df8,
+	0xcfea5dc4,
+	0x7d0befec,
+	0xcfea5dc6,
+	0xe522efdc,
+	0x5dc6cfda,
+	0x4e08fd1f,
+	0x6e0faff8,
+	0x7c1f761f,
+	0xfdeff91f,
+	0x6079abf8,
+	0x761cee24,
+	0xf91f2bfb,
+	0xefefcfec,
+	0xf91f6079,
+	0x761c27fb,
+	0xefdf5da7,
+	0xcfdc7fdd,
+	0xd09c4bf8,
+	0x47fd7c1f,
+	0x761ccfcf,
+	0x7eef7fed,
+	0x7dfdf093,
+	0xef7e7f1e,
+	0x771efb18,
+	0x6079e722,
+	0xe6bbe5bb,
+	0xae0ae5bb,
+	0x600bae85,
+	0xe2bbe2bb,
+	0xe2bbe2bb,
+	0xaf02e2bb,
+	0xe2bb2ff9,
+	0x6079e2bb
+};
+
+uint patch_2f00[] = {
+	0x30303030,
+	0x3e3e3434,
+	0xabbf9b99,
+	0x4b4fbdbd,
+	0x59949334,
+	0x9fff37fb,
+	0x9b177dd9,
+	0x936956bb,
+	0xfbdd697b,
+	0xdd2fd113,
+	0x1db9f7bb,
+	0x36313963,
+	0x79373369,
+	0x3193137f,
+	0x7331737a,
+	0xf7bb9b99,
+	0x9bb19795,
+	0x77fdfd3d,
+	0x573b773f,
+	0x737933f7,
+	0xb991d115,
+	0x31699315,
+	0x31531694,
+	0xbf4fbdbd,
+	0x35931497,
+	0x35376956,
+	0xbd697b9d,
+	0x96931313,
+	0x19797937,
+	0x6935af78,
+	0xb9b3baa3,
+	0xb8788683,
+	0x368f78f7,
+	0x87778733,
+	0x3ffffb3b,
+	0x8e8f78b8,
+	0x1d118e13,
+	0xf3ff3f8b,
+	0x6bd8e173,
+	0xd1366856,
+	0x68d1687b,
+	0x3daf78b8,
+	0x3a3a3f87,
+	0x8f81378f,
+	0xf876f887,
+	0x77fd8778,
+	0x737de8d6,
+	0xbbf8bfff,
+	0xd8df87f7,
+	0xfd876f7b,
+	0x8bfff8bd,
+	0x8683387d,
+	0xb873d87b,
+	0x3b8fd7f8,
+	0xf7338883,
+	0xbb8ee1f8,
+	0xef837377,
+	0x3337b836,
+	0x817d11f8,
+	0x7378b878,
+	0xd3368b7d,
+	0xed731b7d,
+	0x833731f3,
+	0xf22f3f23
+};
+
+uint patch_2e00[] = {
+	0x27eeeeee,
+	0xeeeeeeee,
+	0xeeeeeeee,
+	0xeeeeeeee,
+	0xee4bf4fb,
+	0xdbd259bb,
+	0x1979577f,
+	0xdfd2d573,
+	0xb773f737,
+	0x4b4fbdbd,
+	0x25b9b177,
+	0xd2d17376,
+	0x956bbfdd,
+	0x697bdd2f,
+	0xff9f79ff,
+	0xff9ff22f
+};
+#endif
+
+/*
+ *  USB SOF patch arrays.
+ */
+
+#ifdef CONFIG_USB_SOF_UCODE_PATCH
+
+uint patch_2000[] = {
+	0x7fff0000,
+	0x7ffd0000,
+	0x7ffb0000,
+	0x49f7ba5b,
+	0xba383ffb,
+	0xf9b8b46d,
+	0xe5ab4e07,
+	0xaf77bffe,
+	0x3f7bbf79,
+	0xba5bba38,
+	0xe7676076,
+	0x60750000
+};
+
+uint patch_2f00[] = {
+	0x3030304c,
+	0xcab9e441,
+	0xa1aaf220
+};
+#endif
+
+void
+cpm_load_patch(cpm8xx_t	*cp)
+{
+	volatile uint		*dp;		/* Dual-ported RAM. */
+	volatile cpm8xx_t	*commproc;
+	volatile iic_t		*iip;
+	volatile spi_t		*spp;
+	volatile smc_uart_t	*smp;
+	int	i;
+
+	commproc = cp;
+
+#ifdef CONFIG_USB_SOF_UCODE_PATCH
+	commproc->cp_rccr = 0;
+
+	dp = (uint *)(commproc->cp_dpmem);
+	for (i=0; i<(sizeof(patch_2000)/4); i++)
+		*dp++ = patch_2000[i];
+
+	dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
+	for (i=0; i<(sizeof(patch_2f00)/4); i++)
+		*dp++ = patch_2f00[i];
+
+	commproc->cp_rccr = 0x0009;
+
+	printk("USB SOF microcode patch installed\n");
+#endif /* CONFIG_USB_SOF_UCODE_PATCH */
+
+#if defined(CONFIG_I2C_SPI_UCODE_PATCH) || \
+    defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
+
+	commproc->cp_rccr = 0;
+
+	dp = (uint *)(commproc->cp_dpmem);
+	for (i=0; i<(sizeof(patch_2000)/4); i++)
+		*dp++ = patch_2000[i];
+
+	dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
+	for (i=0; i<(sizeof(patch_2f00)/4); i++)
+		*dp++ = patch_2f00[i];
+
+	iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC];
+# define RPBASE 0x0500
+	iip->iic_rpbase = RPBASE;
+
+	/* Put SPI above the IIC, also 32-byte aligned.
+	*/
+	i = (RPBASE + sizeof(iic_t) + 31) & ~31;
+	spp = (spi_t *)&commproc->cp_dparam[PROFF_SPI];
+	spp->spi_rpbase = i;
+
+# if defined(CONFIG_I2C_SPI_UCODE_PATCH)
+	commproc->cp_cpmcr1 = 0x802a;
+	commproc->cp_cpmcr2 = 0x8028;
+	commproc->cp_cpmcr3 = 0x802e;
+	commproc->cp_cpmcr4 = 0x802c;
+	commproc->cp_rccr = 1;
+
+	printk("I2C/SPI microcode patch installed.\n");
+# endif /* CONFIG_I2C_SPI_UCODE_PATCH */
+
+# if defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
+
+	dp = (uint *)&(commproc->cp_dpmem[0x0e00]);
+	for (i=0; i<(sizeof(patch_2e00)/4); i++)
+		*dp++ = patch_2e00[i];
+
+	commproc->cp_cpmcr1 = 0x8080;
+	commproc->cp_cpmcr2 = 0x808a;
+	commproc->cp_cpmcr3 = 0x8028;
+	commproc->cp_cpmcr4 = 0x802a;
+	commproc->cp_rccr = 3;
+
+	smp = (smc_uart_t *)&commproc->cp_dparam[PROFF_SMC1];
+	smp->smc_rpbase = 0x1FC0;
+
+	printk("I2C/SPI/SMC1 microcode patch installed.\n");
+# endif /* CONFIG_I2C_SPI_SMC1_UCODE_PATCH) */
+
+#endif /* some variation of the I2C/SPI patch was selected */
+}
+
+/*
+ *  Take this entire routine out, since no one calls it and its
+ * logic is suspect.
+ */
+
+#if 0
+void
+verify_patch(volatile immap_t *immr)
+{
+	volatile uint		*dp;
+	volatile cpm8xx_t	*commproc;
+	int i;
+
+	commproc = (cpm8xx_t *)&immr->im_cpm;
+
+	printk("cp_rccr %x\n", commproc->cp_rccr);
+	commproc->cp_rccr = 0;
+
+	dp = (uint *)(commproc->cp_dpmem);
+	for (i=0; i<(sizeof(patch_2000)/4); i++)
+		if (*dp++ != patch_2000[i]) {
+			printk("patch_2000 bad at %d\n", i);
+			dp--;
+			printk("found 0x%X, wanted 0x%X\n", *dp, patch_2000[i]);
+			break;
+		}
+
+	dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
+	for (i=0; i<(sizeof(patch_2f00)/4); i++)
+		if (*dp++ != patch_2f00[i]) {
+			printk("patch_2f00 bad at %d\n", i);
+			dp--;
+			printk("found 0x%X, wanted 0x%X\n", *dp, patch_2f00[i]);
+			break;
+		}
+
+	commproc->cp_rccr = 0x0009;
+}
+#endif
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
new file mode 100644
index 0000000..d15f0c1
--- /dev/null
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -0,0 +1,209 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+#include <asm/prom.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/8xx_immap.h>
+#include <asm/mpc8xx.h>
+
+#include "mpc8xx_pic.h"
+
+
+#define PIC_VEC_SPURRIOUS      15
+
+extern int cpm_get_irq(struct pt_regs *regs);
+
+static struct device_node *mpc8xx_pic_node;
+static struct irq_host *mpc8xx_pic_host;
+#define NR_MASK_WORDS   ((NR_IRQS + 31) / 32)
+static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+static sysconf8xx_t	*siu_reg;
+
+int cpm_get_irq(struct pt_regs *regs);
+
+static void mpc8xx_unmask_irq(unsigned int virq)
+{
+	int	bit, word;
+	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+
+	bit = irq_nr & 0x1f;
+	word = irq_nr >> 5;
+
+	ppc_cached_irq_mask[word] |= (1 << (31-bit));
+	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+}
+
+static void mpc8xx_mask_irq(unsigned int virq)
+{
+	int	bit, word;
+	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+
+	bit = irq_nr & 0x1f;
+	word = irq_nr >> 5;
+
+	ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
+	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+}
+
+static void mpc8xx_mask_and_ack(unsigned int virq)
+{
+	int	bit, word;
+	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+
+	bit = irq_nr & 0x1f;
+	word = irq_nr >> 5;
+
+	ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
+	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+	out_be32(&siu_reg->sc_sipend, 1 << (31-bit));
+}
+
+static void mpc8xx_end_irq(unsigned int virq)
+{
+	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
+			&& irq_desc[irq_nr].action) {
+		int bit, word;
+
+		bit = irq_nr & 0x1f;
+		word = irq_nr >> 5;
+
+		ppc_cached_irq_mask[word] |= (1 << (31-bit));
+		out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+	}
+}
+
+static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
+{
+       struct irq_desc *desc = get_irq_desc(virq);
+
+
+        desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
+        desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
+        if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+                desc->status |= IRQ_LEVEL;
+
+        if (flow_type & IRQ_TYPE_EDGE_FALLING) {
+		irq_hw_number_t hw = (unsigned int)irq_map[virq].hwirq;
+		unsigned int siel = in_be32(&siu_reg->sc_siel);
+                if ((hw & 1) == 0)
+                        siel |= (0x80000000 >> hw);
+                else
+                        siel &= ~(0x80000000 >> (hw & ~1));
+		out_be32(&siu_reg->sc_siel, siel);
+	}
+        return 0;
+}
+
+static struct irq_chip mpc8xx_pic = {
+	.typename = " MPC8XX SIU ",
+	.enable = mpc8xx_unmask_irq,
+	.disable = mpc8xx_mask_irq,
+	.unmask = mpc8xx_unmask_irq,
+	.mask_ack = mpc8xx_mask_and_ack,
+	.end = mpc8xx_end_irq,
+	.set_type = mpc8xx_set_irq_type,
+};
+
+unsigned int mpc8xx_get_irq(void)
+{
+	int irq;
+
+	/* For MPC8xx, read the SIVEC register and shift the bits down
+	 * to get the irq number.
+	 */
+	irq = in_be32(&siu_reg->sc_sivec) >> 26;
+
+	/*
+	 * When we read the sivec without an interrupt to process, we will
+	 * get back SIU_LEVEL7.  In this case, return -1
+	 */
+//        if (irq == CPM_INTERRUPT)
+//        	irq = CPM_IRQ_OFFSET + cpm_get_irq(regs);
+//	else
+		if (irq == PIC_VEC_SPURRIOUS)
+			irq = NO_IRQ;
+        return irq_linear_revmap(mpc8xx_pic_host, irq);
+
+//	return irq;
+}
+
+static int mpc8xx_pic_host_match(struct irq_host *h, struct device_node *node)
+{
+	return mpc8xx_pic_node == NULL || mpc8xx_pic_node == node;
+}
+
+static int mpc8xx_pic_host_map(struct irq_host *h, unsigned int virq,
+			  irq_hw_number_t hw)
+{
+	pr_debug("mpc8xx_pic_host_map(%d, 0x%lx)\n", virq, hw);
+
+	set_irq_chip_and_handler(virq, &mpc8xx_pic, handle_level_irq);
+	return 0;
+}
+
+static void mpc8xx_pic_host_unmap(struct irq_host *h, unsigned int virq)
+{
+	/* Make sure irq is masked in hardware */
+	mpc8xx_mask_irq(virq);
+
+	/* remove chip and handler */
+	set_irq_chip_and_handler(virq, NULL, NULL);
+}
+
+static int mpc8xx_pic_host_xlate(struct irq_host *h, struct device_node *ct,
+			    u32 *intspec, unsigned int intsize,
+			    irq_hw_number_t *out_hwirq, unsigned int *out_flags)
+{
+	static unsigned char map_pic_senses[4] = {
+		IRQ_TYPE_LEVEL_LOW,
+		IRQ_TYPE_LEVEL_HIGH,
+		IRQ_TYPE_EDGE_FALLING,
+		IRQ_TYPE_EDGE_RISING,
+	};
+
+	*out_hwirq = intspec[0];
+	if (intsize > 1 && intspec[1] < 4)
+		*out_flags = map_pic_senses[intspec[1]];
+	else
+		*out_flags = IRQ_TYPE_NONE;
+
+	return 0;
+}
+
+static struct irq_host_ops mpc8xx_pic_host_ops = {
+	.match = mpc8xx_pic_host_match,
+	.map = mpc8xx_pic_host_map,
+	.unmap = mpc8xx_pic_host_unmap,
+	.xlate = mpc8xx_pic_host_xlate,
+};
+
+void mpc8xx_pic_init(struct device_node *np)
+{
+	struct resource res;
+	int ret;
+
+	/* create a legacy host */
+	if (np)
+		mpc8xx_pic_node = of_node_get(np);
+
+	ret = of_address_to_resource(np, 0, &res);
+	if (ret)
+		return;
+
+	siu_reg = (void *)ioremap(res.start, res.end - res.start + 1);
+	if (siu_reg == NULL)
+		return;
+
+	mpc8xx_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &mpc8xx_pic_host_ops, 64);
+	if (mpc8xx_pic_host == NULL) {
+		printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");
+	}
+}
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.h b/arch/powerpc/sysdev/mpc8xx_pic.h
new file mode 100644
index 0000000..c94d3f5
--- /dev/null
+++ b/arch/powerpc/sysdev/mpc8xx_pic.h
@@ -0,0 +1,12 @@
+#ifndef _PPC_KERNEL_MPC8xx_H
+#define _PPC_KERNEL_MPC8xx_H
+
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+extern struct hw_interrupt_type mpc8xx_pic;
+
+void mpc8xx_pic_init(struct device_node *node);
+unsigned int mpc8xx_get_irq(void);
+
+#endif /* _PPC_KERNEL_PPC8xx_H */
diff --git a/include/asm-powerpc/fs_pd.h b/include/asm-powerpc/fs_pd.h
index 3d0e819..4c3af35 100644
--- a/include/asm-powerpc/fs_pd.h
+++ b/include/asm-powerpc/fs_pd.h
@@ -11,19 +11,11 @@
 
 #ifndef FS_PD_H
 #define FS_PD_H
-#include <asm/cpm2.h>
 #include <sysdev/fsl_soc.h>
 #include <asm/time.h>
 
-static inline int uart_baudrate(void)
-{
-        return get_baudrate();
-}
-
-static inline int uart_clock(void)
-{
-        return ppc_proc_freq;
-}
+#ifdef CONFIG_CPM2
+#include <asm/cpm2.h>
 
 #define cpm2_map(member)						\
 ({									\
@@ -41,5 +33,37 @@ ({									\
 })
 
 #define cpm2_unmap(addr)	iounmap(addr)
+#endif
+
+#ifdef CONFIG_8xx
+#include <asm/8xx_immap.h>
+
+#define immr_map(member)						\
+({									\
+	u32 offset = offsetof(immap_t, member);				\
+	void *addr = ioremap (IMAP_ADDR + offset,			\
+			      sizeof( ((immap_t*)0)->member));		\
+	addr;								\
+})
+
+#define immr_map_size(member, size)					\
+({									\
+	u32 offset = offsetof(immap_t, member);				\
+	void *addr = ioremap (IMAP_ADDR + offset, size);		\
+	addr;								\
+})
+
+#define immr_unmap(addr)		iounmap(addr)
+#endif
+
+static inline int uart_baudrate(void)
+{
+        return get_baudrate();
+}
+
+static inline int uart_clock(void)
+{
+        return ppc_proc_freq;
+}
 
 #endif
diff --git a/include/asm-powerpc/mpc8xx.h b/include/asm-powerpc/mpc8xx.h
new file mode 100644
index 0000000..58eb15d
--- /dev/null
+++ b/include/asm-powerpc/mpc8xx.h
@@ -0,0 +1,38 @@
+/* This is the single file included by all MPC8xx build options.
+ * Since there are many different boards and no standard configuration,
+ * we have a unique include file for each.  Rather than change every
+ * file that has to include MPC8xx configuration, they all include
+ * this one and the configuration switching is done here.
+ */
+#ifdef __KERNEL__
+#ifndef __CONFIG_8xx_DEFS
+#define __CONFIG_8xx_DEFS
+
+
+#ifdef CONFIG_8xx
+
+#ifdef CONFIG_FADS
+#include <platforms/fads.h>
+#endif
+
+#if defined(CONFIG_MPC885ADS)
+#include <platforms/8xx/mpc885ads.h>
+#endif
+
+/* Currently, all 8xx boards that support a processor to PCI/ISA bridge
+ * use the same memory map.
+ */
+#if !defined(_IO_BASE)  /* defined in board specific header */
+#define _IO_BASE        0
+#endif
+#define _ISA_MEM_BASE   0
+#define PCI_DRAM_OFFSET 0
+
+#ifndef __ASSEMBLY__
+//struct pt_regs;
+//#define PPC_PIN_SIZE	(24 * 1024 * 1024)	/* 24Mbytes of data pinned */
+#endif /* !__ASSEMBLY__ */
+
+#endif /* CONFIG_8xx */
+#endif /* __CONFIG_8xx_DEFS */
+#endif /* __KERNEL__ */

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 5/5] [POWERPC] 8xx: Add mpc885ads support and common mpc8xx.
       [not found] <20061114012504.17455.13833.stgit@localhost.localdomain>
                   ` (3 preceding siblings ...)
  2006-11-14  1:28 ` [PATCH 4/5] [POWERPC] 8xx: powerpc port of core CPM, CPM PIC, etc Vitaly Bordug
@ 2006-11-14  1:28 ` Vitaly Bordug
  2006-11-14  2:47   ` Benjamin Herrenschmidt
  4 siblings, 1 reply; 17+ messages in thread
From: Vitaly Bordug @ 2006-11-14  1:28 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev


This adds the core 8xx stuff and specifically mpc885ads board-specific
bits to arch/powerpc. Respective Kconfig has been cleaned up from the stuff
not yet ported over to avoid confusion.

Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com>
---

 arch/powerpc/boot/dts/mpc885ads.dts          |  195 ++++++
 arch/powerpc/configs/mpc885_ads_defconfig    |  827 ++++++++++++++++++++++++++
 arch/powerpc/platforms/8xx/Kconfig           |  267 --------
 arch/powerpc/platforms/8xx/Makefile          |    5 
 arch/powerpc/platforms/8xx/m8xx_setup.c      |  327 ++++++++++
 arch/powerpc/platforms/8xx/mpc885ads.h       |   95 +++
 arch/powerpc/platforms/8xx/mpc885ads_setup.c |  365 +++++++++++
 arch/powerpc/platforms/Makefile              |    1 
 8 files changed, 1825 insertions(+), 257 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts
new file mode 100644
index 0000000..e5b0c48
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc885ads.dts
@@ -0,0 +1,195 @@
+/*
+ * MPC885 ADS Device Tree Source
+ *
+ * Copyright 2006 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+
+{
+	model = "MPC885ADS";
+	compatible = "mpc8xx";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	linux,phandle = <100>;
+
+	cpus {
+		#cpus = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		linux,phandle = <200>;
+
+		PowerPC,885@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <20>;	// 32 bytes
+			i-cache-line-size = <20>;	// 32 bytes
+			d-cache-size = <2000>;		// L1, 8K
+			i-cache-size = <2000>;		// L1, 8K
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+			32-bit;
+			interrupts = <f 2>;	// decrementer interrupt
+			interrupt-parent = <ff000000>;
+			linux,phandle = <201>;
+			linux,boot-cpu;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		linux,phandle = <300>;
+		reg = <00000000 800000>;
+	};
+
+	flash@fe000000 {
+		device_type = "mtd";
+		compatible = "physmap";
+		reg = <fe000000 00800000>;
+		bank-width = <4>;
+		partitions = <00000000 00080001
+				00080000 00780000>;
+		partition-names = "firmware\0fs";
+	};
+
+	soc885@ff000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		device_type = "soc";
+		ranges = <0 ff000000 00100000>;
+		reg = <ff000000 00000200>;
+		bus-frequency = <0>;
+		mdio@e80 {
+			device_type = "mdio";
+			compatible = "fs_enet";
+			reg = <e80 8>;
+			linux,phandle = <e80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ethernet-phy@0 {
+				linux,phandle = <e8000>;
+				reg = <0>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@1 {
+				linux,phandle = <e8001>;
+				reg = <1>;
+				device_type = "ethernet-phy";
+			};
+			ethernet-phy@2 {
+				linux,phandle = <e8002>;
+				reg = <2>;
+				device_type = "ethernet-phy";
+			};
+		};
+
+		fec@e00 {
+			device_type = "network";
+			compatible = "fs_enet";
+			model = "FEC";
+			device-id = <1>;
+			reg = <e00 188>;
+			mac-address = [ 00 00 0C 00 01 FD ];
+			interrupts = <3 2>;
+			interrupt-parent = <ff000000>;
+			phy-handle = <e8000>;
+		};
+
+		fec@1e00 {
+			device_type = "network";
+			compatible = "fs_enet";
+			model = "FEC";
+			device-id = <2>;
+			reg = <1e00 188>;
+			mac-address = [ 00 00 0C 00 02 FD ];
+			interrupts = <7 2>;
+			interrupt-parent = <ff000000>;
+			phy-handle = <e8001>;
+		};
+		
+		pic@ff000000 {
+			linux,phandle = <ff000000>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0 24>;
+			built-in;
+			device_type = "mpc8xx-pic";
+			compatible = "CPM"; 
+		};
+		
+		cpm@ff000000 {
+			linux,phandle = <ff000000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			#interrupt-cells = <2>;
+			device_type = "cpm";
+			model = "CPM";
+			ranges = <0 0 4000>;
+			reg = <860 f0>;
+			command-proc = <9c0>;
+			brg-frequency = <0>;
+			interrupts = <0 2>;	// cpm error interrupt
+			interrupt-parent = <930>;
+
+			pic@930 {
+				linux,phandle = <930>;
+				interrupt-controller;
+				#address-cells = <0>;
+				#interrupt-cells = <2>;
+				interrupts = <5 2 0 2>;
+				interrupt-parent = <ff000000>;
+				reg = <930 20>;
+				built-in;
+				device_type = "cpm-pic";
+				compatible = "CPM"; 
+			};
+
+			smc@a80 {
+				device_type = "serial";
+				compatible = "cpm_uart";
+				model = "SMC";
+				device-id = <1>;
+				reg = <a80 10 3e80 40>;
+				clock-setup = <00ffffff 0>;
+				rx-clock = <1>;
+				tx-clock = <1>;
+				current-speed = <0>;
+				interrupts = <4 3>;
+				interrupt-parent = <930>;
+			};
+
+			smc@a90 {
+				device_type = "serial";
+				compatible = "cpm_uart";
+				model = "SMC";
+				device-id = <2>;
+				reg = <a90 20 3f80 40>;
+				clock-setup = <ff00ffff 90000>;
+				rx-clock = <2>;
+				tx-clock = <2>;
+				current-speed = <0>;
+				interrupts = <3 3>;
+				interrupt-parent = <930>;
+			};
+			scc@a40 {
+				device_type = "network";
+				compatible = "fs_enet";
+				model = "SCC";
+				device-id = <3>;
+				reg = <a40 18 3e00 80>;
+				mac-address = [ 00 00 0C 00 03 FD ];
+				interrupts = <1c 3>;
+				interrupt-parent = <930>;
+				phy-handle = <e8002>;
+			};
+		};
+
+	};
+};
diff --git a/arch/powerpc/configs/mpc885_ads_defconfig b/arch/powerpc/configs/mpc885_ads_defconfig
new file mode 100644
index 0000000..e2c17d8
--- /dev/null
+++ b/arch/powerpc/configs/mpc885_ads_defconfig
@@ -0,0 +1,827 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.19-rc4
+# Fri Nov 10 21:30:40 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_IRQ_PER_CPU=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+# CONFIG_PPC_UDBG_16550 is not set
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_PPC_86xx is not set
+CONFIG_PPC_8xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_E200 is not set
+CONFIG_8xx=y
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+# CONFIG_BUG is not set
+CONFIG_ELF_CORE=y
+# CONFIG_BASE_FULL is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=1
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_WANT_EARLY_SERIAL is not set
+CONFIG_EMBEDDEDBOOT=y
+# CONFIG_MPIC is not set
+
+#
+# Platform support
+#
+CONFIG_CPM1=y
+# CONFIG_MPC8XXFADS is not set
+# CONFIG_MPC86XADS is not set
+CONFIG_MPC885ADS=y
+
+#
+# MPC8xx CPM Options
+#
+
+#
+# Generic MPC8xx Options
+#
+CONFIG_8xx_COPYBACK=y
+# CONFIG_8xx_CPU6 is not set
+CONFIG_NO_UCODE_PATCH=y
+# CONFIG_USB_SOF_UCODE_PATCH is not set
+# CONFIG_I2C_SPI_UCODE_PATCH is not set
+# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_MATH_EMULATION=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+# CONFIG_PROC_DEVICETREE is not set
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
+CONFIG_FSL_SOC=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+# CONFIG_PCI_QSPAN is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_CONSISTENT_START=0xff100000
+CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_BOOT_LOAD=0x00400000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+CONFIG_DAVICOM_PHY=y
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+CONFIG_FIXED_PHY=y
+CONFIG_FIXED_MII_10_FDX=y
+# CONFIG_FIXED_MII_100_FDX is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_FEC_8XX is not set
+CONFIG_FS_ENET=y
+CONFIG_FS_ENET_HAS_SCC=y
+CONFIG_FS_ENET_HAS_FEC=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_CPM=y
+CONFIG_SERIAL_CPM_CONSOLE=y
+# CONFIG_SERIAL_CPM_SCC1 is not set
+# CONFIG_SERIAL_CPM_SCC2 is not set
+# CONFIG_SERIAL_CPM_SCC3 is not set
+# CONFIG_SERIAL_CPM_SCC4 is not set
+CONFIG_SERIAL_CPM_SMC1=y
+CONFIG_SERIAL_CPM_SMC2=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
index c8c0ba3..b65f0a0 100644
--- a/arch/powerpc/platforms/8xx/Kconfig
+++ b/arch/powerpc/platforms/8xx/Kconfig
@@ -1,105 +1,17 @@
+menu "Platform support"
+        depends on PPC_8xx
+
 config FADS
 	bool
 
+config CPM1
+	bool
+
 choice
 	prompt "8xx Machine Type"
 	depends on 8xx
-	default RPXLITE
-
-config RPXLITE
-	bool "RPX-Lite"
-	---help---
-	  Single-board computers based around the PowerPC MPC8xx chips and
-	  intended for embedded applications.  The following types are
-	  supported:
-
-	  RPX-Lite:
-	  Embedded Planet RPX Lite. PC104 form-factor SBC based on the MPC823.
-
-	  RPX-Classic:
-	  Embedded Planet RPX Classic Low-fat. Credit-card-size SBC based on
-	  the MPC 860
-
-	  BSE-IP:
-	  Bright Star Engineering ip-Engine.
-
-	  TQM823L:
-	  TQM850L:
-	  TQM855L:
-	  TQM860L:
-	  MPC8xx based family of mini modules, half credit card size,
-	  up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports,
-	  2 x CAN bus interface, ...
-	  Manufacturer: TQ Components, www.tq-group.de
-	  Date of Release: October (?) 1999
-	  End of Life: not yet :-)
-	  URL:
-	  - module: <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>
-	  - starter kit: <http://www.denx.de/PDF/STK8xxLHWM201.pdf>
-	  - images: <http://www.denx.de/embedded-ppc-en.html>
-
-	  FPS850L:
-	  FingerPrint Sensor System (based on TQM850L)
-	  Manufacturer: IKENDI AG, <http://www.ikendi.com/>
-	  Date of Release: November 1999
-	  End of life: end 2000 ?
-	  URL: see TQM850L
-
-	  IVMS8:
-	  MPC860 based board used in the "Integrated Voice Mail System",
-	  Small Version (8 voice channels)
-	  Manufacturer: Speech Design, <http://www.speech-design.de/>
-	  Date of Release: December 2000 (?)
-	  End of life: -
-	  URL: <http://www.speech-design.de/>
-
-	  IVML24:
-	  MPC860 based board used in the "Integrated Voice Mail System",
-	  Large Version (24 voice channels)
-	  Manufacturer: Speech Design, <http://www.speech-design.de/>
-	  Date of Release: March 2001  (?)
-	  End of life: -
-	  URL: <http://www.speech-design.de/>
-
-	  HERMES:
-	  Hermes-Pro ISDN/LAN router with integrated 8 x hub
-	  Manufacturer: Multidata Gesellschaft fur Datentechnik und Informatik
-	  <http://www.multidata.de/>
-	  Date of Release: 2000 (?)
-	  End of life: -
-	  URL: <http://www.multidata.de/english/products/hpro.htm>
-
-	  IP860:
-	  VMEBus IP (Industry Pack) carrier board with MPC860
-	  Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
-	  Date of Release: ?
-	  End of life: -
-	  URL: <http://www.microsys.de/html/ip860.html>
-
-	  PCU_E:
-	  PCU = Peripheral Controller Unit, Extended
-	  Manufacturer: Siemens AG, ICN (Information and Communication Networks)
-	  	<http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html>
-	  Date of Release: April 2001
-	  End of life: August 2001
-	  URL: n. a.
-
-config RPXCLASSIC
-	bool "RPX-Classic"
-	help
-	  The RPX-Classic is a single-board computer based on the Motorola
-	  MPC860.  It features 16MB of DRAM and a variable amount of flash,
-	  I2C EEPROM, thermal monitoring, a PCMCIA slot, a DIP switch and two
-	  LEDs.  Variants with Ethernet ports exist.  Say Y here to support it
-	  directly.
+	default MPC885ADS
 
-config BSEIP
-	bool "BSE-IP"
-	help
-	  Say Y here to support the Bright Star Engineering ipEngine SBC.
-	  This is a credit-card-sized device featuring a MPC823 processor,
-	  26MB DRAM, 4MB flash, Ethernet, a 16K-gate FPGA, USB, an LCD/video
-	  controller, and two RS232 ports.
 
 config MPC8XXFADS
 	bool "FADS"
@@ -115,103 +27,17 @@ config MPC86XADS
 
 config MPC885ADS
 	bool "MPC885ADS"
+	select CPM1
 	help
 	  Freescale Semiconductor MPC885 Application Development System (ADS).
 	  Also known as DUET.
 	  The MPC885ADS is meant to serve as a platform for s/w and h/w
 	  development around the MPC885 processor family.
 
-config TQM823L
-	bool "TQM823L"
-	help
-	  Say Y here to support the TQM823L, one of an MPC8xx-based family of
-	  mini SBCs (half credit-card size) from TQ Components first released
-	  in late 1999.  Technical references are at
-	  <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
-	  <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
-	  <http://www.denx.de/embedded-ppc-en.html>.
-
-config TQM850L
-	bool "TQM850L"
-	help
-	  Say Y here to support the TQM850L, one of an MPC8xx-based family of
-	  mini SBCs (half credit-card size) from TQ Components first released
-	  in late 1999.  Technical references are at
-	  <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
-	  <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
-	  <http://www.denx.de/embedded-ppc-en.html>.
-
-config TQM855L
-	bool "TQM855L"
-	help
-	  Say Y here to support the TQM855L, one of an MPC8xx-based family of
-	  mini SBCs (half credit-card size) from TQ Components first released
-	  in late 1999.  Technical references are at
-	  <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
-	  <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
-	  <http://www.denx.de/embedded-ppc-en.html>.
-
-config TQM860L
-	bool "TQM860L"
-	help
-	  Say Y here to support the TQM860L, one of an MPC8xx-based family of
-	  mini SBCs (half credit-card size) from TQ Components first released
-	  in late 1999.  Technical references are at
-	  <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
-	  <http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
-	  <http://www.denx.de/embedded-ppc-en.html>.
-
-config FPS850L
-	bool "FPS850L"
-
-config IVMS8
-	bool "IVMS8"
-	help
-	  Say Y here to support the Integrated Voice-Mail Small 8-channel SBC
-	  from Speech Design, released March 2001.  The manufacturer's website
-	  is at <http://www.speech-design.de/>.
-
-config IVML24
-	bool "IVML24"
-	help
-	  Say Y here to support the Integrated Voice-Mail Large 24-channel SBC
-	  from Speech Design, released March 2001.  The manufacturer's website
-	  is at <http://www.speech-design.de/>.
-
-config HERMES_PRO
-	bool "HERMES"
-
-config IP860
-	bool "IP860"
-
-config LWMON
-	bool "LWMON"
-
-config PCU_E
-	bool "PCU_E"
-
-config CCM
-	bool "CCM"
-
-config LANTEC
-	bool "LANTEC"
-
-config MBX
-	bool "MBX"
-	help
-	  MBX is a line of Motorola single-board computer based around the
-	  MPC821 and MPC860 processors, and intended for embedded-controller
-	  applications.  Say Y here to support these boards directly.
-
-config WINCEPT
-	bool "WinCept"
-	help
-	  The Wincept 100/110 is a Motorola single-board computer based on the
-	  MPC821 PowerPC, introduced in 1998 and designed to be used in
-	  thin-client machines.  Say Y to support it directly.
-
 endchoice
 
+endmenu
+
 #
 # MPC8xx Communication options
 #
@@ -219,79 +45,6 @@ #
 menu "MPC8xx CPM Options"
 	depends on 8xx
 
-config SCC_ENET
-	bool "CPM SCC Ethernet"
-	depends on NET_ETHERNET
-	help
-	  Enable Ethernet support via the Motorola MPC8xx serial
-	  communications controller.
-
-choice
-	prompt "SCC used for Ethernet"
-	depends on SCC_ENET
-	default SCC1_ENET
-
-config SCC1_ENET
-	bool "SCC1"
-	help
-	  Use MPC8xx serial communications controller 1 to drive Ethernet
-	  (default).
-
-config SCC2_ENET
-	bool "SCC2"
-	help
-	  Use MPC8xx serial communications controller 2 to drive Ethernet.
-
-config SCC3_ENET
-	bool "SCC3"
-	help
-	  Use MPC8xx serial communications controller 3 to drive Ethernet.
-
-endchoice
-
-config FEC_ENET
-	bool "860T FEC Ethernet"
-	depends on NET_ETHERNET
-	help
-	  Enable Ethernet support via the Fast Ethernet Controller (FCC) on
-	  the Motorola MPC8260.
-
-config USE_MDIO
-	bool "Use MDIO for PHY configuration"
-	depends on FEC_ENET
-	help
-	  On some boards the hardware configuration of the ethernet PHY can be
-	  used without any software interaction over the MDIO interface, so
-	  all MII code can be omitted. Say N here if unsure or if you don't
-	  need link status reports.
-
-config  FEC_AM79C874
-	bool "Support AMD79C874 PHY"
-	depends on USE_MDIO
-
-config FEC_LXT970
-	bool "Support LXT970 PHY"
-	depends on USE_MDIO
-
-config FEC_LXT971
-	bool "Support LXT971 PHY"
-	depends on USE_MDIO
-	
-config FEC_QS6612
-	bool "Support QS6612 PHY"
-	depends on USE_MDIO
-	
-config ENET_BIG_BUFFERS
-	bool "Use Big CPM Ethernet Buffers"
-	depends on SCC_ENET || FEC_ENET
-	help
-	  Allocate large buffers for MPC8xx Ethernet. Increases throughput
-	  and decreases the likelihood of dropped packets, but costs memory.
-
-config HTDMSOUND
-	bool "Embedded Planet HIOX Audio"
-	depends on SOUND=y
-
 # This doesn't really belong here, but it is convenient to ask
 # 8xx specific questions.
 comment "Generic MPC8xx Options"
diff --git a/arch/powerpc/platforms/8xx/Makefile b/arch/powerpc/platforms/8xx/Makefile
new file mode 100644
index 0000000..1b59ffa
--- /dev/null
+++ b/arch/powerpc/platforms/8xx/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the PowerPC 8xx linux kernel.
+#
+obj-$(CONFIG_PPC_8xx)	  += m8xx_setup.o
+obj-$(CONFIG_MPC885ADS)   += mpc885ads_setup.o
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
new file mode 100644
index 0000000..3e73103
--- /dev/null
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -0,0 +1,327 @@
+/*
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *  Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net)
+ *  Further modified for generic 8xx by Dan.
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/ioport.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+
+#include <asm/mmu.h>
+#include <asm/reg.h>
+#include <asm/residual.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/mpc8xx.h>
+#include <asm/8xx_immap.h>
+#include <asm/machdep.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+#include <asm/prom.h>
+#include <asm/fs_pd.h>
+#include <mm/mmu_decl.h>
+
+#include "sysdev/mpc8xx_pic.h"
+
+void m8xx_calibrate_decr(void);
+extern void m8xx_wdt_handler_install(bd_t *bp);
+extern int cpm_pic_init(void);
+extern int cpm_get_irq(void);
+
+/* A place holder for time base interrupts, if they are ever enabled. */
+irqreturn_t timebase_interrupt(int irq, void * dev)
+{
+	printk ("timebase_interrupt()\n");
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction tbint_irqaction = {
+	.handler = timebase_interrupt,
+	.mask = CPU_MASK_NONE,
+	.name = "tbint",
+};
+
+/* per-board overridable init_internal_rtc() function. */
+void __init __attribute__ ((weak))
+init_internal_rtc(void)
+{
+	sit8xx_t *sys_tmr = (sit8xx_t *) immr_map(im_sit);
+
+	/* Disable the RTC one second and alarm interrupts. */
+	clrbits16(&sys_tmr->sit_rtcsc, (RTCSC_SIE | RTCSC_ALE));
+
+	/* Enable the RTC */
+	setbits16(&sys_tmr->sit_rtcsc, (RTCSC_RTF | RTCSC_RTE));
+	immr_unmap(sys_tmr);
+}
+
+static int __init get_freq(char *name, unsigned long *val)
+{
+        struct device_node *cpu;
+        unsigned int *fp;
+        int found = 0;
+
+        /* The cpu node should have timebase and clock frequency properties */
+        cpu = of_find_node_by_type(NULL, "cpu");
+
+        if (cpu) {
+                fp = (unsigned int *)get_property(cpu, name, NULL);
+                if (fp) {
+                        found = 1;
+                        *val = *fp++;
+                }
+
+                of_node_put(cpu);
+        }
+
+        return found;
+}
+
+/* The decrementer counts at the system (internal) clock frequency divided by
+ * sixteen, or external oscillator divided by four.  We force the processor
+ * to use system clock divided by sixteen.
+ */
+void __init mpc8xx_calibrate_decr(void)
+{
+	struct device_node *cpu;
+	cark8xx_t *clk_r1;
+	car8xx_t *clk_r2;
+	sitk8xx_t *sys_tmr1;
+	sit8xx_t *sys_tmr2;
+	int irq, virq;
+
+        clk_r1 = (cark8xx_t *) immr_map(im_clkrstk);
+
+	/* Unlock the SCCR. */
+	out_be32(&clk_r1->cark_sccrk, ~KAPWR_KEY);
+	out_be32(&clk_r1->cark_sccrk, KAPWR_KEY);
+	immr_unmap(clk_r1);
+
+	/* Force all 8xx processors to use divide by 16 processor clock. */
+        clk_r2 = (car8xx_t *) immr_map(im_clkrst);
+	setbits32(&clk_r2->car_sccr, 0x02000000);
+	immr_unmap(clk_r2);
+
+	/* Processor frequency is MHz.
+	 */
+        ppc_tb_freq = 50000000;
+        if (!get_freq("bus-frequency", &ppc_tb_freq)) {
+                printk(KERN_ERR "WARNING: Estimating decrementer frequency "
+                                "(not found)\n");
+        }
+        ppc_tb_freq /= 16;
+        ppc_proc_freq = 50000000;
+        if (!get_freq("clock-frequency", &ppc_proc_freq))
+                printk(KERN_ERR "WARNING: Estimating processor frequency"
+                                "(not found)\n");
+
+        printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq);
+
+	/* Perform some more timer/timebase initialization.  This used
+	 * to be done elsewhere, but other changes caused it to get
+	 * called more than once....that is a bad thing.
+	 *
+	 * First, unlock all of the registers we are going to modify.
+	 * To protect them from corruption during power down, registers
+	 * that are maintained by keep alive power are "locked".  To
+	 * modify these registers we have to write the key value to
+	 * the key location associated with the register.
+	 * Some boards power up with these unlocked, while others
+	 * are locked.  Writing anything (including the unlock code?)
+	 * to the unlocked registers will lock them again.  So, here
+	 * we guarantee the registers are locked, then we unlock them
+	 * for our use.
+	 */
+        sys_tmr1 = (sitk8xx_t *) immr_map(im_sitk);
+	out_be32(&sys_tmr1->sitk_tbscrk, ~KAPWR_KEY);
+	out_be32(&sys_tmr1->sitk_rtcsck, ~KAPWR_KEY);
+	out_be32(&sys_tmr1->sitk_tbk, ~KAPWR_KEY);
+	out_be32(&sys_tmr1->sitk_tbscrk, KAPWR_KEY);
+	out_be32(&sys_tmr1->sitk_rtcsck, KAPWR_KEY);
+	out_be32(&sys_tmr1->sitk_tbk, KAPWR_KEY);
+	immr_unmap(sys_tmr1);
+
+	init_internal_rtc();
+
+	/* Enabling the decrementer also enables the timebase interrupts
+	 * (or from the other point of view, to get decrementer interrupts
+	 * we have to enable the timebase).  The decrementer interrupt
+	 * is wired into the vector table, nothing to do here for that.
+	 */
+        cpu = of_find_node_by_type(NULL, "cpu");
+        virq= irq_of_parse_and_map(cpu, 0);
+	irq = irq_map[virq].hwirq;
+
+	sys_tmr2 = (sit8xx_t *) immr_map(im_sit);
+	out_be16(&sys_tmr2->sit_tbscr, ((1 << (7 - (irq/2))) << 8) |
+					(TBSCR_TBF | TBSCR_TBE));
+	immr_unmap(sys_tmr2);
+
+	if (setup_irq(virq, &tbint_irqaction))
+		panic("Could not allocate timer IRQ!");
+
+#ifdef CONFIG_8xx_WDT
+	/* Install watchdog timer handler early because it might be
+	 * already enabled by the bootloader
+	 */
+	m8xx_wdt_handler_install(binfo);
+#endif
+}
+
+/* The RTC on the MPC8xx is an internal register.
+ * We want to protect this during power down, so we need to unlock,
+ * modify, and re-lock.
+ */
+
+int mpc8xx_set_rtc_time(struct rtc_time *tm)
+{
+	sitk8xx_t *sys_tmr1;
+	sit8xx_t *sys_tmr2;
+	int time;
+
+        sys_tmr1 = (sitk8xx_t *) immr_map(im_sitk);
+	sys_tmr2 = (sit8xx_t *) immr_map(im_sit);
+	time = mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
+                      tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	out_be32(&sys_tmr1->sitk_rtck, KAPWR_KEY);
+	out_be32(&sys_tmr2->sit_rtc, time);
+	out_be32(&sys_tmr1->sitk_rtck, ~KAPWR_KEY);
+
+	immr_unmap(sys_tmr2);
+	immr_unmap(sys_tmr1);
+	return 0;
+}
+
+void mpc8xx_get_rtc_time(struct rtc_time *tm)
+{
+	unsigned long data;
+	sit8xx_t *sys_tmr = (sit8xx_t *) immr_map(im_sit);
+
+	/* Get time from the RTC. */
+	data = in_be32(&sys_tmr->sit_rtc);
+	to_tm(data, tm);
+        tm->tm_year -= 1900;
+        tm->tm_mon -= 1;
+	immr_unmap(sys_tmr);
+	return;
+}
+
+void mpc8xx_restart(char *cmd)
+{
+	__volatile__ unsigned char dummy;
+	car8xx_t * clk_r = (car8xx_t *) immr_map(im_clkrst);
+
+
+	local_irq_disable();
+
+	setbits32(&clk_r->car_plprcr, 0x00000080);
+	/* Clear the ME bit in MSR to cause checkstop on machine check
+	*/
+	mtmsr(mfmsr() & ~0x1000);
+
+	dummy = in_8(&clk_r->res[0]);
+	printk("Restart failed\n");
+	while(1);
+}
+
+void mpc8xx_show_cpuinfo(struct seq_file *m)
+{
+	struct device_node *root;
+	uint memsize = total_memory;
+	const char *model = "";
+
+	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+
+	root = of_find_node_by_path("/");
+	if (root)
+		model = get_property(root, "model", NULL);
+	seq_printf(m, "Machine\t\t: %s\n", model);
+	of_node_put(root);
+
+	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+}
+
+static void cpm_cascade(unsigned int irq, struct irq_desc *desc)
+{
+	int cascade_irq;
+
+	if ((cascade_irq = cpm_get_irq()) >= 0) {
+		struct irq_desc *cdesc = irq_desc + cascade_irq;
+
+		generic_handle_irq(cascade_irq);
+		cdesc->chip->end(cascade_irq);
+	}
+	desc->chip->end(irq);
+}
+
+/* Initialize the internal interrupt controller.  The number of
+ * interrupts supported can vary with the processor type, and the
+ * 82xx family can have up to 64.
+ * External interrupts can be either edge or level triggered, and
+ * need to be initialized by the appropriate driver.
+ */
+void __init m8xx_pic_init(void)
+{
+	struct resource r;
+	struct device_node *np = NULL;
+	int irq;
+
+	np = of_find_node_by_type(np, "mpc8xx-pic");
+
+	if (np == NULL) {
+		printk(KERN_ERR "Could not find open-pic node\n");
+		return;
+	}
+
+	if (of_address_to_resource(np, 0, &r)) {
+		printk(KERN_ERR "Could not map mpic register space\n");
+		of_node_put(np);
+		return;
+	}
+	mpc8xx_pic_init(np);
+
+	irq = cpm_pic_init();
+	if (irq != NO_IRQ)
+		set_irq_chained_handler(irq, cpm_cascade);
+}
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+int __init mpc8xx_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "mpc8xx"))
+		return 1;
+
+	return 0;
+}
diff --git a/arch/powerpc/platforms/8xx/mpc885ads.h b/arch/powerpc/platforms/8xx/mpc885ads.h
new file mode 100644
index 0000000..30cbebf
--- /dev/null
+++ b/arch/powerpc/platforms/8xx/mpc885ads.h
@@ -0,0 +1,95 @@
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Freescale MPC885ADS board.
+ * Copied from the FADS stuff.
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * 2005 (c) MontaVista Software, Inc.  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.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_MPC885ADS_H__
+#define __ASM_MPC885ADS_H__
+
+#include <asm/ppcboot.h>
+#include <sysdev/fsl_soc.h>
+
+/* U-Boot maps BCSR to 0xff080000 */
+#define BCSR_ADDR		((uint)0xff080000)
+#define BCSR_SIZE		((uint)32)
+#define BCSR0			((uint)(BCSR_ADDR + 0x00))
+#define BCSR1			((uint)(BCSR_ADDR + 0x04))
+#define BCSR2			((uint)(BCSR_ADDR + 0x08))
+#define BCSR3			((uint)(BCSR_ADDR + 0x0c))
+#define BCSR4			((uint)(BCSR_ADDR + 0x10))
+
+#define CFG_PHYDEV_ADDR		((uint)0xff0a0000)
+#define BCSR5			((uint)(CFG_PHYDEV_ADDR + 0x300))
+
+#define IMAP_ADDR		(get_immrbase())
+#define IMAP_SIZE		((uint)(64 * 1024))
+
+#define MPC8xx_CPM_OFFSET	(0x9c0)
+#define CPM_MAP_ADDR		(get_immrbase() + MPC8xx_CPM_OFFSET)
+#define CPM_IRQ_OFFSET		16     // for compability with cpm_uart driver
+
+#define PCMCIA_MEM_ADDR		(uint)0xff020000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+
+/* Bits of interest in the BCSRs.
+ */
+#define BCSR1_ETHEN		((uint)0x20000000)
+#define BCSR1_IRDAEN		((uint)0x10000000)
+#define BCSR1_RS232EN_1		((uint)0x01000000)
+#define BCSR1_PCCEN		((uint)0x00800000)
+#define BCSR1_PCCVCC0		((uint)0x00400000)
+#define BCSR1_PCCVPP0		((uint)0x00200000)
+#define BCSR1_PCCVPP1		((uint)0x00100000)
+#define BCSR1_PCCVPP_MASK	(BCSR1_PCCVPP0 | BCSR1_PCCVPP1)
+#define BCSR1_RS232EN_2		((uint)0x00040000)
+#define BCSR1_PCCVCC1		((uint)0x00010000)
+#define BCSR1_PCCVCC_MASK	(BCSR1_PCCVCC0 | BCSR1_PCCVCC1)
+
+#define BCSR4_ETH10_RST		((uint)0x80000000)	/* 10Base-T PHY reset*/
+#define BCSR4_USB_LO_SPD	((uint)0x04000000)
+#define BCSR4_USB_VCC		((uint)0x02000000)
+#define BCSR4_USB_FULL_SPD	((uint)0x00040000)
+#define BCSR4_USB_EN		((uint)0x00020000)
+
+#define BCSR5_MII2_EN		0x40
+#define BCSR5_MII2_RST		0x20
+#define BCSR5_T1_RST		0x10
+#define BCSR5_ATM155_RST	0x08
+#define BCSR5_ATM25_RST		0x04
+#define BCSR5_MII1_EN		0x02
+#define BCSR5_MII1_RST		0x01
+
+/* Interrupt level assignments */
+#define PHY_INTERRUPT	SIU_IRQ7	/* PHY link change interrupt */
+#define SIU_INT_FEC1	SIU_LEVEL1	/* FEC1 interrupt */
+#define SIU_INT_FEC2	SIU_LEVEL3	/* FEC2 interrupt */
+#define FEC_INTERRUPT	SIU_INT_FEC1	/* FEC interrupt */
+
+/* We don't use the 8259 */
+#define NR_8259_INTS	0
+
+/* CPM Ethernet through SCC3 */
+#define PA_ENET_RXD	((ushort)0x0040)
+#define PA_ENET_TXD	((ushort)0x0080)
+#define PE_ENET_TCLK	((uint)0x00004000)
+#define PE_ENET_RCLK	((uint)0x00008000)
+#define PE_ENET_TENA	((uint)0x00000010)
+#define PC_ENET_CLSN	((ushort)0x0400)
+#define PC_ENET_RENA	((ushort)0x0800)
+
+/* Control bits in the SICR to route TCLK (CLK5) and RCLK (CLK6) to
+ * SCC3.  Also, make sure GR3 (bit 8) and SC3 (bit 9) are zero */
+#define SICR_ENET_MASK	((uint)0x00ff0000)
+#define SICR_ENET_CLKRT	((uint)0x002c0000)
+
+#endif /* __ASM_MPC885ADS_H__ */
+#endif /* __KERNEL__ */
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
new file mode 100644
index 0000000..b4f38d9
--- /dev/null
+++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c
@@ -0,0 +1,365 @@
+/*arch/ppc/platforms/mpc885ads-setup.c
+ *
+ * Platform setup for the Freescale mpc885ads board
+ *
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * Copyright 2005 MontaVista Software Inc.
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/root_dev.h>
+
+#include <linux/fs_enet_pd.h>
+#include <linux/fs_uart_pd.h>
+#include <linux/mii.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/ppcboot.h>
+#include <asm/8xx_immap.h>
+#include <asm/commproc.h>
+#include <asm/fs_pd.h>
+#include <asm/prom.h>
+
+extern void cpm_reset(void);
+extern int mpc8xx_probe(void);
+extern void mpc8xx_show_cpuinfo(struct seq_file*);
+extern void mpc8xx_restart(char *cmd);
+extern void mpc8xx_calibrate_decr(void);
+extern int mpc8xx_set_rtc_time(struct rtc_time *tm);
+extern void mpc8xx_get_rtc_time(struct rtc_time *tm);
+extern void m8xx_pic_init(void);
+extern unsigned int mpc8xx_get_irq(void);
+
+static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi);
+static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi);
+static void init_scc3_ioports(struct fs_platform_info* ptr);
+
+void __init mpc885ads_board_setup(void)
+{
+	cpm8xx_t *cp = cpmp;
+ 	unsigned int *bcsr_io;
+	u8 tmpval8;
+
+#ifdef CONFIG_FS_ENET
+	iop8xx_t *io_port;
+#endif
+
+	bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+	if (bcsr_io == NULL) {
+		printk(KERN_CRIT "Could not remap BCSR\n");
+		return;
+	}
+#ifdef CONFIG_SERIAL_CPM_SMC1
+	clrbits32(bcsr_io, BCSR1_RS232EN_1);
+	clrbits32(&cp->cp_simode, 0xe0000000 >> 17);	/* brg1 */
+	tmpval8 = in_8(&(cp->cp_smc[0].smc_smcm)) | (SMCM_RX | SMCM_TX);
+	out_8(&(cp->cp_smc[0].smc_smcm), tmpval8);
+	clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN);	/* brg1 */
+#else
+	setbits32(bcsr_io,BCSR1_RS232EN_1);
+	out_be16(&cp->cp_smc[0].smc_smcmr, 0);
+	out_8(&cp->cp_smc[0].smc_smce, 0);
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC2
+	clrbits32(bcsr_io,BCSR1_RS232EN_2);
+	clrbits32(&cp->cp_simode, 0xe0000000 >> 1);
+	setbits32(&cp->cp_simode, 0x20000000 >> 1);	/* brg2 */
+	tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX);
+	out_8(&(cp->cp_smc[1].smc_smcm), tmpval8);
+	clrbits16(&cp->cp_smc[1].smc_smcmr, SMCMR_REN | SMCMR_TEN);
+
+	init_smc2_uart_ioports(0);
+#else
+	setbits32(bcsr_io,BCSR1_RS232EN_2);
+	out_be16(&cp->cp_smc[1].smc_smcmr, 0);
+	out_8(&cp->cp_smc[1].smc_smce, 0);
+#endif
+	iounmap(bcsr_io);
+
+#ifdef CONFIG_FS_ENET
+	/* use MDC for MII (common) */
+	io_port = (iop8xx_t*)immr_map(im_ioport);
+	setbits16(&io_port->iop_pdpar, 0x0080);
+	clrbits16(&io_port->iop_pddir, 0x0080);
+
+	bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
+	clrbits32(bcsr_io,BCSR5_MII1_EN);
+	clrbits32(bcsr_io,BCSR5_MII1_RST);
+#ifndef CONFIG_FC_ENET_HAS_SCC
+	clrbits32(bcsr_io,BCSR5_MII2_EN);
+	clrbits32(bcsr_io,BCSR5_MII2_RST);
+
+#endif
+	iounmap(bcsr_io);
+	immr_unmap(io_port);
+
+#endif
+}
+
+
+static void init_fec1_ioports(struct fs_platform_info* ptr)
+{
+	cpm8xx_t *cp = cpmp;
+	iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
+
+	/* configure FEC1 pins  */
+	setbits16(&io_port->iop_papar, 0xf830);
+	setbits16(&io_port->iop_padir, 0x0830);
+	clrbits16(&io_port->iop_padir, 0xf000);
+
+	setbits32(&cp->cp_pbpar, 0x00001001);
+	clrbits32(&cp->cp_pbdir, 0x00001001);
+
+	setbits16(&io_port->iop_pcpar, 0x000c);
+	clrbits16(&io_port->iop_pcdir, 0x000c);
+
+	setbits32(&cp->cp_pepar, 0x00000003);
+	setbits32(&cp->cp_pedir, 0x00000003);
+	clrbits32(&cp->cp_peso, 0x00000003);
+	clrbits32(&cp->cp_cptr, 0x00000100);
+
+	immr_unmap(io_port);
+}
+
+
+static void init_fec2_ioports(struct fs_platform_info* ptr)
+{
+	cpm8xx_t *cp = cpmp;
+	iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
+
+	/* configure FEC2 pins */
+	setbits32(&cp->cp_pepar, 0x0003fffc);
+	setbits32(&cp->cp_pedir, 0x0003fffc);
+	clrbits32(&cp->cp_peso, 0x000087fc);
+	setbits32(&cp->cp_peso, 0x00037800);
+	clrbits32(&cp->cp_cptr, 0x00000080);
+
+	immr_unmap(io_port);
+}
+
+void init_fec_ioports(struct fs_platform_info *fpi)
+{
+	int fec_no = fs_get_fec_index(fpi->fs_no);
+
+	switch (fec_no) {
+	case 0:
+		init_fec1_ioports(fpi);
+		break;
+	case 1:
+		init_fec2_ioports(fpi);
+		break;
+	default:
+		printk(KERN_ERR "init_fec_ioports: invalid FEC number\n");
+		return;
+	}
+}
+
+static void init_scc3_ioports(struct fs_platform_info* fpi)
+{
+	unsigned *bcsr_io;
+	iop8xx_t *io_port;
+	cpm8xx_t *cp = cpmp;
+
+	bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
+	io_port = (iop8xx_t *)immr_map(im_ioport);
+
+	if (bcsr_io == NULL) {
+		printk(KERN_CRIT "Could not remap BCSR\n");
+		return;
+	}
+
+	/* Enable the PHY.
+	 */
+	clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
+	udelay(1000);
+	setbits32(bcsr_io+4, BCSR4_ETH10_RST);
+	/* Configure port A pins for Txd and Rxd.
+	 */
+	setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD);
+	clrbits16(&io_port->iop_padir, PA_ENET_RXD | PA_ENET_TXD);
+
+	/* Configure port C pins to enable CLSN and RENA.
+	 */
+	clrbits16(&io_port->iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
+	clrbits16(&io_port->iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
+	setbits16(&io_port->iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
+
+	/* Configure port E for TCLK and RCLK.
+	 */
+	setbits32(&cp->cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
+	clrbits32(&cp->cp_pepar, PE_ENET_TENA);
+	clrbits32(&cp->cp_pedir,
+		  PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
+	clrbits32(&cp->cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
+	setbits32(&cp->cp_peso, PE_ENET_TENA);
+
+	/* Configure Serial Interface clock routing.
+	 * First, clear all SCC bits to zero, then set the ones we want.
+	 */
+	clrbits32(&cp->cp_sicr, SICR_ENET_MASK);
+	setbits32(&cp->cp_sicr, SICR_ENET_CLKRT);
+
+	/* Disable Rx and Tx. SMC1 sshould be stopped if SCC3 eternet are used.
+	 */
+	clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN);
+	/* On the MPC885ADS SCC ethernet PHY is initialized in the full duplex mode
+	 * by H/W setting after reset. SCC ethernet controller support only half duplex.
+	 * This discrepancy of modes causes a lot of carrier lost errors.
+	 */
+
+	/* In the original SCC enet driver the following code is placed at
+	   the end of the initialization */
+	setbits32(&cp->cp_pepar, PE_ENET_TENA);
+	clrbits32(&cp->cp_pedir, PE_ENET_TENA);
+	setbits32(&cp->cp_peso, PE_ENET_TENA);
+
+	setbits32(bcsr_io+4, BCSR1_ETHEN);
+	iounmap(bcsr_io);
+	immr_unmap(io_port);
+}
+
+void init_scc_ioports(struct fs_platform_info *fpi)
+{
+	int scc_no = fs_get_scc_index(fpi->fs_no);
+
+	switch (scc_no) {
+	case 2:
+		init_scc3_ioports(fpi);
+		break;
+	default:
+		printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
+		return;
+	}
+}
+
+
+
+static void init_smc1_uart_ioports(struct fs_uart_platform_info* ptr)
+{
+        unsigned *bcsr_io;
+	cpm8xx_t *cp = cpmp;
+
+	setbits32(&cp->cp_pepar, 0x000000c0);
+	clrbits32(&cp->cp_pedir, 0x000000c0);
+	clrbits32(&cp->cp_peso, 0x00000040);
+	setbits32(&cp->cp_peso, 0x00000080);
+
+        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+        if (bcsr_io == NULL) {
+                printk(KERN_CRIT "Could not remap BCSR1\n");
+                return;
+        }
+        clrbits32(bcsr_io,BCSR1_RS232EN_1);
+        iounmap(bcsr_io);
+}
+
+static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi)
+{
+        unsigned *bcsr_io;
+	cpm8xx_t *cp = cpmp;
+
+	setbits32(&cp->cp_pepar, 0x00000c00);
+	clrbits32(&cp->cp_pedir, 0x00000c00);
+	clrbits32(&cp->cp_peso, 0x00000400);
+	setbits32(&cp->cp_peso, 0x00000800);
+
+        bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
+
+        if (bcsr_io == NULL) {
+                printk(KERN_CRIT "Could not remap BCSR1\n");
+                return;
+        }
+        clrbits32(bcsr_io,BCSR1_RS232EN_2);
+        iounmap(bcsr_io);
+}
+
+void init_smc_ioports(struct fs_uart_platform_info *data)
+{
+	int smc_no = fs_uart_id_fsid2smc(data->fs_no);
+
+	switch (smc_no) {
+	case 0:
+		init_smc1_uart_ioports(data);
+		data->brg = data->clk_rx;
+		break;
+	case 1:
+		init_smc2_uart_ioports(data);
+		data->brg = data->clk_rx;
+		break;
+	default:
+		printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
+		return;
+	}
+}
+
+int platform_device_skip(char *model, int id)
+{
+#ifdef CONFIG_FS_ENET_HAS_SCC
+	const char *dev = "FEC";
+	int n = 2;
+#else
+	const char *dev = "SCC";
+	int n = 3;
+#endif
+
+	if (!strcmp(model, dev) && n == id)
+		return 1;
+
+	return 0;
+}
+
+static void __init mpc885ads_setup_arch(void)
+{
+	struct device_node *cpu;
+
+	cpu = of_find_node_by_type(NULL, "cpu");
+	if (cpu != 0) {
+		const unsigned int *fp;
+
+		fp = get_property(cpu, "clock-frequency", NULL);
+		if (fp != 0)
+			loops_per_jiffy = *fp / HZ;
+		else
+			loops_per_jiffy = 50000000 / HZ;
+		of_node_put(cpu);
+	}
+
+	cpm_reset();
+
+	mpc885ads_board_setup();
+
+	ROOT_DEV = Root_NFS;
+}
+
+define_machine(mpc885_ads) {
+	.name			= "MPC885 ADS",
+	.probe			= mpc8xx_probe,
+	.setup_arch		= mpc885ads_setup_arch,
+	.init_IRQ		= m8xx_pic_init,
+	.show_cpuinfo		= mpc8xx_show_cpuinfo,
+	.get_irq		= mpc8xx_get_irq,
+	.restart		= mpc8xx_restart,
+	.calibrate_decr		= mpc8xx_calibrate_decr,
+	.set_rtc_time		= mpc8xx_set_rtc_time,
+	.get_rtc_time		= mpc8xx_get_rtc_time,
+};
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 7ad2673..f85ed7a 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -8,6 +8,7 @@ endif
 obj-$(CONFIG_PPC_EFIKA)          += efika/
 obj-$(CONFIG_PPC_CHRP)		+= chrp/
 obj-$(CONFIG_4xx)		+= 4xx/
+obj-$(CONFIG_PPC_8xx)		+= 8xx/
 obj-$(CONFIG_PPC_83xx)		+= 83xx/
 obj-$(CONFIG_PPC_85xx)		+= 85xx/
 obj-$(CONFIG_PPC_86xx)		+= 86xx/

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 3/5] [POWERPC] 8xx: platform-related changes to the fsl_soc.c
  2006-11-14  1:28 ` [PATCH 3/5] [POWERPC] 8xx: platform-related changes to the fsl_soc.c Vitaly Bordug
@ 2006-11-14  2:21   ` Benjamin Herrenschmidt
  2006-11-14 12:48     ` Vitaly Bordug
  0 siblings, 1 reply; 17+ messages in thread
From: Benjamin Herrenschmidt @ 2006-11-14  2:21 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, Paul Mackerras

On Tue, 2006-11-14 at 04:28 +0300, Vitaly Bordug wrote:
> Added 8xx SoC peripherials: fec for Ethernet and smc for UARTs.
> Ordinary routines to extract values from the device tree and insert respective
> platform devices

Note that imho, that's at best a temporary thing. It would be much
better to have these drivers register as of_platform_driver's and have
the platform code publish of_platform_device's for all SoC nodes.

Ben.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 4/5] [POWERPC] 8xx: powerpc port of core CPM, CPM PIC, etc.
  2006-11-14  1:28 ` [PATCH 4/5] [POWERPC] 8xx: powerpc port of core CPM, CPM PIC, etc Vitaly Bordug
@ 2006-11-14  2:44   ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 17+ messages in thread
From: Benjamin Herrenschmidt @ 2006-11-14  2:44 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, Paul Mackerras

Great !

Some comments ...

> +static void cpm_mask_irq(unsigned int irq)
> +{
> +        unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
> +
> +	clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
> +}
> +
> +static void cpm_unmask_irq(unsigned int irq)
> +{
> +        unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
> +
> +	setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
> +}

Some space/tab mangling up there :-)

> +static void cpm_mask_and_ack(unsigned int irq)
> +{
> +	/* We do not need to do anything here. */
> +}

Then you probably don't need the callback. What flow handler are you
using ?

> +static void cpm_end_irq(unsigned int irq)
> +{
> +        unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
> +
> +	out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec));
> +}

That looks like a fasteoi type handler to me...

> +static struct irq_chip cpm_pic = {
> +	.typename = " CPM PIC ",
> +	.enable = cpm_unmask_irq,
> +	.disable = cpm_mask_irq,
> +	.unmask = cpm_unmask_irq,
> +	.mask_ack = cpm_mask_and_ack,
> +	.end = cpm_end_irq,
> +};

Remove enable/disable, the common code will use mask/unmask to implement
them. Also, remove mask_ack and use .eoi for your eoi handler and you
should be able to use the handle_fasteoi_irq() flow handler for your
PIC.

> +static int cpm_pic_host_match(struct irq_host *h, struct device_node *node)
> +{
> +	return cpm_pic_node == NULL || cpm_pic_node == node;
> +}

Are you sure you want to match on a NULL node ?

> +static int cpm_pic_host_map(struct irq_host *h, unsigned int virq,
> +			  irq_hw_number_t hw)
> +{
> +	pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw);
> +
> +	get_irq_desc(virq)->status |= IRQ_LEVEL;
> +	set_irq_chip_and_handler(virq, &cpm_pic, handle_level_irq);
> +	return 0;
> +}

As I said above, use fasteoi, not level. Like mpic or xics

> +static void cpm_host_unmap(struct irq_host *h, unsigned int virq)
> +{
> +	/* Make sure irq is masked in hardware */
> +	cpm_mask_irq(virq);
> +
> +	/* remove chip and handler */
> +	set_irq_chip_and_handler(virq, NULL, NULL);
> +}

The above is a duplicate of the common code, you can probably just not
implement an unmap callback at all.

> +static int cpm_pic_host_xlate(struct irq_host *h, struct device_node *ct,
> +			    u32 *intspec, unsigned int intsize,
> +			    irq_hw_number_t *out_hwirq, unsigned int *out_flags)
> +{
> +	static unsigned char map_cpm_senses[4] = {
> +		IRQ_TYPE_LEVEL_LOW,
> +		IRQ_TYPE_LEVEL_HIGH,
> +		IRQ_TYPE_EDGE_FALLING,
> +		IRQ_TYPE_EDGE_RISING,
> +	};
> +
> +	*out_hwirq = intspec[0];
> +	if (intsize > 1 && intspec[1] < 4)
> +		*out_flags = map_cpm_senses[intspec[1]];
> +	else
> +		*out_flags = IRQ_TYPE_NONE;
> +
> +	return 0;
> +}

Can the interrupts have a different sense/polarity ? Because you never
configure that anywhere in the code, so that means you either expect
them to be configured by the firmware, or they have a fixed
sense/polarity in which case, since you can use a fasteoi handler, you
don't even care wether they are level or edge. Thus, if all that is
true, just use a #interrupt-cells of 1 and don't bother with putting
sense/polarity info in the tree at all :-)

> +/* The CPM can generate the error interrupt when there is a race condition
> + * between generating and masking interrupts.  All we have to do is ACK it
> + * and return.  This is a no-op function so we don't need any special
> + * tests in the interrupt handler.
> + */
> +static	irqreturn_t cpm_error_interrupt(int irq, void *dev)
> +{
> +	return IRQ_HANDLED;
> +}

Can you tell me more about this error interrupt ?

> +	ret = of_address_to_resource(np, 0, &res);
> +	if (ret)
> +		return sirq;
> +
> +	cpic_reg = (void *)ioremap(res.start, res.end - res.start + 1);
> +	if (cpic_reg == NULL)
> +		return sirq;

Your error path probably need an of_node_put(np);

> +	sirq = irq_of_parse_and_map(np, 0);

Check for NO_IRQ here in case the device-tree is broken.

> +	/* Initialize the CPM interrupt controller. */
> +	hwirq = (unsigned int)irq_map[sirq].hwirq;
> +	out_be32(&cpic_reg->cpic_cicr,
> +	    (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
> +		((hwirq/2) << 13) | CICR_HP_MASK);

Here you are configuring the HW irq going to the parent controller ?

> +	out_be32(&cpic_reg->cpic_cimr, 0);
> +
> +	/* create a legacy host */
> +	if (np)
> +		cpm_pic_node = of_node_get(np);

The comment probably needs to change or go :-)

> +	cpm_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &cpm_pic_host_ops, 64);
> +	if (cpm_pic_host == NULL) {
> +		printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
> +		sirq = NO_IRQ;
> +                return sirq;
> +	}

More missing of_node_put() in error path.

> +	/* Install our own error handler. */
> +	np = of_find_node_by_type(NULL, "cpm");
> +	eirq= irq_of_parse_and_map(np, 0);
> +	if (setup_irq(eirq, &cpm_error_irqaction))
> +		printk(KERN_ERR "Could not allocate CPM error IRQ!");

Some error checking above might be useful on the result on
of_find_node_by_type() and irq_of_parse_and_map().

 [ skip ucode patches ]

Wouldn't it be better to have that in the device-tree ? Not sure here,
just asking ...

> +
> +#ifdef CONFIG_USB_SOF_UCODE_PATCH
> +	commproc->cp_rccr = 0;
> +
> +	dp = (uint *)(commproc->cp_dpmem);
> +	for (i=0; i<(sizeof(patch_2000)/4); i++)
> +		*dp++ = patch_2000[i];
> +
> +	dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
> +	for (i=0; i<(sizeof(patch_2f00)/4); i++)
> +		*dp++ = patch_2f00[i];
> +
> +	commproc->cp_rccr = 0x0009;
> +
> +	printk("USB SOF microcode patch installed\n");
> +#endif /* CONFIG_USB_SOF_UCODE_PATCH */
> +
> +#if defined(CONFIG_I2C_SPI_UCODE_PATCH) || \
> +    defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
> +
> +	commproc->cp_rccr = 0;
> +
> +	dp = (uint *)(commproc->cp_dpmem);
> +	for (i=0; i<(sizeof(patch_2000)/4); i++)
> +		*dp++ = patch_2000[i];
> +
> +	dp = (uint *)&(commproc->cp_dpmem[0x0f00]);
> +	for (i=0; i<(sizeof(patch_2f00)/4); i++)
> +		*dp++ = patch_2f00[i];
> +
> +	iip = (iic_t *)&commproc->cp_dparam[PROFF_IIC];
> +# define RPBASE 0x0500
> +	iip->iic_rpbase = RPBASE;
> +
> +	/* Put SPI above the IIC, also 32-byte aligned.
> +	*/
> +	i = (RPBASE + sizeof(iic_t) + 31) & ~31;
> +	spp = (spi_t *)&commproc->cp_dparam[PROFF_SPI];
> +	spp->spi_rpbase = i;
> +
> +# if defined(CONFIG_I2C_SPI_UCODE_PATCH)
> +	commproc->cp_cpmcr1 = 0x802a;
> +	commproc->cp_cpmcr2 = 0x8028;
> +	commproc->cp_cpmcr3 = 0x802e;
> +	commproc->cp_cpmcr4 = 0x802c;
> +	commproc->cp_rccr = 1;
> +
> +	printk("I2C/SPI microcode patch installed.\n");
> +# endif /* CONFIG_I2C_SPI_UCODE_PATCH */
> +
> +# if defined(CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
> +
> +	dp = (uint *)&(commproc->cp_dpmem[0x0e00]);
> +	for (i=0; i<(sizeof(patch_2e00)/4); i++)
> +		*dp++ = patch_2e00[i];
> +
> +	commproc->cp_cpmcr1 = 0x8080;
> +	commproc->cp_cpmcr2 = 0x808a;
> +	commproc->cp_cpmcr3 = 0x8028;
> +	commproc->cp_cpmcr4 = 0x802a;
> +	commproc->cp_rccr = 3;
> +
> +	smp = (smc_uart_t *)&commproc->cp_dparam[PROFF_SMC1];
> +	smp->smc_rpbase = 0x1FC0;
> +
> +	printk("I2C/SPI/SMC1 microcode patch installed.\n");
> +# endif /* CONFIG_I2C_SPI_SMC1_UCODE_PATCH) */
> +
> +#endif /* some variation of the I2C/SPI patch was selected */
> +}

A lot of ifdefs in there ... I would prefer a few device-tree entries
indicating what has to be done so that a given kernel image can be made
to work on 2 or 3 revs of a board needing a different patch. That should
be all small enough. You can still have CONFIG options to define which
patches are supported (built in the kernel image) so that one can choose
to only have one in to get the smallest possible image, but it would be
nice to have the ability to select them as a set and have the platform
define, via the tree, which patches to apply.

> +/*
> + *  Take this entire routine out, since no one calls it and its
> + * logic is suspect.
> + */

Well... just do it then :-)

> +static void mpc8xx_end_irq(unsigned int virq)
> +{
> +	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
> +
> +	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))
> +			&& irq_desc[irq_nr].action) {
> +		int bit, word;
> +
> +		bit = irq_nr & 0x1f;
> +		word = irq_nr >> 5;
> +
> +		ppc_cached_irq_mask[word] |= (1 << (31-bit));
> +		out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
> +	}
> +}

You should never need a end() handler. You might want an eoi() if you
have a smart controller and can use fasteoi(). For normal level or edge,
the flow handler will implement the logic of unmasking when needed.

> +static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
> +{
> +       struct irq_desc *desc = get_irq_desc(virq);
> +
> +
> +        desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
> +        desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
> +        if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
> +                desc->status |= IRQ_LEVEL;
> +
> +        if (flow_type & IRQ_TYPE_EDGE_FALLING) {
> +		irq_hw_number_t hw = (unsigned int)irq_map[virq].hwirq;
> +		unsigned int siel = in_be32(&siu_reg->sc_siel);
> +                if ((hw & 1) == 0)
> +                        siel |= (0x80000000 >> hw);
> +                else
> +                        siel &= ~(0x80000000 >> (hw & ~1));
> +		out_be32(&siu_reg->sc_siel, siel);
> +	}
> +        return 0;
> +}

Don't you need to change the flow handler too between edge/level ?

Also, waht is this sc_siel register for ? I'm surprised you have to
do something when swithing an irq to edge but not undo it when
switching it to level...

> +static struct irq_chip mpc8xx_pic = {
> +	.typename = " MPC8XX SIU ",
> +	.enable = mpc8xx_unmask_irq,
> +	.disable = mpc8xx_mask_irq,
> +	.unmask = mpc8xx_unmask_irq,
> +	.mask_ack = mpc8xx_mask_and_ack,
> +	.end = mpc8xx_end_irq,
> +	.set_type = mpc8xx_set_irq_type,
> +};

Remove enable/disable/end. Add ack() if you use the edge flow handler.

> +unsigned int mpc8xx_get_irq(void)
> +{
> +	int irq;
> +
> +	/* For MPC8xx, read the SIVEC register and shift the bits down
> +	 * to get the irq number.
> +	 */
> +	irq = in_be32(&siu_reg->sc_sivec) >> 26;
> +
> +	/*
> +	 * When we read the sivec without an interrupt to process, we will
> +	 * get back SIU_LEVEL7.  In this case, return -1
> +	 */
> +//        if (irq == CPM_INTERRUPT)
> +//        	irq = CPM_IRQ_OFFSET + cpm_get_irq(regs);
> +//	else
> +		if (irq == PIC_VEC_SPURRIOUS)
> +			irq = NO_IRQ;
> +        return irq_linear_revmap(mpc8xx_pic_host, irq);
> +
> +//	return irq;
> +}

Needs cleanups :-) Also is a bit buggy, you probably want

		if (irq == PIC_VEC_SPURRIOUS)
			return NO_IRQ;

> +static int mpc8xx_pic_host_match(struct irq_host *h, struct device_node *node)
> +{
> +	return mpc8xx_pic_node == NULL || mpc8xx_pic_node == node;
> +}

Why match when mpc8xx_pic_node is NULL ? This is something that 8259
does for weird reasons of being compatible with crappy device-trees on
some machines. Not something you should bring in for new ports.

> +static void mpc8xx_pic_host_unmap(struct irq_host *h, unsigned int virq)
> +{
> +	/* Make sure irq is masked in hardware */
> +	mpc8xx_mask_irq(virq);
> +
> +	/* remove chip and handler */
> +	set_irq_chip_and_handler(virq, NULL, NULL);
> +}

You probably don't need an unmap callback at all.

> +void mpc8xx_pic_init(struct device_node *np)
> +{
> +	struct resource res;
> +	int ret;
> +
> +	/* create a legacy host */
> +	if (np)
> +		mpc8xx_pic_node = of_node_get(np);
> +
> +	ret = of_address_to_resource(np, 0, &res);
> +	if (ret)
> +		return;
> +
> +	siu_reg = (void *)ioremap(res.start, res.end - res.start + 1);
> +	if (siu_reg == NULL)
> +		return;

of_node_put(np);

> +	mpc8xx_pic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, 64, &mpc8xx_pic_host_ops, 64);
> +	if (mpc8xx_pic_host == NULL) {
> +		printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");
> +	}
> +}

> +/* Currently, all 8xx boards that support a processor to PCI/ISA bridge
> + * use the same memory map.
> + */
> +#if !defined(_IO_BASE)  /* defined in board specific header */
> +#define _IO_BASE        0
> +#endif
> +#define _ISA_MEM_BASE   0
> +#define PCI_DRAM_OFFSET 0

The above should now be defined generically in asm-powerpc/io.h (at
least with my latest patches).

> +#ifndef __ASSEMBLY__
> +//struct pt_regs;
> +//#define PPC_PIN_SIZE	(24 * 1024 * 1024)	/* 24Mbytes of data pinned */
> +#endif /* !__ASSEMBLY__ */

Some cleanup is overdue here :-)\

Cheers,
Ben.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 5/5] [POWERPC] 8xx: Add mpc885ads support and common mpc8xx.
  2006-11-14  1:28 ` [PATCH 5/5] [POWERPC] 8xx: Add mpc885ads support and common mpc8xx Vitaly Bordug
@ 2006-11-14  2:47   ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 17+ messages in thread
From: Benjamin Herrenschmidt @ 2006-11-14  2:47 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, Paul Mackerras

Few comments..

> +/*
> + * Called very early, device-tree isn't unflattened
> + */
> +int __init mpc8xx_probe(void)
> +{
> +	unsigned long root = of_get_flat_dt_root();
> +
> +	if (of_flat_dt_is_compatible(root, "mpc8xx"))
> +		return 1;
> +
> +	return 0;
> +}

Why hooks on that ?

Normally, board support files test for their specific board. Thus they
have their own probe() function, generally static just before the ppc_md
definition. You probably want to remove the above,.

> +define_machine(mpc885_ads) {
> +	.name			= "MPC885 ADS",
> +	.probe			= mpc8xx_probe,

Do your own probe function that specifically checks for and MPC885 ADS
board.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 3/5] [POWERPC] 8xx: platform-related changes to the fsl_soc.c
  2006-11-14  2:21   ` Benjamin Herrenschmidt
@ 2006-11-14 12:48     ` Vitaly Bordug
  0 siblings, 0 replies; 17+ messages in thread
From: Vitaly Bordug @ 2006-11-14 12:48 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Paul Mackerras

On Tue, 14 Nov 2006 13:21:14 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> On Tue, 2006-11-14 at 04:28 +0300, Vitaly Bordug wrote:
> > Added 8xx SoC peripherials: fec for Ethernet and smc for UARTs.
> > Ordinary routines to extract values from the device tree and insert respective
> > platform devices
> 
> Note that imho, that's at best a temporary thing. It would be much
> better to have these drivers register as of_platform_driver's and have
> the platform code publish of_platform_device's for all SoC nodes.
> 
The platform device way will persist until we haven't care about arch/ppc stuff anymore. 
As for now, I'm trying to keep both powerpc and ppc approaches sane.

Hence it is temporary, but it is the way of merge. of_platform_device rework is not a big deal - we'll do
it later.


-- 
Sincerely, 
Vitaly

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port
  2006-11-14  1:28 ` [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port Vitaly Bordug
@ 2006-11-15 18:23   ` Christoph Hellwig
  2006-11-15 23:36     ` Vitaly Bordug
  2006-11-16 22:48     ` Benjamin Herrenschmidt
  2006-11-17  8:00   ` Christoph Hellwig
  1 sibling, 2 replies; 17+ messages in thread
From: Christoph Hellwig @ 2006-11-15 18:23 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, Paul Mackerras

On Tue, Nov 14, 2006 at 04:28:16AM +0300, Vitaly Bordug wrote:
> --- /dev/null
> +++ b/arch/powerpc/kernel/dma-mapping.c

Can we please give this a more descriptive name? MIPS names the
equivalent dma-noncoherent.c which makes a lot of sense to me.

> +#include <linux/module.h>
> +#include <linux/signal.h>
> +#include <linux/sched.h>
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/string.h>
> +#include <linux/types.h>
> +#include <linux/ptrace.h>
> +#include <linux/mman.h>
> +#include <linux/mm.h>
> +#include <linux/swap.h>
> +#include <linux/stddef.h>
> +#include <linux/vmalloc.h>
> +#include <linux/init.h>
> +#include <linux/delay.h>
> +#include <linux/bootmem.h>
> +#include <linux/highmem.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/hardirq.h>
> +
> +#include <asm/pgalloc.h>
> +#include <asm/prom.h>
> +#include <asm/io.h>
> +#include <asm/mmu_context.h>
> +#include <asm/pgtable.h>
> +#include <asm/mmu.h>
> +#include <asm/uaccess.h>
> +#include <asm/smp.h>
> +#include <asm/machdep.h>

Do you really need all these headers?

> +int map_page(unsigned long va, phys_addr_t pa, int flags);

this one doesn't seem to be used ever.  And even if it was a non-static
forward-declaration in a .c is not something we'd want.

> +/*
> + * VM region handling support.
> + *
> + * This should become something generic, handling VM region allocations for
> + * vmalloc and similar (ioremap, module space, etc).
> + *
> + * I envisage vmalloc()'s supporting vm_struct becoming:
> + *
> + *  struct vm_struct {
> + *    struct vm_region	region;
> + *    unsigned long	flags;
> + *    struct page	**pages;
> + *    unsigned int	nr_pages;
> + *    unsigned long	phys_addr;
> + *  };
> + *
> + * get_vm_area() would then call vm_region_alloc with an appropriate
> + * struct vm_region head (eg):
> + *
> + *  struct vm_region vmalloc_head = {
> + *	.vm_list	= LIST_HEAD_INIT(vmalloc_head.vm_list),
> + *	.vm_start	= VMALLOC_START,
> + *	.vm_end		= VMALLOC_END,
> + *  };
> + *
> + * However, vmalloc_head.vm_start is variable (typically, it is dependent on
> + * the amount of RAM found at boot time.)  I would imagine that get_vm_area()
> + * would have to initialise this each time prior to calling vm_region_alloc(

Yeah, I suspect you should do that instead of adding another copy of
a copy of core VM code..

Btw, is there anything ppc-specific in the noncoherent dma code?
It might be a good idea to put it into lib/ otherwise, I'll contribute
a dma-coherent.c for simple architectures for there aswell..

> --- a/arch/powerpc/mm/fault.c
> +++ b/arch/powerpc/mm/fault.c
> @@ -447,3 +447,102 @@ void bad_page_fault(struct pt_regs *regs
>  
>  	die("Kernel access of bad area", regs, sig);
>  }
> +
> +#ifdef CONFIG_8xx
> +

Can we put this functions into a separate file instea of an
ifdefed section

> +/* The pgtable.h claims some functions generically exist, but I
> + * can't find them......
> + */
> +pte_t *va_to_pte(unsigned long address)
> +{
> +	pgd_t *dir;
> +	pmd_t *pmd;
> +	pte_t *pte;
> +
> +	if (address < TASK_SIZE)
> +		return NULL;
> +
> +	dir = pgd_offset(&init_mm, address);
> +	if (dir) {
> +		pmd = pmd_offset(dir, address & PAGE_MASK);
> +		if (pmd && pmd_present(*pmd)) {
> +			pte = pte_offset_kernel(pmd, address & PAGE_MASK);
> +			if (pte && pte_present(*pte))
> +				return(pte);
> +		}
> +	}
> +	return NULL;
> +}

But wha do you need this for anyway?  It's not used anywhere currently,
and it's not 8xx-specific at all?

> +unsigned long va_to_phys(unsigned long address)
> +{
> +	pte_t *pte;
> +
> +	pte = va_to_pte(address);
> +	if (pte)
> +		return(((unsigned long)(pte_val(*pte)) & PAGE_MASK) | (address & ~(PAGE_MASK)));
> +	return (0);
> +}

Shouldn't you use virt_to_phys instead?

Also for the last two I'd prefer if you'd find a way to avoid adding
them.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port
  2006-11-15 18:23   ` Christoph Hellwig
@ 2006-11-15 23:36     ` Vitaly Bordug
  2006-11-16 22:48     ` Benjamin Herrenschmidt
  1 sibling, 0 replies; 17+ messages in thread
From: Vitaly Bordug @ 2006-11-15 23:36 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linuxppc-dev, Paul Mackerras

[-- Attachment #1: Type: text/plain, Size: 708 bytes --]

Hi Christoph,

As a short disclaimer, the patch under consideration is a direct copy from arch/ppc (since the aim is to move the migration
forward). Apparently it looks like it's a good time to clean it up, and maybe move to /lib so that we have central stuff to deal with non-cache-coherent targets. But I have to say I don't know much about other arch's approaches to consider what
we have below ppc-specific or not.

All your notes make sense so I'll clean up and will remove ifdeffed section.
But as for generic approach, my opinion is that it should be carefully considered, and I suggest to get back to it once  the 8xx framework will get in. 

Thanks for your time!

--
Sincerely, Vitaly

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port
  2006-11-15 18:23   ` Christoph Hellwig
  2006-11-15 23:36     ` Vitaly Bordug
@ 2006-11-16 22:48     ` Benjamin Herrenschmidt
  2006-11-17  6:49       ` Christoph Hellwig
  1 sibling, 1 reply; 17+ messages in thread
From: Benjamin Herrenschmidt @ 2006-11-16 22:48 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linuxppc-dev, Paul Mackerras


> But wha do you need this for anyway?  It's not used anywhere currently,
> and it's not 8xx-specific at all?
> 
> > +unsigned long va_to_phys(unsigned long address)
> > +{
> > +	pte_t *pte;
> > +
> > +	pte = va_to_pte(address);
> > +	if (pte)
> > +		return(((unsigned long)(pte_val(*pte)) & PAGE_MASK) | (address & ~(PAGE_MASK)));
> > +	return (0);
> > +}
> 
> Shouldn't you use virt_to_phys instead?
> 
> Also for the last two I'd prefer if you'd find a way to avoid adding
> them.

I think those 2 are used for cases where they either have a non-linear
mapping a-la Amiga/APUS or in cases where they try to get addresses of
things in the vmalloc area no ?.

Ben.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port
  2006-11-16 22:48     ` Benjamin Herrenschmidt
@ 2006-11-17  6:49       ` Christoph Hellwig
  0 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2006-11-17  6:49 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Paul Mackerras

On Fri, Nov 17, 2006 at 09:48:43AM +1100, Benjamin Herrenschmidt wrote:
> I think those 2 are used for cases where they either have a non-linear
> mapping a-la Amiga/APUS or in cases where they try to get addresses of
> things in the vmalloc area no ?.

For vmalloc we should be using vmalloc_to_page and then page_to_phys,
but again, I'd prefer to see the actual user before making detailed
suggestions.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port
  2006-11-14  1:28 ` [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port Vitaly Bordug
  2006-11-15 18:23   ` Christoph Hellwig
@ 2006-11-17  8:00   ` Christoph Hellwig
  2006-11-18  1:24     ` Dan Malek
  1 sibling, 1 reply; 17+ messages in thread
From: Christoph Hellwig @ 2006-11-17  8:00 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, Paul Mackerras

I've done some grepping, so here are some more useful comments on
the fault.c additions:

> +#ifdef CONFIG_8xx
> +
> +/* The pgtable.h claims some functions generically exist, but I
> + * can't find them......
> + */

This comment is copied from arch/ppc/ but utterly wrong - no one
but 8xx implements any of these functions.  I'd say just kill it.

> +pte_t *va_to_pte(unsigned long address)

this is used by arch/ppc/fec.c to set mapping uncachable, which
seems rather odd to me.  For now we'll have to keep it I think, but
it might make sense to move the implementation to fec.c.

> +unsigned long va_to_phys(unsigned long address)

this is completely unused. You should probably remove it from arch/ppc
aswell.

> +void
> +print_8xx_pte(struct mm_struct *mm, unsigned long addr)

> +int
> +get_8xx_pte(struct mm_struct *mm, unsigned long addr)

These two are only used by arch/ppc/kernel/softemu8xx.c and should
bew move to that file.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port
  2006-11-17  8:00   ` Christoph Hellwig
@ 2006-11-18  1:24     ` Dan Malek
  2006-11-20 10:24       ` Christoph Hellwig
  0 siblings, 1 reply; 17+ messages in thread
From: Dan Malek @ 2006-11-18  1:24 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linuxppc-dev, Paul Mackerras


On Nov 17, 2006, at 3:00 AM, Christoph Hellwig wrote:

> this is used by arch/ppc/fec.c to set mapping uncachable, which
> seems rather odd to me.

I thought arch/ppc/fec.c is dead in favor of the
"generic" version in the drivers/net directory?

We use the va_to_pte() functions to find
the mappings to create "coherent" cache areas
by changing the cache attributes of the vmalloc()
space.  We can't use virt_to_phys() or similar
associated functions because they simply do the
kernel virtual arithmetic and don't return the
proper PTEs for for changing these attributes.

I believe this is also used on the 4xx, but I
could be mistaken.

> .....  For now we'll have to keep it I think, but
> it might make sense to move the implementation to fec.c.

I don't know what version of fec.c you are looking
at, but it should use the dma_alloc_coherent() functions
and be stashing both the physical and virtual addresses.
I made this change long ago and I hope it hasn't
been lost.

The coherent dma functions will in turn use
the va_to_pte() (or associated functions) mentioned
above.

Thanks.


	-- Dan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port
  2006-11-18  1:24     ` Dan Malek
@ 2006-11-20 10:24       ` Christoph Hellwig
  2006-11-21  0:26         ` Dan Malek
  0 siblings, 1 reply; 17+ messages in thread
From: Christoph Hellwig @ 2006-11-20 10:24 UTC (permalink / raw)
  To: Dan Malek; +Cc: linuxppc-dev, Paul Mackerras

On Fri, Nov 17, 2006 at 08:24:16PM -0500, Dan Malek wrote:
> On Nov 17, 2006, at 3:00 AM, Christoph Hellwig wrote:
> 
> >this is used by arch/ppc/fec.c to set mapping uncachable, which
> >seems rather odd to me.
> 
> I thought arch/ppc/fec.c is dead in favor of the
> "generic" version in the drivers/net directory?

Sorry, I actually meant drivers/net/fec.c.

> We use the va_to_pte() functions to find
> the mappings to create "coherent" cache areas
> by changing the cache attributes of the vmalloc()
> space.  We can't use virt_to_phys() or similar
> associated functions because they simply do the
> kernel virtual arithmetic and don't return the
> proper PTEs for for changing these attributes.

Yes, I noticed that in the second round of actually
looking at all the users.

> >it might make sense to move the implementation to fec.c.
> 
> I don't know what version of fec.c you are looking
> at, but it should use the dma_alloc_coherent() functions
> and be stashing both the physical and virtual addresses.
> I made this change long ago and I hope it hasn't
> been lost.
> 
> The coherent dma functions will in turn use
> the va_to_pte() (or associated functions) mentioned
> above.

drivers/net/fec.c in current linus tree doesn't use the dma
api at all, and there is no dma api implementation that
uses va_to_pte().  The only users of va_to_pte() in current
Linus tree are drivers/net/fec.c:fec_uncachable() in the #else
block of a large #ifdef / #ifelse spagethhi sections and va_to_phys in
arch/ppc/mm/fault.c under CONFIG_8xx, which is unused.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port
  2006-11-20 10:24       ` Christoph Hellwig
@ 2006-11-21  0:26         ` Dan Malek
  0 siblings, 0 replies; 17+ messages in thread
From: Dan Malek @ 2006-11-21  0:26 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linuxppc-dev, Paul Mackerras


On Nov 20, 2006, at 5:24 AM, Christoph Hellwig wrote:

> Sorry, I actually meant drivers/net/fec.c.

That's the wrong one, too :-)

Since I was able to go on an adventure among
the Ethernet drivers today, I noticed all of the
PQs use the drivers/net/fs_enet directory.
The MPC8xx will use some combination
of the SCC or FEC MAC driver functions
in that directory.  They all use the cache
coherent DMA allocators properly.

Thanks.

	-- Dan

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2006-11-21 14:44 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20061114012504.17455.13833.stgit@localhost.localdomain>
2006-11-14  1:28 ` [PATCH 1/5] [POWERPC] 8xx: platform-specific mmu updates Vitaly Bordug
2006-11-14  1:28 ` [PATCH 2/5] [POWERPC] 8xx: generic 8xx code arch/powerpc port Vitaly Bordug
2006-11-15 18:23   ` Christoph Hellwig
2006-11-15 23:36     ` Vitaly Bordug
2006-11-16 22:48     ` Benjamin Herrenschmidt
2006-11-17  6:49       ` Christoph Hellwig
2006-11-17  8:00   ` Christoph Hellwig
2006-11-18  1:24     ` Dan Malek
2006-11-20 10:24       ` Christoph Hellwig
2006-11-21  0:26         ` Dan Malek
2006-11-14  1:28 ` [PATCH 3/5] [POWERPC] 8xx: platform-related changes to the fsl_soc.c Vitaly Bordug
2006-11-14  2:21   ` Benjamin Herrenschmidt
2006-11-14 12:48     ` Vitaly Bordug
2006-11-14  1:28 ` [PATCH 4/5] [POWERPC] 8xx: powerpc port of core CPM, CPM PIC, etc Vitaly Bordug
2006-11-14  2:44   ` Benjamin Herrenschmidt
2006-11-14  1:28 ` [PATCH 5/5] [POWERPC] 8xx: Add mpc885ads support and common mpc8xx Vitaly Bordug
2006-11-14  2:47   ` Benjamin Herrenschmidt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).