/packages/linux: Add kernel 2.6.20 for efika
authorStelios Koroneos <skoroneos@digital-opsis.com>
Mon, 19 Feb 2007 20:18:25 +0000 (20:18 +0000)
committerStelios Koroneos <skoroneos@digital-opsis.com>
Mon, 19 Feb 2007 20:18:25 +0000 (20:18 +0000)
35 files changed:
packages/linux/linux-efika-2.6.20/.mtn2git_empty [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0001-powerpc-serial-Dispose-irq-mapping-when-done-in-mpc52xx_serial.c.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0003-powerpc-Add-device-tree-fixups-for-the-EFIKA.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0004-powerpc-Use-common-52xx-of_platform-probe-code-for-EFIKA.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0005-powerpc-Restore-proper-link-order-in-platform.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0007-Implement-support-for-split-endian-OHCI.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0008-ohci-Rework-bus-glue-integration-to-allow-several-at-once.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0009-ohci-Add-support-for-OHCI-controller-on-the-of_platform-bus.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0010-libata-Add-support-for-the-MPC52xx-ATA-controller.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0011-ohci-Whitespace-and-typo-fix-in-ohci-ppc-of.c.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0012-ata-Fix-pata_mpc52xx.c-compatible-list.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0013-powerpc-serial-Fix-mpc52xx_uart.c-compatible-list.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0014-powerpc-Small-cleanup-of-EFIKA-platform.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0015-powerpc-Add-a-unified-uevent-handler-for-bus-based-on-of_device.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0016-macintosh-Use-the-new-of_device-common-uevent-handler.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0017-powerpc-Add-uevent-handler-for-of_platform_bus.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0018-powerpc-Add-uevent-handler-for-ibmebus.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0019-MPC5200-Bestcomm-platform-driver.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0020-Fec-MPC5200-eth-driver.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0021-POWERPC-Copy-bestcomm-support-files-into-arch-powerpc.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0022-MPC52xx-PCI-now-working-on-lite5200.-ugly-but-working.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0023-POWERPC-Make-FEC-work-on-the-lite5200.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0024-Add-missing-function-prototype.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0025-POWERPC-Misc-EFIKA-fixups-for-rtas-chrp.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0026-POWERPC-Cleanup-mpc52xx-PCI-support.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0027-POWERPC-Change-name-of-mpc52xx-pci-support-file-in-Makefile.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0028-POWERPC-Change-link-order-so-mpc52xx-fec-always-shows-up-as-eth0.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0029-POWERPC-Fixup-pr_print-format-for-mpc52xx-pci-support.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0030-POWERPC-Add-mpc52xx-lite5200-PCI-support.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0031-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/0032-POWERPC-EFIKA-Adds-missing-interrupts-from-bestcomm-node.txt [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/defconfig [new file with mode: 0644]
packages/linux/linux-efika-2.6.20/v4l.diff [new file with mode: 0644]
packages/linux/linux-efika_2.6.20.bb [new file with mode: 0644]

diff --git a/packages/linux/linux-efika-2.6.20/.mtn2git_empty b/packages/linux/linux-efika-2.6.20/.mtn2git_empty
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/packages/linux/linux-efika-2.6.20/0001-powerpc-serial-Dispose-irq-mapping-when-done-in-mpc52xx_serial.c.txt b/packages/linux/linux-efika-2.6.20/0001-powerpc-serial-Dispose-irq-mapping-when-done-in-mpc52xx_serial.c.txt
new file mode 100644 (file)
index 0000000..ef3c42d
--- /dev/null
@@ -0,0 +1,27 @@
+From 733239db928c98f4d110fc33f0cf1278cf5385ef Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Mon, 18 Dec 2006 22:48:02 +0100
+Subject: [PATCH] [PATCH] powerpc/serial: Dispose irq mapping when done in mpc52xx_serial.c
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ drivers/serial/mpc52xx_uart.c |    3 +++
+ 1 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
+index 9d11a75..eef3b02 100644
+--- a/drivers/serial/mpc52xx_uart.c
++++ b/drivers/serial/mpc52xx_uart.c
+@@ -997,6 +997,9 @@ mpc52xx_uart_of_remove(struct of_device *op)
+       if (port)
+               uart_remove_one_port(&mpc52xx_uart_driver, port);
++      if (port->irq != NO_IRQ)
++              irq_dispose_mapping(port->irq);
++
+       return 0;
+ }
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0003-powerpc-Add-device-tree-fixups-for-the-EFIKA.txt b/packages/linux/linux-efika-2.6.20/0003-powerpc-Add-device-tree-fixups-for-the-EFIKA.txt
new file mode 100644 (file)
index 0000000..eddebfe
--- /dev/null
@@ -0,0 +1,110 @@
+From 7fa32df37b889fd0520b28870153b711c65192d2 Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Sat, 23 Dec 2006 20:25:18 +0100
+Subject: [PATCH] [PATCH] powerpc: Add device tree fixups for the EFIKA
+
+We make the efika device tree compliant with the defined bindings
+(at least compliant enough). This is mostly done by mangling
+the device_type and compatible properties, but also adding
+some missing bits.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ arch/powerpc/kernel/prom_init.c |   76 +++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 76 insertions(+), 0 deletions(-)
+
+diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
+index 520ef42..5291d62 100644
+--- a/arch/powerpc/kernel/prom_init.c
++++ b/arch/powerpc/kernel/prom_init.c
+@@ -2117,11 +2117,87 @@ static void __init fixup_device_tree_pmac(void)
+ #define fixup_device_tree_pmac()
+ #endif
++#ifdef CONFIG_PPC_EFIKA
++/* The current fw of the Efika has a device tree needs quite a few
++ * fixups to be compliant with the mpc52xx bindings. It's currently
++ * unknown if it will ever be compliant (come on bPlan ...) so we do fixups.
++ * NOTE that we (barely) tolerate it because the EFIKA was out before
++ * the bindings were finished, for any new boards -> RTFM ! */
++
++struct subst_entry {
++      char *path;
++      char *property;
++      void *value;
++      int value_len;
++};
++
++static void __init fixup_device_tree_efika(void)
++{
++      /* Substitution table */
++      #define prop_cstr(x) x, sizeof(x)
++      int prop_sound_irq[3] = { 2, 2, 0 };
++      struct subst_entry efika_subst_table[] = {
++              { "/",                  "device_type",  prop_cstr("efika") },
++              { "/builtin",           "compatible",   prop_cstr("soc") },
++              { "/builtin/ata",       "compatible",   prop_cstr("mpc5200b-ata\0mpc52xx-ata"), },
++              { "/builtin/bestcomm",  "compatible",   prop_cstr("mpc5200b-bestcomm\0mpc52xx-bestcomm") },
++              { "/builtin/ethernet",  "compatible",   prop_cstr("mpc5200b-fec\0mpc52xx-fec") },
++              { "/builtin/pic",       "compatible",   prop_cstr("mpc5200b-pic\0mpc52xx-pic") },
++              { "/builtin/serial",    "compatible",   prop_cstr("mpc5200b-psc-uart\0mpc52xx-psc-uart") },
++              { "/builtin/sound",     "compatible",   prop_cstr("mpc5200b-psc-ac97\0mpc52xx-psc-ac97") },
++              { "/builtin/sound",     "interrupts",   prop_sound_irq, sizeof(prop_sound_irq) },
++              { "/builtin/sram",      "compatible",   prop_cstr("mpc5200b-sram\0mpc52xx-sram") },
++              { "/builtin/sram",      "device_type",  prop_cstr("sram") },
++              {}
++      };
++      #undef prop_cstr
++
++      /* Vars */
++      u32 node;
++      char prop[64];
++      int rv, i;
++
++      /* Check if we're really running on a EFIKA */
++      node = call_prom("finddevice", 1, 1, ADDR("/"));
++      if (!PHANDLE_VALID(node))
++              return;
++
++      rv = prom_getprop(node, "model", prop, sizeof(prop));
++      if (rv == PROM_ERROR)
++              return;
++      if (strcmp(prop, "EFIKA5K2"))
++              return;
++
++      prom_printf("Applying EFIKA device tree fixups\n");
++
++      /* Process substitution table */
++      for (i=0; efika_subst_table[i].path; i++) {
++              struct subst_entry *se = &efika_subst_table[i];
++
++              node = call_prom("finddevice", 1, 1, ADDR(se->path));
++              if (!PHANDLE_VALID(node)) {
++                      prom_printf("fixup_device_tree_efika: ",
++                              "skipped entry %x - not found\n", i);
++                      continue;
++              }
++
++              rv = prom_setprop(node, se->path, se->property,
++                                      se->value, se->value_len );
++              if (rv == PROM_ERROR)
++                      prom_printf("fixup_device_tree_efika: ",
++                              "skipped entry %x - setprop error\n", i);
++      }
++}
++#else
++#define fixup_device_tree_efika()
++#endif
++
+ static void __init fixup_device_tree(void)
+ {
+       fixup_device_tree_maple();
+       fixup_device_tree_chrp();
+       fixup_device_tree_pmac();
++      fixup_device_tree_efika();
+ }
+ static void __init prom_find_boot_cpu(void)
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0004-powerpc-Use-common-52xx-of_platform-probe-code-for-EFIKA.txt b/packages/linux/linux-efika-2.6.20/0004-powerpc-Use-common-52xx-of_platform-probe-code-for-EFIKA.txt
new file mode 100644 (file)
index 0000000..763d532
--- /dev/null
@@ -0,0 +1,106 @@
+From ae911446f91481cf26e6dc5edef034a50a6c410c Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Sat, 23 Dec 2006 20:33:30 +0100
+Subject: [PATCH] [PATCH] powerpc: Use common 52xx of_platform probe code for EFIKA
+
+Now that the device tree has the good properties, we can
+remove all the efika_init code by a single call to common code.
+
+While we're modifying that file, a few whitespaces/alignement/typo
+fixes are made (nothing significant).
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ arch/powerpc/platforms/52xx/efika-setup.c |   64 ++++++++---------------------
+ 1 files changed, 18 insertions(+), 46 deletions(-)
+
+diff --git a/arch/powerpc/platforms/52xx/efika-setup.c b/arch/powerpc/platforms/52xx/efika-setup.c
+index 110c980..d61ce84 100644
+--- a/arch/powerpc/platforms/52xx/efika-setup.c
++++ b/arch/powerpc/platforms/52xx/efika-setup.c
+@@ -2,7 +2,7 @@
+  *
+  * Efika 5K2 platform setup
+  * Some code really inspired from the lite5200b platform.
+- * 
++ *
+  * Copyright (C) 2006 bplan GmbH
+  *
+  * This file is licensed under the terms of the GNU General Public License
+@@ -81,35 +81,7 @@ static void __init efika_setup_arch(void)
+       efika_pcisetup();
+       if (ppc_md.progress)
+-              ppc_md.progress("Linux/PPC " UTS_RELEASE " runnung on Efika ;-)\n", 0x0);
+-}
+-
+-static void __init efika_init(void)
+-{
+-      struct device_node *np;
+-      struct device_node *cnp = NULL;
+-      const u32 *base;
+-
+-      /* Find every child of the SOC node and add it to of_platform */
+-      np = of_find_node_by_name(NULL, "builtin");
+-      if (np) {
+-              char name[BUS_ID_SIZE];
+-              while ((cnp = of_get_next_child(np, cnp))) {
+-                      strcpy(name, cnp->name);
+-
+-                      base = get_property(cnp, "reg", NULL);
+-                      if (base == NULL)
+-                              continue;
+-
+-                      snprintf(name+strlen(name), BUS_ID_SIZE, "@%x", *base);
+-                      of_platform_device_create(cnp, name, NULL);
+-
+-                      printk(KERN_INFO EFIKA_PLATFORM_NAME" : Added %s (type '%s' at '%s') to the known devices\n", name, cnp->type, cnp->full_name);
+-              }
+-      }
+-
+-      if (ppc_md.progress)
+-              ppc_md.progress("  Have fun with your Efika!    ", 0x7777);
++              ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0);
+ }
+ static int __init efika_probe(void)
+@@ -131,20 +103,20 @@ static int __init efika_probe(void)
+ define_machine(efika)
+ {
+-      .name = EFIKA_PLATFORM_NAME,
+-      .probe = efika_probe,
+-      .setup_arch = efika_setup_arch,
+-      .init = efika_init,
+-      .show_cpuinfo = efika_show_cpuinfo,
+-      .init_IRQ = mpc52xx_init_irq,
+-      .get_irq = mpc52xx_get_irq,
+-      .restart = rtas_restart,
+-      .power_off = rtas_power_off,
+-      .halt = rtas_halt,
+-      .set_rtc_time = rtas_set_rtc_time,
+-      .get_rtc_time = rtas_get_rtc_time,
+-      .progress = rtas_progress,
+-      .get_boot_time = rtas_get_boot_time,
+-      .calibrate_decr = generic_calibrate_decr,
+-      .phys_mem_access_prot = pci_phys_mem_access_prot,
++      .name                   = EFIKA_PLATFORM_NAME,
++      .probe                  = efika_probe,
++      .setup_arch             = efika_setup_arch,
++      .init                   = mpc52xx_declare_of_platform_devices,
++      .show_cpuinfo           = efika_show_cpuinfo,
++      .init_IRQ               = mpc52xx_init_irq,
++      .get_irq                = mpc52xx_get_irq,
++      .restart                = rtas_restart,
++      .power_off              = rtas_power_off,
++      .halt                   = rtas_halt,
++      .set_rtc_time           = rtas_set_rtc_time,
++      .get_rtc_time           = rtas_get_rtc_time,
++      .progress               = rtas_progress,
++      .get_boot_time          = rtas_get_boot_time,
++      .calibrate_decr         = generic_calibrate_decr,
++      .phys_mem_access_prot   = pci_phys_mem_access_prot,
+ };
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0005-powerpc-Restore-proper-link-order-in-platform.txt b/packages/linux/linux-efika-2.6.20/0005-powerpc-Restore-proper-link-order-in-platform.txt
new file mode 100644 (file)
index 0000000..0b4bbe3
--- /dev/null
@@ -0,0 +1,33 @@
+From 720e2caeeff0d9585d5627d29ffd660a5a9d9f88 Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Sat, 23 Dec 2006 20:43:39 +0100
+Subject: [PATCH] [PATCH] powerpc: Restore 'proper' link order in platform
+
+The 52xx was put before CHRP to allow EFIKA to be recognized
+properly. Now the efika tree is fixed up in prom_init so
+no need for this ugly hack. So we restore the 'normal'
+order.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ arch/powerpc/platforms/Makefile |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
+index 507d1b9..44d95ea 100644
+--- a/arch/powerpc/platforms/Makefile
++++ b/arch/powerpc/platforms/Makefile
+@@ -5,9 +5,9 @@ ifeq ($(CONFIG_PPC64),y)
+ obj-$(CONFIG_PPC_PMAC)                += powermac/
+ endif
+ endif
+-obj-$(CONFIG_PPC_MPC52xx)     += 52xx/
+ obj-$(CONFIG_PPC_CHRP)                += chrp/
+ obj-$(CONFIG_4xx)             += 4xx/
++obj-$(CONFIG_PPC_MPC52xx)     += 52xx/
+ obj-$(CONFIG_PPC_83xx)                += 83xx/
+ obj-$(CONFIG_PPC_85xx)                += 85xx/
+ obj-$(CONFIG_PPC_86xx)                += 86xx/
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt b/packages/linux/linux-efika-2.6.20/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt
new file mode 100644 (file)
index 0000000..39f6fef
--- /dev/null
@@ -0,0 +1,236 @@
+From 9282a04f14cef512736ac4a895fb48456e6a8989 Mon Sep 17 00:00:00 2001
+From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Date: Thu, 14 Dec 2006 14:13:26 +1100
+Subject: [PATCH] [PATCH] Rework the OHCI quirk mecanism as suggested by David
+
+This patch applies David Brownell's suggestion for reworking the
+OHCI quirk mechanism via a table of PCI IDs. It adapts the existing
+quirks to use that mechanism.
+
+This also moves the quirks to reset() as suggested by the comment
+in there. This is necessary as we need to have the endian properly
+set before we try to init the controller.
+
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Acked-by: David Brownell <dbrownell@users.sourceforge.net>
+
+ drivers/usb/host/ohci-pci.c |  173 +++++++++++++++++++++++++++-----------------
+ 1 file changed, 110 insertions(+), 63 deletions(-)
+---
+ drivers/usb/host/ohci-pci.c |  173 +++++++++++++++++++++++++++----------------
+ 1 files changed, 110 insertions(+), 63 deletions(-)
+
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 596e0b4..82fbec3 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -20,79 +20,128 @@
+ /*-------------------------------------------------------------------------*/
+-static int
+-ohci_pci_reset (struct usb_hcd *hcd)
++/* AMD 756, for most chips (early revs), corrupts register
++ * values on read ... so enable the vendor workaround.
++ */
++static int __devinit ohci_quirk_amd756(struct usb_hcd *hcd)
+ {
+       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+-      ohci_hcd_init (ohci);
+-      return ohci_init (ohci);
++      ohci->flags = OHCI_QUIRK_AMD756;
++      ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
++
++      /* also erratum 10 (suspend/resume issues) */
++      device_init_wakeup(&hcd->self.root_hub->dev, 0);
++
++      return 0;
+ }
+-static int __devinit
+-ohci_pci_start (struct usb_hcd *hcd)
++/* Apple's OHCI driver has a lot of bizarre workarounds
++ * for this chip.  Evidently control and bulk lists
++ * can get confused.  (B&W G3 models, and ...)
++ */
++static int __devinit ohci_quirk_opti(struct usb_hcd *hcd)
+ {
+       struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+-      int             ret;
+-      /* REVISIT this whole block should move to reset(), which handles
+-       * all the other one-time init.
++      ohci_dbg (ohci, "WARNING: OPTi workarounds unavailable\n");
++
++      return 0;
++}
++
++/* Check for NSC87560. We have to look at the bridge (fn1) to
++ * identify the USB (fn2). This quirk might apply to more or
++ * even all NSC stuff.
++ */
++static int __devinit ohci_quirk_ns(struct usb_hcd *hcd)
++{
++      struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
++      struct pci_dev  *b;
++
++      b  = pci_get_slot (pdev->bus, PCI_DEVFN (PCI_SLOT (pdev->devfn), 1));
++      if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
++          && b->vendor == PCI_VENDOR_ID_NS) {
++              struct ohci_hcd *ohci = hcd_to_ohci (hcd);
++
++              ohci->flags |= OHCI_QUIRK_SUPERIO;
++              ohci_dbg (ohci, "Using NSC SuperIO setup\n");
++      }
++      pci_dev_put(b);
++
++      return 0;
++}
++
++/* Check for Compaq's ZFMicro chipset, which needs short
++ * delays before control or bulk queues get re-activated
++ * in finish_unlinks()
++ */
++static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd)
++{
++      struct ohci_hcd *ohci = hcd_to_ohci (hcd);
++
++      ohci->flags |= OHCI_QUIRK_ZFMICRO;
++      ohci_dbg (ohci, "enabled Compaq ZFMicro chipset quirk\n");
++
++      return 0;
++}
++
++
++/* List of quirks for OHCI */
++static const struct pci_device_id ohci_pci_quirks[] = {
++      {
++              PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x740c),
++              .driver_data = (unsigned long)ohci_quirk_amd756,
++      },
++      {
++              PCI_DEVICE(PCI_VENDOR_ID_OPTI, 0xc861),
++              .driver_data = (unsigned long)ohci_quirk_opti,
++      },
++      {
++              PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_ANY_ID),
++              .driver_data = (unsigned long)ohci_quirk_ns,
++      },
++      {
++              PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xa0f8),
++              .driver_data = (unsigned long)ohci_quirk_zfmicro,
++      },
++      /* FIXME for some of the early AMD 760 southbridges, OHCI
++       * won't work at all.  blacklist them.
+        */
++      {},
++};
++
++static int ohci_pci_reset (struct usb_hcd *hcd)
++{
++      struct ohci_hcd *ohci = hcd_to_ohci (hcd);
++      int ret = 0;
++
+       if (hcd->self.controller) {
+               struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
++              const struct pci_device_id *quirk_id;
+-              /* AMD 756, for most chips (early revs), corrupts register
+-               * values on read ... so enable the vendor workaround.
+-               */
+-              if (pdev->vendor == PCI_VENDOR_ID_AMD
+-                              && pdev->device == 0x740c) {
+-                      ohci->flags = OHCI_QUIRK_AMD756;
+-                      ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
+-                      /* also erratum 10 (suspend/resume issues) */
+-                      device_init_wakeup(&hcd->self.root_hub->dev, 0);
++              quirk_id = pci_match_id(ohci_pci_quirks, pdev);
++              if (quirk_id != NULL) {
++                      int (*quirk)(struct usb_hcd *ohci);
++                      quirk = (void *)quirk_id->driver_data;
++                      ret = quirk(hcd);
+               }
++      }
++      if (ret == 0) {
++              ohci_hcd_init (ohci);
++              return ohci_init (ohci);
++      }
++      return ret;
++}
+-              /* FIXME for some of the early AMD 760 southbridges, OHCI
+-               * won't work at all.  blacklist them.
+-               */
+-
+-              /* Apple's OHCI driver has a lot of bizarre workarounds
+-               * for this chip.  Evidently control and bulk lists
+-               * can get confused.  (B&W G3 models, and ...)
+-               */
+-              else if (pdev->vendor == PCI_VENDOR_ID_OPTI
+-                              && pdev->device == 0xc861) {
+-                      ohci_dbg (ohci,
+-                              "WARNING: OPTi workarounds unavailable\n");
+-              }
+-              /* Check for NSC87560. We have to look at the bridge (fn1) to
+-               * identify the USB (fn2). This quirk might apply to more or
+-               * even all NSC stuff.
+-               */
+-              else if (pdev->vendor == PCI_VENDOR_ID_NS) {
+-                      struct pci_dev  *b;
+-
+-                      b  = pci_get_slot (pdev->bus,
+-                                      PCI_DEVFN (PCI_SLOT (pdev->devfn), 1));
+-                      if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
+-                                      && b->vendor == PCI_VENDOR_ID_NS) {
+-                              ohci->flags |= OHCI_QUIRK_SUPERIO;
+-                              ohci_dbg (ohci, "Using NSC SuperIO setup\n");
+-                      }
+-                      pci_dev_put(b);
+-              }
++static int __devinit ohci_pci_start (struct usb_hcd *hcd)
++{
++      struct ohci_hcd *ohci = hcd_to_ohci (hcd);
++      int             ret;
+-              /* Check for Compaq's ZFMicro chipset, which needs short
+-               * delays before control or bulk queues get re-activated
+-               * in finish_unlinks()
+-               */
+-              else if (pdev->vendor == PCI_VENDOR_ID_COMPAQ
+-                              && pdev->device  == 0xa0f8) {
+-                      ohci->flags |= OHCI_QUIRK_ZFMICRO;
+-                      ohci_dbg (ohci,
+-                              "enabled Compaq ZFMicro chipset quirk\n");
+-              }
++#ifdef CONFIG_PM /* avoid warnings about unused pdev */
++      if (hcd->self.controller) {
++              struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+               /* RWC may not be set for add-in PCI cards, since boot
+                * firmware probably ignored them.  This transfers PCI
+@@ -101,16 +150,14 @@ ohci_pci_start (struct usb_hcd *hcd)
+               if (device_may_wakeup(&pdev->dev))
+                       ohci->hc_control |= OHCI_CTRL_RWC;
+       }
++#endif /* CONFIG_PM */
+-      /* NOTE: there may have already been a first reset, to
+-       * keep bios/smm irqs from making trouble
+-       */
+-      if ((ret = ohci_run (ohci)) < 0) {
++      ret = ohci_run (ohci);
++      if (ret < 0) {
+               ohci_err (ohci, "can't start\n");
+               ohci_stop (hcd);
+-              return ret;
+       }
+-      return 0;
++      return ret;
+ }
+ #ifdef        CONFIG_PM
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0007-Implement-support-for-split-endian-OHCI.txt b/packages/linux/linux-efika-2.6.20/0007-Implement-support-for-split-endian-OHCI.txt
new file mode 100644 (file)
index 0000000..f49e0cf
--- /dev/null
@@ -0,0 +1,367 @@
+From a87f8738eb3651b7eea1feae793def3a48dc36c6 Mon Sep 17 00:00:00 2001
+From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Date: Thu, 14 Dec 2006 14:13:28 +1100
+Subject: [PATCH] [PATCH] Implement support for "split" endian OHCI
+
+This patch separates support for big endian MMIO register access
+and big endian descriptors in order to support the Toshiba SCC
+implementation which has big endian registers but little endian
+in-memory descriptors.
+
+It simplifies the access functions a bit in ohci.h while at it.
+
+Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Acked-by: David Brownell <dbrownell@users.sourceforge.net>
+
+ drivers/usb/host/Kconfig        |   10 ++
+ drivers/usb/host/ohci-pci.c     |   26 +++++++
+ drivers/usb/host/ohci-ppc-soc.c |    2
+ drivers/usb/host/ohci.h         |  147 +++++++++++++++++++++++++---------------
+ 4 files changed, 130 insertions(+), 55 deletions(-)
+---
+ drivers/usb/host/Kconfig        |   10 ++-
+ drivers/usb/host/ohci-pci.c     |   26 +++++++
+ drivers/usb/host/ohci-ppc-soc.c |    2 +-
+ drivers/usb/host/ohci.h         |  147 +++++++++++++++++++++++++--------------
+ 4 files changed, 130 insertions(+), 55 deletions(-)
+
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index cc60759..faabce8 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -101,7 +101,8 @@ config USB_OHCI_HCD_PPC_SOC
+       bool "OHCI support for on-chip PPC USB controller"
+       depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
+       default y
+-      select USB_OHCI_BIG_ENDIAN
++      select USB_OHCI_BIG_ENDIAN_DESC
++      select USB_OHCI_BIG_ENDIAN_MMIO
+       ---help---
+         Enables support for the USB controller on the MPC52xx or
+         STB03xxx processor chip.  If unsure, say Y.
+@@ -115,7 +116,12 @@ config USB_OHCI_HCD_PCI
+         Enables support for PCI-bus plug-in USB controller cards.
+         If unsure, say Y.
+-config USB_OHCI_BIG_ENDIAN
++config USB_OHCI_BIG_ENDIAN_DESC
++      bool
++      depends on USB_OHCI_HCD
++      default n
++
++config USB_OHCI_BIG_ENDIAN_MMIO
+       bool
+       depends on USB_OHCI_HCD
+       default n
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 82fbec3..292daf0 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -85,6 +85,27 @@ static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd)
+       return 0;
+ }
++/* Check for Toshiba SCC OHCI which has big endian registers
++ * and little endian in memory data structures
++ */
++static int __devinit ohci_quirk_toshiba_scc(struct usb_hcd *hcd)
++{
++      struct ohci_hcd *ohci = hcd_to_ohci (hcd);
++
++      /* That chip is only present in the southbridge of some
++       * cell based platforms which are supposed to select
++       * CONFIG_USB_OHCI_BIG_ENDIAN_MMIO. We verify here if
++       * that was the case though.
++       */
++#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
++      ohci->flags |= OHCI_QUIRK_BE_MMIO;
++      ohci_dbg (ohci, "enabled big endian Toshiba quirk\n");
++      return 0;
++#else
++      ohci_err (ohci, "unsupported big endian Toshiba quirk\n");
++      return -ENXIO;
++#endif
++}
+ /* List of quirks for OHCI */
+ static const struct pci_device_id ohci_pci_quirks[] = {
+@@ -104,9 +125,14 @@ static const struct pci_device_id ohci_pci_quirks[] = {
+               PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xa0f8),
+               .driver_data = (unsigned long)ohci_quirk_zfmicro,
+       },
++      {
++              PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, 0x01b6),
++              .driver_data = (unsigned long)ohci_quirk_toshiba_scc,
++      },
+       /* FIXME for some of the early AMD 760 southbridges, OHCI
+        * won't work at all.  blacklist them.
+        */
++
+       {},
+ };
+diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
+index e1a7eb8..c7ce8e6 100644
+--- a/drivers/usb/host/ohci-ppc-soc.c
++++ b/drivers/usb/host/ohci-ppc-soc.c
+@@ -72,7 +72,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
+       }
+       ohci = hcd_to_ohci(hcd);
+-      ohci->flags |= OHCI_BIG_ENDIAN;
++      ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
+       ohci_hcd_init(ohci);
+       retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
+diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
+index 405257f..fc7c161 100644
+--- a/drivers/usb/host/ohci.h
++++ b/drivers/usb/host/ohci.h
+@@ -394,8 +394,9 @@ struct ohci_hcd {
+ #define       OHCI_QUIRK_AMD756       0x01                    /* erratum #4 */
+ #define       OHCI_QUIRK_SUPERIO      0x02                    /* natsemi */
+ #define       OHCI_QUIRK_INITRESET    0x04                    /* SiS, OPTi, ... */
+-#define       OHCI_BIG_ENDIAN         0x08                    /* big endian HC */
+-#define       OHCI_QUIRK_ZFMICRO      0x10                    /* Compaq ZFMicro chipset*/
++#define       OHCI_QUIRK_BE_DESC      0x08                    /* BE descriptors */
++#define       OHCI_QUIRK_BE_MMIO      0x10                    /* BE registers */
++#define       OHCI_QUIRK_ZFMICRO      0x20                    /* Compaq ZFMicro chipset*/
+       // there are also chip quirks/bugs in init logic
+ };
+@@ -439,117 +440,156 @@ static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci)
+  * a minority (notably the IBM STB04XXX and the Motorola MPC5200
+  * processors) implement them in big endian format.
+  *
++ * In addition some more exotic implementations like the Toshiba
++ * Spider (aka SCC) cell southbridge are "mixed" endian, that is,
++ * they have a different endianness for registers vs. in-memory
++ * descriptors.
++ *
+  * This attempts to support either format at compile time without a
+  * runtime penalty, or both formats with the additional overhead
+  * of checking a flag bit.
++ *
++ * That leads to some tricky Kconfig rules howevber. There are
++ * different defaults based on some arch/ppc platforms, though
++ * the basic rules are:
++ *
++ * Controller type              Kconfig options needed
++ * ---------------              ----------------------
++ * little endian                CONFIG_USB_OHCI_LITTLE_ENDIAN
++ *
++ * fully big endian             CONFIG_USB_OHCI_BIG_ENDIAN_DESC _and_
++ *                              CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
++ *
++ * mixed endian                 CONFIG_USB_OHCI_LITTLE_ENDIAN _and_
++ *                              CONFIG_USB_OHCI_BIG_ENDIAN_{MMIO,DESC}
++ *
++ * (If you have a mixed endian controller, you -must- also define
++ * CONFIG_USB_OHCI_LITTLE_ENDIAN or things will not work when building
++ * both your mixed endian and a fully big endian controller support in
++ * the same kernel image).
+  */
+-#ifdef CONFIG_USB_OHCI_BIG_ENDIAN
++#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_DESC
++#ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN
++#define big_endian_desc(ohci) (ohci->flags & OHCI_QUIRK_BE_DESC)
++#else
++#define big_endian_desc(ohci) 1               /* only big endian */
++#endif
++#else
++#define big_endian_desc(ohci) 0               /* only little endian */
++#endif
++#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
+ #ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN
+-#define big_endian(ohci)      (ohci->flags & OHCI_BIG_ENDIAN) /* either */
++#define big_endian_mmio(ohci) (ohci->flags & OHCI_QUIRK_BE_MMIO)
++#else
++#define big_endian_mmio(ohci) 1               /* only big endian */
++#endif
+ #else
+-#define big_endian(ohci)      1               /* only big endian */
++#define big_endian_mmio(ohci) 0               /* only little endian */
+ #endif
+ /*
+  * Big-endian read/write functions are arch-specific.
+  * Other arches can be added if/when they're needed.
++ *
++ * REVISIT: arch/powerpc now has readl/writel_be, so the
++ * definition below can die once the STB04xxx support is
++ * finally ported over.
+  */
+-#if defined(CONFIG_PPC)
++#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE)
+ #define readl_be(addr)                in_be32((__force unsigned *)addr)
+ #define writel_be(val, addr)  out_be32((__force unsigned *)addr, val)
+ #endif
+-static inline unsigned int ohci_readl (const struct ohci_hcd *ohci,
+-                                                      __hc32 __iomem * regs)
++static inline unsigned int _ohci_readl (const struct ohci_hcd *ohci,
++                                      __hc32 __iomem * regs)
+ {
+-      return big_endian(ohci) ? readl_be (regs) : readl ((__force u32 *)regs);
++      return big_endian_mmio(ohci) ?
++              readl_be ((__force u32 *)regs) :
++              readl ((__force u32 *)regs);
+ }
+-static inline void ohci_writel (const struct ohci_hcd *ohci,
+-                              const unsigned int val, __hc32 __iomem *regs)
++static inline void _ohci_writel (const struct ohci_hcd *ohci,
++                               const unsigned int val, __hc32 __iomem *regs)
+ {
+-      big_endian(ohci) ? writel_be (val, regs) :
+-                         writel (val, (__force u32 *)regs);
++      big_endian_mmio(ohci) ?
++              writel_be (val, (__force u32 *)regs) :
++              writel (val, (__force u32 *)regs);
+ }
+-#else /* !CONFIG_USB_OHCI_BIG_ENDIAN */
+-
+-#define big_endian(ohci)      0               /* only little endian */
+-
+ #ifdef CONFIG_ARCH_LH7A404
+-      /* Marc Singer: at the time this code was written, the LH7A404
+-       * had a problem reading the USB host registers.  This
+-       * implementation of the ohci_readl function performs the read
+-       * twice as a work-around.
+-       */
+-static inline unsigned int
+-ohci_readl (const struct ohci_hcd *ohci, const __hc32 *regs)
+-{
+-      *(volatile __force unsigned int*) regs;
+-      return *(volatile __force unsigned int*) regs;
+-}
++/* Marc Singer: at the time this code was written, the LH7A404
++ * had a problem reading the USB host registers.  This
++ * implementation of the ohci_readl function performs the read
++ * twice as a work-around.
++ */
++#define ohci_readl(o,r)               (_ohci_readl(o,r),_ohci_readl(o,r))
++#define ohci_writel(o,v,r)    _ohci_writel(o,v,r)
+ #else
+-      /* Standard version of ohci_readl uses standard, platform
+-       * specific implementation. */
+-static inline unsigned int
+-ohci_readl (const struct ohci_hcd *ohci, __hc32 __iomem * regs)
+-{
+-      return readl(regs);
+-}
++#define ohci_readl(o,r)               _ohci_readl(o,r)
++#define ohci_writel(o,v,r)    _ohci_writel(o,v,r)
+ #endif
+-static inline void ohci_writel (const struct ohci_hcd *ohci,
+-                              const unsigned int val, __hc32 __iomem *regs)
+-{
+-      writel (val, regs);
+-}
+-
+-#endif        /* !CONFIG_USB_OHCI_BIG_ENDIAN */
+ /*-------------------------------------------------------------------------*/
+ /* cpu to ohci */
+ static inline __hc16 cpu_to_hc16 (const struct ohci_hcd *ohci, const u16 x)
+ {
+-      return big_endian(ohci) ? (__force __hc16)cpu_to_be16(x) : (__force __hc16)cpu_to_le16(x);
++      return big_endian_desc(ohci) ?
++              (__force __hc16)cpu_to_be16(x) :
++              (__force __hc16)cpu_to_le16(x);
+ }
+ static inline __hc16 cpu_to_hc16p (const struct ohci_hcd *ohci, const u16 *x)
+ {
+-      return big_endian(ohci) ? cpu_to_be16p(x) : cpu_to_le16p(x);
++      return big_endian_desc(ohci) ?
++              cpu_to_be16p(x) :
++              cpu_to_le16p(x);
+ }
+ static inline __hc32 cpu_to_hc32 (const struct ohci_hcd *ohci, const u32 x)
+ {
+-      return big_endian(ohci) ? (__force __hc32)cpu_to_be32(x) : (__force __hc32)cpu_to_le32(x);
++      return big_endian_desc(ohci) ?
++              (__force __hc32)cpu_to_be32(x) :
++              (__force __hc32)cpu_to_le32(x);
+ }
+ static inline __hc32 cpu_to_hc32p (const struct ohci_hcd *ohci, const u32 *x)
+ {
+-      return big_endian(ohci) ? cpu_to_be32p(x) : cpu_to_le32p(x);
++      return big_endian_desc(ohci) ?
++              cpu_to_be32p(x) :
++              cpu_to_le32p(x);
+ }
+ /* ohci to cpu */
+ static inline u16 hc16_to_cpu (const struct ohci_hcd *ohci, const __hc16 x)
+ {
+-      return big_endian(ohci) ? be16_to_cpu((__force __be16)x) : le16_to_cpu((__force __le16)x);
++      return big_endian_desc(ohci) ?
++              be16_to_cpu((__force __be16)x) :
++              le16_to_cpu((__force __le16)x);
+ }
+ static inline u16 hc16_to_cpup (const struct ohci_hcd *ohci, const __hc16 *x)
+ {
+-      return big_endian(ohci) ? be16_to_cpup((__force __be16 *)x) : le16_to_cpup((__force __le16 *)x);
++      return big_endian_desc(ohci) ?
++              be16_to_cpup((__force __be16 *)x) :
++              le16_to_cpup((__force __le16 *)x);
+ }
+ static inline u32 hc32_to_cpu (const struct ohci_hcd *ohci, const __hc32 x)
+ {
+-      return big_endian(ohci) ? be32_to_cpu((__force __be32)x) : le32_to_cpu((__force __le32)x);
++      return big_endian_desc(ohci) ?
++              be32_to_cpu((__force __be32)x) :
++              le32_to_cpu((__force __le32)x);
+ }
+ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x)
+ {
+-      return big_endian(ohci) ? be32_to_cpup((__force __be32 *)x) : le32_to_cpup((__force __le32 *)x);
++      return big_endian_desc(ohci) ?
++              be32_to_cpup((__force __be32 *)x) :
++              le32_to_cpup((__force __le32 *)x);
+ }
+ /*-------------------------------------------------------------------------*/
+@@ -557,6 +597,9 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x)
+ /* HCCA frame number is 16 bits, but is accessed as 32 bits since not all
+  * hardware handles 16 bit reads.  That creates a different confusion on
+  * some big-endian SOC implementations.  Same thing happens with PSW access.
++ *
++ * FIXME: Deal with that as a runtime quirk when STB03xxx is ported over
++ * to arch/powerpc
+  */
+ #ifdef CONFIG_STB03xxx
+@@ -568,7 +611,7 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x)
+ static inline u16 ohci_frame_no(const struct ohci_hcd *ohci)
+ {
+       u32 tmp;
+-      if (big_endian(ohci)) {
++      if (big_endian_desc(ohci)) {
+               tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no);
+               tmp >>= OHCI_BE_FRAME_NO_SHIFT;
+       } else
+@@ -580,7 +623,7 @@ static inline u16 ohci_frame_no(const struct ohci_hcd *ohci)
+ static inline __hc16 *ohci_hwPSWp(const struct ohci_hcd *ohci,
+                                  const struct td *td, int index)
+ {
+-      return (__hc16 *)(big_endian(ohci) ?
++      return (__hc16 *)(big_endian_desc(ohci) ?
+                       &td->hwPSW[index ^ 1] : &td->hwPSW[index]);
+ }
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0008-ohci-Rework-bus-glue-integration-to-allow-several-at-once.txt b/packages/linux/linux-efika-2.6.20/0008-ohci-Rework-bus-glue-integration-to-allow-several-at-once.txt
new file mode 100644 (file)
index 0000000..c209ee0
--- /dev/null
@@ -0,0 +1,470 @@
+From 51294aa1482ea961a3e51ddac587b70b7c1c8ba0 Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Wed, 13 Dec 2006 20:35:37 +0100
+Subject: [PATCH] [PATCH] ohci: Rework bus glue integration to allow several at once
+
+The previous model had the module_init & module_exit function in the
+bus glue .c files themselves. That's a problem if several glues need
+to be selected at once and the driver is built has module. This case
+is quite common in embedded system where you want to handle both the
+integrated ohci controller and some extra controller on PCI.
+
+The ohci-hcd.c file now provide the module_init & module_exit and
+appropriate driver registering/unregistering is done conditionally,
+using #ifdefs.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+Acked-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/host/ohci-at91.c    |   15 ------
+ drivers/usb/host/ohci-au1xxx.c  |   16 ------
+ drivers/usb/host/ohci-ep93xx.c  |   12 -----
+ drivers/usb/host/ohci-hcd.c     |   98 +++++++++++++++++++++++++++++++++------
+ drivers/usb/host/ohci-lh7a404.c |   16 ------
+ drivers/usb/host/ohci-omap.c    |   19 --------
+ drivers/usb/host/ohci-pci.c     |   20 --------
+ drivers/usb/host/ohci-pnx4008.c |   12 -----
+ drivers/usb/host/ohci-pnx8550.c |   16 ------
+ drivers/usb/host/ohci-ppc-soc.c |   16 ------
+ drivers/usb/host/ohci-pxa27x.c  |   16 ------
+ drivers/usb/host/ohci-s3c2410.c |   12 -----
+ drivers/usb/host/ohci-sa1111.c  |   16 ------
+ 13 files changed, 83 insertions(+), 201 deletions(-)
+
+diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
+index cc40551..53f62cf 100644
+--- a/drivers/usb/host/ohci-at91.c
++++ b/drivers/usb/host/ohci-at91.c
+@@ -320,18 +320,3 @@ static struct platform_driver ohci_hcd_at91_driver = {
+       },
+ };
+-static int __init ohci_hcd_at91_init (void)
+-{
+-      if (usb_disabled())
+-              return -ENODEV;
+-
+-      return platform_driver_register(&ohci_hcd_at91_driver);
+-}
+-
+-static void __exit ohci_hcd_at91_cleanup (void)
+-{
+-      platform_driver_unregister(&ohci_hcd_at91_driver);
+-}
+-
+-module_init (ohci_hcd_at91_init);
+-module_exit (ohci_hcd_at91_cleanup);
+diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
+index e70b243..663a060 100644
+--- a/drivers/usb/host/ohci-au1xxx.c
++++ b/drivers/usb/host/ohci-au1xxx.c
+@@ -345,19 +345,3 @@ static struct platform_driver ohci_hcd_au1xxx_driver = {
+       },
+ };
+-static int __init ohci_hcd_au1xxx_init (void)
+-{
+-      pr_debug (DRIVER_INFO " (Au1xxx)");
+-      pr_debug ("block sizes: ed %d td %d\n",
+-              sizeof (struct ed), sizeof (struct td));
+-
+-      return platform_driver_register(&ohci_hcd_au1xxx_driver);
+-}
+-
+-static void __exit ohci_hcd_au1xxx_cleanup (void)
+-{
+-      platform_driver_unregister(&ohci_hcd_au1xxx_driver);
+-}
+-
+-module_init (ohci_hcd_au1xxx_init);
+-module_exit (ohci_hcd_au1xxx_cleanup);
+diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
+index 43ae696..e9974c3 100644
+--- a/drivers/usb/host/ohci-ep93xx.c
++++ b/drivers/usb/host/ohci-ep93xx.c
+@@ -214,15 +214,3 @@ static struct platform_driver ohci_hcd_ep93xx_driver = {
+       },
+ };
+-static int __init ohci_hcd_ep93xx_init(void)
+-{
+-      return platform_driver_register(&ohci_hcd_ep93xx_driver);
+-}
+-
+-static void __exit ohci_hcd_ep93xx_cleanup(void)
+-{
+-      platform_driver_unregister(&ohci_hcd_ep93xx_driver);
+-}
+-
+-module_init(ohci_hcd_ep93xx_init);
+-module_exit(ohci_hcd_ep93xx_cleanup);
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index c1c1d87..9926b8f 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -855,63 +855,131 @@ MODULE_LICENSE ("GPL");
+ #ifdef CONFIG_PCI
+ #include "ohci-pci.c"
++#define PCI_DRIVER            ohci_pci_driver
+ #endif
+ #ifdef CONFIG_SA1111
+ #include "ohci-sa1111.c"
++#define SA1111_DRIVER         ohci_hcd_sa1111_driver
+ #endif
+ #ifdef CONFIG_ARCH_S3C2410
+ #include "ohci-s3c2410.c"
++#define PLATFORM_DRIVER               ohci_hcd_s3c2410_driver
+ #endif
+ #ifdef CONFIG_ARCH_OMAP
+ #include "ohci-omap.c"
++#define PLATFORM_DRIVER               ohci_hcd_omap_driver
+ #endif
+ #ifdef CONFIG_ARCH_LH7A404
+ #include "ohci-lh7a404.c"
++#define PLATFORM_DRIVER               ohci_hcd_lh7a404_driver
+ #endif
+ #ifdef CONFIG_PXA27x
+ #include "ohci-pxa27x.c"
++#define PLATFORM_DRIVER               ohci_hcd_pxa27x_driver
+ #endif
+ #ifdef CONFIG_ARCH_EP93XX
+ #include "ohci-ep93xx.c"
++#define PLATFORM_DRIVER               ohci_hcd_ep93xx_driver
+ #endif
+ #ifdef CONFIG_SOC_AU1X00
+ #include "ohci-au1xxx.c"
++#define PLATFORM_DRIVER               ohci_hcd_au1xxx_driver
+ #endif
+-#ifdef CONFIG_PNX8550
+-#include "ohci-pnx8550.c"
+-#endif
++#ifdef CONFIG_PNX8550 
++#include "ohci-pnx8550.c" 
++#define PLATFORM_DRIVER               ohci_hcd_pnx8550_driver
++#endif 
+ #ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
+ #include "ohci-ppc-soc.c"
++#define PLATFORM_DRIVER               ohci_hcd_ppc_soc_driver
+ #endif
+ #ifdef CONFIG_ARCH_AT91
+ #include "ohci-at91.c"
++#define PLATFORM_DRIVER               ohci_hcd_at91_driver
+ #endif
+ #ifdef CONFIG_ARCH_PNX4008
+ #include "ohci-pnx4008.c"
++#define PLATFORM_DRIVER               usb_hcd_pnx4008_driver
+ #endif
+-#if !(defined(CONFIG_PCI) \
+-      || defined(CONFIG_SA1111) \
+-      || defined(CONFIG_ARCH_S3C2410) \
+-      || defined(CONFIG_ARCH_OMAP) \
+-      || defined (CONFIG_ARCH_LH7A404) \
+-      || defined (CONFIG_PXA27x) \
+-      || defined (CONFIG_ARCH_EP93XX) \
+-      || defined (CONFIG_SOC_AU1X00) \
+-      || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
+-      || defined (CONFIG_ARCH_AT91) \
+-      || defined (CONFIG_ARCH_PNX4008) \
+-      )
++
++#if   !defined(PCI_DRIVER) &&         \
++      !defined(PLATFORM_DRIVER) &&    \
++      !defined(SA1111_DRIVER)
+ #error "missing bus glue for ohci-hcd"
+ #endif
++
++static int __init ohci_hcd_mod_init(void)
++{
++      int retval = 0;
++      int ls = 0;
++
++      if (usb_disabled())
++              return -ENODEV;
++
++      printk (KERN_DEBUG "%s: " DRIVER_INFO "\n", hcd_name);
++      pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
++              sizeof (struct ed), sizeof (struct td));
++
++#ifdef PLATFORM_DRIVER
++      retval = platform_driver_register(&PLATFORM_DRIVER);
++      if (retval < 0)
++              return retval;
++      ls++;
++#endif
++
++#ifdef SA1111_DRIVER
++      retval = sa1111_driver_register(&SA1111_DRIVER);
++      if (retval < 0)
++              goto error;
++      ls++;
++#endif
++
++#ifdef PCI_DRIVER
++      retval = pci_register_driver(&PCI_DRIVER);
++      if (retval < 0)
++              goto error;
++      ls++;
++#endif
++
++      return retval;
++
++      /* Error path */
++error:
++#ifdef PLATFORM_DRIVER
++      if (ls--)
++              platform_driver_unregister(&PLATFORM_DRIVER);
++#endif
++#ifdef SA1111_DRIVER
++      if (ls--)
++              sa1111_driver_unregister(&SA1111_DRIVER);
++#endif
++      return retval;
++}
++module_init(ohci_hcd_mod_init);
++
++static void __exit ohci_hcd_mod_exit(void)
++{
++#ifdef PCI_DRIVER
++      pci_unregister_driver(&PCI_DRIVER);
++#endif
++#ifdef SA1111_DRIVER
++      sa1111_driver_unregister(&SA1111_DRIVER);
++#endif
++#ifdef PLATFORM_DRIVER
++      platform_driver_unregister(&PLATFORM_DRIVER);
++#endif
++}
++module_exit(ohci_hcd_mod_exit);
++
+diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
+index e9807cf..4a043ab 100644
+--- a/drivers/usb/host/ohci-lh7a404.c
++++ b/drivers/usb/host/ohci-lh7a404.c
+@@ -251,19 +251,3 @@ static struct platform_driver ohci_hcd_lh7a404_driver = {
+       },
+ };
+-static int __init ohci_hcd_lh7a404_init (void)
+-{
+-      pr_debug (DRIVER_INFO " (LH7A404)");
+-      pr_debug ("block sizes: ed %d td %d\n",
+-              sizeof (struct ed), sizeof (struct td));
+-
+-      return platform_driver_register(&ohci_hcd_lh7a404_driver);
+-}
+-
+-static void __exit ohci_hcd_lh7a404_cleanup (void)
+-{
+-      platform_driver_unregister(&ohci_hcd_lh7a404_driver);
+-}
+-
+-module_init (ohci_hcd_lh7a404_init);
+-module_exit (ohci_hcd_lh7a404_cleanup);
+diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
+index 27be1f9..5cfa3d1 100644
+--- a/drivers/usb/host/ohci-omap.c
++++ b/drivers/usb/host/ohci-omap.c
+@@ -544,22 +544,3 @@ static struct platform_driver ohci_hcd_omap_driver = {
+       },
+ };
+-static int __init ohci_hcd_omap_init (void)
+-{
+-      printk (KERN_DEBUG "%s: " DRIVER_INFO " (OMAP)\n", hcd_name);
+-      if (usb_disabled())
+-              return -ENODEV;
+-
+-      pr_debug("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
+-              sizeof (struct ed), sizeof (struct td));
+-
+-      return platform_driver_register(&ohci_hcd_omap_driver);
+-}
+-
+-static void __exit ohci_hcd_omap_cleanup (void)
+-{
+-      platform_driver_unregister(&ohci_hcd_omap_driver);
+-}
+-
+-module_init (ohci_hcd_omap_init);
+-module_exit (ohci_hcd_omap_cleanup);
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index 292daf0..b331ac4 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -311,23 +311,3 @@ static struct pci_driver ohci_pci_driver = {
+       .shutdown =     usb_hcd_pci_shutdown,
+ };
+-
+-static int __init ohci_hcd_pci_init (void)
+-{
+-      printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name);
+-      if (usb_disabled())
+-              return -ENODEV;
+-
+-      pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
+-              sizeof (struct ed), sizeof (struct td));
+-      return pci_register_driver (&ohci_pci_driver);
+-}
+-module_init (ohci_hcd_pci_init);
+-
+-/*-------------------------------------------------------------------------*/
+-
+-static void __exit ohci_hcd_pci_cleanup (void)
+-{
+-      pci_unregister_driver (&ohci_pci_driver);
+-}
+-module_exit (ohci_hcd_pci_cleanup);
+diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
+index 3a8cbfb..893b172 100644
+--- a/drivers/usb/host/ohci-pnx4008.c
++++ b/drivers/usb/host/ohci-pnx4008.c
+@@ -465,15 +465,3 @@ static struct platform_driver usb_hcd_pnx4008_driver = {
+       .remove = usb_hcd_pnx4008_remove,
+ };
+-static int __init usb_hcd_pnx4008_init(void)
+-{
+-      return platform_driver_register(&usb_hcd_pnx4008_driver);
+-}
+-
+-static void __exit usb_hcd_pnx4008_cleanup(void)
+-{
+-      return platform_driver_unregister(&usb_hcd_pnx4008_driver);
+-}
+-
+-module_init(usb_hcd_pnx4008_init);
+-module_exit(usb_hcd_pnx4008_cleanup);
+diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
+index 6922b91..de45eb0 100644
+--- a/drivers/usb/host/ohci-pnx8550.c
++++ b/drivers/usb/host/ohci-pnx8550.c
+@@ -240,19 +240,3 @@ static struct platform_driver ohci_hcd_pnx8550_driver = {
+       .remove         = ohci_hcd_pnx8550_drv_remove,
+ };
+-static int __init ohci_hcd_pnx8550_init (void)
+-{
+-      pr_debug (DRIVER_INFO " (pnx8550)");
+-      pr_debug ("block sizes: ed %d td %d\n",
+-              sizeof (struct ed), sizeof (struct td));
+-
+-      return platform_driver_register(&ohci_hcd_pnx8550_driver);
+-}
+-
+-static void __exit ohci_hcd_pnx8550_cleanup (void)
+-{
+-      platform_driver_unregister(&ohci_hcd_pnx8550_driver);
+-}
+-
+-module_init (ohci_hcd_pnx8550_init);
+-module_exit (ohci_hcd_pnx8550_cleanup);
+diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
+index c7ce8e6..1a2e177 100644
+--- a/drivers/usb/host/ohci-ppc-soc.c
++++ b/drivers/usb/host/ohci-ppc-soc.c
+@@ -208,19 +208,3 @@ static struct platform_driver ohci_hcd_ppc_soc_driver = {
+       },
+ };
+-static int __init ohci_hcd_ppc_soc_init(void)
+-{
+-      pr_debug(DRIVER_INFO " (PPC SOC)\n");
+-      pr_debug("block sizes: ed %d td %d\n", sizeof(struct ed),
+-                                                      sizeof(struct td));
+-
+-      return platform_driver_register(&ohci_hcd_ppc_soc_driver);
+-}
+-
+-static void __exit ohci_hcd_ppc_soc_cleanup(void)
+-{
+-      platform_driver_unregister(&ohci_hcd_ppc_soc_driver);
+-}
+-
+-module_init(ohci_hcd_ppc_soc_init);
+-module_exit(ohci_hcd_ppc_soc_cleanup);
+diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
+index 3bbea84..f1563dc 100644
+--- a/drivers/usb/host/ohci-pxa27x.c
++++ b/drivers/usb/host/ohci-pxa27x.c
+@@ -369,19 +369,3 @@ static struct platform_driver ohci_hcd_pxa27x_driver = {
+       },
+ };
+-static int __init ohci_hcd_pxa27x_init (void)
+-{
+-      pr_debug (DRIVER_INFO " (pxa27x)");
+-      pr_debug ("block sizes: ed %d td %d\n",
+-              sizeof (struct ed), sizeof (struct td));
+-
+-      return platform_driver_register(&ohci_hcd_pxa27x_driver);
+-}
+-
+-static void __exit ohci_hcd_pxa27x_cleanup (void)
+-{
+-      platform_driver_unregister(&ohci_hcd_pxa27x_driver);
+-}
+-
+-module_init (ohci_hcd_pxa27x_init);
+-module_exit (ohci_hcd_pxa27x_cleanup);
+diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
+index b350d45..6829814 100644
+--- a/drivers/usb/host/ohci-s3c2410.c
++++ b/drivers/usb/host/ohci-s3c2410.c
+@@ -501,15 +501,3 @@ static struct platform_driver ohci_hcd_s3c2410_driver = {
+       },
+ };
+-static int __init ohci_hcd_s3c2410_init (void)
+-{
+-      return platform_driver_register(&ohci_hcd_s3c2410_driver);
+-}
+-
+-static void __exit ohci_hcd_s3c2410_cleanup (void)
+-{
+-      platform_driver_unregister(&ohci_hcd_s3c2410_driver);
+-}
+-
+-module_init (ohci_hcd_s3c2410_init);
+-module_exit (ohci_hcd_s3c2410_cleanup);
+diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
+index fe0090e..0f48f2d 100644
+--- a/drivers/usb/host/ohci-sa1111.c
++++ b/drivers/usb/host/ohci-sa1111.c
+@@ -269,19 +269,3 @@ static struct sa1111_driver ohci_hcd_sa1111_driver = {
+       .remove         = ohci_hcd_sa1111_drv_remove,
+ };
+-static int __init ohci_hcd_sa1111_init (void)
+-{
+-      dbg (DRIVER_INFO " (SA-1111)");
+-      dbg ("block sizes: ed %d td %d",
+-              sizeof (struct ed), sizeof (struct td));
+-
+-      return sa1111_driver_register(&ohci_hcd_sa1111_driver);
+-}
+-
+-static void __exit ohci_hcd_sa1111_cleanup (void)
+-{
+-      sa1111_driver_unregister(&ohci_hcd_sa1111_driver);
+-}
+-
+-module_init (ohci_hcd_sa1111_init);
+-module_exit (ohci_hcd_sa1111_cleanup);
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0009-ohci-Add-support-for-OHCI-controller-on-the-of_platform-bus.txt b/packages/linux/linux-efika-2.6.20/0009-ohci-Add-support-for-OHCI-controller-on-the-of_platform-bus.txt
new file mode 100644 (file)
index 0000000..2b53e48
--- /dev/null
@@ -0,0 +1,349 @@
+From 944afcaa19737396ed514e3e845a3db2de9377f3 Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Wed, 13 Dec 2006 21:03:30 +0100
+Subject: [PATCH] [PATCH] ohci: Add support for OHCI controller on the of_platform bus
+
+PPC embedded systems can have a ohci controller builtin. In the
+new model, it will end up as a driver on the of_platform bus,
+this patches takes care of them.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+Acked-by: David Brownell <dbrownell@users.sourceforge.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/usb/host/Kconfig       |   23 ++++-
+ drivers/usb/host/ohci-hcd.c    |   20 ++++
+ drivers/usb/host/ohci-ppc-of.c |  232 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 274 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
+index faabce8..c49715d 100644
+--- a/drivers/usb/host/Kconfig
++++ b/drivers/usb/host/Kconfig
+@@ -107,9 +107,30 @@ config USB_OHCI_HCD_PPC_SOC
+         Enables support for the USB controller on the MPC52xx or
+         STB03xxx processor chip.  If unsure, say Y.
++config USB_OHCI_HCD_PPC_OF
++      bool "OHCI support for PPC USB controller on OF platform bus"
++      depends on USB_OHCI_HCD && PPC_OF
++      default y
++      ---help---
++        Enables support for the USB controller PowerPC present on the
++        OpenFirmware platform bus.
++
++config USB_OHCI_HCD_PPC_OF_BE
++      bool "Support big endian HC"
++      depends on USB_OHCI_HCD_PPC_OF
++      default y
++      select USB_OHCI_BIG_ENDIAN_DESC
++      select USB_OHCI_BIG_ENDIAN_MMIO
++
++config USB_OHCI_HCD_PPC_OF_LE
++      bool "Support little endian HC"
++      depends on USB_OHCI_HCD_PPC_OF
++      default n
++      select USB_OHCI_LITTLE_ENDIAN
++
+ config USB_OHCI_HCD_PCI
+       bool "OHCI support for PCI-bus USB controllers"
+-      depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx)
++      depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF)
+       default y
+       select USB_OHCI_LITTLE_ENDIAN
+       ---help---
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 9926b8f..c6ae1ff 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -914,8 +914,14 @@ MODULE_LICENSE ("GPL");
+ #endif
++#ifdef CONFIG_USB_OHCI_HCD_PPC_OF
++#include "ohci-ppc-of.c"
++#define OF_PLATFORM_DRIVER    ohci_hcd_ppc_of_driver
++#endif
++
+ #if   !defined(PCI_DRIVER) &&         \
+       !defined(PLATFORM_DRIVER) &&    \
++      !defined(OF_PLATFORM_DRIVER) && \
+       !defined(SA1111_DRIVER)
+ #error "missing bus glue for ohci-hcd"
+ #endif
+@@ -939,6 +945,13 @@ static int __init ohci_hcd_mod_init(void)
+       ls++;
+ #endif
++#ifdef OF_PLATFORM_DRIVER
++      retval = of_register_platform_driver(&OF_PLATFORM_DRIVER);
++      if (retval < 0)
++              goto error;
++      ls++;
++#endif
++
+ #ifdef SA1111_DRIVER
+       retval = sa1111_driver_register(&SA1111_DRIVER);
+       if (retval < 0)
+@@ -961,6 +974,10 @@ error:
+       if (ls--)
+               platform_driver_unregister(&PLATFORM_DRIVER);
+ #endif
++#ifdef OF_PLATFORM_DRIVER
++      if (ls--)
++              of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
++#endif
+ #ifdef SA1111_DRIVER
+       if (ls--)
+               sa1111_driver_unregister(&SA1111_DRIVER);
+@@ -977,6 +994,9 @@ static void __exit ohci_hcd_mod_exit(void)
+ #ifdef SA1111_DRIVER
+       sa1111_driver_unregister(&SA1111_DRIVER);
+ #endif
++#ifdef OF_PLATFORM_DRIVER
++      of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
++#endif
+ #ifdef PLATFORM_DRIVER
+       platform_driver_unregister(&PLATFORM_DRIVER);
+ #endif
+diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
+new file mode 100644
+index 0000000..84b555b
+--- /dev/null
++++ b/drivers/usb/host/ohci-ppc-of.c
+@@ -0,0 +1,232 @@
++/*
++ * OHCI HCD (Host Controller Driver) for USB.
++ *
++ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
++ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
++ * (C) Copyright 2002 Hewlett-Packard Company
++ * (C) Copyright 2006 Sylvain Munaut <tnt@246tNt.com>
++ *
++ * Bus glue for OHCI HC on the of_platform bus
++ *
++ * Modified for of_platform bus from ohci-sa1111.c
++ *
++ * This file is licenced under the GPL.
++ */
++
++#include <linux/signal.h>
++
++#include <asm/of_platform.h>
++#include <asm/prom.h>
++
++
++static int __devinit
++ohci_ppc_of_start(struct usb_hcd *hcd)
++{
++      struct ohci_hcd *ohci = hcd_to_ohci(hcd);
++      int             ret;
++
++      if ((ret = ohci_init(ohci)) < 0)
++              return ret;
++
++      if ((ret = ohci_run(ohci)) < 0) {
++              err("can't start %s", ohci_to_hcd(ohci)->self.bus_name);
++              ohci_stop(hcd);
++              return ret;
++      }
++
++      return 0;
++}
++
++static const struct hc_driver ohci_ppc_of_hc_driver = {
++      .description =          hcd_name,
++      .product_desc =         "OF OHCI",
++      .hcd_priv_size =        sizeof(struct ohci_hcd),
++
++      /*
++       * generic hardware linkage
++       */
++      .irq =                  ohci_irq,
++      .flags =                HCD_USB11 | HCD_MEMORY,
++
++      /*
++       * basic lifecycle operations
++       */
++      .start =                ohci_ppc_of_start,
++      .stop =                 ohci_stop,
++      .shutdown =             ohci_shutdown,
++
++      /*
++       * managing i/o requests and associated device resources
++       */
++      .urb_enqueue =          ohci_urb_enqueue,
++      .urb_dequeue =          ohci_urb_dequeue,
++      .endpoint_disable =     ohci_endpoint_disable,
++
++      /*
++       * scheduling support
++       */
++      .get_frame_number =     ohci_get_frame,
++
++      /*
++       * root hub support
++       */
++      .hub_status_data =      ohci_hub_status_data,
++      .hub_control =          ohci_hub_control,
++      .hub_irq_enable =       ohci_rhsc_enable,
++#ifdef        CONFIG_PM
++      .bus_suspend =          ohci_bus_suspend,
++      .bus_resume =           ohci_bus_resume,
++#endif
++      .start_port_reset =     ohci_start_port_reset,
++};
++
++
++static int __devinit
++ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match)
++{
++      struct device_node *dn = op->node;
++      struct usb_hcd *hcd;
++      struct ohci_hcd *ohci;
++      struct resource res;
++      int irq;
++
++      int rv;
++      int is_bigendian;
++
++      if (usb_disabled())
++              return -ENODEV;
++
++      is_bigendian = 
++              device_is_compatible(dn, "ohci-bigendian") ||
++              device_is_compatible(dn, "ohci-be");;
++
++      dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
++
++      rv = of_address_to_resource(dn, 0, &res);
++      if (rv)
++              return rv;
++
++      hcd = usb_create_hcd(&ohci_ppc_of_hc_driver, &op->dev, "PPC-OF USB");
++      if (!hcd)
++              return -ENOMEM;
++
++      hcd->rsrc_start = res.start;
++      hcd->rsrc_len = res.end - res.start + 1;
++
++      if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
++              printk(KERN_ERR __FILE__ ": request_mem_region failed\n");
++              rv = -EBUSY;
++              goto err_rmr;
++      }
++
++      irq = irq_of_parse_and_map(dn, 0);
++      if (irq == NO_IRQ) {
++              printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
++              rv = -EBUSY;
++              goto err_irq;
++      }
++
++      hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
++      if (!hcd->regs) {
++              printk(KERN_ERR __FILE__ ": ioremap failed\n");
++              rv = -ENOMEM;
++              goto err_ioremap;
++      }
++
++      ohci = hcd_to_ohci(hcd);
++      if (is_bigendian)
++              ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
++
++      ohci_hcd_init(ohci);
++
++      rv = usb_add_hcd(hcd, irq, 0);
++      if (rv == 0)
++              return 0;
++
++      iounmap(hcd->regs);
++err_ioremap:
++      irq_dispose_mapping(irq);
++err_irq:
++      release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
++err_rmr:
++      usb_put_hcd(hcd);
++
++      return rv;
++}
++
++static int ohci_hcd_ppc_of_remove(struct of_device *op)
++{
++      struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
++      dev_set_drvdata(&op->dev, NULL);
++
++      dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
++
++      usb_remove_hcd(hcd);
++
++      iounmap(hcd->regs);
++      irq_dispose_mapping(hcd->irq);
++      release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
++
++      usb_put_hcd(hcd);
++
++      return 0;
++}
++
++static int ohci_hcd_ppc_of_shutdown(struct of_device *op)
++{
++      struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
++
++        if (hcd->driver->shutdown)
++                hcd->driver->shutdown(hcd);
++
++      return 0;
++}
++
++
++static struct of_device_id ohci_hcd_ppc_of_match[] = {
++#ifdef CONFIG_USB_OHCI_HCD_PPC_OF_BE
++      {
++              .name = "usb",
++              .compatible = "ohci-bigendian",
++      },
++      {
++              .name = "usb",
++              .compatible = "ohci-be",
++      },
++#endif
++#ifdef CONFIG_USB_OHCI_HCD_PPC_OF_LE
++      {
++              .name = "usb",
++              .compatible = "ohci-littledian",
++      },
++      {
++              .name = "usb",
++              .compatible = "ohci-le",
++      },
++#endif
++      {},
++};
++MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match); 
++
++#if   !defined(CONFIG_USB_OHCI_HCD_PPC_OF_BE) && \
++      !defined(CONFIG_USB_OHCI_HCD_PPC_OF_LE)
++#error "No endianess selected for ppc-of-ohci"
++#endif
++
++
++static struct of_platform_driver ohci_hcd_ppc_of_driver = {
++      .name           = "ppc-of-ohci",
++      .match_table    = ohci_hcd_ppc_of_match,
++      .probe          = ohci_hcd_ppc_of_probe,
++      .remove         = ohci_hcd_ppc_of_remove,
++      .shutdown       = ohci_hcd_ppc_of_shutdown,
++#ifdef CONFIG_PM
++      /*.suspend      = ohci_hcd_ppc_soc_drv_suspend,*/
++      /*.resume       = ohci_hcd_ppc_soc_drv_resume,*/
++#endif
++      .driver         = {
++              .name   = "ppc-of-ohci",
++              .owner  = THIS_MODULE,
++      },
++};
++
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0010-libata-Add-support-for-the-MPC52xx-ATA-controller.txt b/packages/linux/linux-efika-2.6.20/0010-libata-Add-support-for-the-MPC52xx-ATA-controller.txt
new file mode 100644 (file)
index 0000000..4a69da5
--- /dev/null
@@ -0,0 +1,620 @@
+From 83ebd6314e55f9baf2c4e795397346b338274ef5 Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Fri, 8 Dec 2006 00:08:14 +0100
+Subject: [PATCH] [PATCH] libata: Add support for the MPC52xx ATA controller
+
+This patch adds initial libata support for the Freescale
+MPC5200 integrated IDE controller.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+Signed-off-by: Jeff Garzik <jeff@garzik.org>
+---
+ drivers/ata/Kconfig        |    9 +
+ drivers/ata/Makefile       |    1 +
+ drivers/ata/pata_mpc52xx.c |  563 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 573 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index b34e0a9..fa1d327 100644
+--- a/drivers/ata/Kconfig
++++ b/drivers/ata/Kconfig
+@@ -337,6 +337,15 @@ config PATA_MARVELL
+         If unsure, say N.
++config PATA_MPC52xx
++      tristate "Freescale MPC52xx SoC internal IDE"
++      depends on PPC_MPC52xx
++      help
++        This option enables support for integrated IDE controller
++        of the Freescale MPC52xx SoC.
++
++        If unsure, say N.
++
+ config PATA_MPIIX
+       tristate "Intel PATA MPIIX support"
+       depends on PCI
+diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
+index bc3d81a..3081e1f 100644
+--- a/drivers/ata/Makefile
++++ b/drivers/ata/Makefile
+@@ -38,6 +38,7 @@ obj-$(CONFIG_PATA_NETCELL)   += pata_netcell.o
+ obj-$(CONFIG_PATA_NS87410)    += pata_ns87410.o
+ obj-$(CONFIG_PATA_OPTI)               += pata_opti.o
+ obj-$(CONFIG_PATA_OPTIDMA)    += pata_optidma.o
++obj-$(CONFIG_PATA_MPC52xx)    += pata_mpc52xx.o
+ obj-$(CONFIG_PATA_MARVELL)    += pata_marvell.o
+ obj-$(CONFIG_PATA_MPIIX)      += pata_mpiix.o
+ obj-$(CONFIG_PATA_OLDPIIX)    += pata_oldpiix.o
+diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
+new file mode 100644
+index 0000000..8b7019a
+--- /dev/null
++++ b/drivers/ata/pata_mpc52xx.c
+@@ -0,0 +1,563 @@
++/*
++ * drivers/ata/pata_mpc52xx.c
++ *
++ * libata driver for the Freescale MPC52xx on-chip IDE interface
++ *
++ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
++ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/libata.h>
++
++#include <asm/io.h>
++#include <asm/types.h>
++#include <asm/prom.h>
++#include <asm/of_platform.h>
++#include <asm/mpc52xx.h>
++
++
++#define DRV_NAME      "mpc52xx_ata"
++#define DRV_VERSION   "0.1.0"
++
++
++/* Private structures used by the driver */
++struct mpc52xx_ata_timings {
++      u32     pio1;
++      u32     pio2;
++};
++
++struct mpc52xx_ata_priv {
++      unsigned int                    ipb_period;
++      struct mpc52xx_ata __iomem *    ata_regs;
++      int                             ata_irq;
++      struct mpc52xx_ata_timings      timings[2];
++      int                             csel;
++};
++
++
++/* ATAPI-4 PIO specs (in ns) */
++static const int ataspec_t0[5]    = {600, 383, 240, 180, 120};
++static const int ataspec_t1[5]    = { 70,  50,  30,  30,  25};
++static const int ataspec_t2_8[5]  = {290, 290, 290,  80,  70};
++static const int ataspec_t2_16[5] = {165, 125, 100,  80,  70};
++static const int ataspec_t2i[5]   = {  0,   0,   0,  70,  25};
++static const int ataspec_t4[5]    = { 30,  20,  15,  10,  10};
++static const int ataspec_ta[5]    = { 35,  35,  35,  35,  35};
++
++#define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c)))
++
++
++/* Bit definitions inside the registers */
++#define MPC52xx_ATA_HOSTCONF_SMR      0x80000000UL /* State machine reset */
++#define MPC52xx_ATA_HOSTCONF_FR               0x40000000UL /* FIFO Reset */
++#define MPC52xx_ATA_HOSTCONF_IE               0x02000000UL /* Enable interrupt in PIO */
++#define MPC52xx_ATA_HOSTCONF_IORDY    0x01000000UL /* Drive supports IORDY protocol */
++
++#define MPC52xx_ATA_HOSTSTAT_TIP      0x80000000UL /* Transaction in progress */
++#define MPC52xx_ATA_HOSTSTAT_UREP     0x40000000UL /* UDMA Read Extended Pause */
++#define MPC52xx_ATA_HOSTSTAT_RERR     0x02000000UL /* Read Error */
++#define MPC52xx_ATA_HOSTSTAT_WERR     0x01000000UL /* Write Error */
++
++#define MPC52xx_ATA_FIFOSTAT_EMPTY    0x01 /* FIFO Empty */
++
++#define MPC52xx_ATA_DMAMODE_WRITE     0x01 /* Write DMA */
++#define MPC52xx_ATA_DMAMODE_READ      0x02 /* Read DMA */
++#define MPC52xx_ATA_DMAMODE_UDMA      0x04 /* UDMA enabled */
++#define MPC52xx_ATA_DMAMODE_IE                0x08 /* Enable drive interrupt to CPU in DMA mode */
++#define MPC52xx_ATA_DMAMODE_FE                0x10 /* FIFO Flush enable in Rx mode */
++#define MPC52xx_ATA_DMAMODE_FR                0x20 /* FIFO Reset */
++#define MPC52xx_ATA_DMAMODE_HUT               0x40 /* Host UDMA burst terminate */
++
++
++/* Structure of the hardware registers */
++struct mpc52xx_ata {
++
++      /* Host interface registers */
++      u32 config;             /* ATA + 0x00 Host configuration */
++      u32 host_status;        /* ATA + 0x04 Host controller status */
++      u32 pio1;               /* ATA + 0x08 PIO Timing 1 */
++      u32 pio2;               /* ATA + 0x0c PIO Timing 2 */
++      u32 mdma1;              /* ATA + 0x10 MDMA Timing 1 */
++      u32 mdma2;              /* ATA + 0x14 MDMA Timing 2 */
++      u32 udma1;              /* ATA + 0x18 UDMA Timing 1 */
++      u32 udma2;              /* ATA + 0x1c UDMA Timing 2 */
++      u32 udma3;              /* ATA + 0x20 UDMA Timing 3 */
++      u32 udma4;              /* ATA + 0x24 UDMA Timing 4 */
++      u32 udma5;              /* ATA + 0x28 UDMA Timing 5 */
++      u32 share_cnt;          /* ATA + 0x2c ATA share counter */
++      u32 reserved0[3];
++
++      /* FIFO registers */
++      u32 fifo_data;          /* ATA + 0x3c */
++      u8  fifo_status_frame;  /* ATA + 0x40 */
++      u8  fifo_status;        /* ATA + 0x41 */
++      u16 reserved7[1];
++      u8  fifo_control;       /* ATA + 0x44 */
++      u8  reserved8[5];
++      u16 fifo_alarm;         /* ATA + 0x4a */
++      u16 reserved9;
++      u16 fifo_rdp;           /* ATA + 0x4e */
++      u16 reserved10;
++      u16 fifo_wrp;           /* ATA + 0x52 */
++      u16 reserved11;
++      u16 fifo_lfrdp;         /* ATA + 0x56 */
++      u16 reserved12;
++      u16 fifo_lfwrp;         /* ATA + 0x5a */
++
++      /* Drive TaskFile registers */
++      u8  tf_control;         /* ATA + 0x5c TASKFILE Control/Alt Status */
++      u8  reserved13[3];
++      u16 tf_data;            /* ATA + 0x60 TASKFILE Data */
++      u16 reserved14;
++      u8  tf_features;        /* ATA + 0x64 TASKFILE Features/Error */
++      u8  reserved15[3];
++      u8  tf_sec_count;       /* ATA + 0x68 TASKFILE Sector Count */
++      u8  reserved16[3];
++      u8  tf_sec_num;         /* ATA + 0x6c TASKFILE Sector Number */
++      u8  reserved17[3];
++      u8  tf_cyl_low;         /* ATA + 0x70 TASKFILE Cylinder Low */
++      u8  reserved18[3];
++      u8  tf_cyl_high;        /* ATA + 0x74 TASKFILE Cylinder High */
++      u8  reserved19[3];
++      u8  tf_dev_head;        /* ATA + 0x78 TASKFILE Device/Head */
++      u8  reserved20[3];
++      u8  tf_command;         /* ATA + 0x7c TASKFILE Command/Status */
++      u8  dma_mode;           /* ATA + 0x7d ATA Host DMA Mode configuration */
++      u8  reserved21[2];
++};
++
++
++/* ======================================================================== */
++/* Aux fns                                                                  */
++/* ======================================================================== */
++
++
++/* MPC52xx low level hw control */
++
++static int
++mpc52xx_ata_compute_pio_timings(struct mpc52xx_ata_priv *priv, int dev, int pio)
++{
++      struct mpc52xx_ata_timings *timing = &priv->timings[dev];
++      unsigned int ipb_period = priv->ipb_period;
++      unsigned int t0, t1, t2_8, t2_16, t2i, t4, ta;
++
++      if ((pio<0) || (pio>4))
++              return -EINVAL;
++
++      t0      = CALC_CLKCYC(ipb_period, 1000 * ataspec_t0[pio]);
++      t1      = CALC_CLKCYC(ipb_period, 1000 * ataspec_t1[pio]);
++      t2_8    = CALC_CLKCYC(ipb_period, 1000 * ataspec_t2_8[pio]);
++      t2_16   = CALC_CLKCYC(ipb_period, 1000 * ataspec_t2_16[pio]);
++      t2i     = CALC_CLKCYC(ipb_period, 1000 * ataspec_t2i[pio]);
++      t4      = CALC_CLKCYC(ipb_period, 1000 * ataspec_t4[pio]);
++      ta      = CALC_CLKCYC(ipb_period, 1000 * ataspec_ta[pio]);
++
++      timing->pio1 = (t0 << 24) | (t2_8 << 16) | (t2_16 << 8) | (t2i);
++      timing->pio2 = (t4 << 24) | (t1 << 16) | (ta << 8);
++
++      return 0;
++}
++
++static void
++mpc52xx_ata_apply_timings(struct mpc52xx_ata_priv *priv, int device)
++{
++      struct mpc52xx_ata __iomem *regs = priv->ata_regs;
++      struct mpc52xx_ata_timings *timing = &priv->timings[device];
++
++      out_be32(&regs->pio1,  timing->pio1);
++      out_be32(&regs->pio2,  timing->pio2);
++      out_be32(&regs->mdma1, 0);
++      out_be32(&regs->mdma2, 0);
++      out_be32(&regs->udma1, 0);
++      out_be32(&regs->udma2, 0);
++      out_be32(&regs->udma3, 0);
++      out_be32(&regs->udma4, 0);
++      out_be32(&regs->udma5, 0);
++
++      priv->csel = device;
++}
++
++static int
++mpc52xx_ata_hw_init(struct mpc52xx_ata_priv *priv)
++{
++      struct mpc52xx_ata __iomem *regs = priv->ata_regs;
++      int tslot;
++
++      /* Clear share_cnt (all sample code do this ...) */
++      out_be32(&regs->share_cnt, 0);
++
++      /* Configure and reset host */
++      out_be32(&regs->config,
++                      MPC52xx_ATA_HOSTCONF_IE |
++                      MPC52xx_ATA_HOSTCONF_IORDY |
++                      MPC52xx_ATA_HOSTCONF_SMR |
++                      MPC52xx_ATA_HOSTCONF_FR);
++
++      udelay(10);
++
++      out_be32(&regs->config,
++                      MPC52xx_ATA_HOSTCONF_IE |
++                      MPC52xx_ATA_HOSTCONF_IORDY);
++
++      /* Set the time slot to 1us */
++      tslot = CALC_CLKCYC(priv->ipb_period, 1000000);
++      out_be32(&regs->share_cnt, tslot << 16 );
++
++      /* Init timings to PIO0 */
++      memset(priv->timings, 0x00, 2*sizeof(struct mpc52xx_ata_timings));
++
++      mpc52xx_ata_compute_pio_timings(priv, 0, 0);
++      mpc52xx_ata_compute_pio_timings(priv, 1, 0);
++
++      mpc52xx_ata_apply_timings(priv, 0);
++
++      return 0;
++}
++
++
++/* ======================================================================== */
++/* libata driver                                                            */
++/* ======================================================================== */
++
++static void
++mpc52xx_ata_set_piomode(struct ata_port *ap, struct ata_device *adev)
++{
++      struct mpc52xx_ata_priv *priv = ap->host->private_data;
++      int pio, rv;
++
++      pio = adev->pio_mode - XFER_PIO_0;
++
++      rv = mpc52xx_ata_compute_pio_timings(priv, adev->devno, pio);
++
++      if (rv) {
++              printk(KERN_ERR DRV_NAME
++                      ": Trying to select invalid PIO mode %d\n", pio);
++              return;
++      }
++
++      mpc52xx_ata_apply_timings(priv, adev->devno);
++}
++static void
++mpc52xx_ata_dev_select(struct ata_port *ap, unsigned int device)
++{
++      struct mpc52xx_ata_priv *priv = ap->host->private_data;
++
++      if (device != priv->csel)
++              mpc52xx_ata_apply_timings(priv, device);
++
++      ata_std_dev_select(ap,device);
++}
++
++static void
++mpc52xx_ata_error_handler(struct ata_port *ap)
++{
++      ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
++                      ata_std_postreset);
++}
++
++
++
++static struct scsi_host_template mpc52xx_ata_sht = {
++      .module                 = THIS_MODULE,
++      .name                   = DRV_NAME,
++      .ioctl                  = ata_scsi_ioctl,
++      .queuecommand           = ata_scsi_queuecmd,
++      .can_queue              = ATA_DEF_QUEUE,
++      .this_id                = ATA_SHT_THIS_ID,
++      .sg_tablesize           = LIBATA_MAX_PRD,
++      .max_sectors            = ATA_MAX_SECTORS,
++      .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
++      .emulated               = ATA_SHT_EMULATED,
++      .use_clustering         = ATA_SHT_USE_CLUSTERING,
++      .proc_name              = DRV_NAME,
++      .dma_boundary           = ATA_DMA_BOUNDARY,
++      .slave_configure        = ata_scsi_slave_config,
++      .bios_param             = ata_std_bios_param,
++};
++
++static struct ata_port_operations mpc52xx_ata_port_ops = {
++      .port_disable           = ata_port_disable,
++      .set_piomode            = mpc52xx_ata_set_piomode,
++      .dev_select             = mpc52xx_ata_dev_select,
++      .tf_load                = ata_tf_load,
++      .tf_read                = ata_tf_read,
++      .check_status           = ata_check_status,
++      .exec_command           = ata_exec_command,
++      .freeze                 = ata_bmdma_freeze,
++      .thaw                   = ata_bmdma_thaw,
++      .error_handler          = mpc52xx_ata_error_handler,
++      .qc_prep                = ata_qc_prep,
++      .qc_issue               = ata_qc_issue_prot,
++      .data_xfer              = ata_mmio_data_xfer,
++      .irq_handler            = ata_interrupt,
++      .irq_clear              = ata_bmdma_irq_clear,
++      .port_start             = ata_port_start,
++      .port_stop              = ata_port_stop,
++      .host_stop              = ata_host_stop,
++};
++
++static struct ata_probe_ent mpc52xx_ata_probe_ent = {
++      .port_ops       = &mpc52xx_ata_port_ops,
++      .sht            = &mpc52xx_ata_sht,
++      .n_ports        = 1,
++      .pio_mask       = 0x1f,         /* Up to PIO4 */
++      .mwdma_mask     = 0x00,         /* No MWDMA   */
++      .udma_mask      = 0x00,         /* No UDMA    */
++      .port_flags     = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_MMIO,
++      .irq_flags      = 0,
++};
++
++static int __devinit
++mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv)
++{
++      struct ata_probe_ent *ae = &mpc52xx_ata_probe_ent;
++      struct ata_ioports *aio = &ae->port[0];
++      int rv;
++
++      INIT_LIST_HEAD(&ae->node);
++      ae->dev = dev;
++      ae->irq = priv->ata_irq;
++
++      aio->cmd_addr           = 0;    /* Don't have a classic reg block */
++      aio->altstatus_addr     = (unsigned long)&priv->ata_regs->tf_control;
++      aio->ctl_addr           = (unsigned long)&priv->ata_regs->tf_control;
++      aio->data_addr          = (unsigned long)&priv->ata_regs->tf_data;
++      aio->error_addr         = (unsigned long)&priv->ata_regs->tf_features;
++      aio->feature_addr       = (unsigned long)&priv->ata_regs->tf_features;
++      aio->nsect_addr         = (unsigned long)&priv->ata_regs->tf_sec_count;
++      aio->lbal_addr          = (unsigned long)&priv->ata_regs->tf_sec_num;
++      aio->lbam_addr          = (unsigned long)&priv->ata_regs->tf_cyl_low;
++      aio->lbah_addr          = (unsigned long)&priv->ata_regs->tf_cyl_high;
++      aio->device_addr        = (unsigned long)&priv->ata_regs->tf_dev_head;
++      aio->status_addr        = (unsigned long)&priv->ata_regs->tf_command;
++      aio->command_addr       = (unsigned long)&priv->ata_regs->tf_command;
++
++      ae->private_data = priv;
++
++      rv = ata_device_add(ae);
++
++      return rv ? 0 : -EINVAL;
++}
++
++static struct mpc52xx_ata_priv *
++mpc52xx_ata_remove_one(struct device *dev)
++{
++      struct ata_host *host = dev_get_drvdata(dev);
++      struct mpc52xx_ata_priv *priv = host->private_data;
++
++      ata_host_remove(host);
++
++      return priv;
++}
++
++
++/* ======================================================================== */
++/* OF Platform driver                                                       */
++/* ======================================================================== */
++
++static int __devinit
++mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
++{
++      unsigned int ipb_freq;
++      struct resource res_mem;
++      int ata_irq = NO_IRQ;
++      struct mpc52xx_ata __iomem *ata_regs = NULL;
++      struct mpc52xx_ata_priv *priv = NULL;
++      int rv;
++
++      /* Get ipb frequency */
++      ipb_freq = mpc52xx_find_ipb_freq(op->node);
++      if (!ipb_freq) {
++              printk(KERN_ERR DRV_NAME ": "
++                      "Unable to find IPB Bus frequency\n" );
++              return -ENODEV;
++      }
++
++      /* Get IRQ and register */
++      rv = of_address_to_resource(op->node, 0, &res_mem);
++      if (rv) {
++              printk(KERN_ERR DRV_NAME ": "
++                      "Error while parsing device node resource\n" );
++              return rv;
++      }
++
++      ata_irq = irq_of_parse_and_map(op->node, 0);
++      if (ata_irq == NO_IRQ) {
++              printk(KERN_ERR DRV_NAME ": "
++                      "Error while mapping the irq\n");
++              return -EINVAL;
++      }
++
++      /* Request mem region */
++      if (!request_mem_region(res_mem.start,
++                              sizeof(struct mpc52xx_ata), DRV_NAME)) {
++              printk(KERN_ERR DRV_NAME ": "
++                      "Error while requesting mem region\n");
++              irq_dispose_mapping(ata_irq);
++              return -EBUSY;
++      }
++
++      /* Remap registers */
++      ata_regs = ioremap(res_mem.start, sizeof(struct mpc52xx_ata));
++      if (!ata_regs) {
++              printk(KERN_ERR DRV_NAME ": "
++                      "Error while mapping register set\n");
++              rv = -ENOMEM;
++              goto err;
++      }
++
++      /* Prepare our private structure */
++      priv = kmalloc(sizeof(struct mpc52xx_ata_priv), GFP_ATOMIC);
++      if (!priv) {
++              printk(KERN_ERR DRV_NAME ": "
++                      "Error while allocating private structure\n");
++              rv = -ENOMEM;
++              goto err;
++      }
++
++      priv->ipb_period = 1000000000 / (ipb_freq / 1000);
++      priv->ata_regs = ata_regs;
++      priv->ata_irq = ata_irq;
++      priv->csel = -1;
++
++      /* Init the hw */
++      rv = mpc52xx_ata_hw_init(priv);
++      if (rv) {
++              printk(KERN_ERR DRV_NAME ": Error during HW init\n");
++              goto err;
++      }
++
++      /* Register ourselves to libata */
++      rv = mpc52xx_ata_init_one(&op->dev, priv);
++      if (rv) {
++              printk(KERN_ERR DRV_NAME ": "
++                      "Error while registering to ATA layer\n");
++              return rv;
++      }
++
++      /* Done */
++      return 0;
++
++      /* Error path */
++err:
++      kfree(priv);
++
++      if (ata_regs)
++              iounmap(ata_regs);
++
++      release_mem_region(res_mem.start, sizeof(struct mpc52xx_ata));
++
++      irq_dispose_mapping(ata_irq);
++
++      return rv;
++}
++
++static int
++mpc52xx_ata_remove(struct of_device *op)
++{
++      struct mpc52xx_ata_priv *priv;
++      struct resource res_mem;
++      int rv;
++
++      /* Unregister */
++      priv = mpc52xx_ata_remove_one(&op->dev);
++
++      /* Free everything */
++      iounmap(priv->ata_regs);
++
++      rv = of_address_to_resource(op->node, 0, &res_mem);
++      if (rv) {
++              printk(KERN_ERR DRV_NAME ": "
++                      "Error while parsing device node resource\n");
++              printk(KERN_ERR DRV_NAME ": "
++                      "Zone may not be properly released\n");
++      } else
++              release_mem_region(res_mem.start, sizeof(struct mpc52xx_ata));
++
++      irq_dispose_mapping(priv->ata_irq);
++
++      kfree(priv);
++
++      return 0;
++}
++
++
++#ifdef CONFIG_PM
++
++static int
++mpc52xx_ata_suspend(struct of_device *op, pm_message_t state)
++{
++      return 0;       /* FIXME : What to do here ? */
++}
++
++static int
++mpc52xx_ata_resume(struct of_device *op)
++{
++      return 0;       /* FIXME : What to do here ? */
++}
++
++#endif
++
++
++static struct of_device_id mpc52xx_ata_of_match[] = {
++      {
++              .compatible = "mpc5200-ata",
++      },
++      {
++              .compatible = "mpc52xx-ata",
++      },
++      {},
++};
++
++
++static struct of_platform_driver mpc52xx_ata_of_platform_driver = {
++      .owner          = THIS_MODULE,
++      .name           = DRV_NAME,
++      .match_table    = mpc52xx_ata_of_match,
++      .probe          = mpc52xx_ata_probe,
++      .remove         = mpc52xx_ata_remove,
++#ifdef CONFIG_PM
++      .suspend        = mpc52xx_ata_suspend,
++      .resume         = mpc52xx_ata_resume,
++#endif
++      .driver         = {
++              .name   = DRV_NAME,
++              .owner  = THIS_MODULE,
++      },
++};
++
++
++/* ======================================================================== */
++/* Module                                                                   */
++/* ======================================================================== */
++
++static int __init
++mpc52xx_ata_init(void)
++{
++      printk(KERN_INFO "ata: MPC52xx IDE/ATA libata driver\n");
++      return of_register_platform_driver(&mpc52xx_ata_of_platform_driver);
++}
++
++static void __exit
++mpc52xx_ata_exit(void)
++{
++      of_unregister_platform_driver(&mpc52xx_ata_of_platform_driver);
++}
++
++module_init(mpc52xx_ata_init);
++module_exit(mpc52xx_ata_exit);
++
++MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
++MODULE_DESCRIPTION("Freescale MPC52xx IDE/ATA libata driver");
++MODULE_LICENSE("GPL");
++MODULE_DEVICE_TABLE(of, mpc52xx_ata_of_match);
++MODULE_VERSION(DRV_VERSION);
++
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0011-ohci-Whitespace-and-typo-fix-in-ohci-ppc-of.c.txt b/packages/linux/linux-efika-2.6.20/0011-ohci-Whitespace-and-typo-fix-in-ohci-ppc-of.c.txt
new file mode 100644 (file)
index 0000000..2228fa0
--- /dev/null
@@ -0,0 +1,38 @@
+From 947dc060772ceb8b33a35bd2ded245908fa9442f Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Sat, 23 Dec 2006 22:16:05 +0100
+Subject: [PATCH] [PATCH] ohci: Whitespace and typo fix in ohci-ppc-of.c
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ drivers/usb/host/ohci-ppc-of.c |    6 +++---
+ 1 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
+index 84b555b..08e237c 100644
+--- a/drivers/usb/host/ohci-ppc-of.c
++++ b/drivers/usb/host/ohci-ppc-of.c
+@@ -96,9 +96,9 @@ ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match)
+       if (usb_disabled())
+               return -ENODEV;
+-      is_bigendian = 
++      is_bigendian =
+               device_is_compatible(dn, "ohci-bigendian") ||
+-              device_is_compatible(dn, "ohci-be");;
++              device_is_compatible(dn, "ohci-be");
+       dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
+@@ -206,7 +206,7 @@ static struct of_device_id ohci_hcd_ppc_of_match[] = {
+ #endif
+       {},
+ };
+-MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match); 
++MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match);
+ #if   !defined(CONFIG_USB_OHCI_HCD_PPC_OF_BE) && \
+       !defined(CONFIG_USB_OHCI_HCD_PPC_OF_LE)
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0012-ata-Fix-pata_mpc52xx.c-compatible-list.txt b/packages/linux/linux-efika-2.6.20/0012-ata-Fix-pata_mpc52xx.c-compatible-list.txt
new file mode 100644 (file)
index 0000000..33f2ffc
--- /dev/null
@@ -0,0 +1,31 @@
+From 20e872b5fed46ba15ed6f2c29cc2adf98657c9a4 Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Sat, 23 Dec 2006 22:20:06 +0100
+Subject: [PATCH] [PATCH] ata: Fix pata_mpc52xx.c 'compatible' list
+
+The list contained an entry to support a non-standard device-tree,
+this is now handled by fixups in early boot.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ drivers/ata/pata_mpc52xx.c |    4 +---
+ 1 files changed, 1 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
+index 8b7019a..ff40016 100644
+--- a/drivers/ata/pata_mpc52xx.c
++++ b/drivers/ata/pata_mpc52xx.c
+@@ -509,9 +509,7 @@ mpc52xx_ata_resume(struct of_device *op)
+ static struct of_device_id mpc52xx_ata_of_match[] = {
+       {
+-              .compatible = "mpc5200-ata",
+-      },
+-      {
++              .type = "ata",
+               .compatible = "mpc52xx-ata",
+       },
+       {},
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0013-powerpc-serial-Fix-mpc52xx_uart.c-compatible-list.txt b/packages/linux/linux-efika-2.6.20/0013-powerpc-serial-Fix-mpc52xx_uart.c-compatible-list.txt
new file mode 100644 (file)
index 0000000..d0c5a46
--- /dev/null
@@ -0,0 +1,28 @@
+From f3736d1a7f74d7dec888a8a8d8c593ca08a31000 Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Sat, 23 Dec 2006 22:21:43 +0100
+Subject: [PATCH] [PATCH] powerpc/serial: Fix mpc52xx_uart.c 'compatible' list
+
+The list contained an entry to support a non-standard device-tree,
+this is now handled by fixups in early boot.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ drivers/serial/mpc52xx_uart.c |    1 -
+ 1 files changed, 0 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
+index eef3b02..c20cd81 100644
+--- a/drivers/serial/mpc52xx_uart.c
++++ b/drivers/serial/mpc52xx_uart.c
+@@ -128,7 +128,6 @@ static irqreturn_t mpc52xx_uart_int(int irq,void *dev_id);
+ #if defined(CONFIG_PPC_MERGE)
+ static struct of_device_id mpc52xx_uart_of_match[] = {
+       { .type = "serial", .compatible = "mpc52xx-psc-uart", },
+-      { .type = "serial", .compatible = "mpc5200-psc", }, /* Efika only! */
+       {},
+ };
+ #endif
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0014-powerpc-Small-cleanup-of-EFIKA-platform.txt b/packages/linux/linux-efika-2.6.20/0014-powerpc-Small-cleanup-of-EFIKA-platform.txt
new file mode 100644 (file)
index 0000000..a373e97
--- /dev/null
@@ -0,0 +1,144 @@
+From 65cd4fcc30440e903fd99973918373ee4534b70a Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Sat, 23 Dec 2006 22:39:18 +0100
+Subject: [PATCH] [PATCH] powerpc: Small cleanup of EFIKA platform
+
+This is just some cleanup to remove the efika.h header that just have
+2 lines in it and is not really necessary.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ arch/powerpc/platforms/52xx/efika-pci.c   |   23 ++++++++++++++++-------
+ arch/powerpc/platforms/52xx/efika-setup.c |    7 ++++---
+ arch/powerpc/platforms/52xx/efika.h       |   19 -------------------
+ 3 files changed, 20 insertions(+), 29 deletions(-)
+
+diff --git a/arch/powerpc/platforms/52xx/efika-pci.c b/arch/powerpc/platforms/52xx/efika-pci.c
+index 62e05b2..3732dec 100644
+--- a/arch/powerpc/platforms/52xx/efika-pci.c
++++ b/arch/powerpc/platforms/52xx/efika-pci.c
+@@ -1,3 +1,13 @@
++/*
++ * Efika 5K2 PCI support thru RTAS
++ *
++ * Copyright (C) 2006 bplan GmbH
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ *
++ */
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+@@ -12,7 +22,6 @@
+ #include <asm/pci-bridge.h>
+ #include <asm/rtas.h>
+-#include "efika.h"
+ #ifdef CONFIG_PCI
+ /*
+@@ -62,7 +71,7 @@ void __init efika_pcisetup(void)
+       root = of_find_node_by_path("/");
+       if (root == NULL) {
+-              printk(KERN_WARNING EFIKA_PLATFORM_NAME
++              printk(KERN_WARNING __FILE__
+                      ": Unable to find the root node\n");
+               return;
+       }
+@@ -76,30 +85,30 @@ void __init efika_pcisetup(void)
+       of_node_put(root);
+       if (pcictrl == NULL) {
+-              printk(KERN_WARNING EFIKA_PLATFORM_NAME
++              printk(KERN_WARNING __FILE__
+                      ": Unable to find the PCI bridge node\n");
+               return;
+       }
+       bus_range = get_property(pcictrl, "bus-range", &len);
+       if (bus_range == NULL || len < 2 * sizeof(int)) {
+-              printk(KERN_WARNING EFIKA_PLATFORM_NAME
++              printk(KERN_WARNING __FILE__
+                      ": Can't get bus-range for %s\n", pcictrl->full_name);
+               return;
+       }
+       if (bus_range[1] == bus_range[0])
+-              printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d",
++              printk(KERN_INFO __FILE__ ": PCI bus %d",
+                      bus_range[0]);
+       else
+-              printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d",
++              printk(KERN_INFO __FILE__ ": PCI buses %d..%d",
+                      bus_range[0], bus_range[1]);
+       printk(" controlled by %s\n", pcictrl->full_name);
+       printk("\n");
+       hose = pcibios_alloc_controller();
+       if (!hose) {
+-              printk(KERN_WARNING EFIKA_PLATFORM_NAME
++              printk(KERN_WARNING __FILE__
+                      ": Can't allocate PCI controller structure for %s\n",
+                      pcictrl->full_name);
+               return;
+diff --git a/arch/powerpc/platforms/52xx/efika-setup.c b/arch/powerpc/platforms/52xx/efika-setup.c
+index d61ce84..17bf73a 100644
+--- a/arch/powerpc/platforms/52xx/efika-setup.c
++++ b/arch/powerpc/platforms/52xx/efika-setup.c
+@@ -1,5 +1,4 @@
+ /*
+- *
+  * Efika 5K2 platform setup
+  * Some code really inspired from the lite5200b platform.
+  *
+@@ -32,7 +31,9 @@
+ #include <asm/of_platform.h>
+ #include <asm/mpc52xx.h>
+-#include "efika.h"
++
++extern void __init efika_pcisetup(void);
++
+ static void efika_show_cpuinfo(struct seq_file *m)
+ {
+@@ -103,7 +104,7 @@ static int __init efika_probe(void)
+ define_machine(efika)
+ {
+-      .name                   = EFIKA_PLATFORM_NAME,
++      .name                   = "Efika",
+       .probe                  = efika_probe,
+       .setup_arch             = efika_setup_arch,
+       .init                   = mpc52xx_declare_of_platform_devices,
+diff --git a/arch/powerpc/platforms/52xx/efika.h b/arch/powerpc/platforms/52xx/efika.h
+deleted file mode 100644
+index 2f060fd..0000000
+--- a/arch/powerpc/platforms/52xx/efika.h
++++ /dev/null
+@@ -1,19 +0,0 @@
+-/*
+- * Efika 5K2 platform setup - Header file
+- *
+- * Copyright (C) 2006 bplan GmbH
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- *
+- */
+-
+-#ifndef __ARCH_POWERPC_EFIKA__
+-#define __ARCH_POWERPC_EFIKA__
+-
+-#define EFIKA_PLATFORM_NAME "Efika"
+-
+-extern void __init efika_pcisetup(void);
+-
+-#endif
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0015-powerpc-Add-a-unified-uevent-handler-for-bus-based-on-of_device.txt b/packages/linux/linux-efika-2.6.20/0015-powerpc-Add-a-unified-uevent-handler-for-bus-based-on-of_device.txt
new file mode 100644 (file)
index 0000000..6de1fd2
--- /dev/null
@@ -0,0 +1,116 @@
+From 90dc591d4c897c7a49191888c1e4d413cc08b8b7 Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Sat, 23 Dec 2006 23:08:56 +0100
+Subject: [PATCH] [PATCH] powerpc: Add a unified uevent handler for bus based on of_device
+
+This common uevent handler allow the several bus types based on
+of_device to generate the uevent properly and avoiding
+code duplication.
+
+This handlers take a struct device as argument and can therefore
+be used as the uevent call directly if no special treatment is
+needed for the bus.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ arch/powerpc/kernel/of_device.c |   66 +++++++++++++++++++++++++++++++++++++++
+ include/asm-powerpc/of_device.h |    3 ++
+ 2 files changed, 69 insertions(+), 0 deletions(-)
+
+diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
+index e921514..ac024ad 100644
+--- a/arch/powerpc/kernel/of_device.c
++++ b/arch/powerpc/kernel/of_device.c
+@@ -120,6 +120,71 @@ void of_device_unregister(struct of_device *ofdev)
+ }
++int of_device_uevent(struct device *dev,
++              char **envp, int num_envp, char *buffer, int buffer_size)
++{
++      struct of_device *ofdev;
++      const char *compat;
++      char *compat2;
++      char compat_buf[128];   /* need to be size of 'compatible' */
++      int i = 0, length = 0, seen = 0, cplen, sl;
++
++      if (!dev)
++              return -ENODEV;
++
++      ofdev = to_of_device(dev);
++
++      if (add_uevent_var(envp, num_envp, &i,
++                         buffer, buffer_size, &length,
++                         "OF_NAME=%s", ofdev->node->name))
++              return -ENOMEM;
++
++      if (add_uevent_var(envp, num_envp, &i,
++                         buffer, buffer_size, &length,
++                         "OF_TYPE=%s", ofdev->node->type))
++              return -ENOMEM;
++
++        /* Since the compatible field can contain pretty much anything
++         * it's not really legal to split it out with commas. We split it
++         * up using a number of environment variables instead. */
++
++      compat = get_property(ofdev->node, "compatible", &cplen);
++      compat2 = compat_buf;
++      if (compat)
++              memcpy(compat2, compat, cplen);
++      while (compat && *compat && cplen > 0) {
++              if (add_uevent_var(envp, num_envp, &i,
++                                 buffer, buffer_size, &length,
++                                 "OF_COMPATIBLE_%d=%s", seen, compat))
++                      return -ENOMEM;
++
++              sl = strlen (compat) + 1;
++              compat += sl;
++              compat2 += sl;
++              cplen -= sl;
++              seen++;
++              compat2[-1] = 'C'; 
++      }
++      compat2[seen?-1:0] = 0;
++
++      if (add_uevent_var(envp, num_envp, &i,
++                         buffer, buffer_size, &length,
++                         "OF_COMPATIBLE_N=%d", seen))
++              return -ENOMEM;
++
++      if (add_uevent_var(envp, num_envp, &i,
++                         buffer, buffer_size, &length,
++                         "MODALIAS=of:N%sT%sC%s",
++                         ofdev->node->name, ofdev->node->type,
++                         compat_buf))
++              return -ENOMEM;
++
++      envp[i] = NULL;
++
++      return 0;
++}
++
++
+ EXPORT_SYMBOL(of_match_node);
+ EXPORT_SYMBOL(of_match_device);
+ EXPORT_SYMBOL(of_device_register);
+@@ -127,3 +192,4 @@ EXPORT_SYMBOL(of_device_unregister);
+ EXPORT_SYMBOL(of_dev_get);
+ EXPORT_SYMBOL(of_dev_put);
+ EXPORT_SYMBOL(of_release_dev);
++EXPORT_SYMBOL(of_device_uevent);
+diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
+index a889b20..4f1aabe 100644
+--- a/include/asm-powerpc/of_device.h
++++ b/include/asm-powerpc/of_device.h
+@@ -32,5 +32,8 @@ extern int of_device_register(struct of_device *ofdev);
+ extern void of_device_unregister(struct of_device *ofdev);
+ extern void of_release_dev(struct device *dev);
++extern int of_device_uevent(struct device *dev,
++      char **envp, int num_envp, char *buffer, int buffer_size);
++
+ #endif /* __KERNEL__ */
+ #endif /* _ASM_POWERPC_OF_DEVICE_H */
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0016-macintosh-Use-the-new-of_device-common-uevent-handler.txt b/packages/linux/linux-efika-2.6.20/0016-macintosh-Use-the-new-of_device-common-uevent-handler.txt
new file mode 100644 (file)
index 0000000..93859bd
--- /dev/null
@@ -0,0 +1,130 @@
+From 2507b27c0841752a6f419439896fcb089fa4a5ba Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Sat, 23 Dec 2006 23:13:56 +0100
+Subject: [PATCH] [PATCH] macintosh: Use the new of_device common uevent handler
+
+The generation of the uevent is now common to all bus using
+of_device.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ drivers/macintosh/macio_asic.c |   98 +---------------------------------------
+ 1 files changed, 1 insertions(+), 97 deletions(-)
+
+diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
+index d562160..e851266 100644
+--- a/drivers/macintosh/macio_asic.c
++++ b/drivers/macintosh/macio_asic.c
+@@ -134,108 +134,12 @@ static int macio_device_resume(struct device * dev)
+       return 0;
+ }
+-static int macio_uevent(struct device *dev, char **envp, int num_envp,
+-                          char *buffer, int buffer_size)
+-{
+-      struct macio_dev * macio_dev;
+-      struct of_device * of;
+-      char *scratch;
+-      const char *compat, *compat2;
+-
+-      int i = 0;
+-      int length, cplen, cplen2, seen = 0;
+-
+-      if (!dev)
+-              return -ENODEV;
+-
+-      macio_dev = to_macio_device(dev);
+-      if (!macio_dev)
+-              return -ENODEV;
+-
+-      of = &macio_dev->ofdev;
+-
+-      /* stuff we want to pass to /sbin/hotplug */
+-      envp[i++] = scratch = buffer;
+-      length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name);
+-      ++length;
+-      buffer_size -= length;
+-      if ((buffer_size <= 0) || (i >= num_envp))
+-              return -ENOMEM;
+-      scratch += length;
+-
+-      envp[i++] = scratch;
+-      length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type);
+-      ++length;
+-      buffer_size -= length;
+-      if ((buffer_size <= 0) || (i >= num_envp))
+-              return -ENOMEM;
+-      scratch += length;
+-
+-        /* Since the compatible field can contain pretty much anything
+-         * it's not really legal to split it out with commas. We split it
+-         * up using a number of environment variables instead. */
+-
+-      compat = get_property(of->node, "compatible", &cplen);
+-      compat2 = compat;
+-      cplen2= cplen;
+-      while (compat && cplen > 0) {
+-                envp[i++] = scratch;
+-              length = scnprintf (scratch, buffer_size,
+-                                   "OF_COMPATIBLE_%d=%s", seen, compat);
+-              ++length;
+-              buffer_size -= length;
+-              if ((buffer_size <= 0) || (i >= num_envp))
+-                      return -ENOMEM;
+-              scratch += length;
+-              length = strlen (compat) + 1;
+-              compat += length;
+-              cplen -= length;
+-              seen++;
+-      }
+-
+-      envp[i++] = scratch;
+-      length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen);
+-      ++length;
+-      buffer_size -= length;
+-      if ((buffer_size <= 0) || (i >= num_envp))
+-              return -ENOMEM;
+-      scratch += length;
+-
+-      envp[i++] = scratch;
+-      length = scnprintf (scratch, buffer_size, "MODALIAS=of:N%sT%s",
+-                      of->node->name, of->node->type);
+-      /* overwrite '\0' */
+-      buffer_size -= length;
+-      if ((buffer_size <= 0) || (i >= num_envp))
+-              return -ENOMEM;
+-      scratch += length;
+-
+-      if (!compat2) {
+-              compat2 = "";
+-              cplen2 = 1;
+-      }
+-      while (cplen2 > 0) {
+-              length = snprintf (scratch, buffer_size, "C%s", compat2);
+-              buffer_size -= length;
+-              if (buffer_size <= 0)
+-                      return -ENOMEM;
+-              scratch += length;
+-              length = strlen (compat2) + 1;
+-              compat2 += length;
+-              cplen2 -= length;
+-      }
+-
+-      envp[i] = NULL;
+-
+-      return 0;
+-}
+-
+ extern struct device_attribute macio_dev_attrs[];
+ struct bus_type macio_bus_type = {
+        .name  = "macio",
+        .match = macio_bus_match,
+-       .uevent = macio_uevent,
++       .uevent = of_device_uevent,
+        .probe = macio_device_probe,
+        .remove        = macio_device_remove,
+        .shutdown = macio_device_shutdown,
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0017-powerpc-Add-uevent-handler-for-of_platform_bus.txt b/packages/linux/linux-efika-2.6.20/0017-powerpc-Add-uevent-handler-for-of_platform_bus.txt
new file mode 100644 (file)
index 0000000..303cf6b
--- /dev/null
@@ -0,0 +1,29 @@
+From 846d6cd8584eee7517543be073c8b3fe9fefd065 Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Sat, 23 Dec 2006 23:16:07 +0100
+Subject: [PATCH] [PATCH] powerpc: Add uevent handler for of_platform_bus
+
+Adding this handler allow userspace to properly handle the module
+autoloading. The generation of the uevent itself is now common to
+all bus using of_device, so not much code here.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ arch/powerpc/kernel/of_platform.c |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
+index b734517..da78e44 100644
+--- a/arch/powerpc/kernel/of_platform.c
++++ b/arch/powerpc/kernel/of_platform.c
+@@ -133,6 +133,7 @@ static int of_platform_device_resume(struct device * dev)
+ struct bus_type of_platform_bus_type = {
+        .name  = "of_platform",
+        .match = of_platform_bus_match,
++       .uevent        = of_device_uevent,
+        .probe = of_platform_device_probe,
+        .remove        = of_platform_device_remove,
+        .suspend       = of_platform_device_suspend,
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0018-powerpc-Add-uevent-handler-for-ibmebus.txt b/packages/linux/linux-efika-2.6.20/0018-powerpc-Add-uevent-handler-for-ibmebus.txt
new file mode 100644 (file)
index 0000000..39392a6
--- /dev/null
@@ -0,0 +1,50 @@
+From ddc4a7296f3abd28a902f38ae915224d6d93edca Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Sat, 23 Dec 2006 23:20:58 +0100
+Subject: [PATCH] [PATCH] powerpc: Add uevent handler for ibmebus
+
+Adding this handler allow userspace to properly handle the module
+autoloading. The generation of the uevent itself is now common to
+all bus using of_device, so not much code here.
+
+But we still need a small wrapper to filter out the dummy root
+device node used by this bus.
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ arch/powerpc/kernel/ibmebus.c |   16 ++++++++++++++++
+ 1 files changed, 16 insertions(+), 0 deletions(-)
+
+diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
+index 82bd2f1..2e8d9fd 100644
+--- a/arch/powerpc/kernel/ibmebus.c
++++ b/arch/powerpc/kernel/ibmebus.c
+@@ -361,9 +361,25 @@ static int ibmebus_bus_match(struct device *dev, struct device_driver *drv)
+       return 0;
+ }
++static int ibmebus_bus_uevent(struct device *dev,
++              char **envp, int num_envp, char *buffer, int buffer_size)
++{
++      struct ibmebus_dev *ebus_dev;
++
++      if (!dev)
++              return -ENODEV;
++
++      ebus_dev = to_ibmebus_dev(dev);
++      if (ebus_dev==ibmebus_bus_device)       /* filter dummy root device */
++              return -ENODEV;
++
++      return of_device_uevent(dev, envp, num_envp, buffer, buffer_size);
++}
++
+ struct bus_type ibmebus_bus_type = {
+       .name = "ibmebus",
+       .match = ibmebus_bus_match,
++      .uevent = ibmebus_bus_uevent,
+ };
+ EXPORT_SYMBOL(ibmebus_bus_type);
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0019-MPC5200-Bestcomm-platform-driver.txt b/packages/linux/linux-efika-2.6.20/0019-MPC5200-Bestcomm-platform-driver.txt
new file mode 100644 (file)
index 0000000..74bfbf9
--- /dev/null
@@ -0,0 +1,1439 @@
+From d9e27abf78b3bd714eb9c37c529d0bff7c5403d9 Mon Sep 17 00:00:00 2001
+From: Andrey Volkov <avolkov@varma-el.com>
+Date: Fri, 18 Aug 2006 10:01:38 -0600
+Subject: [PATCH] [PATCH 01/02] MPC5200 Bestcomm platform driver
+
+This is first part of "platformizied" bestcomm/fec drivers.
+
+Signed-Off-By: Andrey Volkov <avolkov at varma-el.com>
+---
+ arch/ppc/Kconfig                            |    5 +
+ arch/ppc/syslib/Makefile                    |    1 +
+ arch/ppc/syslib/bestcomm/Makefile           |    2 +
+ arch/ppc/syslib/bestcomm/bestcomm.c         |  408 +++++++++++++++++++++++
+ arch/ppc/syslib/bestcomm/bestcomm.h         |  473 +++++++++++++++++++++++++++
+ arch/ppc/syslib/bestcomm/fec.c              |  174 ++++++++++
+ arch/ppc/syslib/bestcomm/fec.h              |   71 ++++
+ arch/ppc/syslib/bestcomm/sdma_fec_rx_task.c |   71 ++++
+ arch/ppc/syslib/bestcomm/sdma_fec_tx_task.c |   84 +++++
+ arch/ppc/syslib/mpc52xx_devices.c           |   22 ++
+ arch/ppc/syslib/mpc52xx_sys.c               |    4 +-
+ include/asm-ppc/mpc52xx.h                   |    2 +
+ 12 files changed, 1315 insertions(+), 2 deletions(-)
+
+diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
+index 8eb82ef..d8a561e 100644
+--- a/arch/ppc/Kconfig
++++ b/arch/ppc/Kconfig
+@@ -775,6 +775,11 @@ config EMBEDDEDBOOT
+ config PPC_MPC52xx
+       bool
++config PPC_BESTCOMM
++      bool
++      depends on PPC_MPC52xx
++      default y
++
+ config 8260
+       bool "CPM2 Support" if WILLOW
+       depends on 6xx
+diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
+index dca23f2..ab015df 100644
+--- a/arch/ppc/syslib/Makefile
++++ b/arch/ppc/syslib/Makefile
+@@ -106,3 +106,4 @@ obj-$(CONFIG_PCI)          += mpc52xx_pci.o
+ endif
+ obj-$(CONFIG_PPC_I8259)               += i8259.o
++obj-$(CONFIG_PPC_BESTCOMM)    += bestcomm/
+diff --git a/arch/ppc/syslib/bestcomm/Makefile b/arch/ppc/syslib/bestcomm/Makefile
+new file mode 100644
+index 0000000..02cc99a
+--- /dev/null
++++ b/arch/ppc/syslib/bestcomm/Makefile
+@@ -0,0 +1,2 @@
++obj-$(CONFIG_PPC_BESTCOMM)    += bestcomm.o
++obj-$(CONFIG_FEC_MPC52xx)     += sdma_fec_rx_task.o sdma_fec_tx_task.o fec.o
+diff --git a/arch/ppc/syslib/bestcomm/bestcomm.c b/arch/ppc/syslib/bestcomm/bestcomm.c
+new file mode 100644
+index 0000000..ef45e02
+--- /dev/null
++++ b/arch/ppc/syslib/bestcomm/bestcomm.c
+@@ -0,0 +1,408 @@
++/*
++ * arch/ppc/syslib/bestcomm/bestcomm.c
++ *
++ * Driver for MPC52xx processor BestComm peripheral controller
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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.
++ *
++ * HISTORY:
++ *
++ * 2005-08-14 Converted to platform driver by 
++ *            Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
++ */
++
++#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/device.h>
++
++#include <asm/bug.h>
++#include <asm/io.h>
++#include <asm/mpc52xx.h>
++
++#include "bestcomm.h"
++
++#define DRIVER_NAME           "mpc52xx-sdma"
++
++struct sdma_io sdma;
++
++static spinlock_t sdma_lock = SPIN_LOCK_UNLOCKED;
++
++#ifdef CONFIG_BESTCOMM_DEBUG
++void sdma_dump(void)
++{
++      int i;
++      printk("** SDMA registers: pa = %08x, va = %08x\n", sdma.base_reg_addr, sdma.io);
++      printk("**  taskBar = %08x\n", sdma.io->taskBar);
++      printk("**  currentPointer = %08x\n", sdma.io->currentPointer);
++      printk("**  endPointer = %08x\n", sdma.io->endPointer);
++      printk("**  variablePointer = %08x\n", sdma.io->variablePointer);
++
++      printk("**  IntVect1 = %08x\n", sdma.io->IntVect1);
++      printk("**  IntVect2 = %08x\n", sdma.io->IntVect2);
++      printk("**  PtdCntrl = %08x\n", sdma.io->PtdCntrl);
++
++      printk("**  IntPend = %08x\n", sdma.io->IntPend);
++      printk("**  IntMask = %08x\n", sdma.io->IntMask);
++
++      printk("**  TCR dump:");        
++
++      for (i=0;i<16;i++)  {
++              if(i%8 == 0)
++                      printk("\n**   %02X:",i);
++              printk(" %04X",sdma.io->tcr[i]);
++      }
++      printk("\n**  IPR dump:");      
++      for (i=0;i<32;i++)  {
++              if(i%16 == 0)
++                      printk("\n**   %02X:",i);
++              printk(" %02X",sdma.io->ipr[i]);
++      }
++      printk("\n**  cReqSelect = %08x\n", sdma.io->cReqSelect);
++      printk("**  task_size0 = %08x\n", sdma.io->task_size0);
++      printk("**  task_size1 = %08x\n", sdma.io->task_size1);
++      printk("**  MDEDebug = %08x\n", sdma.io->MDEDebug);
++      printk("**  ADSDebug = %08x\n", sdma.io->ADSDebug);
++      printk("**  Value1 = %08x\n", sdma.io->Value1);
++      printk("**  Value2 = %08x\n", sdma.io->Value2);
++      printk("**  Control = %08x\n", sdma.io->Control);
++      printk("**  Status = %08x\n", sdma.io->Status);
++      printk("**  PTDDebug = %08x\n", sdma.io->PTDDebug);
++}
++#endif
++
++#ifdef CONFIG_BESTCOMM_DEBUG
++#define SDMA_DUMP_REGS()      sdma_dump()
++#else
++#define SDMA_DUMP_REGS()
++#endif
++
++/*
++ * Use a very simple SRAM allocator.
++ * There is no mechanism for freeing space.
++ * In an attempt to minimize internal fragmentation, the SRAM is
++ * divided into two areas.
++ *
++ * Area 1 is at the beginning of SRAM
++ * and is used for allocations requiring alignments of 16 bytes or less.
++ * Successive allocations return higher addresses.
++ *
++ * Area 2 is at the end of SRAM and is used for the remaining allocations.
++ * Successive allocations return lower addresses.
++ *
++ * I've considered adding routines to support the freeing of SRAM allocations,
++ * but the SRAM is so small (16K) that fragmentation can quickly cause the
++ * SRAM to be unusable.  If you can come up with a slick way to free SRAM
++ * memory without the fragmentation problem, please do so.
++ */
++
++static u8 *area1_end;
++static u8 *area2_begin;
++
++void *sdma_sram_alloc(int size, int alignment, u32 *dma_handle)
++{
++      u8 *a;
++
++      spin_lock(&sdma_lock);
++
++      /* alignment must be a power of 2 */
++      BUG_ON(alignment & (alignment - 1));
++
++      if (alignment < 16) {
++              a = (u8 *)(((u32)area1_end + (alignment-1)) & ~(alignment-1));
++              if (a + size <= area2_begin)
++                      area1_end = a + size;
++              else
++                      a = 0;                          /* out of memory */
++      } else {
++              a = (u8 *)(((u32)area2_begin - size) & ~(alignment - 1));
++              if (a >= area1_end)
++                      area2_begin = a;
++              else
++                      a = 0;                          /* out of memory */
++      }
++      if(a && dma_handle)
++              *dma_handle = sdma_sram_pa(a);
++      spin_unlock(&sdma_lock);
++      return (void *)a;
++}
++
++/* this will need to be updated if Freescale changes their task code FDT */
++static u32 fdt_ops[] = {
++      0xa0045670,     /* FDT[48] */
++      0x80045670,     /* FDT[49] */
++      0x21800000,     /* FDT[50] */
++      0x21e00000,     /* FDT[51] */
++      0x21500000,     /* FDT[52] */
++      0x21400000,     /* FDT[53] */
++      0x21500000,     /* FDT[54] */
++      0x20400000,     /* FDT[55] */
++      0x20500000,     /* FDT[56] */
++      0x20800000,     /* FDT[57] */
++      0x20a00000,     /* FDT[58] */
++      0xc0170000,     /* FDT[59] */
++      0xc0145670,     /* FDT[60] */
++      0xc0345670,     /* FDT[61] */
++      0xa0076540,     /* FDT[62] */
++      0xa0000760,     /* FDT[63] */
++};
++
++static int new_task_number(void)
++{
++      struct sdma_tdt *tdt;
++      int i;
++
++      spin_lock(&sdma_lock);
++
++      tdt = sdma.tdt;
++      for (i=0; i<SDMA_MAX_TASKS; i++, tdt++)
++              if (tdt->start == 0)
++                      break;
++      if (i == SDMA_MAX_TASKS)
++              i = -1;
++
++      spin_unlock(&sdma_lock);
++
++      return i;
++}
++
++int sdma_load_task(u32 *task_image)
++{
++      struct sdma_task_header *head = (struct sdma_task_header *)task_image;
++      struct sdma_tdt *tdt;
++      int tasknum;
++      u32 *desc;
++      u32 *var_src, *var_dst;
++      u32 *inc_src;
++      void *start;
++
++      BUG_ON(head->magic != SDMA_TASK_MAGIC);
++
++      tasknum = new_task_number();
++      if (tasknum < 0)
++              return -ENOMEM;
++
++      desc = (u32 *)(head + 1);
++      var_src = desc + head->desc_size;
++      inc_src = var_src + head->var_size;
++
++      tdt = &sdma.tdt[tasknum];
++
++      start = sdma_sram_alloc(head->desc_size * sizeof(u32), 4, &tdt->start);
++      if (!start)
++              return -ENOMEM;
++      tdt->stop = tdt->start + (head->desc_size - 1)*sizeof(u32);
++      var_dst = sdma_sram_va(tdt->var);
++
++      memcpy(start, desc, head->desc_size * sizeof(u32));
++      memcpy(&var_dst[head->first_var], var_src, head->var_size * sizeof(u32));
++      memcpy(&var_dst[SDMA_MAX_VAR], inc_src, head->inc_size * sizeof(u32));
++
++      return tasknum;
++}
++
++void sdma_set_initiator(int task, int initiator)
++{
++      int i;
++      int num_descs;
++      u32 *desc;
++      int next_drd_has_initiator;
++
++      sdma_set_tcr_initiator(task, initiator);
++
++      desc = sdma_task_desc(task);
++      next_drd_has_initiator = 1;
++      num_descs = sdma_task_num_descs(task);
++
++      for (i=0; i<num_descs; i++, desc++) {
++              if (!sdma_desc_is_drd(*desc))
++                      continue;
++              if (next_drd_has_initiator)
++                      if (sdma_desc_initiator(*desc) != SDMA_INITIATOR_ALWAYS)
++                              sdma_set_desc_initiator(desc, initiator);
++              next_drd_has_initiator = !sdma_drd_is_extended(*desc);
++      }
++}
++
++struct sdma *sdma_alloc(int queue_size)
++{
++      struct sdma *s = kmalloc(sizeof(*s), GFP_KERNEL);
++      void **cookie;
++
++      if (!s)
++              return NULL;
++
++      memset(s, 0, sizeof(*s));
++
++      if (queue_size) {
++              cookie = kmalloc(sizeof(*cookie) * queue_size, GFP_KERNEL);
++              if (!cookie) {
++                      kfree(s);
++                      return NULL;
++              }
++              s->cookie = cookie;
++      }
++
++      s->num_bd = queue_size;
++      return s;
++}
++
++void sdma_free(struct sdma *s)
++{
++      if (s->cookie)
++              kfree(s->cookie);
++      kfree(s);
++}
++
++static int __devinit mpc52xx_sdma_probe(struct device *dev)
++{
++      struct platform_device *pdev = to_platform_device(dev);
++      int task;
++      u32 *context;
++      u32 *fdt;
++      struct sdma_tdt *tdt;
++      struct resource *mem_io, *mem_sram;
++      u32 tdt_pa, var_pa, context_pa, fdt_pa; 
++      int ret = -ENODEV;
++
++      mem_io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      mem_sram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++      if (!mem_io || !mem_sram)
++              goto out;
++
++      if (!request_mem_region(mem_io->start, mem_io->end - mem_io->start + 1, DRIVER_NAME)) {
++              printk(KERN_ERR DRIVER_NAME " - resource unavailable\n");
++              goto out;
++      }
++      sdma.base_reg_addr = mem_io->start;
++
++      sdma.io = ioremap_nocache(mem_io->start, sizeof(struct mpc52xx_sdma));
++
++      if (!sdma.io ) {
++              printk(KERN_ERR DRIVER_NAME " - failed to map sdma regs\n");
++              ret = -ENOMEM;
++              goto map_io_error;
++      }
++
++      SDMA_DUMP_REGS();
++
++      sdma.sram_size = mem_sram->end - mem_sram->start + 1;
++      if (!request_mem_region(mem_sram->start, sdma.sram_size, DRIVER_NAME)) {
++              printk(KERN_ERR DRIVER_NAME " - resource unavailable\n");
++              goto req_sram_error;
++      }
++
++      sdma.base_sram_addr = mem_sram->start;
++      sdma.sram = ioremap_nocache(mem_sram->start, sdma.sram_size);
++      if (!sdma.sram ) {
++              printk(KERN_ERR DRIVER_NAME " - failed to map sdma sram\n");
++              ret = -ENOMEM;
++              goto map_sram_error;
++      }
++
++      area1_end = sdma.sram;
++      area2_begin = area1_end + sdma.sram_size;
++
++      memset(area1_end, 0, sdma.sram_size);
++
++      /* allocate space for task descriptors, contexts, and var tables */
++      sdma.tdt = sdma_sram_alloc(sizeof(struct sdma_tdt) * SDMA_MAX_TASKS, 4, &tdt_pa);
++
++      context = sdma_sram_alloc(SDMA_CONTEXT_SIZE * SDMA_MAX_TASKS,
++                                                        SDMA_CONTEXT_ALIGN, &context_pa);
++      sdma.var = sdma_sram_alloc( (SDMA_VAR_SIZE + SDMA_INC_SIZE) * SDMA_MAX_TASKS, 
++                                                              SDMA_VAR_ALIGN, &var_pa);
++      fdt = sdma_sram_alloc(SDMA_FDT_SIZE, SDMA_FDT_ALIGN, &fdt_pa);
++      memcpy(&fdt[48], fdt_ops, sizeof(fdt_ops));
++
++      out_be32(&sdma.io->taskBar, tdt_pa);
++
++      tdt = sdma.tdt;
++      for (task=0; task < SDMA_MAX_TASKS; task++) {
++              out_be16(&sdma.io->tcr[task], 0);
++              out_8(&sdma.io->ipr[task], 0);
++
++              tdt->context = context_pa;
++              tdt->var = var_pa;
++              tdt->fdt = fdt_pa;
++              var_pa += (SDMA_MAX_VAR + SDMA_MAX_INC)*sizeof(u32);
++              context_pa += SDMA_MAX_CONTEXT*sizeof(u32);
++              tdt++;
++      }
++
++      out_8(&sdma.io->ipr[SDMA_INITIATOR_ALWAYS], SDMA_IPR_ALWAYS);
++
++      /* Disable COMM Bus Prefetch, apparently it's not reliable yet */
++      out_be16(&sdma.io->PtdCntrl, in_be16(&sdma.io->PtdCntrl) | 1);
++
++      printk(KERN_INFO "MPC52xx BestComm inited\n");
++
++      return 0;
++
++map_sram_error:
++      release_mem_region(mem_sram->start, sdma.sram_size);
++req_sram_error:
++      iounmap(sdma.io);
++map_io_error:
++      release_mem_region(mem_io->start, mem_io->end - mem_io->start + 1);
++out:
++      printk(KERN_ERR "DMA: MPC52xx BestComm init FAILED !!!\n");
++      return ret;
++}
++
++
++static struct device_driver mpc52xx_sdma_driver = {
++      .owner    = THIS_MODULE,
++      .name     = DRIVER_NAME,
++      .bus      = &platform_bus_type,
++      .probe    = mpc52xx_sdma_probe,
++/*    .remove   = mpc52xx_sdma_remove,        TODO */
++#ifdef CONFIG_PM
++/*    .suspend        = mpc52xx_sdma_suspend, TODO */
++/*    .resume         = mpc52xx_sdma_resume,  TODO */
++#endif
++};
++
++static int __init
++mpc52xx_sdma_init(void)
++{
++      printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
++      return driver_register(&mpc52xx_sdma_driver);
++}
++
++#ifdef MODULE
++static void __exit
++mpc52xx_sdma_exit(void)
++{
++      driver_unregister(&mpc52xx_sdma_driver);
++}
++#endif
++
++#ifndef MODULE
++ subsys_initcall(mpc52xx_sdma_init);
++#else
++ module_init(mpc52xx_sdma_init);
++ module_exit(mpc52xx_sdma_exit);
++#endif
++
++
++MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
++MODULE_LICENSE("GPL");
++
++EXPORT_SYMBOL(sdma_sram_alloc);
++EXPORT_SYMBOL(sdma_load_task);
++EXPORT_SYMBOL(sdma_set_initiator);
++EXPORT_SYMBOL(sdma_free);
++EXPORT_SYMBOL(sdma);
++
++
+diff --git a/arch/ppc/syslib/bestcomm/bestcomm.h b/arch/ppc/syslib/bestcomm/bestcomm.h
+new file mode 100644
+index 0000000..14bf397
+--- /dev/null
++++ b/arch/ppc/syslib/bestcomm/bestcomm.h
+@@ -0,0 +1,473 @@
++/*
++ * arch/ppc/syslib/bestcomm/bestcomm.h
++ *
++ * Driver for MPC52xx processor BestComm peripheral controller
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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.
++ *
++ * HISTORY:
++ *
++ * 2005-08-14 Converted to platform driver by 
++ *            Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
++ */
++
++#ifndef __BESTCOMM_BESTCOMM_H__
++#define __BESTCOMM_BESTCOMM_H__
++
++/* Buffer Descriptor definitions */
++struct sdma_bd {
++      u32 status;
++      void *data;
++};
++
++struct sdma_bd2 {
++      u32 status;
++      void *data1;
++      void *data2;
++};
++
++struct sdma_io {
++      unsigned long                   base_reg_addr;
++      struct mpc52xx_sdma __iomem     *io;
++      unsigned long                   base_sram_addr;
++      void __iomem                    *sram;
++      size_t                          sram_size;
++
++      struct sdma_tdt __iomem         *tdt;
++      u32 __iomem                     *var;
++};
++extern struct sdma_io sdma;
++
++#define       sdma_sram_pa(virt)      (((unsigned long)(((void __iomem *)(virt))-sdma.sram))+sdma.base_sram_addr)
++#define       sdma_sram_va(pa)        ((void __iomem *)((((unsigned long)(pa))-sdma.base_sram_addr)+((unsigned long)sdma.sram)))
++
++#define       sdma_io_pa(virt)        (((unsigned long)(((void __iomem *)(virt))-((void __iomem *)sdma.io)))+sdma.base_reg_addr)
++#define       sdma_io_va(pa)  ((void __iomem *)((((unsigned long)(pa))-sdma.base_reg_addr)+((unsigned long)sdma.io)))
++
++#define SDMA_LEN_BITS         26
++#define SDMA_LEN_MASK         ((1 << SDMA_LEN_BITS) - 1)
++
++#define SDMA_BD_READY         0x40000000UL
++
++#define SDMA_FEC_TX_BD_TFD    0x08000000UL    /* transmit frame done */
++#define SDMA_FEC_TX_BD_INT    0x04000000UL    /* Interrupt */
++#define SDMA_FEC_TX_BD_TFD_INIT       (SDMA_BD_READY | SDMA_FEC_TX_BD_TFD | \
++                                                      SDMA_FEC_TX_BD_INT)
++
++struct sdma {
++      union {
++              struct sdma_bd *bd;
++              struct sdma_bd2 *bd2;
++      };
++      void **cookie;
++      u16 index;
++      u16 outdex;
++      u16 num_bd;
++      s16 tasknum;
++      u32 flags;
++};
++
++#define SDMA_FLAGS_NONE               0x0000
++#define SDMA_FLAGS_ENABLE_TASK        0x0001
++#define SDMA_FLAGS_BD2                0x0002
++
++/* Task Descriptor Table Entry */
++struct sdma_tdt {
++      u32 start;
++      u32 stop;
++      u32 var;
++      u32 fdt;
++      u32 exec_status; /* used internally by SmartComm engine */
++      u32 mvtp;                /* used internally by SmartComm engine */
++      u32 context;
++      u32 litbase;
++};
++
++//extern struct sdma_tdt *sdma_tdt;
++
++#define SDMA_MAX_TASKS                16
++#define SDMA_MAX_VAR          24
++#define SDMA_MAX_INC          8
++#define SDMA_MAX_FDT          64
++#define SDMA_MAX_CONTEXT      20
++#define SDMA_CONTEXT_SIZE     SDMA_MAX_CONTEXT * sizeof(u32)
++#define SDMA_CONTEXT_ALIGN    0x100
++#define SDMA_VAR_SIZE         SDMA_MAX_VAR * sizeof(u32)
++#define SDMA_VAR_ALIGN                0x80
++#define SDMA_INC_SIZE         SDMA_MAX_INC * sizeof(u32)
++#define SDMA_FDT_SIZE         SDMA_MAX_FDT * sizeof(u32)
++#define SDMA_FDT_ALIGN                0x100
++#define SDMA_BD_ALIGN         0x10
++
++#define TASK_ENABLE           0x8000
++
++#ifndef DPRINK
++      #ifdef CONFIG_BESTCOMM_DEBUG
++      #define DPRINTK(a,b...) printk(KERN_DEBUG "sdma: %s: " a, __FUNCTION__ , ## b)
++      #else
++      #define DPRINTK(a,b...)
++      #endif
++#endif
++
++static inline void sdma_enable_task(int task)
++{
++      DPRINTK("***DMA enable task (%d): tdt = %08x\n",task, sdma.tdt);
++      DPRINTK("***tdt->start   = %08x\n",sdma.tdt[task].start);
++      DPRINTK("***tdt->stop    = %08x\n",sdma.tdt[task].stop);
++      DPRINTK("***tdt->var     = %08x\n",sdma.tdt[task].var);
++      DPRINTK("***tdt->fdt     = %08x\n",sdma.tdt[task].fdt);
++      DPRINTK("***tdt->status  = %08x\n",sdma.tdt[task].exec_status);
++      DPRINTK("***tdt->mvtp    = %08x\n",sdma.tdt[task].mvtp);
++      DPRINTK("***tdt->context = %08x\n",sdma.tdt[task].context);
++      DPRINTK("***tdt->litbase = %08x\n",sdma.tdt[task].litbase);
++      DPRINTK("***--------------\n");
++
++      u16 reg = in_be16(&sdma.io->tcr[task]);
++      DPRINTK("***enable task: &sdma.io->tcr=%08x, reg = %04x\n", &sdma.io->tcr, reg);
++      out_be16(&sdma.io->tcr[task],  reg | TASK_ENABLE);
++}
++
++static inline void sdma_disable_task(int task)
++{
++      u16 reg = in_be16(&sdma.io->tcr[task]);
++      DPRINTK("***disable task(%d): reg = %04x\n", task, reg);
++      out_be16(&sdma.io->tcr[task], reg & ~TASK_ENABLE);
++}
++
++static inline int sdma_irq(struct sdma *s)
++{
++      return MPC52xx_SDMA_IRQ_BASE + s->tasknum;
++}
++
++static inline void sdma_enable(struct sdma *s)
++{
++      sdma_enable_task(s->tasknum);
++}
++
++static inline void sdma_disable(struct sdma *s)
++{
++      sdma_disable_task(s->tasknum);
++}
++
++static inline int sdma_queue_empty(struct sdma *s)
++{
++      return s->index == s->outdex;
++}
++
++static inline void sdma_clear_irq(struct sdma *s)
++{
++      out_be32(&sdma.io->IntPend, 1 << s->tasknum);
++}
++
++static inline int sdma_next_index(struct sdma *s)
++{
++      return ((s->index + 1) == s->num_bd) ? 0 : s->index + 1;
++}
++
++static inline int sdma_next_outdex(struct sdma *s)
++{
++      return ((s->outdex + 1) == s->num_bd) ? 0 : s->outdex + 1;
++}
++
++static inline int sdma_queue_full(struct sdma *s)
++{
++      return s->outdex == sdma_next_index(s);
++}
++
++static inline int sdma_buffer_done(struct sdma *s)
++{
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(s->flags & SDMA_FLAGS_BD2);
++#endif
++      if (sdma_queue_empty(s))
++              return 0;
++      return (s->bd[s->outdex].status & SDMA_BD_READY) == 0;
++}
++
++static inline int sdma_buffer2_done(struct sdma *s)
++{
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(!(s->flags & SDMA_FLAGS_BD2));
++#endif
++      if (sdma_queue_empty(s))
++              return 0;
++
++      return (s->bd2[s->outdex].status & SDMA_BD_READY) == 0;
++}
++
++static inline u32 *sdma_task_desc(int task)
++{
++      return sdma_sram_va(sdma.tdt[task].start);
++}
++
++static inline u32 sdma_task_num_descs(int task)
++{
++      return (sdma.tdt[task].stop - sdma.tdt[task].start)/sizeof(u32) + 1;
++}
++
++static inline u32 *sdma_task_var(int task)
++{
++      return sdma_sram_va(sdma.tdt[task].var);
++}
++
++static inline u32 *sdma_task_inc(int task)
++{
++      return &sdma_task_var(task)[SDMA_MAX_VAR];
++}
++
++static inline void sdma_set_tcr_initiator(int task, int initiator) {
++      u16 *tcr = &sdma.io->tcr[task];
++      out_be16(tcr, (in_be16(tcr) & ~0x1f00) | (initiator << 8));
++}
++
++#define SDMA_DRD_INITIATOR_SHIFT      21
++
++static inline int sdma_desc_initiator(u32 desc)
++{
++      return (desc >> SDMA_DRD_INITIATOR_SHIFT) & 0x1f;
++}
++
++static inline void sdma_set_desc_initiator(u32 *desc, int initiator)
++{
++      *desc = (*desc & ~(0x1f << SDMA_DRD_INITIATOR_SHIFT)) |
++                      ((initiator << SDMA_DRD_INITIATOR_SHIFT) & 0x1f);
++}
++
++static inline void sdma_submit_buffer(struct sdma *s, void *cookie, void *data,
++                                                              int length)
++{
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(s->flags & SDMA_FLAGS_BD2);
++#endif
++      s->cookie[s->index] = cookie;
++      s->bd[s->index].data = data;
++      s->bd[s->index].status = SDMA_BD_READY | length;
++      s->index = sdma_next_index(s);
++      if (s->flags & SDMA_FLAGS_ENABLE_TASK)
++              sdma_enable_task(s->tasknum);
++}
++
++/*
++ * Special submit_buffer function to submit last buffer of a frame to
++ * the FEC tx task.  tfd means "transmit frame done".
++ */
++static inline void sdma_fec_tfd_submit_buffer(struct sdma *s, void *cookie,
++                                                      void *data, int length)
++{
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(s->flags & SDMA_FLAGS_BD2);
++#endif
++      s->cookie[s->index] = cookie;
++      s->bd[s->index].data = data;
++      s->bd[s->index].status = SDMA_FEC_TX_BD_TFD_INIT | length;
++      s->index = sdma_next_index(s);
++      sdma_enable_task(s->tasknum);
++}
++
++static inline void *sdma_retrieve_buffer(struct sdma *s, int *length)
++{
++      void *cookie = s->cookie[s->outdex];
++
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(s->flags & SDMA_FLAGS_BD2);
++#endif
++      if (length)
++              *length = s->bd[s->outdex].status & SDMA_LEN_MASK;
++      s->outdex = sdma_next_outdex(s);
++      return cookie;
++}
++
++static inline void sdma_submit_buffer2(struct sdma *s, void *cookie,
++                                      void *data1, void *data2, int length)
++{
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(!(s->flags & SDMA_FLAGS_BD2));
++#endif
++      s->cookie[s->index] = cookie;
++      s->bd2[s->index].data1 = data1;
++      s->bd2[s->index].data2 = data2;
++      s->bd2[s->index].status = SDMA_BD_READY | length;
++      s->index = sdma_next_index(s);
++      if (s->flags & SDMA_FLAGS_ENABLE_TASK)
++              sdma_enable_task(s->tasknum);
++}
++
++static inline void *sdma_retrieve_buffer2(struct sdma *s, int *length)
++{
++      void *cookie = s->cookie[s->outdex];
++
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(!(s->flags & SDMA_FLAGS_BD2));
++#endif
++      if (length)
++              *length = s->bd2[s->outdex].status & SDMA_LEN_MASK;
++      s->outdex = sdma_next_outdex(s);
++      return cookie;
++}
++
++#define SDMA_TASK_MAGIC               0x4243544B      /* 'BCTK' */
++
++/* the size fields are given in number of 32-bit words */
++struct sdma_task_header {
++      u32     magic;
++      u8      desc_size;
++      u8      var_size;
++      u8      inc_size;
++      u8      first_var;
++      u8      reserved[8];
++};
++
++#define SDMA_DESC_NOP         0x000001f8
++#define SDMA_LCD_MASK         0x80000000
++#define SDMA_DRD_EXTENDED     0x40000000
++
++#define sdma_drd_is_extended(desc) ((desc) & SDMA_DRD_EXTENDED)
++
++static inline int sdma_desc_is_drd(u32 desc) {
++      return !(desc & SDMA_LCD_MASK) && desc != SDMA_DESC_NOP;
++};
++
++#define SDMA_PRAGMA_BIT_RSV           7       /* reserved pragma bit */
++#define SDMA_PRAGMA_BIT_PRECISE_INC   6       /* increment 0=when possible, */
++                                              /*      1=iter end */
++#define SDMA_PRAGMA_BIT_RST_ERROR_NO  5       /* don't reset errors on */
++                                              /* task enable */
++#define SDMA_PRAGMA_BIT_PACK          4       /* pack data enable */
++#define SDMA_PRAGMA_BIT_INTEGER               3       /* data alignment */
++                                              /* 0=frac(msb), 1=int(lsb) */
++#define SDMA_PRAGMA_BIT_SPECREAD      2       /* XLB speculative read */
++#define SDMA_PRAGMA_BIT_CW            1       /* write line buffer enable */
++#define SDMA_PRAGMA_BIT_RL            0       /* read line buffer enable */
++
++#define SDMA_STD_PRAGMA               ((0 << SDMA_PRAGMA_BIT_RSV)             | \
++                               (0 << SDMA_PRAGMA_BIT_PRECISE_INC)     | \
++                               (0 << SDMA_PRAGMA_BIT_RST_ERROR_NO)    | \
++                               (0 << SDMA_PRAGMA_BIT_PACK)            | \
++                               (0 << SDMA_PRAGMA_BIT_INTEGER)         | \
++                               (1 << SDMA_PRAGMA_BIT_SPECREAD)        | \
++                               (1 << SDMA_PRAGMA_BIT_CW)              | \
++                               (1 << SDMA_PRAGMA_BIT_RL))
++
++#define SDMA_PCI_PRAGMA               ((0 << SDMA_PRAGMA_BIT_RSV)             | \
++                               (0 << SDMA_PRAGMA_BIT_PRECISE_INC)     | \
++                               (0 << SDMA_PRAGMA_BIT_RST_ERROR_NO)    | \
++                               (0 << SDMA_PRAGMA_BIT_PACK)            | \
++                               (1 << SDMA_PRAGMA_BIT_INTEGER)         | \
++                               (1 << SDMA_PRAGMA_BIT_SPECREAD)        | \
++                               (1 << SDMA_PRAGMA_BIT_CW)              | \
++                               (1 << SDMA_PRAGMA_BIT_RL))
++
++#define SDMA_ATA_PRAGMA               SDMA_STD_PRAGMA
++#define SDMA_CRC16_DP_0_PRAGMA        SDMA_STD_PRAGMA
++#define SDMA_CRC16_DP_1_PRAGMA        SDMA_STD_PRAGMA
++#define SDMA_FEC_RX_BD_PRAGMA SDMA_STD_PRAGMA
++#define SDMA_FEC_TX_BD_PRAGMA SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_0_PRAGMA  SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_1_PRAGMA  SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_2_PRAGMA  SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_3_PRAGMA  SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_BD_0_PRAGMA       SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_BD_1_PRAGMA       SDMA_STD_PRAGMA
++#define SDMA_GEN_RX_BD_PRAGMA SDMA_STD_PRAGMA
++#define SDMA_GEN_TX_BD_PRAGMA SDMA_STD_PRAGMA
++#define SDMA_GEN_LPC_PRAGMA   SDMA_STD_PRAGMA
++#define SDMA_PCI_RX_PRAGMA    SDMA_PCI_PRAGMA
++#define SDMA_PCI_TX_PRAGMA    SDMA_PCI_PRAGMA
++
++static inline void sdma_set_task_pragma(int task, int pragma)
++{
++      u32 *fdt = &sdma.tdt[task].fdt;
++      *fdt = (*fdt & ~0xff) | pragma;
++}
++
++static inline void sdma_set_task_auto_start(int task, int next_task)
++{
++      u16 *tcr = &sdma.io->tcr[task];
++      out_be16(tcr, (in_be16(tcr) & ~0xff) | 0x00c0 | next_task);
++}
++
++#define SDMA_INITIATOR_ALWAYS  0
++#define SDMA_INITIATOR_SCTMR_0         1
++#define SDMA_INITIATOR_SCTMR_1         2
++#define SDMA_INITIATOR_FEC_RX  3
++#define SDMA_INITIATOR_FEC_TX  4
++#define SDMA_INITIATOR_ATA_RX  5
++#define SDMA_INITIATOR_ATA_TX  6
++#define SDMA_INITIATOR_SCPCI_RX        7
++#define SDMA_INITIATOR_SCPCI_TX        8
++#define SDMA_INITIATOR_PSC3_RX         9
++#define SDMA_INITIATOR_PSC3_TX        10
++#define SDMA_INITIATOR_PSC2_RX        11
++#define SDMA_INITIATOR_PSC2_TX        12
++#define SDMA_INITIATOR_PSC1_RX        13
++#define SDMA_INITIATOR_PSC1_TX        14
++#define SDMA_INITIATOR_SCTMR_2        15
++#define SDMA_INITIATOR_SCLPC  16
++#define SDMA_INITIATOR_PSC5_RX        17
++#define SDMA_INITIATOR_PSC5_TX        18
++#define SDMA_INITIATOR_PSC4_RX        19
++#define SDMA_INITIATOR_PSC4_TX        20
++#define SDMA_INITIATOR_I2C2_RX        21
++#define SDMA_INITIATOR_I2C2_TX        22
++#define SDMA_INITIATOR_I2C1_RX        23
++#define SDMA_INITIATOR_I2C1_TX        24
++#define SDMA_INITIATOR_PSC6_RX        25
++#define SDMA_INITIATOR_PSC6_TX        26
++#define SDMA_INITIATOR_IRDA_RX        25
++#define SDMA_INITIATOR_IRDA_TX        26
++#define SDMA_INITIATOR_SCTMR_3        27
++#define SDMA_INITIATOR_SCTMR_4        28
++#define SDMA_INITIATOR_SCTMR_5        29
++#define SDMA_INITIATOR_SCTMR_6        30
++#define SDMA_INITIATOR_SCTMR_7        31
++
++#define SDMA_IPR_ALWAYS       7
++#define SDMA_IPR_SCTMR_0      2
++#define SDMA_IPR_SCTMR_1      2
++#define SDMA_IPR_FEC_RX       6
++#define SDMA_IPR_FEC_TX       5
++#define SDMA_IPR_ATA_RX       4
++#define SDMA_IPR_ATA_TX       3
++#define SDMA_IPR_SCPCI_RX     2
++#define SDMA_IPR_SCPCI_TX     2
++#define SDMA_IPR_PSC3_RX      2
++#define SDMA_IPR_PSC3_TX      2
++#define SDMA_IPR_PSC2_RX      2
++#define SDMA_IPR_PSC2_TX      2
++#define SDMA_IPR_PSC1_RX      2
++#define SDMA_IPR_PSC1_TX      2
++#define SDMA_IPR_SCTMR_2      2
++#define SDMA_IPR_SCLPC                2
++#define SDMA_IPR_PSC5_RX      2
++#define SDMA_IPR_PSC5_TX      2
++#define SDMA_IPR_PSC4_RX      2
++#define SDMA_IPR_PSC4_TX      2
++#define SDMA_IPR_I2C2_RX      2
++#define SDMA_IPR_I2C2_TX      2
++#define SDMA_IPR_I2C1_RX      2
++#define SDMA_IPR_I2C1_TX      2
++#define SDMA_IPR_PSC6_RX      2
++#define SDMA_IPR_PSC6_TX      2
++#define SDMA_IPR_IRDA_RX      2
++#define SDMA_IPR_IRDA_TX      2
++#define SDMA_IPR_SCTMR_3      2
++#define SDMA_IPR_SCTMR_4      2
++#define SDMA_IPR_SCTMR_5      2
++#define SDMA_IPR_SCTMR_6      2
++#define SDMA_IPR_SCTMR_7      2
++
++extern struct sdma *sdma_alloc(int request_queue_size);
++extern void sdma_free(struct sdma *sdma_struct);
++extern int sdma_load_task(u32 *task_image);
++extern void *sdma_sram_alloc(int size, int alignment, u32 *dma_handle);
++extern void sdma_init_bd(struct sdma *s);
++extern void sdma_init_bd2(struct sdma *s);
++
++#define FIELD_OFFSET(s,f) ((unsigned long)(&(((struct s*)0)->f)))
++
++#endif  /* __BESTCOMM_BESTCOMM_H__ */
+diff --git a/arch/ppc/syslib/bestcomm/fec.c b/arch/ppc/syslib/bestcomm/fec.c
+new file mode 100644
+index 0000000..8756856
+--- /dev/null
++++ b/arch/ppc/syslib/bestcomm/fec.c
+@@ -0,0 +1,174 @@
++/*
++ * arch/ppc/syslib/bestcomm/fec.c
++ *
++ * Driver for MPC52xx processor BestComm FEC controller
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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.
++ *
++ * HISTORY:
++ *
++ * 2005-08-14 Converted to platform driver by 
++ *            Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
++ */
++
++#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <asm/errno.h>                                  
++#include <asm/io.h>
++
++#include <asm/mpc52xx.h>
++
++#include "bestcomm.h"
++#include "fec.h"
++
++/*
++ * Initialize FEC receive task.
++ * Returns task number of FEC receive task.
++ * Returns -1 on failure
++ */
++int sdma_fec_rx_init(struct sdma *s, phys_addr_t fifo, int maxbufsize)
++{
++      struct sdma_fec_rx_var *var;
++      struct sdma_fec_rx_inc *inc;
++
++      static int tasknum = -1;
++      static struct sdma_bd *bd = 0;
++      static u32 bd_pa;
++
++      if (tasknum < 0) {
++              tasknum = sdma_load_task(sdma_fec_rx_task);
++              if (tasknum < 0)
++                      return tasknum;
++      }
++
++      if (!bd) 
++              bd = (struct sdma_bd *)sdma_sram_alloc(sizeof(*bd) * s->num_bd,
++                                                              SDMA_BD_ALIGN, &bd_pa);
++      if (!bd)
++              return -ENOMEM;
++
++      sdma_disable_task(tasknum);
++
++      s->tasknum = tasknum;
++      s->bd = bd;
++      s->flags = SDMA_FLAGS_NONE;
++      s->index = 0;
++      s->outdex = 0;
++      memset(bd, 0, sizeof(*bd) * s->num_bd);
++
++      var = (struct sdma_fec_rx_var *)sdma_task_var(tasknum);
++      var->enable                     = sdma_io_pa(&sdma.io->tcr[tasknum]);
++      var->fifo                       = fifo;
++      var->bd_base            = bd_pa;
++      var->bd_last            = bd_pa + (s->num_bd - 1)*sizeof(struct sdma_bd);
++      var->bd_start           = bd_pa;
++      var->buffer_size        = maxbufsize;
++
++      /* These are constants, they should have been in the image file */
++      inc = (struct sdma_fec_rx_inc *)sdma_task_inc(tasknum);
++      inc->incr_bytes         = -(s16)sizeof(u32);
++      inc->incr_dst           = sizeof(u32);
++      inc->incr_dst_ma        = sizeof(u8);
++
++      sdma_set_task_pragma(tasknum, SDMA_FEC_RX_BD_PRAGMA);
++      sdma_set_task_auto_start(tasknum, tasknum);
++
++      /* clear pending interrupt bits */
++      out_be32(&sdma.io->IntPend, 1<<tasknum);
++
++      out_8(&sdma.io->ipr[SDMA_INITIATOR_FEC_RX], SDMA_IPR_FEC_RX);
++
++      return tasknum;
++}
++
++/*
++ * Return 2nd to last DRD
++ * This is an ugly hack, but at least it's only done once at initialization
++ */
++static u32 *self_modified_drd(int tasknum)
++{
++      u32 *desc;
++      int num_descs;
++      int drd_count;
++      int i;
++
++      num_descs = sdma_task_num_descs(tasknum);
++      desc = sdma_task_desc(tasknum) + num_descs - 1;
++      drd_count = 0;
++      for (i=0; i<num_descs; i++, desc--)
++              if (sdma_desc_is_drd(*desc) && ++drd_count == 3)
++                      break;
++      return desc;
++}
++
++/*
++ * Initialize FEC transmit task.
++ * Returns task number of FEC transmit task.
++ * Returns -1 on failure
++ */
++int sdma_fec_tx_init(struct sdma *s, phys_addr_t fifo)
++{
++      struct sdma_fec_tx_var *var;
++      struct sdma_fec_tx_inc *inc;
++
++      static int tasknum = -1;
++      static struct sdma_bd *bd = 0;
++      static u32 bd_pa;
++
++      if (tasknum < 0) {
++              tasknum = sdma_load_task(sdma_fec_tx_task);
++              if (tasknum < 0)
++                      return tasknum;
++      }
++
++      if (!bd)  
++              bd = (struct sdma_bd *)sdma_sram_alloc(sizeof(*bd) * s->num_bd,
++                                                              SDMA_BD_ALIGN, &bd_pa);
++      if (!bd)
++              return -ENOMEM;
++
++      sdma_disable_task(tasknum);
++
++      s->tasknum = tasknum;
++      s->bd = bd;
++      s->flags = SDMA_FLAGS_ENABLE_TASK;
++      s->index = 0;
++      s->outdex = 0;
++      memset(bd, 0, sizeof(*bd) * s->num_bd);
++
++      var = (struct sdma_fec_tx_var *)sdma_task_var(tasknum);
++      var->DRD                = sdma_sram_pa(self_modified_drd(tasknum));
++      var->fifo               = fifo;
++      var->enable             = sdma_io_pa(&sdma.io->tcr[tasknum]);
++      var->bd_base    = bd_pa;
++      var->bd_last    = bd_pa + (s->num_bd - 1)*sizeof(struct sdma_bd);
++      var->bd_start   = bd_pa;
++
++      /* These are constants, they should have been in the image file */
++      inc = (struct sdma_fec_tx_inc *)sdma_task_inc(tasknum);
++      inc->incr_bytes         = -(s16)sizeof(u32);
++      inc->incr_src           = sizeof(u32);
++      inc->incr_src_ma        = sizeof(u8);
++
++      sdma_set_task_pragma(tasknum, SDMA_FEC_TX_BD_PRAGMA);
++      sdma_set_task_auto_start(tasknum, tasknum);
++
++      /* clear pending interrupt bits */
++      out_be32(&sdma.io->IntPend, 1<<tasknum);
++
++      out_8(&sdma.io->ipr[SDMA_INITIATOR_FEC_TX], SDMA_IPR_FEC_TX);
++
++      return tasknum;
++}
++
++EXPORT_SYMBOL(sdma_fec_rx_init);
++EXPORT_SYMBOL(sdma_fec_tx_init);
+diff --git a/arch/ppc/syslib/bestcomm/fec.h b/arch/ppc/syslib/bestcomm/fec.h
+new file mode 100644
+index 0000000..e3abc0f
+--- /dev/null
++++ b/arch/ppc/syslib/bestcomm/fec.h
+@@ -0,0 +1,71 @@
++/*
++ * arch/ppc/syslib/bestcomm/fec.h
++ *
++ * Driver for MPC52xx processor BestComm FEC controller
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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.
++ *
++ * HISTORY:
++ *
++ * 2005-08-14 Converted to platform driver by 
++ *            Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
++ */
++
++#ifndef __BESTCOMM_FEC_H__
++#define __BESTCOMM_FEC_H__
++
++
++/* rx task vars that need to be set before enabling the task */
++struct sdma_fec_rx_var {
++      u32 enable;             /* (u16*) address of task's control register */
++      u32 fifo;               /* (u32*) address of fec's fifo */
++      u32 bd_base;            /* (struct sdma_bd*) beginning of ring buffer */
++      u32 bd_last;            /* (struct sdma_bd*) end of ring buffer */
++      u32 bd_start;           /* (struct sdma_bd*) current bd */
++      u32 buffer_size;        /* size of receive buffer */
++};
++
++/* rx task incs that need to be set before enabling the task */
++struct sdma_fec_rx_inc {
++      u16 pad0;
++      s16 incr_bytes;
++      u16 pad1;
++      s16 incr_dst;
++      u16 pad2;
++      s16 incr_dst_ma;
++};
++
++/* tx task vars that need to be set before enabling the task */
++struct sdma_fec_tx_var {
++      u32 DRD;                /* (u32*) address of self-modified DRD */
++      u32 fifo;               /* (u32*) address of fec's fifo */
++      u32 enable;             /* (u16*) address of task's control register */
++      u32 bd_base;            /* (struct sdma_bd*) beginning of ring buffer */
++      u32 bd_last;            /* (struct sdma_bd*) end of ring buffer */
++      u32 bd_start;           /* (struct sdma_bd*) current bd */
++      u32 buffer_size;        /* set by uCode for each packet */
++};
++
++/* tx task incs that need to be set before enabling the task */
++struct sdma_fec_tx_inc {
++      u16 pad0;
++      s16 incr_bytes;
++      u16 pad1;
++      s16 incr_src;
++      u16 pad2;
++      s16 incr_src_ma;
++};
++
++extern int sdma_fec_rx_init(struct sdma *s, phys_addr_t fifo, int maxbufsize);
++extern int sdma_fec_tx_init(struct sdma *s, phys_addr_t fifo);
++
++extern u32 sdma_fec_rx_task[];
++extern u32 sdma_fec_tx_task[];
++
++
++#endif  /* __BESTCOMM_FEC_H__ */
+diff --git a/arch/ppc/syslib/bestcomm/sdma_fec_rx_task.c b/arch/ppc/syslib/bestcomm/sdma_fec_rx_task.c
+new file mode 100644
+index 0000000..511b036
+--- /dev/null
++++ b/arch/ppc/syslib/bestcomm/sdma_fec_rx_task.c
+@@ -0,0 +1,71 @@
++/*
++ * sdma_fec_rx_task.c
++ *
++ * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
++ * on Tue Mar 22 11:19:38 2005 GMT
++ */
++
++#include <linux/types.h>
++
++/*
++ * The header consists of the following fields:
++ *    uint32_t        magic;
++ *    uint8_t         desc_size;
++ *    uint8_t         var_size;
++ *    uint8_t         inc_size;
++ *    uint8_t         first_var;
++ *    uint8_t         reserved[8];
++ *
++ * The size fields contain the number of 32-bit words.
++*/
++
++uint32_t sdma_fec_rx_task[] = {
++      /* header */
++      0x4243544b,
++      0x18060709,
++      0x00000000,
++      0x00000000,
++
++      /* Task descriptors */
++      0x808220e3, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
++      0x10601010, /*   DRD1A: var4 = var2; FN=0 MORE init=3 WS=0 RS=0 */
++      0xb8800264, /*   LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc4, idx3 += inc4 */
++      0x10001308, /*     DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
++      0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
++      0x0cccfcca, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var10)  */
++      0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
++      0xb8c58029, /*   LCD: idx3 = *(idx1 + var00000015); idx3 once var0; idx3 += inc5 */
++      0x60000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=0 RS=0 */
++      0x088cf8cc, /*     DRD2B1: idx2 = EU3(); EU3(idx3,var12)  */
++      0x991982f2, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var11; idx2 += inc6, idx3 += inc2 */
++      0x006acf80, /*     DRD1A: *idx3 = *idx0; FN=0 init=3 WS=1 RS=1 */
++      0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
++      0x9999802d, /*   LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
++      0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
++      0x034cfc4e, /*     DRD2B1: var13 = EU3(); EU3(*idx1,var14)  */
++      0x00008868, /*     DRD1A: idx2 = var13; FN=0 init=0 WS=0 RS=0 */
++      0x99198341, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var13; idx2 += inc0, idx3 += inc1 */
++      0x007ecf80, /*     DRD1A: *idx3 = *idx0; FN=0 init=3 WS=3 RS=3 */
++      0x99198272, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc6, idx3 += inc2 */
++      0x046acf80, /*     DRD1A: *idx3 = *idx0; FN=0 INT init=3 WS=1 RS=1 */
++      0x9819002d, /*   LCD: idx2 = idx0; idx2 once var0; idx2 += inc5 */
++      0x0060c790, /*     DRD1A: *idx1 = *idx2; FN=0 init=3 WS=0 RS=0 */
++      0x000001f8, /*   NOP */
++
++      /* VAR[9]-VAR[14] */
++      0x40000000,
++      0x7fff7fff,
++      0x00000000,
++      0x00000003,
++      0x40000008,
++      0x43ffffff,
++
++      /* INC[0]-INC[6] */
++      0x40000000,
++      0xe0000000,
++      0xe0000000,
++      0xa0000008,
++      0x20000000,
++      0x00000000,
++      0x4000ffff,
++};
+diff --git a/arch/ppc/syslib/bestcomm/sdma_fec_tx_task.c b/arch/ppc/syslib/bestcomm/sdma_fec_tx_task.c
+new file mode 100644
+index 0000000..d8d7fd3
+--- /dev/null
++++ b/arch/ppc/syslib/bestcomm/sdma_fec_tx_task.c
+@@ -0,0 +1,84 @@
++/*
++ * sdma_fec_tx_task.c
++ *
++ * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
++ * on Tue Mar 22 11:19:29 2005 GMT
++ */
++
++#include <linux/types.h>
++
++/*
++ * The header consists of the following fields:
++ *    uint32_t        magic;
++ *    uint8_t         desc_size;
++ *    uint8_t         var_size;
++ *    uint8_t         inc_size;
++ *    uint8_t         first_var;
++ *    uint8_t         reserved[8];
++ *
++ * The size fields contain the number of 32-bit words.
++*/
++
++uint32_t sdma_fec_tx_task[] = {
++      /* header */
++      0x4243544b,
++      0x2407070d,
++      0x00000000,
++      0x00000000,
++
++      /* Task descriptors */
++      0x8018001b, /* LCD: idx0 = var0; idx0 <= var0; idx0 += inc3 */
++      0x60000005, /*   DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
++      0x01ccfc0d, /*   DRD2B1: var7 = EU3(); EU3(*idx0,var13)  */
++      0x8082a123, /* LCD: idx0 = var1, idx1 = var5; idx1 <= var4; idx0 += inc4, idx1 += inc3 */
++      0x10801418, /*   DRD1A: var5 = var3; FN=0 MORE init=4 WS=0 RS=0 */
++      0xf88103a4, /*   LCDEXT: idx2 = *idx1, idx3 = var2; idx2 < var14; idx2 += inc4, idx3 += inc4 */
++      0x801a6024, /*   LCD: idx4 = var0; ; idx4 += inc4 */
++      0x10001708, /*     DRD1A: var5 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
++      0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
++      0x0cccfccf, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var15)  */
++      0x991a002c, /*   LCD: idx2 = idx2, idx3 = idx4; idx2 once var0; idx2 += inc5, idx3 += inc4 */
++      0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
++      0x024cfc4d, /*     DRD2B1: var9 = EU3(); EU3(*idx1,var13)  */
++      0x60000003, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */
++      0x0cccf247, /*     DRD2B1: *idx3 = EU3(); EU3(var9,var7)  */
++      0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
++      0xb8c80029, /*   LCD: idx3 = *(idx1 + var0000001a); idx3 once var0; idx3 += inc5 */
++      0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
++      0x088cf8d1, /*     DRD2B1: idx2 = EU3(); EU3(idx3,var17)  */
++      0x00002f10, /*     DRD1A: var11 = idx2; FN=0 init=0 WS=0 RS=0 */
++      0x99198432, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var16; idx2 += inc6, idx3 += inc2 */
++      0x008ac398, /*     DRD1A: *idx0 = *idx3; FN=0 init=4 WS=1 RS=1 */
++      0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
++      0x9999802d, /*   LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
++      0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
++      0x048cfc53, /*     DRD2B1: var18 = EU3(); EU3(*idx1,var19)  */
++      0x60000008, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=8 EXT init=0 WS=0 RS=0 */
++      0x088cf48b, /*     DRD2B1: idx2 = EU3(); EU3(var18,var11)  */
++      0x99198481, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var18; idx2 += inc0, idx3 += inc1 */
++      0x009ec398, /*     DRD1A: *idx0 = *idx3; FN=0 init=4 WS=3 RS=3 */
++      0x991983b2, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var14; idx2 += inc6, idx3 += inc2 */
++      0x088ac398, /*     DRD1A: *idx0 = *idx3; FN=0 TFD init=4 WS=1 RS=1 */
++      0x9919002d, /*   LCD: idx2 = idx2; idx2 once var0; idx2 += inc5 */
++      0x60000005, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
++      0x0c4cf88e, /*     DRD2B1: *idx1 = EU3(); EU3(idx2,var14)  */
++      0x000001f8, /*   NOP */
++
++      /* VAR[13]-VAR[19] */
++      0x0c000000,
++      0x40000000,
++      0x7fff7fff,
++      0x00000000,
++      0x00000003,
++      0x40000004,
++      0x43ffffff,
++
++      /* INC[0]-INC[6] */
++      0x40000000,
++      0xe0000000,
++      0xe0000000,
++      0xa0000008,
++      0x20000000,
++      0x00000000,
++      0x4000ffff,
++};
+diff --git a/arch/ppc/syslib/mpc52xx_devices.c b/arch/ppc/syslib/mpc52xx_devices.c
+index 7487539..abe6161 100644
+--- a/arch/ppc/syslib/mpc52xx_devices.c
++++ b/arch/ppc/syslib/mpc52xx_devices.c
+@@ -33,6 +33,28 @@ static struct fsl_i2c_platform_data mpc52xx_fsl_i2c_pdata = {
+    possibly using IORESOURCE_DMA. But that's when BestComm is ready ... */
+ struct platform_device ppc_sys_platform_devices[] = {
++      [MPC52xx_SDMA] = {
++              .name           = "mpc52xx-sdma",
++              .id             = -1,
++              .num_resources  = 3,
++              .resource       = (struct resource[]) {
++                      {
++                              .start  = 0x1200,
++                              .end    = 0x12ff,
++                              .flags  = IORESOURCE_MEM,
++                      },
++                      {
++                              .start  = 0x8000,
++                              .end    = 0xbfff,
++                              .flags  = IORESOURCE_MEM,
++                      },
++                      {
++                              .start  = MPC52xx_SDMA_IRQ,
++                              .end    = MPC52xx_SDMA_IRQ,
++                              .flags  = IORESOURCE_IRQ,
++                      },
++              },
++      },
+       [MPC52xx_MSCAN1] = {
+               .name           = "mpc52xx-mscan",
+               .id             = 0,
+diff --git a/arch/ppc/syslib/mpc52xx_sys.c b/arch/ppc/syslib/mpc52xx_sys.c
+index b4e6f97..a74b19c 100644
+--- a/arch/ppc/syslib/mpc52xx_sys.c
++++ b/arch/ppc/syslib/mpc52xx_sys.c
+@@ -19,10 +19,10 @@ struct ppc_sys_spec ppc_sys_specs[] = {
+               .ppc_sys_name   = "5200",
+               .mask           = 0xffff0000,
+               .value          = 0x80110000,
+-              .num_devices    = 15,
++              .num_devices    = MPC52xx_NUM_DEVICES,
+               .device_list    = (enum ppc_sys_devices[])
+               {
+-                      MPC52xx_MSCAN1, MPC52xx_MSCAN2, MPC52xx_SPI,
++                      MPC52xx_SDMA, MPC52xx_MSCAN1, MPC52xx_MSCAN2, MPC52xx_SPI,
+                       MPC52xx_USB, MPC52xx_BDLC, MPC52xx_PSC1, MPC52xx_PSC2,
+                       MPC52xx_PSC3, MPC52xx_PSC4, MPC52xx_PSC5, MPC52xx_PSC6,
+                       MPC52xx_FEC, MPC52xx_ATA, MPC52xx_I2C1, MPC52xx_I2C2,
+diff --git a/include/asm-ppc/mpc52xx.h b/include/asm-ppc/mpc52xx.h
+index d9d21aa..4856b74 100644
+--- a/include/asm-ppc/mpc52xx.h
++++ b/include/asm-ppc/mpc52xx.h
+@@ -34,6 +34,8 @@ struct pt_regs;
+ /* ======================================================================== */
+ enum ppc_sys_devices {
++      MPC52xx_SDMA,                            /* Must be first device to probe, 
++                                                                      else FEC/ATA will failed */
+       MPC52xx_MSCAN1,
+       MPC52xx_MSCAN2,
+       MPC52xx_SPI,
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0020-Fec-MPC5200-eth-driver.txt b/packages/linux/linux-efika-2.6.20/0020-Fec-MPC5200-eth-driver.txt
new file mode 100644 (file)
index 0000000..6c9ab0e
--- /dev/null
@@ -0,0 +1,1783 @@
+From 6b6e09cca4346ea737db427d568843034eb348fa Mon Sep 17 00:00:00 2001
+From: Andrey Volkov <avolkov@varma-el.com>
+Date: Fri, 18 Aug 2006 10:02:29 -0600
+Subject: [PATCH] [PATCH 02/02] Fec MPC5200 eth driver
+
+Second part. Contain only FEC parts.
+Depended on previous bestcomm patch.
+
+Signed-Off-By: Andrey Volkov <avolkov at varma-el.com>
+---
+ drivers/net/Kconfig               |    1 +
+ drivers/net/Makefile              |    1 +
+ drivers/net/fec_mpc52xx/Kconfig   |   23 ++
+ drivers/net/fec_mpc52xx/Makefile  |    2 +
+ drivers/net/fec_mpc52xx/fec.c     |  768 +++++++++++++++++++++++++++++++++++++
+ drivers/net/fec_mpc52xx/fec.h     |  308 +++++++++++++++
+ drivers/net/fec_mpc52xx/fec_phy.c |  526 +++++++++++++++++++++++++
+ drivers/net/fec_mpc52xx/fec_phy.h |   73 ++++
+ 8 files changed, 1702 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 8aa8dd0..0658e92 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -1902,6 +1902,7 @@ config NE_H8300
+         controller on the Renesas H8/300 processor.
+ source "drivers/net/fec_8xx/Kconfig"
++source "drivers/net/fec_mpc52xx/Kconfig"
+ source "drivers/net/fs_enet/Kconfig"
+ endmenu
+diff --git a/drivers/net/Makefile b/drivers/net/Makefile
+index 4c0d4e5..e6f903d 100644
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -196,6 +196,7 @@ obj-$(CONFIG_SMC91X) += smc91x.o
+ obj-$(CONFIG_SMC911X) += smc911x.o
+ obj-$(CONFIG_DM9000) += dm9000.o
+ obj-$(CONFIG_FEC_8XX) += fec_8xx/
++obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx/
+ obj-$(CONFIG_MACB) += macb.o
+diff --git a/drivers/net/fec_mpc52xx/Kconfig b/drivers/net/fec_mpc52xx/Kconfig
+new file mode 100644
+index 0000000..098c3fa
+--- /dev/null
++++ b/drivers/net/fec_mpc52xx/Kconfig
+@@ -0,0 +1,23 @@
++menu "MPC5200 Networking Options"
++      depends PPC_MPC52xx && NET_ETHERNET
++
++config FEC_MPC52xx
++      bool "FEC Ethernet"
++      depends on NET_ETHERNET
++      select PPC_BESTCOMM
++      select CRC32
++      ---help---
++        This option enables support for the MPC5200's on-chip
++        Fast Ethernet Controller
++
++config USE_MDIO
++      bool "  Use external Ethernet MII PHY"
++      select MII
++      depends FEC_MPC52xx
++      ---help---
++        The MPC5200's FEC can connect to the Ethernet either with
++        an external MII PHY chip or 10 Mbps 7-wire interface 
++        (Motorola? industry standard).
++        If your board uses an external PHY, say y, else n.
++
++endmenu
+diff --git a/drivers/net/fec_mpc52xx/Makefile b/drivers/net/fec_mpc52xx/Makefile
+new file mode 100644
+index 0000000..b8ae05c
+--- /dev/null
++++ b/drivers/net/fec_mpc52xx/Makefile
+@@ -0,0 +1,2 @@
++obj-$(CONFIG_FEC_MPC52xx)     += fec.o
++obj-$(CONFIG_USE_MDIO)                += fec_phy.o
+diff --git a/drivers/net/fec_mpc52xx/fec.c b/drivers/net/fec_mpc52xx/fec.c
+new file mode 100644
+index 0000000..b5f1559
+--- /dev/null
++++ b/drivers/net/fec_mpc52xx/fec.c
+@@ -0,0 +1,768 @@
++/*
++ * drivers/net/fec_mpc52xx/fec.c
++ *
++ * Driver for the MPC5200 Fast Ethernet Controller
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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.
++ */
++
++#include <linux/module.h>
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/spinlock.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/crc32.h>
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/ethtool.h>
++#include <linux/skbuff.h>
++
++#include <asm/io.h>
++#include <asm/delay.h>
++#include <asm/ppcboot.h>
++#include <asm/mpc52xx.h>
++
++#include <syslib/bestcomm/bestcomm.h>
++#include <syslib/bestcomm/fec.h>
++
++#include "fec_phy.h"
++#include "fec.h"
++
++#define DRIVER_NAME "mpc52xx-fec"
++
++static irqreturn_t fec_interrupt(int, void *, struct pt_regs *);
++static irqreturn_t fec_rx_interrupt(int, void *, struct pt_regs *);
++static irqreturn_t fec_tx_interrupt(int, void *, struct pt_regs *);
++static struct net_device_stats *fec_get_stats(struct net_device *);
++static void fec_set_multicast_list(struct net_device *dev);
++static void fec_reinit(struct net_device *dev);
++
++static u8 mpc52xx_fec_mac_addr[6];
++static u8 null_mac[6];
++
++static void fec_tx_timeout(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++
++      priv->stats.tx_errors++;
++
++      if (!priv->tx_full)
++              netif_wake_queue(dev);
++}
++
++static void fec_set_paddr(struct net_device *dev, u8 *mac)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct mpc52xx_fec *fec = priv->fec;
++
++      out_be32(&fec->paddr1, *(u32*)(&mac[0]));
++      out_be32(&fec->paddr2, (*(u16*)(&mac[4]) << 16) | 0x8808);
++}
++
++static void fec_get_paddr(struct net_device *dev, u8 *mac)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct mpc52xx_fec *fec = priv->fec;
++
++      *(u32*)(&mac[0]) = in_be32(&fec->paddr1);
++      *(u16*)(&mac[4]) = in_be32(&fec->paddr2) >> 16;
++}
++
++static int fec_set_mac_address(struct net_device *dev, void *addr)
++{
++      struct sockaddr *sock = (struct sockaddr *)addr;
++
++      memcpy(dev->dev_addr, sock->sa_data, dev->addr_len);
++
++      fec_set_paddr(dev, sock->sa_data);
++      return 0;
++}
++
++/* This function is called to start or restart the FEC during a link
++ * change.  This happens on fifo errors or when switching between half
++ * and full duplex.
++ */
++static void fec_restart(struct net_device *dev, int duplex)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct mpc52xx_fec *fec = priv->fec;
++      u32 rcntrl;
++      u32 tcntrl;
++      int i;
++
++      out_be32(&fec->rfifo_status, in_be32(&fec->rfifo_status) & 0x700000);
++      out_be32(&fec->tfifo_status, in_be32(&fec->tfifo_status) & 0x700000);
++      out_be32(&fec->reset_cntrl, 0x1000000);
++
++      /* Whack a reset.  We should wait for this. */
++      out_be32(&fec->ecntrl, FEC_ECNTRL_RESET);
++      for (i = 0; i < FEC_RESET_DELAY; ++i) {
++              if ((in_be32(&fec->ecntrl) & FEC_ECNTRL_RESET) == 0)
++                      break;
++              udelay(1);
++      }
++      if (i == FEC_RESET_DELAY)
++              printk (KERN_ERR DRIVER_NAME ": FEC Reset timeout!\n");
++
++      /* Set station address. */
++      fec_set_paddr(dev, dev->dev_addr);
++
++      fec_set_multicast_list(dev);
++
++      rcntrl = FEC_RX_BUFFER_SIZE << 16;      /* max frame length */
++      rcntrl |= FEC_RCNTRL_FCE;
++      rcntrl |= MII_RCNTL_MODE;
++      if (duplex)
++              tcntrl = FEC_TCNTRL_FDEN;               /* FD enable */
++      else {
++              rcntrl |= FEC_RCNTRL_DRT;
++              tcntrl = 0;
++      }
++      out_be32(&fec->r_cntrl, rcntrl);
++      out_be32(&fec->x_cntrl, tcntrl);
++
++      set_phy_speed(fec, priv->phy_speed);
++
++      priv->full_duplex = duplex;
++
++      /* Clear any outstanding interrupt. */
++      out_be32(&fec->ievent, 0xffffffff);     /* clear intr events */
++
++      /* Enable interrupts we wish to service.
++      */
++      out_be32(&fec->imask, FEC_IMASK_ENABLE);
++
++      /* And last, enable the transmit and receive processing.
++      */
++      out_be32(&fec->ecntrl, FEC_ECNTRL_ETHER_EN);
++      out_be32(&fec->r_des_active, 0x01000000);
++
++      /* The tx ring is no longer full. */
++      if (priv->tx_full)
++      {
++              priv->tx_full = 0;
++              netif_wake_queue(dev);
++      }
++}
++
++static void fec_free_rx_buffers(struct sdma *s)
++{
++      struct sk_buff *skb;
++
++      while (!sdma_queue_empty(s)) {
++              skb = sdma_retrieve_buffer(s, NULL);
++              kfree_skb(skb);
++      }
++}
++
++static int fec_open(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct sk_buff *skb;
++      void *data;
++
++      sdma_fec_rx_init(priv->rx_sdma, priv->rx_fifo, FEC_RX_BUFFER_SIZE);
++      sdma_fec_tx_init(priv->tx_sdma, priv->tx_fifo);
++
++      while (!sdma_queue_full(priv->rx_sdma)) {
++              skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
++              if (skb == 0)
++                      goto eagain;
++
++              /* zero out the initial receive buffers to aid debugging */
++              memset(skb->data, 0, FEC_RX_BUFFER_SIZE);
++              data = (void *)virt_to_phys(skb->data);
++              sdma_submit_buffer(priv->rx_sdma, skb, data, FEC_RX_BUFFER_SIZE);
++      }
++
++      fec_set_paddr(dev, dev->dev_addr);
++
++      if (fec_mii_wait(dev) != 0)
++              return -ENODEV;
++
++      sdma_enable(priv->rx_sdma);
++      sdma_enable(priv->tx_sdma);
++
++      netif_start_queue(dev);
++
++      return 0;
++
++eagain:
++      printk(KERN_ERR "fec_open: failed\n");
++
++      fec_free_rx_buffers(priv->rx_sdma);
++
++      return -EAGAIN;
++}
++
++/* This will only be invoked if your driver is _not_ in XOFF state.
++ * What this means is that you need not check it, and that this
++ * invariant will hold if you make sure that the netif_*_queue()
++ * calls are done at the proper times.
++ */
++static int fec_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      void *data;
++
++      if (sdma_queue_full(priv->tx_sdma))
++              panic("MPC52xx transmit queue overrun\n");
++
++      spin_lock_irq(&priv->lock);
++      dev->trans_start = jiffies;
++
++      data = (void *)virt_to_phys(skb->data);
++      sdma_fec_tfd_submit_buffer(priv->tx_sdma, skb, data, skb->len);
++
++      if (sdma_queue_full(priv->tx_sdma)) {
++              priv->tx_full = 1;
++              netif_stop_queue(dev);
++      }
++      spin_unlock_irq(&priv->lock);
++
++      return 0;
++}
++
++/* This handles BestComm transmit task interrupts
++ */
++static irqreturn_t fec_tx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++      struct net_device *dev = dev_id;
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct sk_buff *skb;
++
++      for (;;) {
++              sdma_clear_irq(priv->tx_sdma);
++              spin_lock(&priv->lock);
++              if (!sdma_buffer_done(priv->tx_sdma)) {
++                      spin_unlock(&priv->lock);
++                      break;
++              }
++              skb = sdma_retrieve_buffer(priv->tx_sdma, NULL);
++
++              if (priv->tx_full) {
++                      priv->tx_full = 0;
++                      netif_wake_queue(dev);
++              }
++              spin_unlock(&priv->lock);
++              dev_kfree_skb_irq(skb);
++      }
++
++      return IRQ_HANDLED;
++}
++
++static irqreturn_t fec_rx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++      struct net_device *dev = dev_id;
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct sk_buff *skb;
++      struct sk_buff *rskb;
++      int status;
++
++      for (;;) {
++              sdma_clear_irq(priv->rx_sdma);
++
++              if (!sdma_buffer_done(priv->rx_sdma))
++                      break;
++
++              rskb = sdma_retrieve_buffer(priv->rx_sdma, &status);
++
++              /* Test for errors in received frame */
++              if (status & 0x370000) { 
++                      /* Drop packet and reuse the buffer */
++                      sdma_submit_buffer(
++                              priv->rx_sdma, rskb,
++                              (void *)virt_to_phys(rskb->data),
++                              FEC_RX_BUFFER_SIZE );
++                      
++                      priv->stats.rx_dropped++;
++
++                      continue;
++              }
++
++              /* allocate replacement skb */
++              skb = dev_alloc_skb(FEC_RX_BUFFER_SIZE);
++              if (skb) {
++                      /* Process the received skb */
++                      int length = (status & ((1<<11) - 1)) - sizeof(u32);
++                      skb_put(rskb, length);  /* length included CRC32 */
++
++                      rskb->dev = dev;
++                      rskb->protocol = eth_type_trans(rskb, dev);
++                      netif_rx(rskb);
++                      dev->last_rx = jiffies;
++              } else {
++                      /* Can't get a new one : reuse the same & drop pkt */
++                      printk(KERN_NOTICE
++                              "%s: Memory squeeze, dropping packet.\n",
++                              dev->name);
++                      priv->stats.rx_dropped++;
++
++                      skb = rskb;
++              }
++
++              sdma_submit_buffer( priv->rx_sdma, skb,
++                      (void *)virt_to_phys(skb->data), FEC_RX_BUFFER_SIZE );
++      }
++
++      return IRQ_HANDLED;
++}
++
++static irqreturn_t fec_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++      struct net_device *dev = (struct net_device *)dev_id;
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct mpc52xx_fec *fec = priv->fec;
++      int ievent;
++
++      ievent = in_be32(&fec->ievent);
++      out_be32(&fec->ievent, ievent);         /* clear pending events */
++
++      if (ievent & (FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
++              if (ievent & FEC_IEVENT_RFIFO_ERROR)
++                      printk(KERN_WARNING "FEC_IEVENT_RFIFO_ERROR\n");
++              if (ievent & FEC_IEVENT_XFIFO_ERROR)
++                      printk(KERN_WARNING "FEC_IEVENT_XFIFO_ERROR\n");
++              fec_reinit(dev);
++      }
++      else if (ievent & FEC_IEVENT_MII)
++              fec_mii(dev);
++      return IRQ_HANDLED;
++}
++
++static int fec_close(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      unsigned long timeout;
++
++      priv->open_time = 0;
++      priv->sequence_done = 0;
++
++      netif_stop_queue(dev);
++
++      sdma_disable(priv->rx_sdma);            /* disable receive task */
++
++      /* Wait for queues to drain */
++      timeout = jiffies + 2*HZ;
++      while (time_before(jiffies, timeout) &&
++                                      (!sdma_queue_empty(priv->tx_sdma) ||
++                                      !sdma_queue_empty(priv->rx_sdma))) {
++              set_current_state(TASK_INTERRUPTIBLE);
++              schedule_timeout(HZ/10);
++      }
++      if (time_after_eq(jiffies, timeout))
++              printk(KERN_ERR "fec_close: queues didn't drain\n");
++
++      sdma_disable(priv->tx_sdma);
++
++      fec_free_rx_buffers(priv->rx_sdma);
++
++      fec_get_stats(dev);
++
++      return 0;
++}
++
++/*
++ * Get the current statistics.
++ * This may be called with the card open or closed.
++ */
++static struct net_device_stats *fec_get_stats(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct net_device_stats *stats = &priv->stats;
++      struct mpc52xx_fec *fec = priv->fec;
++
++      stats->rx_bytes = in_be32(&fec->rmon_r_octets);
++      stats->rx_packets = in_be32(&fec->rmon_r_packets);
++      stats->rx_errors = stats->rx_packets - in_be32(&fec->ieee_r_frame_ok);
++      stats->tx_bytes = in_be32(&fec->rmon_t_octets);
++      stats->tx_packets = in_be32(&fec->rmon_t_packets);
++      stats->tx_errors = stats->tx_packets - (
++                                      in_be32(&fec->ieee_t_frame_ok) +
++                                      in_be32(&fec->rmon_t_col) +
++                                      in_be32(&fec->ieee_t_1col) +
++                                      in_be32(&fec->ieee_t_mcol) +
++                                      in_be32(&fec->ieee_t_def));
++      stats->multicast = in_be32(&fec->rmon_r_mc_pkt);
++      stats->collisions = in_be32(&fec->rmon_t_col);
++
++      /* detailed rx_errors: */
++      stats->rx_length_errors = in_be32(&fec->rmon_r_undersize)
++                                      + in_be32(&fec->rmon_r_oversize)
++                                      + in_be32(&fec->rmon_r_frag)
++                                      + in_be32(&fec->rmon_r_jab);
++      stats->rx_over_errors = in_be32(&fec->r_macerr);
++      stats->rx_crc_errors = in_be32(&fec->ieee_r_crc);
++      stats->rx_frame_errors = in_be32(&fec->ieee_r_align);
++      stats->rx_fifo_errors = in_be32(&fec->rmon_r_drop);
++      stats->rx_missed_errors = in_be32(&fec->rmon_r_drop);
++
++      /* detailed tx_errors: */
++      stats->tx_aborted_errors = 0;
++      stats->tx_carrier_errors = in_be32(&fec->ieee_t_cserr);
++      stats->tx_fifo_errors = in_be32(&fec->rmon_t_drop);
++      stats->tx_heartbeat_errors = in_be32(&fec->ieee_t_sqe);
++      stats->tx_window_errors = in_be32(&fec->ieee_t_lcol);
++
++      return stats;
++}
++
++static void fec_update_stat(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct net_device_stats *stats = &priv->stats;
++      struct mpc52xx_fec *fec = priv->fec;
++
++      out_be32(&fec->mib_control, FEC_MIB_DISABLE);
++      memset_io(&fec->rmon_t_drop, 0,
++                      (u32)&fec->reserved10 - (u32)&fec->rmon_t_drop);
++      out_be32(&fec->mib_control, 0);
++      memset(stats, 0, sizeof *stats);
++      fec_get_stats(dev);
++}
++
++/*
++ * Set or clear the multicast filter for this adaptor.
++ */
++static void fec_set_multicast_list(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct mpc52xx_fec *fec = priv->fec;
++      u32 rx_control;
++
++      rx_control = in_be32(&fec->r_cntrl);
++
++      if (dev->flags & IFF_PROMISC) {
++              rx_control |= FEC_RCNTRL_PROM;
++              out_be32(&fec->r_cntrl, rx_control);
++      } else {
++              rx_control &= ~FEC_RCNTRL_PROM;
++              out_be32(&fec->r_cntrl, rx_control);
++
++              if (dev->flags & IFF_ALLMULTI) {
++                      out_be32(&fec->gaddr1, 0xffffffff);
++                      out_be32(&fec->gaddr2, 0xffffffff);
++              } else {
++                      u32 crc;
++                      int i;
++                      struct dev_mc_list *dmi;
++                      u32 gaddr1 = 0x00000000;
++                      u32 gaddr2 = 0x00000000;
++
++                      dmi = dev->mc_list;
++                      for (i=0; i<dev->mc_count; i++) {
++                              crc = ether_crc_le(6, dmi->dmi_addr) >> 26;
++                              if (crc >= 32)
++                                      gaddr1 |= 1 << (crc-32);
++                              else
++                                      gaddr2 |= 1 << crc;
++                              dmi = dmi->next;
++                      }
++                      out_be32(&fec->gaddr1, gaddr1);
++                      out_be32(&fec->gaddr2, gaddr2);
++              }
++      }
++}
++
++static void __init fec_str2mac(char *str, unsigned char *mac)
++{
++      int i;
++      u64 val64;
++
++      val64 = simple_strtoull(str, NULL, 16);
++
++      for (i = 0; i < 6; i++)
++              mac[5-i] = val64 >> (i*8);
++}
++
++int __init mpc52xx_fec_mac_setup(char *mac_address)
++{
++      fec_str2mac(mac_address, mpc52xx_fec_mac_addr);
++      return 0;
++}
++
++__setup("mpc52xx-mac=", mpc52xx_fec_mac_setup);
++
++static void fec_hw_init(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct mpc52xx_fec *fec = priv->fec;
++      bd_t *bd = (bd_t *) &__res;
++
++      out_be32(&fec->op_pause, 0x00010020);
++      out_be32(&fec->rfifo_cntrl, 0x0f000000);
++      out_be32(&fec->rfifo_alarm, 0x0000030c);
++      out_be32(&fec->tfifo_cntrl, 0x0f000000);
++      out_be32(&fec->tfifo_alarm, 0x00000100);
++      out_be32(&fec->x_wmrk, 0x3);            /* xmit fifo watermark = 256 */
++      out_be32(&fec->xmit_fsm, 0x03000000);   /* enable crc generation */
++      out_be32(&fec->iaddr1, 0x00000000);     /* No individual filter */
++      out_be32(&fec->iaddr2, 0x00000000);     /* No individual filter */
++
++      priv->phy_speed = ((bd->bi_ipbfreq >> 20) / 5) << 1;
++
++      fec_restart(dev, 0);    /* always use half duplex mode only */
++      /*
++       * Read MIB counters in order to reset them,
++       * then zero all the stats fields in memory
++       */
++      fec_update_stat(dev);
++}
++
++
++static void fec_reinit(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct mpc52xx_fec *fec = priv->fec;
++      static void fec_update_stat(struct net_device *);
++
++      netif_stop_queue(dev);
++      out_be32(&fec->imask, 0x0);
++
++      /* Disable the rx and tx tasks. */
++      sdma_disable(priv->rx_sdma);
++      sdma_disable(priv->tx_sdma);
++
++      /* Stop FEC */
++      out_be32(&fec->ecntrl, in_be32(&fec->ecntrl) & ~0x2);
++
++      /* Restart the DMA tasks */
++      sdma_fec_rx_init(priv->rx_sdma, priv->rx_fifo, FEC_RX_BUFFER_SIZE);
++      sdma_fec_tx_init(priv->tx_sdma, priv->tx_fifo);
++      fec_hw_init(dev);
++
++      if (priv->sequence_done) {               /* redo the fec_open() */
++              fec_free_rx_buffers(priv->rx_sdma);
++              fec_open(dev);
++      }
++      return;
++}
++
++
++/* ======================================================================== */
++/* Platform Driver                                                               */
++/* ======================================================================== */
++
++static int __devinit
++mpc52xx_fec_probe(struct device *dev)
++{
++      int ret;
++      struct platform_device *pdev = to_platform_device(dev);
++      struct net_device *ndev;
++      struct fec_priv *priv = NULL;
++      struct resource *mem;
++
++      volatile int dbg=0;
++      while(dbg)
++              __asm("nop");
++      /* Reserve FEC control zone */
++      mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if ((mem->end - mem->start + 1) != sizeof(struct mpc52xx_fec)) {
++              printk(KERN_ERR DRIVER_NAME 
++                         " - invalid resource size (%lx != %x), check mpc52xx_devices.c\n",
++                                                                      mem->end - mem->start + 1, sizeof(struct mpc52xx_fec));
++              return -EINVAL;
++      }
++      
++      if (!request_mem_region(mem->start, sizeof(struct mpc52xx_fec),
++                              DRIVER_NAME))
++              return -EBUSY;
++
++      /* Get the ether ndev & it's private zone */
++      ndev = alloc_etherdev(sizeof(struct fec_priv));
++      if (!ndev) {
++              ret = -ENOMEM;
++              goto probe_error;
++      }
++      
++      priv = (struct fec_priv *)ndev->priv;
++      
++      /* Init ether ndev with what we have */
++      ndev->open              = fec_open;
++      ndev->stop              = fec_close;
++      ndev->hard_start_xmit   = fec_hard_start_xmit;
++      ndev->do_ioctl          = fec_ioctl;
++      ndev->get_stats         = fec_get_stats;
++      ndev->set_mac_address   = fec_set_mac_address;
++      ndev->set_multicast_list = fec_set_multicast_list;
++      ndev->tx_timeout        = fec_tx_timeout;
++      ndev->watchdog_timeo    = FEC_WATCHDOG_TIMEOUT;
++      ndev->flags &= ~IFF_RUNNING;
++      ndev->base_addr         = mem->start;
++
++      priv->rx_fifo = ndev->base_addr + FIELD_OFFSET(mpc52xx_fec,rfifo_data);
++      priv->tx_fifo = ndev->base_addr + FIELD_OFFSET(mpc52xx_fec,tfifo_data);
++      priv->t_irq = priv->r_irq = ndev->irq = -1; /* IRQ are free for now */
++      
++      spin_lock_init(&priv->lock);
++
++      /* ioremap the zones */
++      priv->fec = (struct mpc52xx_fec *)
++              ioremap(mem->start, sizeof(struct mpc52xx_fec));
++      
++      if (!priv->fec) {
++              ret = -ENOMEM;
++              goto probe_error;
++      }
++
++      /* SDMA init */
++      priv->rx_sdma = sdma_alloc(FEC_RX_NUM_BD);
++      priv->tx_sdma = sdma_alloc(FEC_TX_NUM_BD);
++      
++      if (!priv->rx_sdma || !priv->tx_sdma) {
++              ret = -ENOMEM;
++              goto probe_error;
++      }
++
++      ret = sdma_fec_rx_init(priv->rx_sdma, priv->rx_fifo,FEC_RX_BUFFER_SIZE);
++      if (ret < 0)
++              goto probe_error;
++
++      ret = sdma_fec_tx_init(priv->tx_sdma, priv->tx_fifo);
++      if (ret < 0)
++              goto probe_error;
++
++      /* Get the IRQ we need one by one */
++              /* Control */
++      ndev->irq = platform_get_irq(pdev, 0);
++      if (request_irq(ndev->irq, &fec_interrupt, SA_INTERRUPT,
++                      DRIVER_NAME "_ctrl", ndev)) {
++              printk(KERN_ERR DRIVER_NAME ": ctrl interrupt request failed\n");
++              ret = -EBUSY;
++              ndev->irq = -1; /* Don't try to free it */
++              goto probe_error;
++      }
++
++              /* RX */
++      priv->r_irq = sdma_irq(priv->rx_sdma);
++      if (request_irq(priv->r_irq, &fec_rx_interrupt, SA_INTERRUPT,
++                      DRIVER_NAME "_rx", ndev)) {
++              printk(KERN_ERR DRIVER_NAME ": rx interrupt request failed\n");
++              ret = -EBUSY;
++              priv->r_irq = -1;       /* Don't try to free it */
++              goto probe_error;
++      }
++
++              /* TX */
++      priv->t_irq = sdma_irq(priv->tx_sdma);
++      if (request_irq(priv->t_irq, &fec_tx_interrupt, SA_INTERRUPT,
++                      DRIVER_NAME "_tx", ndev)) {
++              printk(KERN_ERR DRIVER_NAME ": tx interrupt request failed\n");
++              ret = -EBUSY;
++              priv->t_irq = -1;       /* Don't try to free it */
++              goto probe_error;
++      }
++
++      /* MAC address init */
++      if (memcmp(mpc52xx_fec_mac_addr, null_mac, 6) != 0)
++              memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6);
++      else
++              fec_get_paddr(ndev, ndev->dev_addr);
++
++      /* Hardware init */
++      fec_hw_init(ndev);
++
++      /* Register the new network device */
++      ret = register_netdev(ndev);
++      if(ret < 0)
++              goto probe_error;
++
++      /* MII init : After register ???? */
++      fec_mii_init(ndev);
++      
++      /* We're done ! */
++      dev_set_drvdata(dev, ndev);
++
++      return 0;
++
++
++      /* Error handling - free everything that might be allocated */
++probe_error:
++
++      if (ndev) {
++              if (priv->rx_sdma)      sdma_free(priv->rx_sdma);
++              if (priv->tx_sdma)      sdma_free(priv->tx_sdma);
++              
++              if (ndev->irq >= 0)     free_irq(ndev->irq, ndev);
++              if (priv->r_irq >= 0)   free_irq(priv->r_irq, ndev);
++              if (priv->t_irq >= 0)   free_irq(priv->t_irq, ndev);
++
++              if (priv->fec)          iounmap(priv->fec);
++      
++              free_netdev(ndev);
++      }
++      
++      release_mem_region(mem->start, sizeof(struct mpc52xx_fec));
++
++      return ret;
++}
++
++static int
++mpc52xx_fec_remove(struct device *dev)
++{
++      struct net_device *ndev;
++      struct fec_priv *priv;
++      
++      ndev = (struct net_device *) dev_get_drvdata(dev);
++      if (!ndev)
++              return 0;
++      priv = (struct fec_priv *) ndev->priv;
++
++      unregister_netdev(ndev);
++      
++      free_irq(ndev->irq, ndev);
++      free_irq(priv->r_irq, ndev);
++      free_irq(priv->t_irq, ndev);
++
++      iounmap(priv->fec);
++      
++      release_mem_region(ndev->base_addr, sizeof(struct mpc52xx_fec));
++
++      free_netdev(ndev);
++      
++      dev_set_drvdata(dev, NULL);
++      return 0;
++}
++
++static struct device_driver mpc52xx_fec_driver = {
++      .name     = DRIVER_NAME,
++      .bus            = &platform_bus_type,
++      .probe          = mpc52xx_fec_probe,
++      .remove         = mpc52xx_fec_remove,
++#ifdef CONFIG_PM
++/*    .suspend        = mpc52xx_fec_suspend,  TODO */
++/*    .resume         = mpc52xx_fec_resume,   TODO */
++#endif
++};
++
++/* ======================================================================== */
++/* Module                                                                   */
++/* ======================================================================== */
++
++static int __init
++mpc52xx_fec_init(void)
++{
++      return driver_register(&mpc52xx_fec_driver);
++}
++
++static void __exit
++mpc52xx_fec_exit(void)
++{
++      driver_unregister(&mpc52xx_fec_driver);
++}
++
++
++module_init(mpc52xx_fec_init);
++module_exit(mpc52xx_fec_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Dale Farnsworth");
++MODULE_DESCRIPTION("Ethernet driver for the Freescale MPC52xx FEC");
+diff --git a/drivers/net/fec_mpc52xx/fec.h b/drivers/net/fec_mpc52xx/fec.h
+new file mode 100644
+index 0000000..f9eed36
+--- /dev/null
++++ b/drivers/net/fec_mpc52xx/fec.h
+@@ -0,0 +1,308 @@
++/*
++ * drivers/net/fec_mpc52xx/fec.h
++ *
++ * Driver for the MPC5200 Fast Ethernet Controller
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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.
++ */
++
++#ifndef __DRIVERS_NET_MPC52XX_FEC_H__
++#define __DRIVERS_NET_MPC52XX_FEC_H__
++
++/* Tunable constant */
++/* FEC_RX_BUFFER_SIZE includes 4 bytes for CRC32 */
++#define FEC_RX_BUFFER_SIZE    1522    /* max receive packet size */
++#define FEC_RX_NUM_BD         64
++#define FEC_TX_NUM_BD         64
++
++#define FEC_RESET_DELAY               50      /* uS */
++
++#define FEC_WATCHDOG_TIMEOUT  ((400*HZ)/1000)
++
++struct fec_priv {
++      int full_duplex;
++      int tx_full;
++      int r_irq;
++      int t_irq;
++      u32 last_transmit_time;
++      struct mpc52xx_fec *fec;
++      struct sdma *rx_sdma;
++      struct sdma *tx_sdma;
++      spinlock_t lock;
++      unsigned long open_time;
++      struct net_device_stats stats;
++#ifdef CONFIG_USE_MDIO
++      uint phy_id;
++      uint phy_id_done;
++      uint phy_status;
++      uint phy_speed;
++      phy_info_t *phy;
++      struct tasklet_struct phy_task;
++      uint sequence_done;
++      uint phy_addr;
++      struct timer_list phy_timer_list;
++      u16 old_status;
++      phys_addr_t rx_fifo;
++      phys_addr_t tx_fifo;
++#endif        /* CONFIG_USE_MDIO */
++};
++
++
++/* ======================================================================== */
++/* Hardware register sets & bits                                            */
++/* ======================================================================== */
++
++struct mpc52xx_fec {
++      u32 fec_id;                     /* FEC + 0x000 */
++      u32 ievent;                     /* FEC + 0x004 */
++      u32 imask;                      /* FEC + 0x008 */
++
++      u32 reserved0[1];               /* FEC + 0x00C */
++      u32 r_des_active;               /* FEC + 0x010 */
++      u32 x_des_active;               /* FEC + 0x014 */
++      u32 r_des_active_cl;            /* FEC + 0x018 */
++      u32 x_des_active_cl;            /* FEC + 0x01C */
++      u32 ivent_set;                  /* FEC + 0x020 */
++      u32 ecntrl;                     /* FEC + 0x024 */
++
++      u32 reserved1[6];               /* FEC + 0x028-03C */
++      u32 mii_data;                   /* FEC + 0x040 */
++      u32 mii_speed;                  /* FEC + 0x044 */
++      u32 mii_status;                 /* FEC + 0x048 */
++
++      u32 reserved2[5];               /* FEC + 0x04C-05C */
++      u32 mib_data;                   /* FEC + 0x060 */
++      u32 mib_control;                /* FEC + 0x064 */
++
++      u32 reserved3[6];               /* FEC + 0x068-7C */
++      u32 r_activate;                 /* FEC + 0x080 */
++      u32 r_cntrl;                    /* FEC + 0x084 */
++      u32 r_hash;                     /* FEC + 0x088 */
++      u32 r_data;                     /* FEC + 0x08C */
++      u32 ar_done;                    /* FEC + 0x090 */
++      u32 r_test;                     /* FEC + 0x094 */
++      u32 r_mib;                      /* FEC + 0x098 */
++      u32 r_da_low;                   /* FEC + 0x09C */
++      u32 r_da_high;                  /* FEC + 0x0A0 */
++
++      u32 reserved4[7];               /* FEC + 0x0A4-0BC */
++      u32 x_activate;                 /* FEC + 0x0C0 */
++      u32 x_cntrl;                    /* FEC + 0x0C4 */
++      u32 backoff;                    /* FEC + 0x0C8 */
++      u32 x_data;                     /* FEC + 0x0CC */
++      u32 x_status;                   /* FEC + 0x0D0 */
++      u32 x_mib;                      /* FEC + 0x0D4 */
++      u32 x_test;                     /* FEC + 0x0D8 */
++      u32 fdxfc_da1;                  /* FEC + 0x0DC */
++      u32 fdxfc_da2;                  /* FEC + 0x0E0 */
++      u32 paddr1;                     /* FEC + 0x0E4 */
++      u32 paddr2;                     /* FEC + 0x0E8 */
++      u32 op_pause;                   /* FEC + 0x0EC */
++
++      u32 reserved5[4];               /* FEC + 0x0F0-0FC */
++      u32 instr_reg;                  /* FEC + 0x100 */
++      u32 context_reg;                /* FEC + 0x104 */
++      u32 test_cntrl;                 /* FEC + 0x108 */
++      u32 acc_reg;                    /* FEC + 0x10C */
++      u32 ones;                       /* FEC + 0x110 */
++      u32 zeros;                      /* FEC + 0x114 */
++      u32 iaddr1;                     /* FEC + 0x118 */
++      u32 iaddr2;                     /* FEC + 0x11C */
++      u32 gaddr1;                     /* FEC + 0x120 */
++      u32 gaddr2;                     /* FEC + 0x124 */
++      u32 random;                     /* FEC + 0x128 */
++      u32 rand1;                      /* FEC + 0x12C */
++      u32 tmp;                        /* FEC + 0x130 */
++
++      u32 reserved6[3];               /* FEC + 0x134-13C */
++      u32 fifo_id;                    /* FEC + 0x140 */
++      u32 x_wmrk;                     /* FEC + 0x144 */
++      u32 fcntrl;                     /* FEC + 0x148 */
++      u32 r_bound;                    /* FEC + 0x14C */
++      u32 r_fstart;                   /* FEC + 0x150 */
++      u32 r_count;                    /* FEC + 0x154 */
++      u32 r_lag;                      /* FEC + 0x158 */
++      u32 r_read;                     /* FEC + 0x15C */
++      u32 r_write;                    /* FEC + 0x160 */
++      u32 x_count;                    /* FEC + 0x164 */
++      u32 x_lag;                      /* FEC + 0x168 */
++      u32 x_retry;                    /* FEC + 0x16C */
++      u32 x_write;                    /* FEC + 0x170 */
++      u32 x_read;                     /* FEC + 0x174 */
++
++      u32 reserved7[2];               /* FEC + 0x178-17C */
++      u32 fm_cntrl;                   /* FEC + 0x180 */
++      u32 rfifo_data;                 /* FEC + 0x184 */
++      u32 rfifo_status;               /* FEC + 0x188 */
++      u32 rfifo_cntrl;                /* FEC + 0x18C */
++      u32 rfifo_lrf_ptr;              /* FEC + 0x190 */
++      u32 rfifo_lwf_ptr;              /* FEC + 0x194 */
++      u32 rfifo_alarm;                /* FEC + 0x198 */
++      u32 rfifo_rdptr;                /* FEC + 0x19C */
++      u32 rfifo_wrptr;                /* FEC + 0x1A0 */
++      u32 tfifo_data;                 /* FEC + 0x1A4 */
++      u32 tfifo_status;               /* FEC + 0x1A8 */
++      u32 tfifo_cntrl;                /* FEC + 0x1AC */
++      u32 tfifo_lrf_ptr;              /* FEC + 0x1B0 */
++      u32 tfifo_lwf_ptr;              /* FEC + 0x1B4 */
++      u32 tfifo_alarm;                /* FEC + 0x1B8 */
++      u32 tfifo_rdptr;                /* FEC + 0x1BC */
++      u32 tfifo_wrptr;                /* FEC + 0x1C0 */
++
++      u32 reset_cntrl;                /* FEC + 0x1C4 */
++      u32 xmit_fsm;                   /* FEC + 0x1C8 */
++
++      u32 reserved8[3];               /* FEC + 0x1CC-1D4 */
++      u32 rdes_data0;                 /* FEC + 0x1D8 */
++      u32 rdes_data1;                 /* FEC + 0x1DC */
++      u32 r_length;                   /* FEC + 0x1E0 */
++      u32 x_length;                   /* FEC + 0x1E4 */
++      u32 x_addr;                     /* FEC + 0x1E8 */
++      u32 cdes_data;                  /* FEC + 0x1EC */
++      u32 status;                     /* FEC + 0x1F0 */
++      u32 dma_control;                /* FEC + 0x1F4 */
++      u32 des_cmnd;                   /* FEC + 0x1F8 */
++      u32 data;                       /* FEC + 0x1FC */
++
++      u32 rmon_t_drop;                /* FEC + 0x200 */
++      u32 rmon_t_packets;             /* FEC + 0x204 */
++      u32 rmon_t_bc_pkt;              /* FEC + 0x208 */
++      u32 rmon_t_mc_pkt;              /* FEC + 0x20C */
++      u32 rmon_t_crc_align;           /* FEC + 0x210 */
++      u32 rmon_t_undersize;           /* FEC + 0x214 */
++      u32 rmon_t_oversize;            /* FEC + 0x218 */
++      u32 rmon_t_frag;                /* FEC + 0x21C */
++      u32 rmon_t_jab;                 /* FEC + 0x220 */
++      u32 rmon_t_col;                 /* FEC + 0x224 */
++      u32 rmon_t_p64;                 /* FEC + 0x228 */
++      u32 rmon_t_p65to127;            /* FEC + 0x22C */
++      u32 rmon_t_p128to255;           /* FEC + 0x230 */
++      u32 rmon_t_p256to511;           /* FEC + 0x234 */
++      u32 rmon_t_p512to1023;          /* FEC + 0x238 */
++      u32 rmon_t_p1024to2047;         /* FEC + 0x23C */
++      u32 rmon_t_p_gte2048;           /* FEC + 0x240 */
++      u32 rmon_t_octets;              /* FEC + 0x244 */
++      u32 ieee_t_drop;                /* FEC + 0x248 */
++      u32 ieee_t_frame_ok;            /* FEC + 0x24C */
++      u32 ieee_t_1col;                /* FEC + 0x250 */
++      u32 ieee_t_mcol;                /* FEC + 0x254 */
++      u32 ieee_t_def;                 /* FEC + 0x258 */
++      u32 ieee_t_lcol;                /* FEC + 0x25C */
++      u32 ieee_t_excol;               /* FEC + 0x260 */
++      u32 ieee_t_macerr;              /* FEC + 0x264 */
++      u32 ieee_t_cserr;               /* FEC + 0x268 */
++      u32 ieee_t_sqe;                 /* FEC + 0x26C */
++      u32 t_fdxfc;                    /* FEC + 0x270 */
++      u32 ieee_t_octets_ok;           /* FEC + 0x274 */
++
++      u32 reserved9[2];               /* FEC + 0x278-27C */
++      u32 rmon_r_drop;                /* FEC + 0x280 */
++      u32 rmon_r_packets;             /* FEC + 0x284 */
++      u32 rmon_r_bc_pkt;              /* FEC + 0x288 */
++      u32 rmon_r_mc_pkt;              /* FEC + 0x28C */
++      u32 rmon_r_crc_align;           /* FEC + 0x290 */
++      u32 rmon_r_undersize;           /* FEC + 0x294 */
++      u32 rmon_r_oversize;            /* FEC + 0x298 */
++      u32 rmon_r_frag;                /* FEC + 0x29C */
++      u32 rmon_r_jab;                 /* FEC + 0x2A0 */
++
++      u32 rmon_r_resvd_0;             /* FEC + 0x2A4 */
++
++      u32 rmon_r_p64;                 /* FEC + 0x2A8 */
++      u32 rmon_r_p65to127;            /* FEC + 0x2AC */
++      u32 rmon_r_p128to255;           /* FEC + 0x2B0 */
++      u32 rmon_r_p256to511;           /* FEC + 0x2B4 */
++      u32 rmon_r_p512to1023;          /* FEC + 0x2B8 */
++      u32 rmon_r_p1024to2047;         /* FEC + 0x2BC */
++      u32 rmon_r_p_gte2048;           /* FEC + 0x2C0 */
++      u32 rmon_r_octets;              /* FEC + 0x2C4 */
++      u32 ieee_r_drop;                /* FEC + 0x2C8 */
++      u32 ieee_r_frame_ok;            /* FEC + 0x2CC */
++      u32 ieee_r_crc;                 /* FEC + 0x2D0 */
++      u32 ieee_r_align;               /* FEC + 0x2D4 */
++      u32 r_macerr;                   /* FEC + 0x2D8 */
++      u32 r_fdxfc;                    /* FEC + 0x2DC */
++      u32 ieee_r_octets_ok;           /* FEC + 0x2E0 */
++
++      u32 reserved10[7];              /* FEC + 0x2E4-2FC */
++
++      u32 reserved11[64];             /* FEC + 0x300-3FF */
++};
++
++#define       FEC_MIB_DISABLE                 0x80000000
++
++#define       FEC_IEVENT_HBERR                0x80000000
++#define       FEC_IEVENT_BABR                 0x40000000
++#define       FEC_IEVENT_BABT                 0x20000000
++#define       FEC_IEVENT_GRA                  0x10000000
++#define       FEC_IEVENT_TFINT                0x08000000
++#define       FEC_IEVENT_MII                  0x00800000
++#define       FEC_IEVENT_LATE_COL             0x00200000
++#define       FEC_IEVENT_COL_RETRY_LIM        0x00100000
++#define       FEC_IEVENT_XFIFO_UN             0x00080000
++#define       FEC_IEVENT_XFIFO_ERROR          0x00040000
++#define       FEC_IEVENT_RFIFO_ERROR          0x00020000
++
++#define       FEC_IMASK_HBERR                 0x80000000
++#define       FEC_IMASK_BABR                  0x40000000
++#define       FEC_IMASK_BABT                  0x20000000
++#define       FEC_IMASK_GRA                   0x10000000
++#define       FEC_IMASK_MII                   0x00800000
++#define       FEC_IMASK_LATE_COL              0x00200000
++#define       FEC_IMASK_COL_RETRY_LIM         0x00100000
++#define       FEC_IMASK_XFIFO_UN              0x00080000
++#define       FEC_IMASK_XFIFO_ERROR           0x00040000
++#define       FEC_IMASK_RFIFO_ERROR           0x00020000
++
++#define       FEC_RCNTRL_MAX_FL_SHIFT         16
++#define       FEC_RCNTRL_LOOP                 0x01
++#define       FEC_RCNTRL_DRT                  0x02
++#define       FEC_RCNTRL_MII_MODE             0x04
++#define       FEC_RCNTRL_PROM                 0x08
++#define       FEC_RCNTRL_BC_REJ               0x10
++#define       FEC_RCNTRL_FCE                  0x20
++
++#define       FEC_TCNTRL_GTS                  0x00000001
++#define       FEC_TCNTRL_HBC                  0x00000002
++#define       FEC_TCNTRL_FDEN                 0x00000004
++#define       FEC_TCNTRL_TFC_PAUSE            0x00000008
++#define       FEC_TCNTRL_RFC_PAUSE            0x00000010
++
++#define       FEC_ECNTRL_RESET                0x00000001
++#define       FEC_ECNTRL_ETHER_EN             0x00000002
++
++struct mibCounters {
++      unsigned int byteReceived;
++      unsigned int byteSent;
++      unsigned int framesReceived;
++      unsigned int framesSent;
++      unsigned int totalByteReceived;
++      unsigned int totalFramesReceived;
++      unsigned int broadcastFramesReceived;
++      unsigned int multicastFramesReceived;
++      unsigned int cRCError;
++      unsigned int oversizeFrames;
++      unsigned int fragments;
++      unsigned int jabber;
++      unsigned int collision;
++      unsigned int lateCollision;
++      unsigned int frames64;
++      unsigned int frames65_127;
++      unsigned int frames128_255;
++      unsigned int frames256_511;
++      unsigned int frames512_1023;
++      unsigned int frames1024_MaxSize;
++      unsigned int macRxError;
++      unsigned int droppedFrames;
++      unsigned int outMulticastFrames;
++      unsigned int outBroadcastFrames;
++      unsigned int undersizeFrames;
++};
++
++
++#endif        /* __DRIVERS_NET_MPC52XX_FEC_H__ */
+diff --git a/drivers/net/fec_mpc52xx/fec_phy.c b/drivers/net/fec_mpc52xx/fec_phy.c
+new file mode 100644
+index 0000000..2a287de
+--- /dev/null
++++ b/drivers/net/fec_mpc52xx/fec_phy.c
+@@ -0,0 +1,526 @@
++/*
++ * arch/ppc/52xx_io/fec_phy.c
++ *
++ * Driver for the MPC5200 Fast Ethernet Controller
++ * Based heavily on the MII support for the MPC8xx by Dan Malek
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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.
++ */
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/netdevice.h>
++#include <linux/mii.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <asm/io.h>
++#include <asm/mpc52xx.h>
++#include <syslib/bestcomm/bestcomm.h>
++#include <syslib/bestcomm/fec.h>
++#include "fec_phy.h"
++#include "fec.h"
++
++static int mpc52xx_netdev_ethtool_ioctl(struct net_device *dev, void *useraddr);
++
++/* MII processing.  We keep this as simple as possible.  Requests are
++ * placed on the list (if there is room).  When the request is finished
++ * by the MII, an optional function may be called.
++ */
++typedef struct mii_list {
++      uint    mii_regval;
++      void    (*mii_func)(uint val, struct net_device *dev, uint data);
++      struct  mii_list *mii_next;
++      uint    mii_data;
++} mii_list_t;
++
++#define               NMII    20
++mii_list_t    mii_cmds[NMII];
++mii_list_t    *mii_free;
++mii_list_t    *mii_head;
++mii_list_t    *mii_tail;
++
++typedef struct mdio_read_data {
++      __u16 regval;
++      struct task_struct *sleeping_task;
++} mdio_read_data_t;
++
++static int mii_queue(struct net_device *dev, int request,
++              void (*func)(uint, struct net_device *, uint), uint data);
++
++/* Make MII read/write commands for the FEC.
++ * */
++#define mk_mii_read(REG)      (0x60020000 | ((REG & 0x1f) << 18))
++#define mk_mii_write(REG, VAL)        (0x50020000 | ((REG & 0x1f) << 18) | \
++                                                      (VAL & 0xffff))
++#define mk_mii_end    0
++
++/* Register definitions for the PHY.
++*/
++
++#define MII_REG_CR     0      /* Control Register */
++#define MII_REG_SR     1      /* Status Register */
++#define MII_REG_PHYIR1         2      /* PHY Identification Register 1 */
++#define MII_REG_PHYIR2         3      /* PHY Identification Register 2 */
++#define MII_REG_ANAR   4      /* A-N Advertisement Register */
++#define MII_REG_ANLPAR         5      /* A-N Link Partner Ability Register */
++#define MII_REG_ANER   6      /* A-N Expansion Register */
++#define MII_REG_ANNPTR         7      /* A-N Next Page Transmit Register */
++#define MII_REG_ANLPRNPR 8    /* A-N Link Partner Received Next Page Reg. */
++
++/* values for phy_status */
++
++#define PHY_CONF_ANE  0x0001  /* 1 auto-negotiation enabled */
++#define PHY_CONF_LOOP 0x0002  /* 1 loopback mode enabled */
++#define PHY_CONF_SPMASK       0x00f0  /* mask for speed */
++#define PHY_CONF_10HDX        0x0010  /* 10 Mbit half duplex supported */
++#define PHY_CONF_10FDX        0x0020  /* 10 Mbit full duplex supported */
++#define PHY_CONF_100HDX       0x0040  /* 100 Mbit half duplex supported */
++#define PHY_CONF_100FDX       0x0080  /* 100 Mbit full duplex supported */
++
++#define PHY_STAT_LINK 0x0100  /* 1 up - 0 down */
++#define PHY_STAT_FAULT        0x0200  /* 1 remote fault */
++#define PHY_STAT_ANC  0x0400  /* 1 auto-negotiation complete  */
++#define PHY_STAT_SPMASK       0xf000  /* mask for speed */
++#define PHY_STAT_10HDX        0x1000  /* 10 Mbit half duplex selected */
++#define PHY_STAT_10FDX        0x2000  /* 10 Mbit full duplex selected */
++#define PHY_STAT_100HDX       0x4000  /* 100 Mbit half duplex selected */
++#define PHY_STAT_100FDX       0x8000  /* 100 Mbit full duplex selected */
++
++void fec_mii(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct mpc52xx_fec *fec = priv->fec;
++      mii_list_t      *mip;
++      uint            mii_reg;
++
++      mii_reg = in_be32(&fec->mii_data);
++
++      if ((mip = mii_head) == NULL) {
++              printk(KERN_ERR "MII and no head!\n");
++              return;
++      }
++
++      if (mip->mii_func != NULL)
++              (*(mip->mii_func))(mii_reg, dev, mip->mii_data);
++
++      mii_head = mip->mii_next;
++      mip->mii_next = mii_free;
++      mii_free = mip;
++
++      if ((mip = mii_head) != NULL)
++              out_be32(&fec->mii_data, mip->mii_regval);
++}
++
++static int mii_queue(struct net_device *dev, int regval,
++                              void (*func)(uint, struct net_device *, uint),
++                              uint data)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      struct mpc52xx_fec *fec = priv->fec;
++      mii_list_t      *mip;
++      int             retval;
++
++      /* Add PHY address to register command.
++      */
++      regval |= priv->phy_addr << 23;
++
++      retval = 0;
++
++      if ((mip = mii_free) != NULL) {
++              mii_free = mip->mii_next;
++              mip->mii_regval = regval;
++              mip->mii_func = func;
++              mip->mii_next = NULL;
++              mip->mii_data = data;
++              if (mii_head) {
++                      mii_tail->mii_next = mip;
++                      mii_tail = mip;
++              } else {
++                      mii_head = mii_tail = mip;
++                      out_be32(&fec->mii_data, regval);
++              }
++      } else
++              retval = 1;
++
++      return retval;
++}
++
++static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c)
++{
++      int k;
++
++      if (!c)
++              return;
++
++      for (k = 0; (c+k)->mii_data != mk_mii_end; k++)
++              mii_queue(dev, (c+k)->mii_data, (c+k)->funct, 0);
++}
++
++static void mii_parse_sr(uint mii_reg, struct net_device *dev, uint data)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      uint s = priv->phy_status;
++
++      s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
++
++      if (mii_reg & 0x0004)
++              s |= PHY_STAT_LINK;
++      if (mii_reg & 0x0010)
++              s |= PHY_STAT_FAULT;
++      if (mii_reg & 0x0020)
++              s |= PHY_STAT_ANC;
++
++      priv->phy_status = s;
++}
++
++static void mii_parse_cr(uint mii_reg, struct net_device *dev, uint data)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      uint s = priv->phy_status;
++
++      s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP);
++
++      if (mii_reg & 0x1000)
++              s |= PHY_CONF_ANE;
++      if (mii_reg & 0x4000)
++              s |= PHY_CONF_LOOP;
++
++      priv->phy_status = s;
++}
++
++static void mii_parse_anar(uint mii_reg, struct net_device *dev, uint data)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      uint s = priv->phy_status;
++
++      s &= ~(PHY_CONF_SPMASK);
++
++      if (mii_reg & 0x0020)
++              s |= PHY_CONF_10HDX;
++      if (mii_reg & 0x0040)
++              s |= PHY_CONF_10FDX;
++      if (mii_reg & 0x0080)
++              s |= PHY_CONF_100HDX;
++      if (mii_reg & 0x0100)
++              s |= PHY_CONF_100FDX;
++
++      priv->phy_status = s;
++}
++
++/* ------------------------------------------------------------------------- */
++/* Generic PHY support.  Should work for all PHYs, but does not support link
++ * change interrupts.
++ */
++static phy_info_t phy_info_generic = {
++      0x00000000, /* 0-->match any PHY */
++      "GENERIC",
++
++      (const phy_cmd_t []) {  /* config */
++              /* advertise only half-duplex capabilities */
++              { mk_mii_write(MII_ADVERTISE, MII_ADVERTISE_HALF),
++                      mii_parse_anar },
++
++              /* enable auto-negotiation */
++              { mk_mii_write(MII_BMCR, BMCR_ANENABLE), mii_parse_cr },
++              { mk_mii_end, }
++      },
++      (const phy_cmd_t []) {  /* startup */
++              /* restart auto-negotiation */
++              { mk_mii_write(MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART)),
++                      NULL },
++              { mk_mii_end, }
++      },
++      (const phy_cmd_t []) { /* ack_int */
++              /* We don't actually use the ack_int table with a generic
++               * PHY, but putting a reference to mii_parse_sr here keeps
++               * us from getting a compiler warning about unused static
++               * functions in the case where we only compile in generic
++               * PHY support.
++               */
++              { mk_mii_read(MII_BMSR), mii_parse_sr },
++              { mk_mii_end, }
++      },
++      (const phy_cmd_t []) {  /* shutdown */
++              { mk_mii_end, }
++      },
++};
++/* -------------------------------------------------------------------- */
++
++/* register definitions for the 971 */
++
++#define MII_LXT971_PCR        16      /* Port Control Register        */
++#define MII_LXT971_SR2        17      /* Status Register 2            */
++#define MII_LXT971_IER        18      /* Interrupt Enable Register    */
++#define MII_LXT971_ISR        19      /* Interrupt Status Register    */
++#define MII_LXT971_LCR        20      /* LED Control Register         */
++#define MII_LXT971_TCR        30      /* Transmit Control Register    */
++
++static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev, uint data)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      uint s = priv->phy_status;
++
++      s &= ~(PHY_STAT_SPMASK);
++
++      if (mii_reg & 0x4000) {
++              if (mii_reg & 0x0200)
++                      s |= PHY_STAT_100FDX;
++              else
++                      s |= PHY_STAT_100HDX;
++      } else {
++              if (mii_reg & 0x0200)
++                      s |= PHY_STAT_10FDX;
++              else
++                      s |= PHY_STAT_10HDX;
++      }
++      if (mii_reg & 0x0008)
++              s |= PHY_STAT_FAULT;
++
++      priv->phy_status = s;
++}
++
++static phy_info_t phy_info_lxt971 = {
++      0x0001378e,
++      "LXT971",
++
++      (const phy_cmd_t []) {  /* config */
++              { mk_mii_write(MII_REG_ANAR, 0x0A1), NULL }, /* 10/100, HD */
++              { mk_mii_read(MII_REG_CR), mii_parse_cr },
++              { mk_mii_read(MII_REG_ANAR), mii_parse_anar },
++              { mk_mii_end, }
++      },
++      (const phy_cmd_t []) {  /* startup - enable interrupts */
++              { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL },
++              { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */
++
++              /* Somehow does the 971 tell me that the link is down
++               * the first read after power-up.
++               * read here to get a valid value in ack_int */
++
++              { mk_mii_read(MII_REG_SR), mii_parse_sr },
++              { mk_mii_end, }
++      },
++      (const phy_cmd_t []) { /* ack_int */
++              /* find out the current status */
++
++              { mk_mii_read(MII_REG_SR), mii_parse_sr },
++              { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 },
++
++              /* we only need to read ISR to acknowledge */
++
++              { mk_mii_read(MII_LXT971_ISR), NULL },
++              { mk_mii_end, }
++      },
++      (const phy_cmd_t []) {  /* shutdown - disable interrupts */
++              { mk_mii_write(MII_LXT971_IER, 0x0000), NULL },
++              { mk_mii_end, }
++      },
++};
++
++static phy_info_t *phy_info[] = {
++      &phy_info_lxt971,
++      /* Generic PHY support.  This must be the last PHY in the table.
++       * It will be used to support any PHY that doesn't match a previous
++       * entry in the table.
++       */
++      &phy_info_generic,
++      NULL
++};
++
++static void mii_display_config(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      uint s = priv->phy_status;
++
++      printk(KERN_INFO "%s: config: auto-negotiation ", dev->name);
++
++      if (s & PHY_CONF_ANE)
++              printk("on");
++      else
++              printk("off");
++
++      if (s & PHY_CONF_100FDX)
++              printk(", 100FDX");
++      if (s & PHY_CONF_100HDX)
++              printk(", 100HDX");
++      if (s & PHY_CONF_10FDX)
++              printk(", 10FDX");
++      if (s & PHY_CONF_10HDX)
++              printk(", 10HDX");
++      if (!(s & PHY_CONF_SPMASK))
++              printk(", No speed/duplex selected?");
++
++      if (s & PHY_CONF_LOOP)
++              printk(", loopback enabled");
++
++      printk(".\n");
++
++      priv->sequence_done = 1;
++}
++
++static void mii_queue_config(uint mii_reg, struct net_device *dev, uint data)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++
++      priv->phy_task.func = (void *)mii_display_config;
++      priv->phy_task.data = (unsigned long)dev;
++      tasklet_schedule(&priv->phy_task);
++}
++
++
++phy_cmd_t phy_cmd_config[] =  { { mk_mii_read(MII_REG_CR), mii_queue_config },
++                              { mk_mii_end, } };
++
++
++/* Read remainder of PHY ID.
++*/
++static void mii_discover_phy3(uint mii_reg, struct net_device *dev, uint data)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      int     i;
++
++      priv->phy_id |= (mii_reg & 0xffff);
++
++      for (i = 0; phy_info[i]; i++) {
++              if (phy_info[i]->id == (priv->phy_id >> 4) || !phy_info[i]->id)
++                      break;
++              if (phy_info[i]->id == 0)       /* check generic entry */
++                      break;
++      }
++
++      if (!phy_info[i])
++              panic("%s: PHY id 0x%08x is not supported!\n",
++                      dev->name, priv->phy_id);
++
++      priv->phy = phy_info[i];
++      priv->phy_id_done = 1;
++
++      printk(KERN_INFO "%s: Phy @ 0x%x, type %s (0x%08x)\n",
++              dev->name, priv->phy_addr, priv->phy->name, priv->phy_id);
++}
++
++/* Scan all of the MII PHY addresses looking for someone to respond
++ * with a valid ID.  This usually happens quickly.
++ */
++static void mii_discover_phy(uint mii_reg, struct net_device *dev, uint data)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      uint    phytype;
++
++      if ((phytype = (mii_reg & 0xffff)) != 0xffff) {
++              /* Got first part of ID, now get remainder.
++              */
++              priv->phy_id = phytype << 16;
++              mii_queue(dev, mk_mii_read(MII_REG_PHYIR2), mii_discover_phy3,
++                                                                      0);
++      } else {
++              priv->phy_addr++;
++              if (priv->phy_addr < 32)
++                      mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
++                                                      mii_discover_phy, 0);
++              else
++                      printk(KERN_ERR "fec: No PHY device found.\n");
++      }
++}
++
++static int mpc52xx_netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
++{
++      __u32 ethcmd;
++
++      if (copy_from_user(&ethcmd, useraddr, sizeof ethcmd))
++              return -EFAULT;
++
++      switch (ethcmd) {
++
++              /* Get driver info */
++      case ETHTOOL_GDRVINFO:{
++                      struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
++                      strncpy(info.driver, "MPC5200 FEC",
++                              sizeof info.driver - 1);
++                      if (copy_to_user(useraddr, &info, sizeof info))
++                              return -EFAULT;
++                      return 0;
++              }
++              /* get message-level */
++      case ETHTOOL_GMSGLVL:{
++                      struct ethtool_value edata = { ETHTOOL_GMSGLVL };
++                      edata.data = 0; /* XXX */
++                      if (copy_to_user(useraddr, &edata, sizeof edata))
++                              return -EFAULT;
++                      return 0;
++              }
++              /* set message-level */
++      case ETHTOOL_SMSGLVL:{
++                      struct ethtool_value edata;
++                      if (copy_from_user(&edata, useraddr, sizeof edata))
++                              return -EFAULT;
++                      return 0;
++              }
++      }
++      return -EOPNOTSUPP;
++}
++
++int fec_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++      int retval;
++
++      switch (cmd) {
++      case SIOCETHTOOL:
++              retval = mpc52xx_netdev_ethtool_ioctl(
++                                      dev, (void *) rq->ifr_data);
++              break;
++
++      default:
++              retval = -EOPNOTSUPP;
++              break;
++      }
++      return retval;
++}
++
++void fec_mii_init(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++      int i;
++
++      for (i=0; i<NMII-1; i++)
++              mii_cmds[i].mii_next = &mii_cmds[i+1];
++      mii_free = mii_cmds;
++
++      /* Queue up command to detect the PHY and initialize the
++       * remainder of the interface.
++       */
++      priv->phy_id_done = 0;
++      priv->phy_addr = 0;
++      mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy, 0);
++
++      priv->old_status = 0;
++}
++
++int fec_mii_wait(struct net_device *dev)
++{
++      struct fec_priv *priv = (struct fec_priv *)dev->priv;
++
++      if (!priv->sequence_done) {
++              if (!priv->phy) {
++                      printk("KERN_ERR fec_open: PHY not configured\n");
++                      return -ENODEV;         /* No PHY we understand */
++              }
++
++              mii_do_cmd(dev, priv->phy->config);
++              mii_do_cmd(dev, phy_cmd_config); /* display configuration */
++              while(!priv->sequence_done)
++                      schedule();
++
++              mii_do_cmd(dev, priv->phy->startup);
++      }
++      return 0;
++}
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Dale Farnsworth");
++MODULE_DESCRIPTION("PHY driver for Motorola MPC52xx FEC");
+diff --git a/drivers/net/fec_mpc52xx/fec_phy.h b/drivers/net/fec_mpc52xx/fec_phy.h
+new file mode 100644
+index 0000000..5c23bff
+--- /dev/null
++++ b/drivers/net/fec_mpc52xx/fec_phy.h
+@@ -0,0 +1,73 @@
++/*
++ * arch/ppc/52xx_io/fec_phy.h
++ *
++ * Driver for the MPC5200 Fast Ethernet Controller
++ * Based heavily on the MII support for the MPC8xx by Dan Malek
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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 CONFIG_USE_MDIO
++#define MII_ADVERTISE_HALF    (ADVERTISE_100HALF | ADVERTISE_10HALF | \
++                               ADVERTISE_CSMA)
++
++#define MII_ADVERTISE_ALL     (ADVERTISE_100FULL | ADVERTISE_10FULL | \
++                               MII_ADVERTISE_HALF)
++#ifdef PHY_INTERRUPT
++#define MII_ADVERTISE_DEFAULT MII_ADVERTISE_ALL
++#else
++#define MII_ADVERTISE_DEFAULT MII_ADVERTISE_HALF
++#endif
++
++#define MII_RCNTL_MODE                FEC_RCNTRL_MII_MODE
++#define set_phy_speed(fec, s) out_be32(&fec->mii_speed, s)
++#define FEC_IMASK_ENABLE      0xf0fe0000
++
++typedef struct {
++      uint mii_data;
++      void (*funct)(uint mii_reg, struct net_device *dev, uint data);
++} phy_cmd_t;
++
++typedef struct {
++      uint id;
++      char *name;
++
++      const phy_cmd_t *config;
++      const phy_cmd_t *startup;
++      const phy_cmd_t *ack_int;
++      const phy_cmd_t *shutdown;
++} phy_info_t;
++
++#else
++#define MII_RCNTL_MODE                0
++#define set_phy_speed(fec, s)
++#define FEC_IMASK_ENABLE      0xf07e0000
++#define fec_mii_wait(dev)     0
++#define fec_mii(dev)  printk(KERN_WARNING "unexpected FEC_IEVENT_MII\n")
++#define fec_mii_init(dev)
++#endif        /* CONFIG_USE_MDIO */
++
++/* MII-related definitions */
++#define FEC_MII_DATA_ST               0x40000000      /* Start frame */
++#define FEC_MII_DATA_OP_RD    0x20000000      /* Perform read */
++#define FEC_MII_DATA_OP_WR    0x10000000      /* Perform write */
++#define FEC_MII_DATA_PA_MSK   0x0f800000      /* PHY Address mask */
++#define FEC_MII_DATA_RA_MSK   0x007c0000      /* PHY Register mask */
++#define FEC_MII_DATA_TA               0x00020000      /* Turnaround */
++#define FEC_MII_DATA_DATAMSK  0x00000fff      /* PHY data mask */
++
++#define FEC_MII_DATA_RA_SHIFT 0x12            /* MII reg addr bits */
++#define FEC_MII_DATA_PA_SHIFT 0x17            /* MII PHY addr bits */
++
++#define FEC_MII_SPEED         (5 * 2)
++
++extern void fec_mii_init(struct net_device *dev);
++extern int fec_mii_wait(struct net_device *dev);
++extern void fec_mii(struct net_device *dev);
++
++extern int fec_ioctl(struct net_device *, struct ifreq *rq, int cmd);
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0021-POWERPC-Copy-bestcomm-support-files-into-arch-powerpc.txt b/packages/linux/linux-efika-2.6.20/0021-POWERPC-Copy-bestcomm-support-files-into-arch-powerpc.txt
new file mode 100644 (file)
index 0000000..958ca7f
--- /dev/null
@@ -0,0 +1,1335 @@
+From 50ea8834d3b4c79ddaa8f1df88d285ebe8e71cd4 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Mon, 4 Dec 2006 22:19:21 -0700
+Subject: [PATCH] [POWERPC] Copy bestcomm support files into arch/powerpc
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ arch/powerpc/platforms/52xx/bestcomm.c         |  408 ++++++++++++++++++++
+ arch/powerpc/platforms/52xx/bestcomm.h         |  473 ++++++++++++++++++++++++
+ arch/powerpc/platforms/52xx/fec.c              |  174 +++++++++
+ arch/powerpc/platforms/52xx/fec.h              |   71 ++++
+ arch/powerpc/platforms/52xx/sdma_fec_rx_task.c |   71 ++++
+ arch/powerpc/platforms/52xx/sdma_fec_tx_task.c |   84 +++++
+ 6 files changed, 1281 insertions(+), 0 deletions(-)
+
+diff --git a/arch/powerpc/platforms/52xx/bestcomm.c b/arch/powerpc/platforms/52xx/bestcomm.c
+new file mode 100644
+index 0000000..ef45e02
+--- /dev/null
++++ b/arch/powerpc/platforms/52xx/bestcomm.c
+@@ -0,0 +1,408 @@
++/*
++ * arch/ppc/syslib/bestcomm/bestcomm.c
++ *
++ * Driver for MPC52xx processor BestComm peripheral controller
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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.
++ *
++ * HISTORY:
++ *
++ * 2005-08-14 Converted to platform driver by 
++ *            Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
++ */
++
++#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/device.h>
++
++#include <asm/bug.h>
++#include <asm/io.h>
++#include <asm/mpc52xx.h>
++
++#include "bestcomm.h"
++
++#define DRIVER_NAME           "mpc52xx-sdma"
++
++struct sdma_io sdma;
++
++static spinlock_t sdma_lock = SPIN_LOCK_UNLOCKED;
++
++#ifdef CONFIG_BESTCOMM_DEBUG
++void sdma_dump(void)
++{
++      int i;
++      printk("** SDMA registers: pa = %08x, va = %08x\n", sdma.base_reg_addr, sdma.io);
++      printk("**  taskBar = %08x\n", sdma.io->taskBar);
++      printk("**  currentPointer = %08x\n", sdma.io->currentPointer);
++      printk("**  endPointer = %08x\n", sdma.io->endPointer);
++      printk("**  variablePointer = %08x\n", sdma.io->variablePointer);
++
++      printk("**  IntVect1 = %08x\n", sdma.io->IntVect1);
++      printk("**  IntVect2 = %08x\n", sdma.io->IntVect2);
++      printk("**  PtdCntrl = %08x\n", sdma.io->PtdCntrl);
++
++      printk("**  IntPend = %08x\n", sdma.io->IntPend);
++      printk("**  IntMask = %08x\n", sdma.io->IntMask);
++
++      printk("**  TCR dump:");        
++
++      for (i=0;i<16;i++)  {
++              if(i%8 == 0)
++                      printk("\n**   %02X:",i);
++              printk(" %04X",sdma.io->tcr[i]);
++      }
++      printk("\n**  IPR dump:");      
++      for (i=0;i<32;i++)  {
++              if(i%16 == 0)
++                      printk("\n**   %02X:",i);
++              printk(" %02X",sdma.io->ipr[i]);
++      }
++      printk("\n**  cReqSelect = %08x\n", sdma.io->cReqSelect);
++      printk("**  task_size0 = %08x\n", sdma.io->task_size0);
++      printk("**  task_size1 = %08x\n", sdma.io->task_size1);
++      printk("**  MDEDebug = %08x\n", sdma.io->MDEDebug);
++      printk("**  ADSDebug = %08x\n", sdma.io->ADSDebug);
++      printk("**  Value1 = %08x\n", sdma.io->Value1);
++      printk("**  Value2 = %08x\n", sdma.io->Value2);
++      printk("**  Control = %08x\n", sdma.io->Control);
++      printk("**  Status = %08x\n", sdma.io->Status);
++      printk("**  PTDDebug = %08x\n", sdma.io->PTDDebug);
++}
++#endif
++
++#ifdef CONFIG_BESTCOMM_DEBUG
++#define SDMA_DUMP_REGS()      sdma_dump()
++#else
++#define SDMA_DUMP_REGS()
++#endif
++
++/*
++ * Use a very simple SRAM allocator.
++ * There is no mechanism for freeing space.
++ * In an attempt to minimize internal fragmentation, the SRAM is
++ * divided into two areas.
++ *
++ * Area 1 is at the beginning of SRAM
++ * and is used for allocations requiring alignments of 16 bytes or less.
++ * Successive allocations return higher addresses.
++ *
++ * Area 2 is at the end of SRAM and is used for the remaining allocations.
++ * Successive allocations return lower addresses.
++ *
++ * I've considered adding routines to support the freeing of SRAM allocations,
++ * but the SRAM is so small (16K) that fragmentation can quickly cause the
++ * SRAM to be unusable.  If you can come up with a slick way to free SRAM
++ * memory without the fragmentation problem, please do so.
++ */
++
++static u8 *area1_end;
++static u8 *area2_begin;
++
++void *sdma_sram_alloc(int size, int alignment, u32 *dma_handle)
++{
++      u8 *a;
++
++      spin_lock(&sdma_lock);
++
++      /* alignment must be a power of 2 */
++      BUG_ON(alignment & (alignment - 1));
++
++      if (alignment < 16) {
++              a = (u8 *)(((u32)area1_end + (alignment-1)) & ~(alignment-1));
++              if (a + size <= area2_begin)
++                      area1_end = a + size;
++              else
++                      a = 0;                          /* out of memory */
++      } else {
++              a = (u8 *)(((u32)area2_begin - size) & ~(alignment - 1));
++              if (a >= area1_end)
++                      area2_begin = a;
++              else
++                      a = 0;                          /* out of memory */
++      }
++      if(a && dma_handle)
++              *dma_handle = sdma_sram_pa(a);
++      spin_unlock(&sdma_lock);
++      return (void *)a;
++}
++
++/* this will need to be updated if Freescale changes their task code FDT */
++static u32 fdt_ops[] = {
++      0xa0045670,     /* FDT[48] */
++      0x80045670,     /* FDT[49] */
++      0x21800000,     /* FDT[50] */
++      0x21e00000,     /* FDT[51] */
++      0x21500000,     /* FDT[52] */
++      0x21400000,     /* FDT[53] */
++      0x21500000,     /* FDT[54] */
++      0x20400000,     /* FDT[55] */
++      0x20500000,     /* FDT[56] */
++      0x20800000,     /* FDT[57] */
++      0x20a00000,     /* FDT[58] */
++      0xc0170000,     /* FDT[59] */
++      0xc0145670,     /* FDT[60] */
++      0xc0345670,     /* FDT[61] */
++      0xa0076540,     /* FDT[62] */
++      0xa0000760,     /* FDT[63] */
++};
++
++static int new_task_number(void)
++{
++      struct sdma_tdt *tdt;
++      int i;
++
++      spin_lock(&sdma_lock);
++
++      tdt = sdma.tdt;
++      for (i=0; i<SDMA_MAX_TASKS; i++, tdt++)
++              if (tdt->start == 0)
++                      break;
++      if (i == SDMA_MAX_TASKS)
++              i = -1;
++
++      spin_unlock(&sdma_lock);
++
++      return i;
++}
++
++int sdma_load_task(u32 *task_image)
++{
++      struct sdma_task_header *head = (struct sdma_task_header *)task_image;
++      struct sdma_tdt *tdt;
++      int tasknum;
++      u32 *desc;
++      u32 *var_src, *var_dst;
++      u32 *inc_src;
++      void *start;
++
++      BUG_ON(head->magic != SDMA_TASK_MAGIC);
++
++      tasknum = new_task_number();
++      if (tasknum < 0)
++              return -ENOMEM;
++
++      desc = (u32 *)(head + 1);
++      var_src = desc + head->desc_size;
++      inc_src = var_src + head->var_size;
++
++      tdt = &sdma.tdt[tasknum];
++
++      start = sdma_sram_alloc(head->desc_size * sizeof(u32), 4, &tdt->start);
++      if (!start)
++              return -ENOMEM;
++      tdt->stop = tdt->start + (head->desc_size - 1)*sizeof(u32);
++      var_dst = sdma_sram_va(tdt->var);
++
++      memcpy(start, desc, head->desc_size * sizeof(u32));
++      memcpy(&var_dst[head->first_var], var_src, head->var_size * sizeof(u32));
++      memcpy(&var_dst[SDMA_MAX_VAR], inc_src, head->inc_size * sizeof(u32));
++
++      return tasknum;
++}
++
++void sdma_set_initiator(int task, int initiator)
++{
++      int i;
++      int num_descs;
++      u32 *desc;
++      int next_drd_has_initiator;
++
++      sdma_set_tcr_initiator(task, initiator);
++
++      desc = sdma_task_desc(task);
++      next_drd_has_initiator = 1;
++      num_descs = sdma_task_num_descs(task);
++
++      for (i=0; i<num_descs; i++, desc++) {
++              if (!sdma_desc_is_drd(*desc))
++                      continue;
++              if (next_drd_has_initiator)
++                      if (sdma_desc_initiator(*desc) != SDMA_INITIATOR_ALWAYS)
++                              sdma_set_desc_initiator(desc, initiator);
++              next_drd_has_initiator = !sdma_drd_is_extended(*desc);
++      }
++}
++
++struct sdma *sdma_alloc(int queue_size)
++{
++      struct sdma *s = kmalloc(sizeof(*s), GFP_KERNEL);
++      void **cookie;
++
++      if (!s)
++              return NULL;
++
++      memset(s, 0, sizeof(*s));
++
++      if (queue_size) {
++              cookie = kmalloc(sizeof(*cookie) * queue_size, GFP_KERNEL);
++              if (!cookie) {
++                      kfree(s);
++                      return NULL;
++              }
++              s->cookie = cookie;
++      }
++
++      s->num_bd = queue_size;
++      return s;
++}
++
++void sdma_free(struct sdma *s)
++{
++      if (s->cookie)
++              kfree(s->cookie);
++      kfree(s);
++}
++
++static int __devinit mpc52xx_sdma_probe(struct device *dev)
++{
++      struct platform_device *pdev = to_platform_device(dev);
++      int task;
++      u32 *context;
++      u32 *fdt;
++      struct sdma_tdt *tdt;
++      struct resource *mem_io, *mem_sram;
++      u32 tdt_pa, var_pa, context_pa, fdt_pa; 
++      int ret = -ENODEV;
++
++      mem_io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      mem_sram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++      if (!mem_io || !mem_sram)
++              goto out;
++
++      if (!request_mem_region(mem_io->start, mem_io->end - mem_io->start + 1, DRIVER_NAME)) {
++              printk(KERN_ERR DRIVER_NAME " - resource unavailable\n");
++              goto out;
++      }
++      sdma.base_reg_addr = mem_io->start;
++
++      sdma.io = ioremap_nocache(mem_io->start, sizeof(struct mpc52xx_sdma));
++
++      if (!sdma.io ) {
++              printk(KERN_ERR DRIVER_NAME " - failed to map sdma regs\n");
++              ret = -ENOMEM;
++              goto map_io_error;
++      }
++
++      SDMA_DUMP_REGS();
++
++      sdma.sram_size = mem_sram->end - mem_sram->start + 1;
++      if (!request_mem_region(mem_sram->start, sdma.sram_size, DRIVER_NAME)) {
++              printk(KERN_ERR DRIVER_NAME " - resource unavailable\n");
++              goto req_sram_error;
++      }
++
++      sdma.base_sram_addr = mem_sram->start;
++      sdma.sram = ioremap_nocache(mem_sram->start, sdma.sram_size);
++      if (!sdma.sram ) {
++              printk(KERN_ERR DRIVER_NAME " - failed to map sdma sram\n");
++              ret = -ENOMEM;
++              goto map_sram_error;
++      }
++
++      area1_end = sdma.sram;
++      area2_begin = area1_end + sdma.sram_size;
++
++      memset(area1_end, 0, sdma.sram_size);
++
++      /* allocate space for task descriptors, contexts, and var tables */
++      sdma.tdt = sdma_sram_alloc(sizeof(struct sdma_tdt) * SDMA_MAX_TASKS, 4, &tdt_pa);
++
++      context = sdma_sram_alloc(SDMA_CONTEXT_SIZE * SDMA_MAX_TASKS,
++                                                        SDMA_CONTEXT_ALIGN, &context_pa);
++      sdma.var = sdma_sram_alloc( (SDMA_VAR_SIZE + SDMA_INC_SIZE) * SDMA_MAX_TASKS, 
++                                                              SDMA_VAR_ALIGN, &var_pa);
++      fdt = sdma_sram_alloc(SDMA_FDT_SIZE, SDMA_FDT_ALIGN, &fdt_pa);
++      memcpy(&fdt[48], fdt_ops, sizeof(fdt_ops));
++
++      out_be32(&sdma.io->taskBar, tdt_pa);
++
++      tdt = sdma.tdt;
++      for (task=0; task < SDMA_MAX_TASKS; task++) {
++              out_be16(&sdma.io->tcr[task], 0);
++              out_8(&sdma.io->ipr[task], 0);
++
++              tdt->context = context_pa;
++              tdt->var = var_pa;
++              tdt->fdt = fdt_pa;
++              var_pa += (SDMA_MAX_VAR + SDMA_MAX_INC)*sizeof(u32);
++              context_pa += SDMA_MAX_CONTEXT*sizeof(u32);
++              tdt++;
++      }
++
++      out_8(&sdma.io->ipr[SDMA_INITIATOR_ALWAYS], SDMA_IPR_ALWAYS);
++
++      /* Disable COMM Bus Prefetch, apparently it's not reliable yet */
++      out_be16(&sdma.io->PtdCntrl, in_be16(&sdma.io->PtdCntrl) | 1);
++
++      printk(KERN_INFO "MPC52xx BestComm inited\n");
++
++      return 0;
++
++map_sram_error:
++      release_mem_region(mem_sram->start, sdma.sram_size);
++req_sram_error:
++      iounmap(sdma.io);
++map_io_error:
++      release_mem_region(mem_io->start, mem_io->end - mem_io->start + 1);
++out:
++      printk(KERN_ERR "DMA: MPC52xx BestComm init FAILED !!!\n");
++      return ret;
++}
++
++
++static struct device_driver mpc52xx_sdma_driver = {
++      .owner    = THIS_MODULE,
++      .name     = DRIVER_NAME,
++      .bus      = &platform_bus_type,
++      .probe    = mpc52xx_sdma_probe,
++/*    .remove   = mpc52xx_sdma_remove,        TODO */
++#ifdef CONFIG_PM
++/*    .suspend        = mpc52xx_sdma_suspend, TODO */
++/*    .resume         = mpc52xx_sdma_resume,  TODO */
++#endif
++};
++
++static int __init
++mpc52xx_sdma_init(void)
++{
++      printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
++      return driver_register(&mpc52xx_sdma_driver);
++}
++
++#ifdef MODULE
++static void __exit
++mpc52xx_sdma_exit(void)
++{
++      driver_unregister(&mpc52xx_sdma_driver);
++}
++#endif
++
++#ifndef MODULE
++ subsys_initcall(mpc52xx_sdma_init);
++#else
++ module_init(mpc52xx_sdma_init);
++ module_exit(mpc52xx_sdma_exit);
++#endif
++
++
++MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
++MODULE_LICENSE("GPL");
++
++EXPORT_SYMBOL(sdma_sram_alloc);
++EXPORT_SYMBOL(sdma_load_task);
++EXPORT_SYMBOL(sdma_set_initiator);
++EXPORT_SYMBOL(sdma_free);
++EXPORT_SYMBOL(sdma);
++
++
+diff --git a/arch/powerpc/platforms/52xx/bestcomm.h b/arch/powerpc/platforms/52xx/bestcomm.h
+new file mode 100644
+index 0000000..14bf397
+--- /dev/null
++++ b/arch/powerpc/platforms/52xx/bestcomm.h
+@@ -0,0 +1,473 @@
++/*
++ * arch/ppc/syslib/bestcomm/bestcomm.h
++ *
++ * Driver for MPC52xx processor BestComm peripheral controller
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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.
++ *
++ * HISTORY:
++ *
++ * 2005-08-14 Converted to platform driver by 
++ *            Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
++ */
++
++#ifndef __BESTCOMM_BESTCOMM_H__
++#define __BESTCOMM_BESTCOMM_H__
++
++/* Buffer Descriptor definitions */
++struct sdma_bd {
++      u32 status;
++      void *data;
++};
++
++struct sdma_bd2 {
++      u32 status;
++      void *data1;
++      void *data2;
++};
++
++struct sdma_io {
++      unsigned long                   base_reg_addr;
++      struct mpc52xx_sdma __iomem     *io;
++      unsigned long                   base_sram_addr;
++      void __iomem                    *sram;
++      size_t                          sram_size;
++
++      struct sdma_tdt __iomem         *tdt;
++      u32 __iomem                     *var;
++};
++extern struct sdma_io sdma;
++
++#define       sdma_sram_pa(virt)      (((unsigned long)(((void __iomem *)(virt))-sdma.sram))+sdma.base_sram_addr)
++#define       sdma_sram_va(pa)        ((void __iomem *)((((unsigned long)(pa))-sdma.base_sram_addr)+((unsigned long)sdma.sram)))
++
++#define       sdma_io_pa(virt)        (((unsigned long)(((void __iomem *)(virt))-((void __iomem *)sdma.io)))+sdma.base_reg_addr)
++#define       sdma_io_va(pa)  ((void __iomem *)((((unsigned long)(pa))-sdma.base_reg_addr)+((unsigned long)sdma.io)))
++
++#define SDMA_LEN_BITS         26
++#define SDMA_LEN_MASK         ((1 << SDMA_LEN_BITS) - 1)
++
++#define SDMA_BD_READY         0x40000000UL
++
++#define SDMA_FEC_TX_BD_TFD    0x08000000UL    /* transmit frame done */
++#define SDMA_FEC_TX_BD_INT    0x04000000UL    /* Interrupt */
++#define SDMA_FEC_TX_BD_TFD_INIT       (SDMA_BD_READY | SDMA_FEC_TX_BD_TFD | \
++                                                      SDMA_FEC_TX_BD_INT)
++
++struct sdma {
++      union {
++              struct sdma_bd *bd;
++              struct sdma_bd2 *bd2;
++      };
++      void **cookie;
++      u16 index;
++      u16 outdex;
++      u16 num_bd;
++      s16 tasknum;
++      u32 flags;
++};
++
++#define SDMA_FLAGS_NONE               0x0000
++#define SDMA_FLAGS_ENABLE_TASK        0x0001
++#define SDMA_FLAGS_BD2                0x0002
++
++/* Task Descriptor Table Entry */
++struct sdma_tdt {
++      u32 start;
++      u32 stop;
++      u32 var;
++      u32 fdt;
++      u32 exec_status; /* used internally by SmartComm engine */
++      u32 mvtp;                /* used internally by SmartComm engine */
++      u32 context;
++      u32 litbase;
++};
++
++//extern struct sdma_tdt *sdma_tdt;
++
++#define SDMA_MAX_TASKS                16
++#define SDMA_MAX_VAR          24
++#define SDMA_MAX_INC          8
++#define SDMA_MAX_FDT          64
++#define SDMA_MAX_CONTEXT      20
++#define SDMA_CONTEXT_SIZE     SDMA_MAX_CONTEXT * sizeof(u32)
++#define SDMA_CONTEXT_ALIGN    0x100
++#define SDMA_VAR_SIZE         SDMA_MAX_VAR * sizeof(u32)
++#define SDMA_VAR_ALIGN                0x80
++#define SDMA_INC_SIZE         SDMA_MAX_INC * sizeof(u32)
++#define SDMA_FDT_SIZE         SDMA_MAX_FDT * sizeof(u32)
++#define SDMA_FDT_ALIGN                0x100
++#define SDMA_BD_ALIGN         0x10
++
++#define TASK_ENABLE           0x8000
++
++#ifndef DPRINK
++      #ifdef CONFIG_BESTCOMM_DEBUG
++      #define DPRINTK(a,b...) printk(KERN_DEBUG "sdma: %s: " a, __FUNCTION__ , ## b)
++      #else
++      #define DPRINTK(a,b...)
++      #endif
++#endif
++
++static inline void sdma_enable_task(int task)
++{
++      DPRINTK("***DMA enable task (%d): tdt = %08x\n",task, sdma.tdt);
++      DPRINTK("***tdt->start   = %08x\n",sdma.tdt[task].start);
++      DPRINTK("***tdt->stop    = %08x\n",sdma.tdt[task].stop);
++      DPRINTK("***tdt->var     = %08x\n",sdma.tdt[task].var);
++      DPRINTK("***tdt->fdt     = %08x\n",sdma.tdt[task].fdt);
++      DPRINTK("***tdt->status  = %08x\n",sdma.tdt[task].exec_status);
++      DPRINTK("***tdt->mvtp    = %08x\n",sdma.tdt[task].mvtp);
++      DPRINTK("***tdt->context = %08x\n",sdma.tdt[task].context);
++      DPRINTK("***tdt->litbase = %08x\n",sdma.tdt[task].litbase);
++      DPRINTK("***--------------\n");
++
++      u16 reg = in_be16(&sdma.io->tcr[task]);
++      DPRINTK("***enable task: &sdma.io->tcr=%08x, reg = %04x\n", &sdma.io->tcr, reg);
++      out_be16(&sdma.io->tcr[task],  reg | TASK_ENABLE);
++}
++
++static inline void sdma_disable_task(int task)
++{
++      u16 reg = in_be16(&sdma.io->tcr[task]);
++      DPRINTK("***disable task(%d): reg = %04x\n", task, reg);
++      out_be16(&sdma.io->tcr[task], reg & ~TASK_ENABLE);
++}
++
++static inline int sdma_irq(struct sdma *s)
++{
++      return MPC52xx_SDMA_IRQ_BASE + s->tasknum;
++}
++
++static inline void sdma_enable(struct sdma *s)
++{
++      sdma_enable_task(s->tasknum);
++}
++
++static inline void sdma_disable(struct sdma *s)
++{
++      sdma_disable_task(s->tasknum);
++}
++
++static inline int sdma_queue_empty(struct sdma *s)
++{
++      return s->index == s->outdex;
++}
++
++static inline void sdma_clear_irq(struct sdma *s)
++{
++      out_be32(&sdma.io->IntPend, 1 << s->tasknum);
++}
++
++static inline int sdma_next_index(struct sdma *s)
++{
++      return ((s->index + 1) == s->num_bd) ? 0 : s->index + 1;
++}
++
++static inline int sdma_next_outdex(struct sdma *s)
++{
++      return ((s->outdex + 1) == s->num_bd) ? 0 : s->outdex + 1;
++}
++
++static inline int sdma_queue_full(struct sdma *s)
++{
++      return s->outdex == sdma_next_index(s);
++}
++
++static inline int sdma_buffer_done(struct sdma *s)
++{
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(s->flags & SDMA_FLAGS_BD2);
++#endif
++      if (sdma_queue_empty(s))
++              return 0;
++      return (s->bd[s->outdex].status & SDMA_BD_READY) == 0;
++}
++
++static inline int sdma_buffer2_done(struct sdma *s)
++{
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(!(s->flags & SDMA_FLAGS_BD2));
++#endif
++      if (sdma_queue_empty(s))
++              return 0;
++
++      return (s->bd2[s->outdex].status & SDMA_BD_READY) == 0;
++}
++
++static inline u32 *sdma_task_desc(int task)
++{
++      return sdma_sram_va(sdma.tdt[task].start);
++}
++
++static inline u32 sdma_task_num_descs(int task)
++{
++      return (sdma.tdt[task].stop - sdma.tdt[task].start)/sizeof(u32) + 1;
++}
++
++static inline u32 *sdma_task_var(int task)
++{
++      return sdma_sram_va(sdma.tdt[task].var);
++}
++
++static inline u32 *sdma_task_inc(int task)
++{
++      return &sdma_task_var(task)[SDMA_MAX_VAR];
++}
++
++static inline void sdma_set_tcr_initiator(int task, int initiator) {
++      u16 *tcr = &sdma.io->tcr[task];
++      out_be16(tcr, (in_be16(tcr) & ~0x1f00) | (initiator << 8));
++}
++
++#define SDMA_DRD_INITIATOR_SHIFT      21
++
++static inline int sdma_desc_initiator(u32 desc)
++{
++      return (desc >> SDMA_DRD_INITIATOR_SHIFT) & 0x1f;
++}
++
++static inline void sdma_set_desc_initiator(u32 *desc, int initiator)
++{
++      *desc = (*desc & ~(0x1f << SDMA_DRD_INITIATOR_SHIFT)) |
++                      ((initiator << SDMA_DRD_INITIATOR_SHIFT) & 0x1f);
++}
++
++static inline void sdma_submit_buffer(struct sdma *s, void *cookie, void *data,
++                                                              int length)
++{
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(s->flags & SDMA_FLAGS_BD2);
++#endif
++      s->cookie[s->index] = cookie;
++      s->bd[s->index].data = data;
++      s->bd[s->index].status = SDMA_BD_READY | length;
++      s->index = sdma_next_index(s);
++      if (s->flags & SDMA_FLAGS_ENABLE_TASK)
++              sdma_enable_task(s->tasknum);
++}
++
++/*
++ * Special submit_buffer function to submit last buffer of a frame to
++ * the FEC tx task.  tfd means "transmit frame done".
++ */
++static inline void sdma_fec_tfd_submit_buffer(struct sdma *s, void *cookie,
++                                                      void *data, int length)
++{
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(s->flags & SDMA_FLAGS_BD2);
++#endif
++      s->cookie[s->index] = cookie;
++      s->bd[s->index].data = data;
++      s->bd[s->index].status = SDMA_FEC_TX_BD_TFD_INIT | length;
++      s->index = sdma_next_index(s);
++      sdma_enable_task(s->tasknum);
++}
++
++static inline void *sdma_retrieve_buffer(struct sdma *s, int *length)
++{
++      void *cookie = s->cookie[s->outdex];
++
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(s->flags & SDMA_FLAGS_BD2);
++#endif
++      if (length)
++              *length = s->bd[s->outdex].status & SDMA_LEN_MASK;
++      s->outdex = sdma_next_outdex(s);
++      return cookie;
++}
++
++static inline void sdma_submit_buffer2(struct sdma *s, void *cookie,
++                                      void *data1, void *data2, int length)
++{
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(!(s->flags & SDMA_FLAGS_BD2));
++#endif
++      s->cookie[s->index] = cookie;
++      s->bd2[s->index].data1 = data1;
++      s->bd2[s->index].data2 = data2;
++      s->bd2[s->index].status = SDMA_BD_READY | length;
++      s->index = sdma_next_index(s);
++      if (s->flags & SDMA_FLAGS_ENABLE_TASK)
++              sdma_enable_task(s->tasknum);
++}
++
++static inline void *sdma_retrieve_buffer2(struct sdma *s, int *length)
++{
++      void *cookie = s->cookie[s->outdex];
++
++#ifdef CONFIG_BESTCOMM_DEBUG
++      BUG_ON(!(s->flags & SDMA_FLAGS_BD2));
++#endif
++      if (length)
++              *length = s->bd2[s->outdex].status & SDMA_LEN_MASK;
++      s->outdex = sdma_next_outdex(s);
++      return cookie;
++}
++
++#define SDMA_TASK_MAGIC               0x4243544B      /* 'BCTK' */
++
++/* the size fields are given in number of 32-bit words */
++struct sdma_task_header {
++      u32     magic;
++      u8      desc_size;
++      u8      var_size;
++      u8      inc_size;
++      u8      first_var;
++      u8      reserved[8];
++};
++
++#define SDMA_DESC_NOP         0x000001f8
++#define SDMA_LCD_MASK         0x80000000
++#define SDMA_DRD_EXTENDED     0x40000000
++
++#define sdma_drd_is_extended(desc) ((desc) & SDMA_DRD_EXTENDED)
++
++static inline int sdma_desc_is_drd(u32 desc) {
++      return !(desc & SDMA_LCD_MASK) && desc != SDMA_DESC_NOP;
++};
++
++#define SDMA_PRAGMA_BIT_RSV           7       /* reserved pragma bit */
++#define SDMA_PRAGMA_BIT_PRECISE_INC   6       /* increment 0=when possible, */
++                                              /*      1=iter end */
++#define SDMA_PRAGMA_BIT_RST_ERROR_NO  5       /* don't reset errors on */
++                                              /* task enable */
++#define SDMA_PRAGMA_BIT_PACK          4       /* pack data enable */
++#define SDMA_PRAGMA_BIT_INTEGER               3       /* data alignment */
++                                              /* 0=frac(msb), 1=int(lsb) */
++#define SDMA_PRAGMA_BIT_SPECREAD      2       /* XLB speculative read */
++#define SDMA_PRAGMA_BIT_CW            1       /* write line buffer enable */
++#define SDMA_PRAGMA_BIT_RL            0       /* read line buffer enable */
++
++#define SDMA_STD_PRAGMA               ((0 << SDMA_PRAGMA_BIT_RSV)             | \
++                               (0 << SDMA_PRAGMA_BIT_PRECISE_INC)     | \
++                               (0 << SDMA_PRAGMA_BIT_RST_ERROR_NO)    | \
++                               (0 << SDMA_PRAGMA_BIT_PACK)            | \
++                               (0 << SDMA_PRAGMA_BIT_INTEGER)         | \
++                               (1 << SDMA_PRAGMA_BIT_SPECREAD)        | \
++                               (1 << SDMA_PRAGMA_BIT_CW)              | \
++                               (1 << SDMA_PRAGMA_BIT_RL))
++
++#define SDMA_PCI_PRAGMA               ((0 << SDMA_PRAGMA_BIT_RSV)             | \
++                               (0 << SDMA_PRAGMA_BIT_PRECISE_INC)     | \
++                               (0 << SDMA_PRAGMA_BIT_RST_ERROR_NO)    | \
++                               (0 << SDMA_PRAGMA_BIT_PACK)            | \
++                               (1 << SDMA_PRAGMA_BIT_INTEGER)         | \
++                               (1 << SDMA_PRAGMA_BIT_SPECREAD)        | \
++                               (1 << SDMA_PRAGMA_BIT_CW)              | \
++                               (1 << SDMA_PRAGMA_BIT_RL))
++
++#define SDMA_ATA_PRAGMA               SDMA_STD_PRAGMA
++#define SDMA_CRC16_DP_0_PRAGMA        SDMA_STD_PRAGMA
++#define SDMA_CRC16_DP_1_PRAGMA        SDMA_STD_PRAGMA
++#define SDMA_FEC_RX_BD_PRAGMA SDMA_STD_PRAGMA
++#define SDMA_FEC_TX_BD_PRAGMA SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_0_PRAGMA  SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_1_PRAGMA  SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_2_PRAGMA  SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_3_PRAGMA  SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_BD_0_PRAGMA       SDMA_STD_PRAGMA
++#define SDMA_GEN_DP_BD_1_PRAGMA       SDMA_STD_PRAGMA
++#define SDMA_GEN_RX_BD_PRAGMA SDMA_STD_PRAGMA
++#define SDMA_GEN_TX_BD_PRAGMA SDMA_STD_PRAGMA
++#define SDMA_GEN_LPC_PRAGMA   SDMA_STD_PRAGMA
++#define SDMA_PCI_RX_PRAGMA    SDMA_PCI_PRAGMA
++#define SDMA_PCI_TX_PRAGMA    SDMA_PCI_PRAGMA
++
++static inline void sdma_set_task_pragma(int task, int pragma)
++{
++      u32 *fdt = &sdma.tdt[task].fdt;
++      *fdt = (*fdt & ~0xff) | pragma;
++}
++
++static inline void sdma_set_task_auto_start(int task, int next_task)
++{
++      u16 *tcr = &sdma.io->tcr[task];
++      out_be16(tcr, (in_be16(tcr) & ~0xff) | 0x00c0 | next_task);
++}
++
++#define SDMA_INITIATOR_ALWAYS  0
++#define SDMA_INITIATOR_SCTMR_0         1
++#define SDMA_INITIATOR_SCTMR_1         2
++#define SDMA_INITIATOR_FEC_RX  3
++#define SDMA_INITIATOR_FEC_TX  4
++#define SDMA_INITIATOR_ATA_RX  5
++#define SDMA_INITIATOR_ATA_TX  6
++#define SDMA_INITIATOR_SCPCI_RX        7
++#define SDMA_INITIATOR_SCPCI_TX        8
++#define SDMA_INITIATOR_PSC3_RX         9
++#define SDMA_INITIATOR_PSC3_TX        10
++#define SDMA_INITIATOR_PSC2_RX        11
++#define SDMA_INITIATOR_PSC2_TX        12
++#define SDMA_INITIATOR_PSC1_RX        13
++#define SDMA_INITIATOR_PSC1_TX        14
++#define SDMA_INITIATOR_SCTMR_2        15
++#define SDMA_INITIATOR_SCLPC  16
++#define SDMA_INITIATOR_PSC5_RX        17
++#define SDMA_INITIATOR_PSC5_TX        18
++#define SDMA_INITIATOR_PSC4_RX        19
++#define SDMA_INITIATOR_PSC4_TX        20
++#define SDMA_INITIATOR_I2C2_RX        21
++#define SDMA_INITIATOR_I2C2_TX        22
++#define SDMA_INITIATOR_I2C1_RX        23
++#define SDMA_INITIATOR_I2C1_TX        24
++#define SDMA_INITIATOR_PSC6_RX        25
++#define SDMA_INITIATOR_PSC6_TX        26
++#define SDMA_INITIATOR_IRDA_RX        25
++#define SDMA_INITIATOR_IRDA_TX        26
++#define SDMA_INITIATOR_SCTMR_3        27
++#define SDMA_INITIATOR_SCTMR_4        28
++#define SDMA_INITIATOR_SCTMR_5        29
++#define SDMA_INITIATOR_SCTMR_6        30
++#define SDMA_INITIATOR_SCTMR_7        31
++
++#define SDMA_IPR_ALWAYS       7
++#define SDMA_IPR_SCTMR_0      2
++#define SDMA_IPR_SCTMR_1      2
++#define SDMA_IPR_FEC_RX       6
++#define SDMA_IPR_FEC_TX       5
++#define SDMA_IPR_ATA_RX       4
++#define SDMA_IPR_ATA_TX       3
++#define SDMA_IPR_SCPCI_RX     2
++#define SDMA_IPR_SCPCI_TX     2
++#define SDMA_IPR_PSC3_RX      2
++#define SDMA_IPR_PSC3_TX      2
++#define SDMA_IPR_PSC2_RX      2
++#define SDMA_IPR_PSC2_TX      2
++#define SDMA_IPR_PSC1_RX      2
++#define SDMA_IPR_PSC1_TX      2
++#define SDMA_IPR_SCTMR_2      2
++#define SDMA_IPR_SCLPC                2
++#define SDMA_IPR_PSC5_RX      2
++#define SDMA_IPR_PSC5_TX      2
++#define SDMA_IPR_PSC4_RX      2
++#define SDMA_IPR_PSC4_TX      2
++#define SDMA_IPR_I2C2_RX      2
++#define SDMA_IPR_I2C2_TX      2
++#define SDMA_IPR_I2C1_RX      2
++#define SDMA_IPR_I2C1_TX      2
++#define SDMA_IPR_PSC6_RX      2
++#define SDMA_IPR_PSC6_TX      2
++#define SDMA_IPR_IRDA_RX      2
++#define SDMA_IPR_IRDA_TX      2
++#define SDMA_IPR_SCTMR_3      2
++#define SDMA_IPR_SCTMR_4      2
++#define SDMA_IPR_SCTMR_5      2
++#define SDMA_IPR_SCTMR_6      2
++#define SDMA_IPR_SCTMR_7      2
++
++extern struct sdma *sdma_alloc(int request_queue_size);
++extern void sdma_free(struct sdma *sdma_struct);
++extern int sdma_load_task(u32 *task_image);
++extern void *sdma_sram_alloc(int size, int alignment, u32 *dma_handle);
++extern void sdma_init_bd(struct sdma *s);
++extern void sdma_init_bd2(struct sdma *s);
++
++#define FIELD_OFFSET(s,f) ((unsigned long)(&(((struct s*)0)->f)))
++
++#endif  /* __BESTCOMM_BESTCOMM_H__ */
+diff --git a/arch/powerpc/platforms/52xx/fec.c b/arch/powerpc/platforms/52xx/fec.c
+new file mode 100644
+index 0000000..8756856
+--- /dev/null
++++ b/arch/powerpc/platforms/52xx/fec.c
+@@ -0,0 +1,174 @@
++/*
++ * arch/ppc/syslib/bestcomm/fec.c
++ *
++ * Driver for MPC52xx processor BestComm FEC controller
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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.
++ *
++ * HISTORY:
++ *
++ * 2005-08-14 Converted to platform driver by 
++ *            Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
++ */
++
++#include <linux/config.h>
++#include <linux/version.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <asm/errno.h>                                  
++#include <asm/io.h>
++
++#include <asm/mpc52xx.h>
++
++#include "bestcomm.h"
++#include "fec.h"
++
++/*
++ * Initialize FEC receive task.
++ * Returns task number of FEC receive task.
++ * Returns -1 on failure
++ */
++int sdma_fec_rx_init(struct sdma *s, phys_addr_t fifo, int maxbufsize)
++{
++      struct sdma_fec_rx_var *var;
++      struct sdma_fec_rx_inc *inc;
++
++      static int tasknum = -1;
++      static struct sdma_bd *bd = 0;
++      static u32 bd_pa;
++
++      if (tasknum < 0) {
++              tasknum = sdma_load_task(sdma_fec_rx_task);
++              if (tasknum < 0)
++                      return tasknum;
++      }
++
++      if (!bd) 
++              bd = (struct sdma_bd *)sdma_sram_alloc(sizeof(*bd) * s->num_bd,
++                                                              SDMA_BD_ALIGN, &bd_pa);
++      if (!bd)
++              return -ENOMEM;
++
++      sdma_disable_task(tasknum);
++
++      s->tasknum = tasknum;
++      s->bd = bd;
++      s->flags = SDMA_FLAGS_NONE;
++      s->index = 0;
++      s->outdex = 0;
++      memset(bd, 0, sizeof(*bd) * s->num_bd);
++
++      var = (struct sdma_fec_rx_var *)sdma_task_var(tasknum);
++      var->enable                     = sdma_io_pa(&sdma.io->tcr[tasknum]);
++      var->fifo                       = fifo;
++      var->bd_base            = bd_pa;
++      var->bd_last            = bd_pa + (s->num_bd - 1)*sizeof(struct sdma_bd);
++      var->bd_start           = bd_pa;
++      var->buffer_size        = maxbufsize;
++
++      /* These are constants, they should have been in the image file */
++      inc = (struct sdma_fec_rx_inc *)sdma_task_inc(tasknum);
++      inc->incr_bytes         = -(s16)sizeof(u32);
++      inc->incr_dst           = sizeof(u32);
++      inc->incr_dst_ma        = sizeof(u8);
++
++      sdma_set_task_pragma(tasknum, SDMA_FEC_RX_BD_PRAGMA);
++      sdma_set_task_auto_start(tasknum, tasknum);
++
++      /* clear pending interrupt bits */
++      out_be32(&sdma.io->IntPend, 1<<tasknum);
++
++      out_8(&sdma.io->ipr[SDMA_INITIATOR_FEC_RX], SDMA_IPR_FEC_RX);
++
++      return tasknum;
++}
++
++/*
++ * Return 2nd to last DRD
++ * This is an ugly hack, but at least it's only done once at initialization
++ */
++static u32 *self_modified_drd(int tasknum)
++{
++      u32 *desc;
++      int num_descs;
++      int drd_count;
++      int i;
++
++      num_descs = sdma_task_num_descs(tasknum);
++      desc = sdma_task_desc(tasknum) + num_descs - 1;
++      drd_count = 0;
++      for (i=0; i<num_descs; i++, desc--)
++              if (sdma_desc_is_drd(*desc) && ++drd_count == 3)
++                      break;
++      return desc;
++}
++
++/*
++ * Initialize FEC transmit task.
++ * Returns task number of FEC transmit task.
++ * Returns -1 on failure
++ */
++int sdma_fec_tx_init(struct sdma *s, phys_addr_t fifo)
++{
++      struct sdma_fec_tx_var *var;
++      struct sdma_fec_tx_inc *inc;
++
++      static int tasknum = -1;
++      static struct sdma_bd *bd = 0;
++      static u32 bd_pa;
++
++      if (tasknum < 0) {
++              tasknum = sdma_load_task(sdma_fec_tx_task);
++              if (tasknum < 0)
++                      return tasknum;
++      }
++
++      if (!bd)  
++              bd = (struct sdma_bd *)sdma_sram_alloc(sizeof(*bd) * s->num_bd,
++                                                              SDMA_BD_ALIGN, &bd_pa);
++      if (!bd)
++              return -ENOMEM;
++
++      sdma_disable_task(tasknum);
++
++      s->tasknum = tasknum;
++      s->bd = bd;
++      s->flags = SDMA_FLAGS_ENABLE_TASK;
++      s->index = 0;
++      s->outdex = 0;
++      memset(bd, 0, sizeof(*bd) * s->num_bd);
++
++      var = (struct sdma_fec_tx_var *)sdma_task_var(tasknum);
++      var->DRD                = sdma_sram_pa(self_modified_drd(tasknum));
++      var->fifo               = fifo;
++      var->enable             = sdma_io_pa(&sdma.io->tcr[tasknum]);
++      var->bd_base    = bd_pa;
++      var->bd_last    = bd_pa + (s->num_bd - 1)*sizeof(struct sdma_bd);
++      var->bd_start   = bd_pa;
++
++      /* These are constants, they should have been in the image file */
++      inc = (struct sdma_fec_tx_inc *)sdma_task_inc(tasknum);
++      inc->incr_bytes         = -(s16)sizeof(u32);
++      inc->incr_src           = sizeof(u32);
++      inc->incr_src_ma        = sizeof(u8);
++
++      sdma_set_task_pragma(tasknum, SDMA_FEC_TX_BD_PRAGMA);
++      sdma_set_task_auto_start(tasknum, tasknum);
++
++      /* clear pending interrupt bits */
++      out_be32(&sdma.io->IntPend, 1<<tasknum);
++
++      out_8(&sdma.io->ipr[SDMA_INITIATOR_FEC_TX], SDMA_IPR_FEC_TX);
++
++      return tasknum;
++}
++
++EXPORT_SYMBOL(sdma_fec_rx_init);
++EXPORT_SYMBOL(sdma_fec_tx_init);
+diff --git a/arch/powerpc/platforms/52xx/fec.h b/arch/powerpc/platforms/52xx/fec.h
+new file mode 100644
+index 0000000..e3abc0f
+--- /dev/null
++++ b/arch/powerpc/platforms/52xx/fec.h
+@@ -0,0 +1,71 @@
++/*
++ * arch/ppc/syslib/bestcomm/fec.h
++ *
++ * Driver for MPC52xx processor BestComm FEC controller
++ *
++ * Author: Dale Farnsworth <dfarnsworth@mvista.com>
++ *
++ * 2003-2004 (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.
++ *
++ * HISTORY:
++ *
++ * 2005-08-14 Converted to platform driver by 
++ *            Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
++ */
++
++#ifndef __BESTCOMM_FEC_H__
++#define __BESTCOMM_FEC_H__
++
++
++/* rx task vars that need to be set before enabling the task */
++struct sdma_fec_rx_var {
++      u32 enable;             /* (u16*) address of task's control register */
++      u32 fifo;               /* (u32*) address of fec's fifo */
++      u32 bd_base;            /* (struct sdma_bd*) beginning of ring buffer */
++      u32 bd_last;            /* (struct sdma_bd*) end of ring buffer */
++      u32 bd_start;           /* (struct sdma_bd*) current bd */
++      u32 buffer_size;        /* size of receive buffer */
++};
++
++/* rx task incs that need to be set before enabling the task */
++struct sdma_fec_rx_inc {
++      u16 pad0;
++      s16 incr_bytes;
++      u16 pad1;
++      s16 incr_dst;
++      u16 pad2;
++      s16 incr_dst_ma;
++};
++
++/* tx task vars that need to be set before enabling the task */
++struct sdma_fec_tx_var {
++      u32 DRD;                /* (u32*) address of self-modified DRD */
++      u32 fifo;               /* (u32*) address of fec's fifo */
++      u32 enable;             /* (u16*) address of task's control register */
++      u32 bd_base;            /* (struct sdma_bd*) beginning of ring buffer */
++      u32 bd_last;            /* (struct sdma_bd*) end of ring buffer */
++      u32 bd_start;           /* (struct sdma_bd*) current bd */
++      u32 buffer_size;        /* set by uCode for each packet */
++};
++
++/* tx task incs that need to be set before enabling the task */
++struct sdma_fec_tx_inc {
++      u16 pad0;
++      s16 incr_bytes;
++      u16 pad1;
++      s16 incr_src;
++      u16 pad2;
++      s16 incr_src_ma;
++};
++
++extern int sdma_fec_rx_init(struct sdma *s, phys_addr_t fifo, int maxbufsize);
++extern int sdma_fec_tx_init(struct sdma *s, phys_addr_t fifo);
++
++extern u32 sdma_fec_rx_task[];
++extern u32 sdma_fec_tx_task[];
++
++
++#endif  /* __BESTCOMM_FEC_H__ */
+diff --git a/arch/powerpc/platforms/52xx/sdma_fec_rx_task.c b/arch/powerpc/platforms/52xx/sdma_fec_rx_task.c
+new file mode 100644
+index 0000000..511b036
+--- /dev/null
++++ b/arch/powerpc/platforms/52xx/sdma_fec_rx_task.c
+@@ -0,0 +1,71 @@
++/*
++ * sdma_fec_rx_task.c
++ *
++ * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
++ * on Tue Mar 22 11:19:38 2005 GMT
++ */
++
++#include <linux/types.h>
++
++/*
++ * The header consists of the following fields:
++ *    uint32_t        magic;
++ *    uint8_t         desc_size;
++ *    uint8_t         var_size;
++ *    uint8_t         inc_size;
++ *    uint8_t         first_var;
++ *    uint8_t         reserved[8];
++ *
++ * The size fields contain the number of 32-bit words.
++*/
++
++uint32_t sdma_fec_rx_task[] = {
++      /* header */
++      0x4243544b,
++      0x18060709,
++      0x00000000,
++      0x00000000,
++
++      /* Task descriptors */
++      0x808220e3, /* LCD: idx0 = var1, idx1 = var4; idx1 <= var3; idx0 += inc4, idx1 += inc3 */
++      0x10601010, /*   DRD1A: var4 = var2; FN=0 MORE init=3 WS=0 RS=0 */
++      0xb8800264, /*   LCD: idx2 = *idx1, idx3 = var0; idx2 < var9; idx2 += inc4, idx3 += inc4 */
++      0x10001308, /*     DRD1A: var4 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
++      0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
++      0x0cccfcca, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var10)  */
++      0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
++      0xb8c58029, /*   LCD: idx3 = *(idx1 + var00000015); idx3 once var0; idx3 += inc5 */
++      0x60000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=0 RS=0 */
++      0x088cf8cc, /*     DRD2B1: idx2 = EU3(); EU3(idx3,var12)  */
++      0x991982f2, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var11; idx2 += inc6, idx3 += inc2 */
++      0x006acf80, /*     DRD1A: *idx3 = *idx0; FN=0 init=3 WS=1 RS=1 */
++      0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
++      0x9999802d, /*   LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
++      0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
++      0x034cfc4e, /*     DRD2B1: var13 = EU3(); EU3(*idx1,var14)  */
++      0x00008868, /*     DRD1A: idx2 = var13; FN=0 init=0 WS=0 RS=0 */
++      0x99198341, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var13; idx2 += inc0, idx3 += inc1 */
++      0x007ecf80, /*     DRD1A: *idx3 = *idx0; FN=0 init=3 WS=3 RS=3 */
++      0x99198272, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var9; idx2 += inc6, idx3 += inc2 */
++      0x046acf80, /*     DRD1A: *idx3 = *idx0; FN=0 INT init=3 WS=1 RS=1 */
++      0x9819002d, /*   LCD: idx2 = idx0; idx2 once var0; idx2 += inc5 */
++      0x0060c790, /*     DRD1A: *idx1 = *idx2; FN=0 init=3 WS=0 RS=0 */
++      0x000001f8, /*   NOP */
++
++      /* VAR[9]-VAR[14] */
++      0x40000000,
++      0x7fff7fff,
++      0x00000000,
++      0x00000003,
++      0x40000008,
++      0x43ffffff,
++
++      /* INC[0]-INC[6] */
++      0x40000000,
++      0xe0000000,
++      0xe0000000,
++      0xa0000008,
++      0x20000000,
++      0x00000000,
++      0x4000ffff,
++};
+diff --git a/arch/powerpc/platforms/52xx/sdma_fec_tx_task.c b/arch/powerpc/platforms/52xx/sdma_fec_tx_task.c
+new file mode 100644
+index 0000000..d8d7fd3
+--- /dev/null
++++ b/arch/powerpc/platforms/52xx/sdma_fec_tx_task.c
+@@ -0,0 +1,84 @@
++/*
++ * sdma_fec_tx_task.c
++ *
++ * Automatically created based on BestCommAPI-2.2/code_dma/image_rtos1/dma_image.hex
++ * on Tue Mar 22 11:19:29 2005 GMT
++ */
++
++#include <linux/types.h>
++
++/*
++ * The header consists of the following fields:
++ *    uint32_t        magic;
++ *    uint8_t         desc_size;
++ *    uint8_t         var_size;
++ *    uint8_t         inc_size;
++ *    uint8_t         first_var;
++ *    uint8_t         reserved[8];
++ *
++ * The size fields contain the number of 32-bit words.
++*/
++
++uint32_t sdma_fec_tx_task[] = {
++      /* header */
++      0x4243544b,
++      0x2407070d,
++      0x00000000,
++      0x00000000,
++
++      /* Task descriptors */
++      0x8018001b, /* LCD: idx0 = var0; idx0 <= var0; idx0 += inc3 */
++      0x60000005, /*   DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
++      0x01ccfc0d, /*   DRD2B1: var7 = EU3(); EU3(*idx0,var13)  */
++      0x8082a123, /* LCD: idx0 = var1, idx1 = var5; idx1 <= var4; idx0 += inc4, idx1 += inc3 */
++      0x10801418, /*   DRD1A: var5 = var3; FN=0 MORE init=4 WS=0 RS=0 */
++      0xf88103a4, /*   LCDEXT: idx2 = *idx1, idx3 = var2; idx2 < var14; idx2 += inc4, idx3 += inc4 */
++      0x801a6024, /*   LCD: idx4 = var0; ; idx4 += inc4 */
++      0x10001708, /*     DRD1A: var5 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
++      0x60140002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT init=0 WS=2 RS=2 */
++      0x0cccfccf, /*     DRD2B1: *idx3 = EU3(); EU3(*idx3,var15)  */
++      0x991a002c, /*   LCD: idx2 = idx2, idx3 = idx4; idx2 once var0; idx2 += inc5, idx3 += inc4 */
++      0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
++      0x024cfc4d, /*     DRD2B1: var9 = EU3(); EU3(*idx1,var13)  */
++      0x60000003, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=3 EXT init=0 WS=0 RS=0 */
++      0x0cccf247, /*     DRD2B1: *idx3 = EU3(); EU3(var9,var7)  */
++      0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
++      0xb8c80029, /*   LCD: idx3 = *(idx1 + var0000001a); idx3 once var0; idx3 += inc5 */
++      0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
++      0x088cf8d1, /*     DRD2B1: idx2 = EU3(); EU3(idx3,var17)  */
++      0x00002f10, /*     DRD1A: var11 = idx2; FN=0 init=0 WS=0 RS=0 */
++      0x99198432, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var16; idx2 += inc6, idx3 += inc2 */
++      0x008ac398, /*     DRD1A: *idx0 = *idx3; FN=0 init=4 WS=1 RS=1 */
++      0x80004000, /*   LCDEXT: idx2 = 0x00000000; ; */
++      0x9999802d, /*   LCD: idx3 = idx3; idx3 once var0; idx3 += inc5 */
++      0x70000002, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=2 EXT MORE init=0 WS=0 RS=0 */
++      0x048cfc53, /*     DRD2B1: var18 = EU3(); EU3(*idx1,var19)  */
++      0x60000008, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=8 EXT init=0 WS=0 RS=0 */
++      0x088cf48b, /*     DRD2B1: idx2 = EU3(); EU3(var18,var11)  */
++      0x99198481, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var18; idx2 += inc0, idx3 += inc1 */
++      0x009ec398, /*     DRD1A: *idx0 = *idx3; FN=0 init=4 WS=3 RS=3 */
++      0x991983b2, /*   LCD: idx2 = idx2, idx3 = idx3; idx2 > var14; idx2 += inc6, idx3 += inc2 */
++      0x088ac398, /*     DRD1A: *idx0 = *idx3; FN=0 TFD init=4 WS=1 RS=1 */
++      0x9919002d, /*   LCD: idx2 = idx2; idx2 once var0; idx2 += inc5 */
++      0x60000005, /*     DRD2A: EU0=0 EU1=0 EU2=0 EU3=5 EXT init=0 WS=0 RS=0 */
++      0x0c4cf88e, /*     DRD2B1: *idx1 = EU3(); EU3(idx2,var14)  */
++      0x000001f8, /*   NOP */
++
++      /* VAR[13]-VAR[19] */
++      0x0c000000,
++      0x40000000,
++      0x7fff7fff,
++      0x00000000,
++      0x00000003,
++      0x40000004,
++      0x43ffffff,
++
++      /* INC[0]-INC[6] */
++      0x40000000,
++      0xe0000000,
++      0xe0000000,
++      0xa0000008,
++      0x20000000,
++      0x00000000,
++      0x4000ffff,
++};
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0022-MPC52xx-PCI-now-working-on-lite5200.-ugly-but-working.txt b/packages/linux/linux-efika-2.6.20/0022-MPC52xx-PCI-now-working-on-lite5200.-ugly-but-working.txt
new file mode 100644 (file)
index 0000000..dbf6162
--- /dev/null
@@ -0,0 +1,464 @@
+From c4c2f5cb57335b1b47aa8007b0cfce48cc46fa06 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Tue, 21 Nov 2006 14:41:59 -0700
+Subject: [PATCH] [MPC52xx] PCI now working on lite5200... ugly, but working
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ arch/powerpc/platforms/52xx/mpc52xx_pci.c |  334 +++++++++++++++++++++++++++++
+ arch/powerpc/platforms/52xx/mpc52xx_pci.h |  104 +++++++++
+ 2 files changed, 438 insertions(+), 0 deletions(-)
+
+diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+new file mode 100644
+index 0000000..07dce3c
+--- /dev/null
++++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+@@ -0,0 +1,334 @@
++/*
++ * PCI code for the Freescale MPC52xx embedded CPU.
++ *
++ * Copyright (C) 2004 Secret Lab Technologies Ltd.
++ *                        Grant Likely <grant.likely@secretlab.ca>
++ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
++ *
++ * 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.
++ */
++
++#define DEBUG
++
++#include <asm/pci.h>
++#include <asm/mpc52xx.h>
++#include "mpc52xx_pci.h"
++#include <asm/delay.h>
++#include <asm/machdep.h>
++#include <linux/kernel.h>
++
++
++/* This macro is defined to activate the workaround for the bug
++   435 of the MPC5200 (L25R). With it activated, we don't do any
++   32 bits configuration access during type-1 cycles */
++#define MPC5200_BUG_435_WORKAROUND
++
++
++static int
++mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
++                              int offset, int len, u32 *val)
++{
++      struct pci_controller *hose = bus->sysdata;
++      u32 value;
++
++      if (ppc_md.pci_exclude_device)
++              if (ppc_md.pci_exclude_device(bus->number, devfn))
++                      return PCIBIOS_DEVICE_NOT_FOUND;
++
++      out_be32(hose->cfg_addr,
++              (1 << 31) |
++              ((bus->number - hose->bus_offset) << 16) |
++              (devfn << 8) |
++              (offset & 0xfc));
++      mb();
++
++#ifdef MPC5200_BUG_435_WORKAROUND
++      if (bus->number != hose->bus_offset) {
++              switch (len) {
++                    case 1:
++                      value = in_8(((u8 __iomem *)hose->cfg_data) +
++                                   (offset & 3));
++                      break;
++                    case 2:
++                      value = in_le16(((u16 __iomem *)hose->cfg_data) +
++                                      ((offset>>1) & 1));
++                      break;
++
++                    default:
++                      value = in_le16((u16 __iomem *)hose->cfg_data) |
++                              (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
++                      break;
++              }
++      }
++      else
++#endif
++      {
++              value = in_le32(hose->cfg_data);
++
++              if (len != 4) {
++                      value >>= ((offset & 0x3) << 3);
++                      value &= 0xffffffff >> (32 - (len << 3));
++              }
++      }
++
++      *val = value;
++
++      out_be32(hose->cfg_addr, 0);
++      mb();
++
++      return PCIBIOS_SUCCESSFUL;
++}
++
++static int
++mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
++                              int offset, int len, u32 val)
++{
++      struct pci_controller *hose = bus->sysdata;
++      u32 value, mask;
++
++      if (ppc_md.pci_exclude_device)
++              if (ppc_md.pci_exclude_device(bus->number, devfn))
++                      return PCIBIOS_DEVICE_NOT_FOUND;
++
++      out_be32(hose->cfg_addr,
++              (1 << 31) |
++              ((bus->number - hose->bus_offset) << 16) |
++              (devfn << 8) |
++              (offset & 0xfc));
++      mb();
++
++#ifdef MPC5200_BUG_435_WORKAROUND
++      if (bus->number != hose->bus_offset) {
++              switch (len) {
++                    case 1:
++                      out_8(((u8 __iomem *)hose->cfg_data) +
++                              (offset & 3), val);
++                      break;
++                    case 2:
++                      out_le16(((u16 __iomem *)hose->cfg_data) +
++                              ((offset>>1) & 1), val);
++                      break;
++
++                    default:
++                      out_le16((u16 __iomem *)hose->cfg_data,
++                              (u16)val);
++                      out_le16(((u16 __iomem *)hose->cfg_data) + 1,
++                              (u16)(val>>16));
++                      break;
++              }
++      }
++      else
++#endif
++      {
++              if (len != 4) {
++                      value = in_le32(hose->cfg_data);
++
++                      offset = (offset & 0x3) << 3;
++                      mask = (0xffffffff >> (32 - (len << 3)));
++                      mask <<= offset;
++
++                      value &= ~mask;
++                      val = value | ((val << offset) & mask);
++              }
++
++              out_le32(hose->cfg_data, val);
++      }
++      mb();
++
++      out_be32(hose->cfg_addr, 0);
++      mb();
++
++      return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops mpc52xx_pci_ops = {
++      .read  = mpc52xx_pci_read_config,
++      .write = mpc52xx_pci_write_config
++};
++
++
++static void __init
++mpc52xx_pci_setup(struct pci_controller *hose,
++                  struct mpc52xx_pci __iomem *pci_regs)
++{
++      struct resource *res;
++      u32 tmp;
++      int iwcr0 = 0, iwcr1 = 0, iwcr2 = 0;
++
++      pr_debug("mpc52xx_pci_setup()\n");
++
++      pr_debug("iw0btar=%x iw1btar=%x iw2btar=%x iwcr=%x\n",
++               in_be32(&pci_regs->iw0btar), in_be32(&pci_regs->iw1btar),
++               in_be32(&pci_regs->iw2btar), in_be32(&pci_regs->iwcr));
++      pr_debug("tbatr0=%x tbatr1=%x tcr=%x gscr=%x\n",
++               in_be32(&pci_regs->tbatr0), in_be32(&pci_regs->tbatr1),
++               in_be32(&pci_regs->tcr), in_be32(&pci_regs->gscr));
++
++      /* Setup control regs */
++      tmp = in_be32(&pci_regs->scr);
++      tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
++      out_be32(&pci_regs->scr, tmp);
++
++      /* Setup windows */
++      res = &hose->mem_resources[0];
++      if (res->flags) {
++              pr_debug("mem_resource[0] = {.start=%x, .end=%x, .flags=%lx}\n",
++                       res->start, res->end, res->flags);
++              out_be32(&pci_regs->iw0btar,
++                       MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
++                                res->end - res->start + 1));
++              iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
++              if (res->flags & IORESOURCE_PREFETCH)
++                      iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
++              else
++                      iwcr0 |= MPC52xx_PCI_IWCR_READ;
++      }
++
++      res = &hose->mem_resources[1];
++      if (res->flags) {
++              pr_debug("mem_resource[1] = {.start=%x, .end=%x, .flags=%lx}\n",
++                       res->start, res->end, res->flags);
++              out_be32(&pci_regs->iw1btar,
++                       MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
++                                res->end - res->start + 1));
++              iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
++              if (res->flags & IORESOURCE_PREFETCH)
++                      iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
++              else
++                      iwcr1 |= MPC52xx_PCI_IWCR_READ;
++      }
++
++      res = &hose->io_resource;
++      if (!res) {
++              printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__);
++              return;
++      }
++      pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
++               ".io_base_phys=%lx\n",
++               res->start, res->end, res->flags, hose->io_base_phys);
++      out_be32(&pci_regs->iw2btar,
++               MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
++                                              res->start,
++                                              res->end - res->start + 1));
++      iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
++
++      pr_debug("iwcr0=%x iwcr1=%x iwcr2=%x iwcr=%x old_iwcr=%x\n",
++               iwcr0, iwcr1, iwcr2,
++               MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2),
++               in_be32(&pci_regs->iwcr));
++      out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2));
++
++      out_be32(&pci_regs->tbatr0,
++              MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
++      out_be32(&pci_regs->tbatr1,
++              MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
++
++      out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
++
++      /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
++      /* Not necessary and can be a bad thing if for example the bootloader
++         is displaying a splash screen or ... Just left here for
++         documentation purpose if anyone need it */
++      tmp = in_be32(&pci_regs->gscr);
++#if 0
++      out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
++      udelay(50);
++#endif
++      out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
++
++      pr_debug("iw0btar=%x iw1btar=%x iw2btar=%x iwcr=%x\n",
++               in_be32(&pci_regs->iw0btar), in_be32(&pci_regs->iw1btar),
++               in_be32(&pci_regs->iw2btar), in_be32(&pci_regs->iwcr));
++      pr_debug("tbatr0=%x tbatr1=%x tcr=%x gscr=%x\n",
++               in_be32(&pci_regs->tbatr0), in_be32(&pci_regs->tbatr1),
++               in_be32(&pci_regs->tcr), in_be32(&pci_regs->gscr));
++}
++
++static void
++mpc52xx_pci_fixup_resources(struct pci_dev *dev)
++{
++      int i;
++
++      pr_debug("mpc52xx_pci_fixup_resources() %.4x:%.4x\n",
++               dev->vendor, dev->device);
++
++      /* We don't rely on boot loader for PCI and resets all
++         devices */
++      for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++              struct resource *res = &dev->resource[i];
++              if (res->end > res->start) {    /* Only valid resources */
++                      res->end -= res->start;
++                      res->start = 0;
++                      res->flags |= IORESOURCE_UNSET;
++              }
++      }
++
++      /* The PCI Host bridge of MPC52xx has a prefetch memory resource
++         fixed to 1Gb. Doesn't fit in the resource system so we remove it */
++      if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
++           (   dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
++            || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
++              struct resource *res = &dev->resource[1];
++              res->start = res->end = res->flags = 0;
++      }
++}
++
++int __init
++mpc52xx_add_bridge(struct device_node *node)
++{
++      int len;
++      struct mpc52xx_pci __iomem *pci_regs;
++      struct pci_controller *hose;
++      const int *bus_range;
++      struct resource rsrc;
++
++      pr_debug("Adding PCI host bridge %s\n", node->full_name);
++
++      pci_assign_all_buses = 1;
++
++      if (of_address_to_resource(node, 0, &rsrc) != 0) {
++              printk(KERN_ERR "Can't get %s resources\n", node->full_name);
++              return -EINVAL;
++      }
++
++      bus_range = get_property(node, "bus-range", &len);
++      if (bus_range == NULL || len < 2 * sizeof(int)) {
++              printk(KERN_WARNING "Can't get bus-range for %s, assume"
++                      " bus 0\n", node->full_name);
++      }
++
++      hose = pcibios_alloc_controller();
++      if (!hose)
++              return -ENOMEM;
++
++      ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
++
++      hose->arch_data = node;
++      hose->set_cfg_type = 1;
++
++      hose->first_busno = bus_range ? bus_range[0] : 0;
++      hose->last_busno = bus_range ? bus_range[1] : 0xff;
++
++      hose->bus_offset = 0;
++      hose->ops = &mpc52xx_pci_ops;
++
++      pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
++      if (!pci_regs)
++              return -ENOMEM;
++
++      pci_process_bridge_OF_ranges(hose, node, 0);
++
++      hose->cfg_addr = &pci_regs->car;
++
++      hose->cfg_data = hose->io_base_virt;
++      hose->io_base_virt = ioremap(hose->io_base_phys,
++                                   hose->io_resource.end + 1 -
++                                   hose->io_resource.start);
++      isa_io_base = (unsigned long) hose->io_base_virt;
++
++      mpc52xx_pci_setup(hose, pci_regs);
++
++      return 0;
++}
+diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.h b/arch/powerpc/platforms/52xx/mpc52xx_pci.h
+new file mode 100644
+index 0000000..07a659e
+--- /dev/null
++++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.h
+@@ -0,0 +1,104 @@
++/*
++ * PCI Include file the Freescale MPC52xx embedded cpu chips
++ *
++ * Inspired from code written by Dale Farnsworth <dfarnsworth@mvista.com>
++ * for the 2.4 kernel.
++ *
++ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
++ * Copyright (C) 2003 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.
++ */
++
++#ifndef __SYSLIB_MPC52xx_PCI_H__
++#define __SYSLIB_MPC52xx_PCI_H__
++
++/* ======================================================================== */
++/* PCI windows config                                                       */
++/* ======================================================================== */
++
++#define MPC52xx_PCI_TARGET_IO 0xf0000000
++#define MPC52xx_PCI_TARGET_MEM        0x00000000
++
++
++/* ======================================================================== */
++/* Structures mapping & Defines for PCI Unit                                */
++/* ======================================================================== */
++
++#define MPC52xx_PCI_GSCR_BM           0x40000000
++#define MPC52xx_PCI_GSCR_PE           0x20000000
++#define MPC52xx_PCI_GSCR_SE           0x10000000
++#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
++#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT        24
++#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
++#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT        16
++#define MPC52xx_PCI_GSCR_BME          0x00004000
++#define MPC52xx_PCI_GSCR_PEE          0x00002000
++#define MPC52xx_PCI_GSCR_SEE          0x00001000
++#define MPC52xx_PCI_GSCR_PR           0x00000001
++
++
++#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size)     \
++              ( ( (proc_ad) & 0xff000000 )                    | \
++                ( (((size) - 1) >> 8) & 0x00ff0000 )          | \
++                ( ((pci_ad) >> 16) & 0x0000ff00 ) )
++
++#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
++                                               ((win1) << 16) | \
++                                               ((win2) <<  8))
++
++#define MPC52xx_PCI_IWCR_DISABLE      0x0
++#define MPC52xx_PCI_IWCR_ENABLE               0x1
++#define MPC52xx_PCI_IWCR_READ         0x0
++#define MPC52xx_PCI_IWCR_READ_LINE    0x2
++#define MPC52xx_PCI_IWCR_READ_MULTI   0x4
++#define MPC52xx_PCI_IWCR_MEM          0x0
++#define MPC52xx_PCI_IWCR_IO           0x8
++
++#define MPC52xx_PCI_TCR_P             0x01000000
++#define MPC52xx_PCI_TCR_LD            0x00010000
++
++#define MPC52xx_PCI_TBATR_DISABLE     0x0
++#define MPC52xx_PCI_TBATR_ENABLE      0x1
++
++
++#ifndef __ASSEMBLY__
++
++struct mpc52xx_pci {
++      u32     idr;            /* PCI + 0x00 */
++      u32     scr;            /* PCI + 0x04 */
++      u32     ccrir;          /* PCI + 0x08 */
++      u32     cr1;            /* PCI + 0x0C */
++      u32     bar0;           /* PCI + 0x10 */
++      u32     bar1;           /* PCI + 0x14 */
++      u8      reserved1[16];  /* PCI + 0x18 */
++      u32     ccpr;           /* PCI + 0x28 */
++      u32     sid;            /* PCI + 0x2C */
++      u32     erbar;          /* PCI + 0x30 */
++      u32     cpr;            /* PCI + 0x34 */
++      u8      reserved2[4];   /* PCI + 0x38 */
++      u32     cr2;            /* PCI + 0x3C */
++      u8      reserved3[32];  /* PCI + 0x40 */
++      u32     gscr;           /* PCI + 0x60 */
++      u32     tbatr0;         /* PCI + 0x64 */
++      u32     tbatr1;         /* PCI + 0x68 */
++      u32     tcr;            /* PCI + 0x6C */
++      u32     iw0btar;        /* PCI + 0x70 */
++      u32     iw1btar;        /* PCI + 0x74 */
++      u32     iw2btar;        /* PCI + 0x78 */
++      u8      reserved4[4];   /* PCI + 0x7C */
++      u32     iwcr;           /* PCI + 0x80 */
++      u32     icr;            /* PCI + 0x84 */
++      u32     isr;            /* PCI + 0x88 */
++      u32     arb;            /* PCI + 0x8C */
++      u8      reserved5[104]; /* PCI + 0x90 */
++      u32     car;            /* PCI + 0xF8 */
++      u8      reserved6[4];   /* PCI + 0xFC */
++};
++
++#endif  /* __ASSEMBLY__ */
++
++
++#endif  /* __SYSLIB_MPC52xx_PCI_H__ */
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0023-POWERPC-Make-FEC-work-on-the-lite5200.txt b/packages/linux/linux-efika-2.6.20/0023-POWERPC-Make-FEC-work-on-the-lite5200.txt
new file mode 100644 (file)
index 0000000..bdbafcb
--- /dev/null
@@ -0,0 +1,700 @@
+From 3c687b616fee5d7097e965fce80f8f8b2b6e14cf Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Mon, 4 Dec 2006 22:29:03 -0700
+Subject: [PATCH] [POWERPC] Make FEC work on the lite5200
+
+This patch may very well break Eth support on the Efika, and it's not
+very pretty.  But is works well enough for an NFS rootfs.  This also
+makes major bestcomm changes by removing Efika-specific bestcomm
+support and porting the arch/ppc bestcomm support driver which
+was posted to linuxppc-embedded about a year ago.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ arch/powerpc/Kconfig                   |    5 +
+ arch/powerpc/platforms/52xx/Makefile   |    3 +
+ arch/powerpc/platforms/52xx/bestcomm.c |   98 ++++++++++-------------
+ arch/powerpc/platforms/52xx/bestcomm.h |   13 ++-
+ arch/powerpc/platforms/52xx/fec.c      |    1 -
+ arch/powerpc/platforms/52xx/lite5200.c |    9 ++
+ drivers/net/fec_mpc52xx/Kconfig        |    2 +-
+ drivers/net/fec_mpc52xx/fec.c          |  137 +++++++++++++++++++++++++++----
+ drivers/net/fec_mpc52xx/fec_phy.c      |    6 ++
+ 9 files changed, 196 insertions(+), 78 deletions(-)
+
+diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
+index 8699dad..23d7d73 100644
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -429,6 +429,11 @@ config PPC_MPC52xx
+       bool
+       default n
++config PPC_BESTCOMM
++      bool
++      depends on PPC_MPC52xx
++      default y
++
+ config PPC_EFIKA
+       bool "bPlan Efika 5k2. MPC5200B based computer"
+       depends on PPC_MULTIPLATFORM && PPC32
+diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
+index a46184a..d85ea04 100644
+--- a/arch/powerpc/platforms/52xx/Makefile
++++ b/arch/powerpc/platforms/52xx/Makefile
+@@ -3,6 +3,9 @@
+ #
+ ifeq ($(CONFIG_PPC_MERGE),y)
+ obj-y                         += mpc52xx_pic.o mpc52xx_common.o
++obj-$(CONFIG_PCI)             += mpc52xx_pci.o
++obj-$(CONFIG_PPC_BESTCOMM)    += bestcomm.o
++obj-$(CONFIG_FEC_MPC52xx)     += sdma_fec_rx_task.o sdma_fec_tx_task.o fec.o
+ endif
+ obj-$(CONFIG_PPC_EFIKA)               += efika-setup.o efika-pci.o
+diff --git a/arch/powerpc/platforms/52xx/bestcomm.c b/arch/powerpc/platforms/52xx/bestcomm.c
+index ef45e02..9935b01 100644
+--- a/arch/powerpc/platforms/52xx/bestcomm.c
++++ b/arch/powerpc/platforms/52xx/bestcomm.c
+@@ -16,7 +16,6 @@
+  *            Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
+  */
+-#include <linux/config.h>
+ #include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+@@ -24,17 +23,19 @@
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+ #include <linux/string.h>
+-#include <linux/device.h>
+ #include <asm/bug.h>
+ #include <asm/io.h>
+ #include <asm/mpc52xx.h>
++#include <asm/of_platform.h>
+ #include "bestcomm.h"
+-#define DRIVER_NAME           "mpc52xx-sdma"
++#define DRIVER_NAME "mpc52xx-bestcomm"
+ struct sdma_io sdma;
++struct device_node *sdma_node;
++struct device_node *sram_node;
+ static spinlock_t sdma_lock = SPIN_LOCK_UNLOCKED;
+@@ -42,7 +43,8 @@ static spinlock_t sdma_lock = SPIN_LOCK_UNLOCKED;
+ void sdma_dump(void)
+ {
+       int i;
+-      printk("** SDMA registers: pa = %08x, va = %08x\n", sdma.base_reg_addr, sdma.io);
++      printk("** SDMA registers: pa = %.8lx, va = %p\n",
++             sdma.base_reg_addr, sdma.io);
+       printk("**  taskBar = %08x\n", sdma.io->taskBar);
+       printk("**  currentPointer = %08x\n", sdma.io->currentPointer);
+       printk("**  endPointer = %08x\n", sdma.io->endPointer);
+@@ -254,6 +256,7 @@ struct sdma *sdma_alloc(int queue_size)
+       }
+       s->num_bd = queue_size;
++      s->node = sdma_node;
+       return s;
+ }
+@@ -264,29 +267,49 @@ void sdma_free(struct sdma *s)
+       kfree(s);
+ }
+-static int __devinit mpc52xx_sdma_probe(struct device *dev)
++static int __init mpc52xx_sdma_init(void)
+ {
+-      struct platform_device *pdev = to_platform_device(dev);
+       int task;
+       u32 *context;
+       u32 *fdt;
+       struct sdma_tdt *tdt;
+-      struct resource *mem_io, *mem_sram;
+-      u32 tdt_pa, var_pa, context_pa, fdt_pa; 
++      struct resource mem_io, mem_sram;
++      u32 tdt_pa, var_pa, context_pa, fdt_pa;
+       int ret = -ENODEV;
+-      mem_io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      mem_sram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+-      if (!mem_io || !mem_sram)
++      /* Find SDMA registers */
++      sdma_node = of_find_compatible_node(NULL, "dma-controller", "mpc52xx-bestcomm");
++      if (!sdma_node) {
++              printk (KERN_ERR DRIVER_NAME ": could not locate SDRAM controller\n");
+               goto out;
++      }
++
++      if ((ret = of_address_to_resource(sdma_node, 0, &mem_io)) != 0) {
++              printk(KERN_ERR "Could not get address of SDMA controller\n");
++              goto out;
++      }
++
++      /* Find SRAM location */
++      sram_node = of_find_compatible_node(NULL, "sram", "mpc52xx-sram");
++      if (!sram_node) {
++              printk (KERN_ERR DRIVER_NAME ": could not locate SRAM\n");
++              goto out;
++      }
++
++      if ((ret = of_address_to_resource(sram_node, 0, &mem_sram)) != 0) {
++              printk(KERN_ERR "Could not get address of SRAM\n");
++              goto out;
++      }
+-      if (!request_mem_region(mem_io->start, mem_io->end - mem_io->start + 1, DRIVER_NAME)) {
++      /* Map register regions */
++      if (!request_mem_region(mem_io.start, mem_io.end - mem_io.start + 1,
++                              DRIVER_NAME)) {
+               printk(KERN_ERR DRIVER_NAME " - resource unavailable\n");
+               goto out;
+       }
+-      sdma.base_reg_addr = mem_io->start;
++      sdma.base_reg_addr = mem_io.start;
+-      sdma.io = ioremap_nocache(mem_io->start, sizeof(struct mpc52xx_sdma));
++      sdma.io = ioremap_nocache(mem_io.start, sizeof(struct mpc52xx_sdma));
+       if (!sdma.io ) {
+               printk(KERN_ERR DRIVER_NAME " - failed to map sdma regs\n");
+@@ -296,14 +319,14 @@ static int __devinit mpc52xx_sdma_probe(struct device *dev)
+       SDMA_DUMP_REGS();
+-      sdma.sram_size = mem_sram->end - mem_sram->start + 1;
+-      if (!request_mem_region(mem_sram->start, sdma.sram_size, DRIVER_NAME)) {
++      sdma.sram_size = mem_sram.end - mem_sram.start + 1;
++      if (!request_mem_region(mem_sram.start, sdma.sram_size, DRIVER_NAME)) {
+               printk(KERN_ERR DRIVER_NAME " - resource unavailable\n");
+               goto req_sram_error;
+       }
+-      sdma.base_sram_addr = mem_sram->start;
+-      sdma.sram = ioremap_nocache(mem_sram->start, sdma.sram_size);
++      sdma.base_sram_addr = mem_sram.start;
++      sdma.sram = ioremap_nocache(mem_sram.start, sdma.sram_size);
+       if (!sdma.sram ) {
+               printk(KERN_ERR DRIVER_NAME " - failed to map sdma sram\n");
+               ret = -ENOMEM;
+@@ -350,50 +373,17 @@ static int __devinit mpc52xx_sdma_probe(struct device *dev)
+       return 0;
+ map_sram_error:
+-      release_mem_region(mem_sram->start, sdma.sram_size);
++      release_mem_region(mem_sram.start, sdma.sram_size);
+ req_sram_error:
+       iounmap(sdma.io);
+ map_io_error:
+-      release_mem_region(mem_io->start, mem_io->end - mem_io->start + 1);
++      release_mem_region(mem_io.start, mem_io.end - mem_io.start + 1);
+ out:
+       printk(KERN_ERR "DMA: MPC52xx BestComm init FAILED !!!\n");
+       return ret;
+ }
+-
+-static struct device_driver mpc52xx_sdma_driver = {
+-      .owner    = THIS_MODULE,
+-      .name     = DRIVER_NAME,
+-      .bus      = &platform_bus_type,
+-      .probe    = mpc52xx_sdma_probe,
+-/*    .remove   = mpc52xx_sdma_remove,        TODO */
+-#ifdef CONFIG_PM
+-/*    .suspend        = mpc52xx_sdma_suspend, TODO */
+-/*    .resume         = mpc52xx_sdma_resume,  TODO */
+-#endif
+-};
+-
+-static int __init
+-mpc52xx_sdma_init(void)
+-{
+-      printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
+-      return driver_register(&mpc52xx_sdma_driver);
+-}
+-
+-#ifdef MODULE
+-static void __exit
+-mpc52xx_sdma_exit(void)
+-{
+-      driver_unregister(&mpc52xx_sdma_driver);
+-}
+-#endif
+-
+-#ifndef MODULE
+- subsys_initcall(mpc52xx_sdma_init);
+-#else
+- module_init(mpc52xx_sdma_init);
+- module_exit(mpc52xx_sdma_exit);
+-#endif
++subsys_initcall(mpc52xx_sdma_init);
+ MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
+diff --git a/arch/powerpc/platforms/52xx/bestcomm.h b/arch/powerpc/platforms/52xx/bestcomm.h
+index 14bf397..bd2619d 100644
+--- a/arch/powerpc/platforms/52xx/bestcomm.h
++++ b/arch/powerpc/platforms/52xx/bestcomm.h
+@@ -19,6 +19,8 @@
+ #ifndef __BESTCOMM_BESTCOMM_H__
+ #define __BESTCOMM_BESTCOMM_H__
++#include "mpc52xx_pic.h"
++
+ /* Buffer Descriptor definitions */
+ struct sdma_bd {
+       u32 status;
+@@ -70,6 +72,7 @@ struct sdma {
+       u16 num_bd;
+       s16 tasknum;
+       u32 flags;
++      struct device_node *node;
+ };
+ #define SDMA_FLAGS_NONE               0x0000
+@@ -116,7 +119,9 @@ struct sdma_tdt {
+ static inline void sdma_enable_task(int task)
+ {
+-      DPRINTK("***DMA enable task (%d): tdt = %08x\n",task, sdma.tdt);
++      u16 reg;
++
++      DPRINTK("***DMA enable task (%d): tdt = %p\n",task, sdma.tdt);
+       DPRINTK("***tdt->start   = %08x\n",sdma.tdt[task].start);
+       DPRINTK("***tdt->stop    = %08x\n",sdma.tdt[task].stop);
+       DPRINTK("***tdt->var     = %08x\n",sdma.tdt[task].var);
+@@ -127,8 +132,8 @@ static inline void sdma_enable_task(int task)
+       DPRINTK("***tdt->litbase = %08x\n",sdma.tdt[task].litbase);
+       DPRINTK("***--------------\n");
+-      u16 reg = in_be16(&sdma.io->tcr[task]);
+-      DPRINTK("***enable task: &sdma.io->tcr=%08x, reg = %04x\n", &sdma.io->tcr, reg);
++      reg = in_be16(&sdma.io->tcr[task]);
++      DPRINTK("***enable task: &sdma.io->tcr=%p, reg = %04x\n", &sdma.io->tcr, reg);
+       out_be16(&sdma.io->tcr[task],  reg | TASK_ENABLE);
+ }
+@@ -141,7 +146,7 @@ static inline void sdma_disable_task(int task)
+ static inline int sdma_irq(struct sdma *s)
+ {
+-      return MPC52xx_SDMA_IRQ_BASE + s->tasknum;
++      return irq_of_parse_and_map(s->node, s->tasknum);
+ }
+ static inline void sdma_enable(struct sdma *s)
+diff --git a/arch/powerpc/platforms/52xx/fec.c b/arch/powerpc/platforms/52xx/fec.c
+index 8756856..90df6f4 100644
+--- a/arch/powerpc/platforms/52xx/fec.c
++++ b/arch/powerpc/platforms/52xx/fec.c
+@@ -16,7 +16,6 @@
+  *            Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
+  */
+-#include <linux/config.h>
+ #include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
+index 0f21bab..f1bbe24 100644
+--- a/arch/powerpc/platforms/52xx/lite5200.c
++++ b/arch/powerpc/platforms/52xx/lite5200.c
+@@ -107,6 +107,15 @@ static void __init lite52xx_setup_arch(void)
+       mpc52xx_setup_cpu();    /* Generic */
+       lite52xx_setup_cpu();   /* Platorm specific */
++#ifdef CONFIG_PCI
++      np = of_find_node_by_type(np, "pci");
++      if (np)
++              mpc52xx_add_bridge(np);
++
++      //ppc_md.pci_swizzle = common_swizzle;
++      //ppc_md.pci_exclude_device = mpc52xx_exclude_device;
++#endif
++
+ #ifdef CONFIG_BLK_DEV_INITRD
+       if (initrd_start)
+               ROOT_DEV = Root_RAM0;
+diff --git a/drivers/net/fec_mpc52xx/Kconfig b/drivers/net/fec_mpc52xx/Kconfig
+index 098c3fa..b6bce55 100644
+--- a/drivers/net/fec_mpc52xx/Kconfig
++++ b/drivers/net/fec_mpc52xx/Kconfig
+@@ -11,7 +11,7 @@ config FEC_MPC52xx
+         Fast Ethernet Controller
+ config USE_MDIO
+-      bool "  Use external Ethernet MII PHY"
++      bool "Use external Ethernet MII PHY"
+       select MII
+       depends FEC_MPC52xx
+       ---help---
+diff --git a/drivers/net/fec_mpc52xx/fec.c b/drivers/net/fec_mpc52xx/fec.c
+index b5f1559..894da79 100644
+--- a/drivers/net/fec_mpc52xx/fec.c
++++ b/drivers/net/fec_mpc52xx/fec.c
+@@ -30,17 +30,24 @@
+ #include <asm/ppcboot.h>
+ #include <asm/mpc52xx.h>
++#if defined(CONFIG_PPC_MERGE)
++#include <asm/of_device.h>
++#include <asm/of_platform.h>
++#include <platforms/52xx/bestcomm.h>
++#include <platforms/52xx/fec.h>
++#else
+ #include <syslib/bestcomm/bestcomm.h>
+ #include <syslib/bestcomm/fec.h>
++#endif
+ #include "fec_phy.h"
+ #include "fec.h"
+ #define DRIVER_NAME "mpc52xx-fec"
+-static irqreturn_t fec_interrupt(int, void *, struct pt_regs *);
+-static irqreturn_t fec_rx_interrupt(int, void *, struct pt_regs *);
+-static irqreturn_t fec_tx_interrupt(int, void *, struct pt_regs *);
++static irqreturn_t fec_interrupt(int, void *);
++static irqreturn_t fec_rx_interrupt(int, void *);
++static irqreturn_t fec_tx_interrupt(int, void *);
+ static struct net_device_stats *fec_get_stats(struct net_device *);
+ static void fec_set_multicast_list(struct net_device *dev);
+ static void fec_reinit(struct net_device *dev);
+@@ -233,7 +240,7 @@ static int fec_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ /* This handles BestComm transmit task interrupts
+  */
+-static irqreturn_t fec_tx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++static irqreturn_t fec_tx_interrupt(int irq, void *dev_id)
+ {
+       struct net_device *dev = dev_id;
+       struct fec_priv *priv = (struct fec_priv *)dev->priv;
+@@ -259,7 +266,7 @@ static irqreturn_t fec_tx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+       return IRQ_HANDLED;
+ }
+-static irqreturn_t fec_rx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++static irqreturn_t fec_rx_interrupt(int irq, void *dev_id)
+ {
+       struct net_device *dev = dev_id;
+       struct fec_priv *priv = (struct fec_priv *)dev->priv;
+@@ -316,7 +323,7 @@ static irqreturn_t fec_rx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+       return IRQ_HANDLED;
+ }
+-static irqreturn_t fec_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++static irqreturn_t fec_interrupt(int irq, void *dev_id)
+ {
+       struct net_device *dev = (struct net_device *)dev_id;
+       struct fec_priv *priv = (struct fec_priv *)dev->priv;
+@@ -324,13 +331,18 @@ static irqreturn_t fec_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+       int ievent;
+       ievent = in_be32(&fec->ievent);
++      if (!ievent)
++              return IRQ_NONE;
++
+       out_be32(&fec->ievent, ievent);         /* clear pending events */
+       if (ievent & (FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
+-              if (ievent & FEC_IEVENT_RFIFO_ERROR)
+-                      printk(KERN_WARNING "FEC_IEVENT_RFIFO_ERROR\n");
+-              if (ievent & FEC_IEVENT_XFIFO_ERROR)
+-                      printk(KERN_WARNING "FEC_IEVENT_XFIFO_ERROR\n");
++              if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR))
++                      printk(KERN_WARNING "FEC_IEVENT_RFIFO_ERROR (%.8x)\n",
++                             ievent);
++              if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
++                      printk(KERN_WARNING "FEC_IEVENT_XFIFO_ERROR (%.8x)\n",
++                             ievent);
+               fec_reinit(dev);
+       }
+       else if (ievent & FEC_IEVENT_MII)
+@@ -495,7 +507,9 @@ static void fec_hw_init(struct net_device *dev)
+ {
+       struct fec_priv *priv = (struct fec_priv *)dev->priv;
+       struct mpc52xx_fec *fec = priv->fec;
++#if !defined(CONFIG_PPC_MERGE)
+       bd_t *bd = (bd_t *) &__res;
++#endif
+       out_be32(&fec->op_pause, 0x00010020);
+       out_be32(&fec->rfifo_cntrl, 0x0f000000);
+@@ -507,7 +521,9 @@ static void fec_hw_init(struct net_device *dev)
+       out_be32(&fec->iaddr1, 0x00000000);     /* No individual filter */
+       out_be32(&fec->iaddr2, 0x00000000);     /* No individual filter */
++#if !defined(CONFIG_PPC_MERGE)
+       priv->phy_speed = ((bd->bi_ipbfreq >> 20) / 5) << 1;
++#endif
+       fec_restart(dev, 0);    /* always use half duplex mode only */
+       /*
+@@ -522,7 +538,6 @@ static void fec_reinit(struct net_device *dev)
+ {
+       struct fec_priv *priv = (struct fec_priv *)dev->priv;
+       struct mpc52xx_fec *fec = priv->fec;
+-      static void fec_update_stat(struct net_device *);
+       netif_stop_queue(dev);
+       out_be32(&fec->imask, 0x0);
+@@ -551,19 +566,38 @@ static void fec_reinit(struct net_device *dev)
+ /* Platform Driver                                                               */
+ /* ======================================================================== */
++#if defined(CONFIG_PPC_MERGE)
++static int __devinit
++mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
++#else
+ static int __devinit
+ mpc52xx_fec_probe(struct device *dev)
++#endif
+ {
+       int ret;
++#if defined(CONFIG_PPC_MERGE)
++      int rv;
++      struct resource __mem;
++      struct resource *mem = &__mem;
++#else
+       struct platform_device *pdev = to_platform_device(dev);
++      struct resource *mem;
++#endif
+       struct net_device *ndev;
+       struct fec_priv *priv = NULL;
+-      struct resource *mem;
+       volatile int dbg=0;
+       while(dbg)
+               __asm("nop");
+       /* Reserve FEC control zone */
++#if defined(CONFIG_PPC_MERGE)
++      rv = of_address_to_resource(op->node, 0, mem);
++      if (rv) {
++              printk(KERN_ERR DRIVER_NAME ": "
++                      "Error while parsing device node resource\n" );
++              return rv;
++      }
++#else
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if ((mem->end - mem->start + 1) != sizeof(struct mpc52xx_fec)) {
+               printk(KERN_ERR DRIVER_NAME 
+@@ -571,7 +605,8 @@ mpc52xx_fec_probe(struct device *dev)
+                                                                       mem->end - mem->start + 1, sizeof(struct mpc52xx_fec));
+               return -EINVAL;
+       }
+-      
++#endif
++
+       if (!request_mem_region(mem->start, sizeof(struct mpc52xx_fec),
+                               DRIVER_NAME))
+               return -EBUSY;
+@@ -579,6 +614,8 @@ mpc52xx_fec_probe(struct device *dev)
+       /* Get the ether ndev & it's private zone */
+       ndev = alloc_etherdev(sizeof(struct fec_priv));
+       if (!ndev) {
++              printk(KERN_ERR DRIVER_NAME ": "
++                      "Can not allocate the ethernet device\n" );
+               ret = -ENOMEM;
+               goto probe_error;
+       }
+@@ -609,6 +646,8 @@ mpc52xx_fec_probe(struct device *dev)
+               ioremap(mem->start, sizeof(struct mpc52xx_fec));
+       
+       if (!priv->fec) {
++              printk(KERN_ERR DRIVER_NAME ": "
++                      "Can not remap IO memory at 0x%8.8x\n", mem->start );
+               ret = -ENOMEM;
+               goto probe_error;
+       }
+@@ -618,6 +657,8 @@ mpc52xx_fec_probe(struct device *dev)
+       priv->tx_sdma = sdma_alloc(FEC_TX_NUM_BD);
+       
+       if (!priv->rx_sdma || !priv->tx_sdma) {
++              printk(KERN_ERR DRIVER_NAME ": "
++                      "Can not init SDMA tasks\n" );
+               ret = -ENOMEM;
+               goto probe_error;
+       }
+@@ -631,8 +672,13 @@ mpc52xx_fec_probe(struct device *dev)
+               goto probe_error;
+       /* Get the IRQ we need one by one */
+-              /* Control */
++      /* Control */
++#if defined(CONFIG_PPC_MERGE)
++      ndev->irq = irq_of_parse_and_map(op->node, 0);
++#else
+       ndev->irq = platform_get_irq(pdev, 0);
++#endif
++
+       if (request_irq(ndev->irq, &fec_interrupt, SA_INTERRUPT,
+                       DRIVER_NAME "_ctrl", ndev)) {
+               printk(KERN_ERR DRIVER_NAME ": ctrl interrupt request failed\n");
+@@ -641,26 +687,32 @@ mpc52xx_fec_probe(struct device *dev)
+               goto probe_error;
+       }
+-              /* RX */
++      /* RX */
+       priv->r_irq = sdma_irq(priv->rx_sdma);
+       if (request_irq(priv->r_irq, &fec_rx_interrupt, SA_INTERRUPT,
+                       DRIVER_NAME "_rx", ndev)) {
+-              printk(KERN_ERR DRIVER_NAME ": rx interrupt request failed\n");
++              printk(KERN_ERR DRIVER_NAME ": rx request_irq(0x%x) failed\n",
++                     priv->r_irq);
+               ret = -EBUSY;
+               priv->r_irq = -1;       /* Don't try to free it */
+               goto probe_error;
+       }
+-              /* TX */
++      /* TX */
+       priv->t_irq = sdma_irq(priv->tx_sdma);
+       if (request_irq(priv->t_irq, &fec_tx_interrupt, SA_INTERRUPT,
+                       DRIVER_NAME "_tx", ndev)) {
+-              printk(KERN_ERR DRIVER_NAME ": tx interrupt request failed\n");
++              printk(KERN_ERR DRIVER_NAME ": tx request_irq(0x%x) failed\n",
++                     priv->t_irq);
+               ret = -EBUSY;
+               priv->t_irq = -1;       /* Don't try to free it */
+               goto probe_error;
+       }
++#if defined(CONFIG_PPC_MERGE)
++      priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1;
++#endif
++
+       /* MAC address init */
+       if (memcmp(mpc52xx_fec_mac_addr, null_mac, 6) != 0)
+               memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6);
+@@ -679,7 +731,11 @@ mpc52xx_fec_probe(struct device *dev)
+       fec_mii_init(ndev);
+       
+       /* We're done ! */
++#if defined(CONFIG_PPC_MERGE)
++      dev_set_drvdata(&op->dev, ndev);
++#else
+       dev_set_drvdata(dev, ndev);
++#endif
+       return 0;
+@@ -705,13 +761,22 @@ probe_error:
+       return ret;
+ }
++#if defined(CONFIG_PPC_MERGE)
++static int
++mpc52xx_fec_remove(struct of_device *op)
++#else
+ static int
+ mpc52xx_fec_remove(struct device *dev)
++#endif
+ {
+       struct net_device *ndev;
+       struct fec_priv *priv;
+       
++#if defined(CONFIG_PPC_MERGE)
++      ndev = (struct net_device *) dev_get_drvdata(&op->dev);
++#else
+       ndev = (struct net_device *) dev_get_drvdata(dev);
++#endif
+       if (!ndev)
+               return 0;
+       priv = (struct fec_priv *) ndev->priv;
+@@ -728,10 +793,37 @@ mpc52xx_fec_remove(struct device *dev)
+       free_netdev(ndev);
+       
++#if defined(CONFIG_PPC_MERGE)
++      dev_set_drvdata(&op->dev, NULL);
++#else
+       dev_set_drvdata(dev, NULL);
++#endif
+       return 0;
+ }
++#if defined(CONFIG_PPC_MERGE)
++static struct of_device_id mpc52xx_fec_of_match[] = {
++      { .compatible = "mpc5200-ethernet", },
++      { .compatible = "mpc52xx-fec", },
++      {},
++};
++
++static struct of_platform_driver mpc52xx_fec_driver = {
++      .name = DRIVER_NAME,
++      .owner = THIS_MODULE,
++      .match_table = mpc52xx_fec_of_match,
++      .probe = mpc52xx_fec_probe,
++      .remove = mpc52xx_fec_remove,
++#ifdef CONFIG_PM
++/*    .suspend = mpc52xx_fec_suspend, TODO */
++/*    .resume = mpc52xx_fec_resume, TODO */
++#endif
++      .driver = {
++              .name = DRIVER_NAME,
++              .owner = THIS_MODULE,
++      },
++};
++#else
+ static struct device_driver mpc52xx_fec_driver = {
+       .name     = DRIVER_NAME,
+       .bus            = &platform_bus_type,
+@@ -742,6 +834,7 @@ static struct device_driver mpc52xx_fec_driver = {
+ /*    .resume         = mpc52xx_fec_resume,   TODO */
+ #endif
+ };
++#endif
+ /* ======================================================================== */
+ /* Module                                                                   */
+@@ -750,13 +843,21 @@ static struct device_driver mpc52xx_fec_driver = {
+ static int __init
+ mpc52xx_fec_init(void)
+ {
++#if defined(CONFIG_PPC_MERGE)
++      return of_register_platform_driver(&mpc52xx_fec_driver);
++#else
+       return driver_register(&mpc52xx_fec_driver);
++#endif
+ }
+ static void __exit
+ mpc52xx_fec_exit(void)
+ {
++#if defined(CONFIG_PPC_MERGE)
++      of_unregister_platform_driver(&mpc52xx_fec_driver);
++#else
+       driver_unregister(&mpc52xx_fec_driver);
++#endif
+ }
+diff --git a/drivers/net/fec_mpc52xx/fec_phy.c b/drivers/net/fec_mpc52xx/fec_phy.c
+index 2a287de..25e0409 100644
+--- a/drivers/net/fec_mpc52xx/fec_phy.c
++++ b/drivers/net/fec_mpc52xx/fec_phy.c
+@@ -20,8 +20,14 @@
+ #include <linux/mii.h>
+ #include <asm/io.h>
+ #include <asm/mpc52xx.h>
++
++#ifdef CONFIG_PPC_MERGE
++#include <platforms/52xx/bestcomm.h>
++#else
+ #include <syslib/bestcomm/bestcomm.h>
+ #include <syslib/bestcomm/fec.h>
++#endif
++
+ #include "fec_phy.h"
+ #include "fec.h"
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0024-Add-missing-function-prototype.txt b/packages/linux/linux-efika-2.6.20/0024-Add-missing-function-prototype.txt
new file mode 100644 (file)
index 0000000..2fb1a49
--- /dev/null
@@ -0,0 +1,26 @@
+From 4ad1395745f590eba1b5220c8dd3ca6541f49db7 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Mon, 4 Dec 2006 22:55:49 -0700
+Subject: [PATCH] Add missing function prototype
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ include/asm-powerpc/mpc52xx.h |    2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
+
+diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
+index 4560d72..7afd5bf 100644
+--- a/include/asm-powerpc/mpc52xx.h
++++ b/include/asm-powerpc/mpc52xx.h
+@@ -249,6 +249,8 @@ extern void mpc52xx_declare_of_platform_devices(void);
+ extern void mpc52xx_init_irq(void);
+ extern unsigned int mpc52xx_get_irq(void);
++extern int __init mpc52xx_add_bridge(struct device_node *node);
++
+ #endif /* __ASSEMBLY__ */
+ #endif /* __ASM_POWERPC_MPC52xx_H__ */
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0025-POWERPC-Misc-EFIKA-fixups-for-rtas-chrp.txt b/packages/linux/linux-efika-2.6.20/0025-POWERPC-Misc-EFIKA-fixups-for-rtas-chrp.txt
new file mode 100644 (file)
index 0000000..8f39c3a
--- /dev/null
@@ -0,0 +1,133 @@
+From 95f80c44731c46261b0ba334b35ee803f21ef60b Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Mon, 4 Dec 2006 23:01:13 -0700
+Subject: [PATCH] [POWERPC] Misc EFIKA fixups for rtas/chrp
+
+---
+ arch/powerpc/kernel/proc_ppc64.c    |    9 --------
+ arch/powerpc/kernel/rtas-proc.c     |   36 +++++++++++++++++++++++++---------
+ arch/powerpc/platforms/chrp/setup.c |    9 ++++++++
+ 3 files changed, 35 insertions(+), 19 deletions(-)
+
+diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
+index dd7001c..fa54220 100644
+--- a/arch/powerpc/kernel/proc_ppc64.c
++++ b/arch/powerpc/kernel/proc_ppc64.c
+@@ -51,15 +51,6 @@ static int __init proc_ppc64_create(void)
+       if (!root)
+               return 1;
+-      if (!of_find_node_by_path("/rtas"))
+-              return 0;
+-
+-      if (!proc_mkdir("rtas", root))
+-              return 1;
+-
+-      if (!proc_symlink("rtas", NULL, "ppc64/rtas"))
+-              return 1;
+-
+       return 0;
+ }
+ core_initcall(proc_ppc64_create);
+diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
+index 2fe82ab..4c06c32 100644
+--- a/arch/powerpc/kernel/rtas-proc.c
++++ b/arch/powerpc/kernel/rtas-proc.c
+@@ -253,43 +253,59 @@ static void get_location_code(struct seq_file *m,
+ static void check_location_string(struct seq_file *m, const char *c);
+ static void check_location(struct seq_file *m, const char *c);
++static int __init proc_rtas_create(void)
++{
++        struct proc_dir_entry *root;
++
++        root = proc_mkdir("rtas" , NULL);
++        if (!root)
++                return -1;
++
++#ifdef CONFIG_PPC64
++        if (!proc_symlink("rtas", NULL, "ppc64/rtas"))
++                return -1;
++#endif
++
++        return 0;
++}
++
+ static int __init proc_rtas_init(void)
+ {
+       struct proc_dir_entry *entry;
+-      if (!machine_is(pseries))
+-              return -ENODEV;
+-
+       rtas_node = of_find_node_by_name(NULL, "rtas");
+       if (rtas_node == NULL)
+               return -ENODEV;
+-      entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL);
++      if (proc_rtas_create() != 0)
++              return -ENODEV;
++
++      entry = create_proc_entry("rtas/progress", S_IRUGO|S_IWUSR, NULL);
+       if (entry)
+               entry->proc_fops = &ppc_rtas_progress_operations;
+-      entry = create_proc_entry("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL);
++      entry = create_proc_entry("rtas/clock", S_IRUGO|S_IWUSR, NULL);
+       if (entry)
+               entry->proc_fops = &ppc_rtas_clock_operations;
+-      entry = create_proc_entry("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL);
++      entry = create_proc_entry("rtas/poweron", S_IWUSR|S_IRUGO, NULL);
+       if (entry)
+               entry->proc_fops = &ppc_rtas_poweron_operations;
+-      entry = create_proc_entry("ppc64/rtas/sensors", S_IRUGO, NULL);
++      entry = create_proc_entry("rtas/sensors", S_IRUGO, NULL);
+       if (entry)
+               entry->proc_fops = &ppc_rtas_sensors_operations;
+-      entry = create_proc_entry("ppc64/rtas/frequency", S_IWUSR|S_IRUGO,
++      entry = create_proc_entry("rtas/frequency", S_IWUSR|S_IRUGO,
+                                 NULL);
+       if (entry)
+               entry->proc_fops = &ppc_rtas_tone_freq_operations;
+-      entry = create_proc_entry("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL);
++      entry = create_proc_entry("rtas/volume", S_IWUSR|S_IRUGO, NULL);
+       if (entry)
+               entry->proc_fops = &ppc_rtas_tone_volume_operations;
+-      entry = create_proc_entry("ppc64/rtas/rmo_buffer", S_IRUSR, NULL);
++      entry = create_proc_entry("rtas/rmo_buffer", S_IRUSR, NULL);
+       if (entry)
+               entry->proc_fops = &ppc_rtas_rmo_buf_ops;
+diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
+index e1f51d4..ec4515c 100644
+--- a/arch/powerpc/platforms/chrp/setup.c
++++ b/arch/powerpc/platforms/chrp/setup.c
+@@ -580,11 +580,20 @@ static int __init chrp_probe(void)
+ {
+       char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
+                                         "device_type", NULL);
++
++      char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
++                                        "model", NULL);
+       if (dtype == NULL)
+               return 0;
+       if (strcmp(dtype, "chrp"))
+               return 0;
++      /*
++       * Filter out efika because it has its own platform
++      */
++      if (model && (strcmp(model, "EFIKA5K2") == 0) )
++              return 0;
++
+       ISA_DMA_THRESHOLD = ~0L;
+       DMA_MODE_READ = 0x44;
+       DMA_MODE_WRITE = 0x48;
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0026-POWERPC-Cleanup-mpc52xx-PCI-support.txt b/packages/linux/linux-efika-2.6.20/0026-POWERPC-Cleanup-mpc52xx-PCI-support.txt
new file mode 100644 (file)
index 0000000..3119060
--- /dev/null
@@ -0,0 +1,911 @@
+From 78aaa3476bf62a50d85a9753bf1ef82fd296ca73 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Mon, 11 Dec 2006 22:41:49 -0700
+Subject: [PATCH] [POWERPC] Cleanup mpc52xx PCI support
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ arch/powerpc/Kconfig                      |   17 ++-
+ arch/powerpc/platforms/52xx/mpc52xx_pci.c |  334 ------------------------
+ arch/powerpc/platforms/52xx/mpc52xx_pci.h |  104 --------
+ arch/powerpc/platforms/52xx/pci.c         |  404 +++++++++++++++++++++++++++++
+ 4 files changed, 420 insertions(+), 439 deletions(-)
+
+diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
+index 23d7d73..ec17225 100644
+--- a/arch/powerpc/Kconfig
++++ b/arch/powerpc/Kconfig
+@@ -429,6 +429,21 @@ config PPC_MPC52xx
+       bool
+       default n
++config PPC_MPC5200
++      bool
++      select PPC_MPC52xx
++      default n
++
++config PPC_MPC5200_BUGFIX
++      bool "MPC5200 (L25R) bugfix support"
++      depends on PPC_MPC5200
++      default n
++      help
++        Enable workarounds for original MPC5200 errata.  This is not required
++        for MPC5200B based boards.
++
++        It is safe to say 'Y' here
++
+ config PPC_BESTCOMM
+       bool
+       depends on PPC_MPC52xx
+@@ -446,7 +461,7 @@ config PPC_EFIKA
+ config PPC_LITE5200
+       bool "Freescale Lite5200 Eval Board"
+       depends on PPC_MULTIPLATFORM && PPC32
+-      select PPC_MPC52xx
++      select PPC_MPC5200
+       default n
+ config PPC_PMAC
+diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+deleted file mode 100644
+index 07dce3c..0000000
+--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
++++ /dev/null
+@@ -1,334 +0,0 @@
+-/*
+- * PCI code for the Freescale MPC52xx embedded CPU.
+- *
+- * Copyright (C) 2004 Secret Lab Technologies Ltd.
+- *                        Grant Likely <grant.likely@secretlab.ca>
+- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+- *
+- * 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.
+- */
+-
+-#define DEBUG
+-
+-#include <asm/pci.h>
+-#include <asm/mpc52xx.h>
+-#include "mpc52xx_pci.h"
+-#include <asm/delay.h>
+-#include <asm/machdep.h>
+-#include <linux/kernel.h>
+-
+-
+-/* This macro is defined to activate the workaround for the bug
+-   435 of the MPC5200 (L25R). With it activated, we don't do any
+-   32 bits configuration access during type-1 cycles */
+-#define MPC5200_BUG_435_WORKAROUND
+-
+-
+-static int
+-mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+-                              int offset, int len, u32 *val)
+-{
+-      struct pci_controller *hose = bus->sysdata;
+-      u32 value;
+-
+-      if (ppc_md.pci_exclude_device)
+-              if (ppc_md.pci_exclude_device(bus->number, devfn))
+-                      return PCIBIOS_DEVICE_NOT_FOUND;
+-
+-      out_be32(hose->cfg_addr,
+-              (1 << 31) |
+-              ((bus->number - hose->bus_offset) << 16) |
+-              (devfn << 8) |
+-              (offset & 0xfc));
+-      mb();
+-
+-#ifdef MPC5200_BUG_435_WORKAROUND
+-      if (bus->number != hose->bus_offset) {
+-              switch (len) {
+-                    case 1:
+-                      value = in_8(((u8 __iomem *)hose->cfg_data) +
+-                                   (offset & 3));
+-                      break;
+-                    case 2:
+-                      value = in_le16(((u16 __iomem *)hose->cfg_data) +
+-                                      ((offset>>1) & 1));
+-                      break;
+-
+-                    default:
+-                      value = in_le16((u16 __iomem *)hose->cfg_data) |
+-                              (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
+-                      break;
+-              }
+-      }
+-      else
+-#endif
+-      {
+-              value = in_le32(hose->cfg_data);
+-
+-              if (len != 4) {
+-                      value >>= ((offset & 0x3) << 3);
+-                      value &= 0xffffffff >> (32 - (len << 3));
+-              }
+-      }
+-
+-      *val = value;
+-
+-      out_be32(hose->cfg_addr, 0);
+-      mb();
+-
+-      return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static int
+-mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+-                              int offset, int len, u32 val)
+-{
+-      struct pci_controller *hose = bus->sysdata;
+-      u32 value, mask;
+-
+-      if (ppc_md.pci_exclude_device)
+-              if (ppc_md.pci_exclude_device(bus->number, devfn))
+-                      return PCIBIOS_DEVICE_NOT_FOUND;
+-
+-      out_be32(hose->cfg_addr,
+-              (1 << 31) |
+-              ((bus->number - hose->bus_offset) << 16) |
+-              (devfn << 8) |
+-              (offset & 0xfc));
+-      mb();
+-
+-#ifdef MPC5200_BUG_435_WORKAROUND
+-      if (bus->number != hose->bus_offset) {
+-              switch (len) {
+-                    case 1:
+-                      out_8(((u8 __iomem *)hose->cfg_data) +
+-                              (offset & 3), val);
+-                      break;
+-                    case 2:
+-                      out_le16(((u16 __iomem *)hose->cfg_data) +
+-                              ((offset>>1) & 1), val);
+-                      break;
+-
+-                    default:
+-                      out_le16((u16 __iomem *)hose->cfg_data,
+-                              (u16)val);
+-                      out_le16(((u16 __iomem *)hose->cfg_data) + 1,
+-                              (u16)(val>>16));
+-                      break;
+-              }
+-      }
+-      else
+-#endif
+-      {
+-              if (len != 4) {
+-                      value = in_le32(hose->cfg_data);
+-
+-                      offset = (offset & 0x3) << 3;
+-                      mask = (0xffffffff >> (32 - (len << 3)));
+-                      mask <<= offset;
+-
+-                      value &= ~mask;
+-                      val = value | ((val << offset) & mask);
+-              }
+-
+-              out_le32(hose->cfg_data, val);
+-      }
+-      mb();
+-
+-      out_be32(hose->cfg_addr, 0);
+-      mb();
+-
+-      return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static struct pci_ops mpc52xx_pci_ops = {
+-      .read  = mpc52xx_pci_read_config,
+-      .write = mpc52xx_pci_write_config
+-};
+-
+-
+-static void __init
+-mpc52xx_pci_setup(struct pci_controller *hose,
+-                  struct mpc52xx_pci __iomem *pci_regs)
+-{
+-      struct resource *res;
+-      u32 tmp;
+-      int iwcr0 = 0, iwcr1 = 0, iwcr2 = 0;
+-
+-      pr_debug("mpc52xx_pci_setup()\n");
+-
+-      pr_debug("iw0btar=%x iw1btar=%x iw2btar=%x iwcr=%x\n",
+-               in_be32(&pci_regs->iw0btar), in_be32(&pci_regs->iw1btar),
+-               in_be32(&pci_regs->iw2btar), in_be32(&pci_regs->iwcr));
+-      pr_debug("tbatr0=%x tbatr1=%x tcr=%x gscr=%x\n",
+-               in_be32(&pci_regs->tbatr0), in_be32(&pci_regs->tbatr1),
+-               in_be32(&pci_regs->tcr), in_be32(&pci_regs->gscr));
+-
+-      /* Setup control regs */
+-      tmp = in_be32(&pci_regs->scr);
+-      tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+-      out_be32(&pci_regs->scr, tmp);
+-
+-      /* Setup windows */
+-      res = &hose->mem_resources[0];
+-      if (res->flags) {
+-              pr_debug("mem_resource[0] = {.start=%x, .end=%x, .flags=%lx}\n",
+-                       res->start, res->end, res->flags);
+-              out_be32(&pci_regs->iw0btar,
+-                       MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
+-                                res->end - res->start + 1));
+-              iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
+-              if (res->flags & IORESOURCE_PREFETCH)
+-                      iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
+-              else
+-                      iwcr0 |= MPC52xx_PCI_IWCR_READ;
+-      }
+-
+-      res = &hose->mem_resources[1];
+-      if (res->flags) {
+-              pr_debug("mem_resource[1] = {.start=%x, .end=%x, .flags=%lx}\n",
+-                       res->start, res->end, res->flags);
+-              out_be32(&pci_regs->iw1btar,
+-                       MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
+-                                res->end - res->start + 1));
+-              iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
+-              if (res->flags & IORESOURCE_PREFETCH)
+-                      iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
+-              else
+-                      iwcr1 |= MPC52xx_PCI_IWCR_READ;
+-      }
+-
+-      res = &hose->io_resource;
+-      if (!res) {
+-              printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__);
+-              return;
+-      }
+-      pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
+-               ".io_base_phys=%lx\n",
+-               res->start, res->end, res->flags, hose->io_base_phys);
+-      out_be32(&pci_regs->iw2btar,
+-               MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
+-                                              res->start,
+-                                              res->end - res->start + 1));
+-      iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
+-
+-      pr_debug("iwcr0=%x iwcr1=%x iwcr2=%x iwcr=%x old_iwcr=%x\n",
+-               iwcr0, iwcr1, iwcr2,
+-               MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2),
+-               in_be32(&pci_regs->iwcr));
+-      out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2));
+-
+-      out_be32(&pci_regs->tbatr0,
+-              MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
+-      out_be32(&pci_regs->tbatr1,
+-              MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
+-
+-      out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
+-
+-      /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
+-      /* Not necessary and can be a bad thing if for example the bootloader
+-         is displaying a splash screen or ... Just left here for
+-         documentation purpose if anyone need it */
+-      tmp = in_be32(&pci_regs->gscr);
+-#if 0
+-      out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
+-      udelay(50);
+-#endif
+-      out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
+-
+-      pr_debug("iw0btar=%x iw1btar=%x iw2btar=%x iwcr=%x\n",
+-               in_be32(&pci_regs->iw0btar), in_be32(&pci_regs->iw1btar),
+-               in_be32(&pci_regs->iw2btar), in_be32(&pci_regs->iwcr));
+-      pr_debug("tbatr0=%x tbatr1=%x tcr=%x gscr=%x\n",
+-               in_be32(&pci_regs->tbatr0), in_be32(&pci_regs->tbatr1),
+-               in_be32(&pci_regs->tcr), in_be32(&pci_regs->gscr));
+-}
+-
+-static void
+-mpc52xx_pci_fixup_resources(struct pci_dev *dev)
+-{
+-      int i;
+-
+-      pr_debug("mpc52xx_pci_fixup_resources() %.4x:%.4x\n",
+-               dev->vendor, dev->device);
+-
+-      /* We don't rely on boot loader for PCI and resets all
+-         devices */
+-      for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+-              struct resource *res = &dev->resource[i];
+-              if (res->end > res->start) {    /* Only valid resources */
+-                      res->end -= res->start;
+-                      res->start = 0;
+-                      res->flags |= IORESOURCE_UNSET;
+-              }
+-      }
+-
+-      /* The PCI Host bridge of MPC52xx has a prefetch memory resource
+-         fixed to 1Gb. Doesn't fit in the resource system so we remove it */
+-      if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
+-           (   dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
+-            || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
+-              struct resource *res = &dev->resource[1];
+-              res->start = res->end = res->flags = 0;
+-      }
+-}
+-
+-int __init
+-mpc52xx_add_bridge(struct device_node *node)
+-{
+-      int len;
+-      struct mpc52xx_pci __iomem *pci_regs;
+-      struct pci_controller *hose;
+-      const int *bus_range;
+-      struct resource rsrc;
+-
+-      pr_debug("Adding PCI host bridge %s\n", node->full_name);
+-
+-      pci_assign_all_buses = 1;
+-
+-      if (of_address_to_resource(node, 0, &rsrc) != 0) {
+-              printk(KERN_ERR "Can't get %s resources\n", node->full_name);
+-              return -EINVAL;
+-      }
+-
+-      bus_range = get_property(node, "bus-range", &len);
+-      if (bus_range == NULL || len < 2 * sizeof(int)) {
+-              printk(KERN_WARNING "Can't get bus-range for %s, assume"
+-                      " bus 0\n", node->full_name);
+-      }
+-
+-      hose = pcibios_alloc_controller();
+-      if (!hose)
+-              return -ENOMEM;
+-
+-      ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
+-
+-      hose->arch_data = node;
+-      hose->set_cfg_type = 1;
+-
+-      hose->first_busno = bus_range ? bus_range[0] : 0;
+-      hose->last_busno = bus_range ? bus_range[1] : 0xff;
+-
+-      hose->bus_offset = 0;
+-      hose->ops = &mpc52xx_pci_ops;
+-
+-      pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
+-      if (!pci_regs)
+-              return -ENOMEM;
+-
+-      pci_process_bridge_OF_ranges(hose, node, 0);
+-
+-      hose->cfg_addr = &pci_regs->car;
+-
+-      hose->cfg_data = hose->io_base_virt;
+-      hose->io_base_virt = ioremap(hose->io_base_phys,
+-                                   hose->io_resource.end + 1 -
+-                                   hose->io_resource.start);
+-      isa_io_base = (unsigned long) hose->io_base_virt;
+-
+-      mpc52xx_pci_setup(hose, pci_regs);
+-
+-      return 0;
+-}
+diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.h b/arch/powerpc/platforms/52xx/mpc52xx_pci.h
+deleted file mode 100644
+index 07a659e..0000000
+--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.h
++++ /dev/null
+@@ -1,104 +0,0 @@
+-/*
+- * PCI Include file the Freescale MPC52xx embedded cpu chips
+- *
+- * Inspired from code written by Dale Farnsworth <dfarnsworth@mvista.com>
+- * for the 2.4 kernel.
+- *
+- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+- * Copyright (C) 2003 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.
+- */
+-
+-#ifndef __SYSLIB_MPC52xx_PCI_H__
+-#define __SYSLIB_MPC52xx_PCI_H__
+-
+-/* ======================================================================== */
+-/* PCI windows config                                                       */
+-/* ======================================================================== */
+-
+-#define MPC52xx_PCI_TARGET_IO 0xf0000000
+-#define MPC52xx_PCI_TARGET_MEM        0x00000000
+-
+-
+-/* ======================================================================== */
+-/* Structures mapping & Defines for PCI Unit                                */
+-/* ======================================================================== */
+-
+-#define MPC52xx_PCI_GSCR_BM           0x40000000
+-#define MPC52xx_PCI_GSCR_PE           0x20000000
+-#define MPC52xx_PCI_GSCR_SE           0x10000000
+-#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
+-#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT        24
+-#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
+-#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT        16
+-#define MPC52xx_PCI_GSCR_BME          0x00004000
+-#define MPC52xx_PCI_GSCR_PEE          0x00002000
+-#define MPC52xx_PCI_GSCR_SEE          0x00001000
+-#define MPC52xx_PCI_GSCR_PR           0x00000001
+-
+-
+-#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size)     \
+-              ( ( (proc_ad) & 0xff000000 )                    | \
+-                ( (((size) - 1) >> 8) & 0x00ff0000 )          | \
+-                ( ((pci_ad) >> 16) & 0x0000ff00 ) )
+-
+-#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
+-                                               ((win1) << 16) | \
+-                                               ((win2) <<  8))
+-
+-#define MPC52xx_PCI_IWCR_DISABLE      0x0
+-#define MPC52xx_PCI_IWCR_ENABLE               0x1
+-#define MPC52xx_PCI_IWCR_READ         0x0
+-#define MPC52xx_PCI_IWCR_READ_LINE    0x2
+-#define MPC52xx_PCI_IWCR_READ_MULTI   0x4
+-#define MPC52xx_PCI_IWCR_MEM          0x0
+-#define MPC52xx_PCI_IWCR_IO           0x8
+-
+-#define MPC52xx_PCI_TCR_P             0x01000000
+-#define MPC52xx_PCI_TCR_LD            0x00010000
+-
+-#define MPC52xx_PCI_TBATR_DISABLE     0x0
+-#define MPC52xx_PCI_TBATR_ENABLE      0x1
+-
+-
+-#ifndef __ASSEMBLY__
+-
+-struct mpc52xx_pci {
+-      u32     idr;            /* PCI + 0x00 */
+-      u32     scr;            /* PCI + 0x04 */
+-      u32     ccrir;          /* PCI + 0x08 */
+-      u32     cr1;            /* PCI + 0x0C */
+-      u32     bar0;           /* PCI + 0x10 */
+-      u32     bar1;           /* PCI + 0x14 */
+-      u8      reserved1[16];  /* PCI + 0x18 */
+-      u32     ccpr;           /* PCI + 0x28 */
+-      u32     sid;            /* PCI + 0x2C */
+-      u32     erbar;          /* PCI + 0x30 */
+-      u32     cpr;            /* PCI + 0x34 */
+-      u8      reserved2[4];   /* PCI + 0x38 */
+-      u32     cr2;            /* PCI + 0x3C */
+-      u8      reserved3[32];  /* PCI + 0x40 */
+-      u32     gscr;           /* PCI + 0x60 */
+-      u32     tbatr0;         /* PCI + 0x64 */
+-      u32     tbatr1;         /* PCI + 0x68 */
+-      u32     tcr;            /* PCI + 0x6C */
+-      u32     iw0btar;        /* PCI + 0x70 */
+-      u32     iw1btar;        /* PCI + 0x74 */
+-      u32     iw2btar;        /* PCI + 0x78 */
+-      u8      reserved4[4];   /* PCI + 0x7C */
+-      u32     iwcr;           /* PCI + 0x80 */
+-      u32     icr;            /* PCI + 0x84 */
+-      u32     isr;            /* PCI + 0x88 */
+-      u32     arb;            /* PCI + 0x8C */
+-      u8      reserved5[104]; /* PCI + 0x90 */
+-      u32     car;            /* PCI + 0xF8 */
+-      u8      reserved6[4];   /* PCI + 0xFC */
+-};
+-
+-#endif  /* __ASSEMBLY__ */
+-
+-
+-#endif  /* __SYSLIB_MPC52xx_PCI_H__ */
+diff --git a/arch/powerpc/platforms/52xx/pci.c b/arch/powerpc/platforms/52xx/pci.c
+new file mode 100644
+index 0000000..14940af
+--- /dev/null
++++ b/arch/powerpc/platforms/52xx/pci.c
+@@ -0,0 +1,404 @@
++/*
++ * PCI code for the Freescale MPC52xx embedded CPU.
++ *
++ * Copyright (C) 2004 Secret Lab Technologies Ltd.
++ *                        Grant Likely <grant.likely@secretlab.ca>
++ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#undef DEBUG
++
++#include <asm/pci.h>
++#include <asm/mpc52xx.h>
++#include <asm/delay.h>
++#include <asm/machdep.h>
++#include <linux/kernel.h>
++
++
++/* ======================================================================== */
++/* PCI windows config                                                       */
++/* ======================================================================== */
++
++#define MPC52xx_PCI_TARGET_IO 0xf0000000
++#define MPC52xx_PCI_TARGET_MEM        0x00000000
++
++/* ======================================================================== */
++/* Structures mapping & Defines for PCI Unit                                */
++/* ======================================================================== */
++
++#define MPC52xx_PCI_GSCR_BM           0x40000000
++#define MPC52xx_PCI_GSCR_PE           0x20000000
++#define MPC52xx_PCI_GSCR_SE           0x10000000
++#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
++#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT        24
++#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
++#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT        16
++#define MPC52xx_PCI_GSCR_BME          0x00004000
++#define MPC52xx_PCI_GSCR_PEE          0x00002000
++#define MPC52xx_PCI_GSCR_SEE          0x00001000
++#define MPC52xx_PCI_GSCR_PR           0x00000001
++
++
++#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size)     \
++              ( ( (proc_ad) & 0xff000000 )                    | \
++                ( (((size) - 1) >> 8) & 0x00ff0000 )          | \
++                ( ((pci_ad) >> 16) & 0x0000ff00 ) )
++
++#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
++                                               ((win1) << 16) | \
++                                               ((win2) <<  8))
++
++#define MPC52xx_PCI_IWCR_DISABLE      0x0
++#define MPC52xx_PCI_IWCR_ENABLE               0x1
++#define MPC52xx_PCI_IWCR_READ         0x0
++#define MPC52xx_PCI_IWCR_READ_LINE    0x2
++#define MPC52xx_PCI_IWCR_READ_MULTI   0x4
++#define MPC52xx_PCI_IWCR_MEM          0x0
++#define MPC52xx_PCI_IWCR_IO           0x8
++
++#define MPC52xx_PCI_TCR_P             0x01000000
++#define MPC52xx_PCI_TCR_LD            0x00010000
++
++#define MPC52xx_PCI_TBATR_DISABLE     0x0
++#define MPC52xx_PCI_TBATR_ENABLE      0x1
++
++struct mpc52xx_pci {
++      u32     idr;            /* PCI + 0x00 */
++      u32     scr;            /* PCI + 0x04 */
++      u32     ccrir;          /* PCI + 0x08 */
++      u32     cr1;            /* PCI + 0x0C */
++      u32     bar0;           /* PCI + 0x10 */
++      u32     bar1;           /* PCI + 0x14 */
++      u8      reserved1[16];  /* PCI + 0x18 */
++      u32     ccpr;           /* PCI + 0x28 */
++      u32     sid;            /* PCI + 0x2C */
++      u32     erbar;          /* PCI + 0x30 */
++      u32     cpr;            /* PCI + 0x34 */
++      u8      reserved2[4];   /* PCI + 0x38 */
++      u32     cr2;            /* PCI + 0x3C */
++      u8      reserved3[32];  /* PCI + 0x40 */
++      u32     gscr;           /* PCI + 0x60 */
++      u32     tbatr0;         /* PCI + 0x64 */
++      u32     tbatr1;         /* PCI + 0x68 */
++      u32     tcr;            /* PCI + 0x6C */
++      u32     iw0btar;        /* PCI + 0x70 */
++      u32     iw1btar;        /* PCI + 0x74 */
++      u32     iw2btar;        /* PCI + 0x78 */
++      u8      reserved4[4];   /* PCI + 0x7C */
++      u32     iwcr;           /* PCI + 0x80 */
++      u32     icr;            /* PCI + 0x84 */
++      u32     isr;            /* PCI + 0x88 */
++      u32     arb;            /* PCI + 0x8C */
++      u8      reserved5[104]; /* PCI + 0x90 */
++      u32     car;            /* PCI + 0xF8 */
++      u8      reserved6[4];   /* PCI + 0xFC */
++};
++
++static int
++mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
++                              int offset, int len, u32 *val)
++{
++      struct pci_controller *hose = bus->sysdata;
++      u32 value;
++
++      if (ppc_md.pci_exclude_device)
++              if (ppc_md.pci_exclude_device(bus->number, devfn))
++                      return PCIBIOS_DEVICE_NOT_FOUND;
++
++      out_be32(hose->cfg_addr,
++              (1 << 31) |
++              ((bus->number - hose->bus_offset) << 16) |
++              (devfn << 8) |
++              (offset & 0xfc));
++      mb();
++
++#if defined(CONFIG_PPC_MPC5200_BUGFIX)
++      if (bus->number != hose->bus_offset) {
++              /* workaround for the bug 435 of the MPC5200 (L25R);
++               * Don't do 32 bits config access during type-1 cycles */
++              switch (len) {
++                    case 1:
++                      value = in_8(((u8 __iomem *)hose->cfg_data) +
++                                   (offset & 3));
++                      break;
++                    case 2:
++                      value = in_le16(((u16 __iomem *)hose->cfg_data) +
++                                      ((offset>>1) & 1));
++                      break;
++
++                    default:
++                      value = in_le16((u16 __iomem *)hose->cfg_data) |
++                              (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
++                      break;
++              }
++      }
++      else
++#endif
++      {
++              value = in_le32(hose->cfg_data);
++
++              if (len != 4) {
++                      value >>= ((offset & 0x3) << 3);
++                      value &= 0xffffffff >> (32 - (len << 3));
++              }
++      }
++
++      *val = value;
++
++      out_be32(hose->cfg_addr, 0);
++      mb();
++
++      return PCIBIOS_SUCCESSFUL;
++}
++
++static int
++mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
++                              int offset, int len, u32 val)
++{
++      struct pci_controller *hose = bus->sysdata;
++      u32 value, mask;
++
++      if (ppc_md.pci_exclude_device)
++              if (ppc_md.pci_exclude_device(bus->number, devfn))
++                      return PCIBIOS_DEVICE_NOT_FOUND;
++
++      out_be32(hose->cfg_addr,
++              (1 << 31) |
++              ((bus->number - hose->bus_offset) << 16) |
++              (devfn << 8) |
++              (offset & 0xfc));
++      mb();
++
++#if defined(CONFIG_PPC_MPC5200_BUGFIX)
++      if (bus->number != hose->bus_offset) {
++              /* workaround for the bug 435 of the MPC5200 (L25R);
++               * Don't do 32 bits config access during type-1 cycles */
++              switch (len) {
++                    case 1:
++                      out_8(((u8 __iomem *)hose->cfg_data) +
++                              (offset & 3), val);
++                      break;
++                    case 2:
++                      out_le16(((u16 __iomem *)hose->cfg_data) +
++                              ((offset>>1) & 1), val);
++                      break;
++
++                    default:
++                      out_le16((u16 __iomem *)hose->cfg_data,
++                              (u16)val);
++                      out_le16(((u16 __iomem *)hose->cfg_data) + 1,
++                              (u16)(val>>16));
++                      break;
++              }
++      }
++      else
++#endif
++      {
++              if (len != 4) {
++                      value = in_le32(hose->cfg_data);
++
++                      offset = (offset & 0x3) << 3;
++                      mask = (0xffffffff >> (32 - (len << 3)));
++                      mask <<= offset;
++
++                      value &= ~mask;
++                      val = value | ((val << offset) & mask);
++              }
++
++              out_le32(hose->cfg_data, val);
++      }
++      mb();
++
++      out_be32(hose->cfg_addr, 0);
++      mb();
++
++      return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops mpc52xx_pci_ops = {
++      .read  = mpc52xx_pci_read_config,
++      .write = mpc52xx_pci_write_config
++};
++
++
++static void __init
++mpc52xx_pci_setup(struct pci_controller *hose,
++                  struct mpc52xx_pci __iomem *pci_regs)
++{
++      struct resource *res;
++      u32 tmp;
++      int iwcr0 = 0, iwcr1 = 0, iwcr2 = 0;
++
++      pr_debug("mpc52xx_pci_setup(hose=%p, pci_regs=%p)\n", hose, pci_regs);
++
++      /* pci_process_bridge_OF_ranges() found all our addresses for us;
++       * now store them in the right places */
++      hose->cfg_addr = &pci_regs->car;
++      hose->cfg_data = hose->io_base_virt;
++      hose->io_base_virt = ioremap(hose->io_base_phys,
++                                   hose->io_resource.end + 1 -
++                                   hose->io_resource.start);
++      isa_io_base = (unsigned long) hose->io_base_virt;
++
++      /* Control regs */
++      tmp = in_be32(&pci_regs->scr);
++      tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
++      out_be32(&pci_regs->scr, tmp);
++
++      /* Memory windows */
++      res = &hose->mem_resources[0];
++      if (res->flags) {
++              pr_debug("mem_resource[0] = {.start=%x, .end=%x, .flags=%lx}\n",
++                       res->start, res->end, res->flags);
++              out_be32(&pci_regs->iw0btar,
++                       MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
++                                res->end - res->start + 1));
++              iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
++              if (res->flags & IORESOURCE_PREFETCH)
++                      iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
++              else
++                      iwcr0 |= MPC52xx_PCI_IWCR_READ;
++      }
++
++      res = &hose->mem_resources[1];
++      if (res->flags) {
++              pr_debug("mem_resource[1] = {.start=%x, .end=%x, .flags=%lx}\n",
++                       res->start, res->end, res->flags);
++              out_be32(&pci_regs->iw1btar,
++                       MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
++                                res->end - res->start + 1));
++              iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
++              if (res->flags & IORESOURCE_PREFETCH)
++                      iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
++              else
++                      iwcr1 |= MPC52xx_PCI_IWCR_READ;
++      }
++
++      /* IO resources */
++      res = &hose->io_resource;
++      if (!res) {
++              printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__);
++              return;
++      }
++      pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
++               ".io_base_phys=%lx\n",
++               res->start, res->end, res->flags, hose->io_base_phys);
++      out_be32(&pci_regs->iw2btar,
++               MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
++                                              res->start,
++                                              res->end - res->start + 1));
++      iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
++
++      /* Set all the IWCR fields at once; they're in the same reg */
++      out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2));
++
++      out_be32(&pci_regs->tbatr0,
++              MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
++      out_be32(&pci_regs->tbatr1,
++              MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
++
++      out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
++
++#if 0
++      /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
++      /* Not necessary and can be a bad thing if for example the bootloader
++         is displaying a splash screen or ... Just left here for
++         documentation purpose if anyone need it */
++      tmp = in_be32(&pci_regs->gscr);
++      out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
++      udelay(50);
++      out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
++#endif
++}
++
++static void
++mpc52xx_pci_fixup_resources(struct pci_dev *dev)
++{
++      int i;
++
++      pr_debug("mpc52xx_pci_fixup_resources() %.4x:%.4x\n",
++               dev->vendor, dev->device);
++
++      /* We don't rely on boot loader for PCI and resets all
++         devices */
++      for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++              struct resource *res = &dev->resource[i];
++              if (res->end > res->start) {    /* Only valid resources */
++                      res->end -= res->start;
++                      res->start = 0;
++                      res->flags |= IORESOURCE_UNSET;
++              }
++      }
++
++      /* The PCI Host bridge of MPC52xx has a prefetch memory resource
++         fixed to 1Gb. Doesn't fit in the resource system so we remove it */
++      if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
++           (   dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
++            || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
++              struct resource *res = &dev->resource[1];
++              res->start = res->end = res->flags = 0;
++      }
++}
++
++int __init
++mpc52xx_add_bridge(struct device_node *node)
++{
++      int len;
++      struct mpc52xx_pci __iomem *pci_regs;
++      struct pci_controller *hose;
++      const int *bus_range;
++      struct resource rsrc;
++
++      pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
++
++      pci_assign_all_buses = 1;
++
++      if (of_address_to_resource(node, 0, &rsrc) != 0) {
++              printk(KERN_ERR "Can't get %s resources\n", node->full_name);
++              return -EINVAL;
++      }
++
++      bus_range = get_property(node, "bus-range", &len);
++      if (bus_range == NULL || len < 2 * sizeof(int)) {
++              printk(KERN_WARNING "Can't get %s bus-range, assume bus 0\n",
++                     node->full_name);
++              bus_range = NULL;
++      }
++
++      /* There are some PCI quirks on the 52xx, register the hook to
++       * fix them. */
++      ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
++
++      /* Alloc and initialize the pci controller.  Values in the device
++       * tree are needed to configure the 52xx PCI controller.  Rather
++       * than parse the tree here, let pci_process_bridge_OF_ranges()
++       * do it for us and extract the values after the fact */
++      hose = pcibios_alloc_controller();
++      if (!hose)
++              return -ENOMEM;
++
++      hose->arch_data = node;
++      hose->set_cfg_type = 1;
++
++      hose->first_busno = bus_range ? bus_range[0] : 0;
++      hose->last_busno = bus_range ? bus_range[1] : 0xff;
++
++      hose->bus_offset = 0;
++      hose->ops = &mpc52xx_pci_ops;
++
++      pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
++      if (!pci_regs)
++              return -ENOMEM;
++
++      pci_process_bridge_OF_ranges(hose, node, 0);
++
++      /* Finish setting up PCI using values obtained by
++       * pci_proces_bridge_OF_ranges */
++      mpc52xx_pci_setup(hose, pci_regs);
++
++      return 0;
++}
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0027-POWERPC-Change-name-of-mpc52xx-pci-support-file-in-Makefile.txt b/packages/linux/linux-efika-2.6.20/0027-POWERPC-Change-name-of-mpc52xx-pci-support-file-in-Makefile.txt
new file mode 100644 (file)
index 0000000..80a769b
--- /dev/null
@@ -0,0 +1,28 @@
+From 5145742e15b45e96c623f571dee421306dc95a3e Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Mon, 11 Dec 2006 22:45:39 -0700
+Subject: [PATCH] [POWERPC] Change name of mpc52xx pci support file in Makefile
+
+Oops, missed a bit in the previous patch
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ arch/powerpc/platforms/52xx/Makefile |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
+index d85ea04..a7c646a 100644
+--- a/arch/powerpc/platforms/52xx/Makefile
++++ b/arch/powerpc/platforms/52xx/Makefile
+@@ -3,7 +3,7 @@
+ #
+ ifeq ($(CONFIG_PPC_MERGE),y)
+ obj-y                         += mpc52xx_pic.o mpc52xx_common.o
+-obj-$(CONFIG_PCI)             += mpc52xx_pci.o
++obj-$(CONFIG_PCI)             += pci.o
+ obj-$(CONFIG_PPC_BESTCOMM)    += bestcomm.o
+ obj-$(CONFIG_FEC_MPC52xx)     += sdma_fec_rx_task.o sdma_fec_tx_task.o fec.o
+ endif
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0028-POWERPC-Change-link-order-so-mpc52xx-fec-always-shows-up-as-eth0.txt b/packages/linux/linux-efika-2.6.20/0028-POWERPC-Change-link-order-so-mpc52xx-fec-always-shows-up-as-eth0.txt
new file mode 100644 (file)
index 0000000..0761bea
--- /dev/null
@@ -0,0 +1,47 @@
+From 2086d309f8b8de0b41119596d43f2a7bfe028a89 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Mon, 11 Dec 2006 22:46:59 -0700
+Subject: [PATCH] [POWERPC] Change link order so mpc52xx-fec always shows up as eth0
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ drivers/net/Makefile          |    2 +-
+ drivers/net/fec_mpc52xx/fec.c |    2 ++
+ 2 files changed, 3 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/net/Makefile b/drivers/net/Makefile
+index e6f903d..95f0963 100644
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -24,6 +24,7 @@ ucc_geth_driver-objs := ucc_geth.o ucc_geth_phy.o
+ obj-$(CONFIG_PLIP) += plip.o
+ obj-$(CONFIG_ROADRUNNER) += rrunner.o
++obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx/
+ obj-$(CONFIG_HAPPYMEAL) += sunhme.o
+ obj-$(CONFIG_SUNLANCE) += sunlance.o
+@@ -196,7 +197,6 @@ obj-$(CONFIG_SMC91X) += smc91x.o
+ obj-$(CONFIG_SMC911X) += smc911x.o
+ obj-$(CONFIG_DM9000) += dm9000.o
+ obj-$(CONFIG_FEC_8XX) += fec_8xx/
+-obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx/
+ obj-$(CONFIG_MACB) += macb.o
+diff --git a/drivers/net/fec_mpc52xx/fec.c b/drivers/net/fec_mpc52xx/fec.c
+index 894da79..30cef2b 100644
+--- a/drivers/net/fec_mpc52xx/fec.c
++++ b/drivers/net/fec_mpc52xx/fec.c
+@@ -731,6 +731,8 @@ mpc52xx_fec_probe(struct device *dev)
+       fec_mii_init(ndev);
+       
+       /* We're done ! */
++      printk(KERN_INFO "%s: mpc52xx-fec at %#lx,",
++             ndev->name, (long)mem->start);
+ #if defined(CONFIG_PPC_MERGE)
+       dev_set_drvdata(&op->dev, ndev);
+ #else
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0029-POWERPC-Fixup-pr_print-format-for-mpc52xx-pci-support.txt b/packages/linux/linux-efika-2.6.20/0029-POWERPC-Fixup-pr_print-format-for-mpc52xx-pci-support.txt
new file mode 100644 (file)
index 0000000..3a17939
--- /dev/null
@@ -0,0 +1,28 @@
+From 08bb999d4f8b866a570775db5788cd84edafd3f5 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Mon, 11 Dec 2006 23:00:24 -0700
+Subject: [PATCH] [POWERPC] Fixup pr_print format for mpc52xx pci support
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ arch/powerpc/platforms/52xx/pci.c |    4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/powerpc/platforms/52xx/pci.c b/arch/powerpc/platforms/52xx/pci.c
+index 14940af..b732fdc 100644
+--- a/arch/powerpc/platforms/52xx/pci.c
++++ b/arch/powerpc/platforms/52xx/pci.c
+@@ -285,8 +285,8 @@ mpc52xx_pci_setup(struct pci_controller *hose,
+               return;
+       }
+       pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
+-               ".io_base_phys=%lx\n",
+-               res->start, res->end, res->flags, hose->io_base_phys);
++               ".io_base_phys=0x%p\n",
++               res->start, res->end, res->flags, (void*)hose->io_base_phys);
+       out_be32(&pci_regs->iw2btar,
+                MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
+                                               res->start,
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0030-POWERPC-Add-mpc52xx-lite5200-PCI-support.txt b/packages/linux/linux-efika-2.6.20/0030-POWERPC-Add-mpc52xx-lite5200-PCI-support.txt
new file mode 100644 (file)
index 0000000..dae76e0
--- /dev/null
@@ -0,0 +1,871 @@
+From 56aad819c662c854466a8c454c948e79dd2f0777 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Mon, 11 Dec 2006 23:23:40 -0700
+Subject: [PATCH] [POWERPC] Add mpc52xx/lite5200 PCI support
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ arch/powerpc/platforms/52xx/Makefile      |    2 +-
+ arch/powerpc/platforms/52xx/lite5200.c    |    3 -
+ arch/powerpc/platforms/52xx/mpc52xx_pci.c |  412 +++++++++++++++++++++++++++++
+ arch/powerpc/platforms/52xx/pci.c         |  404 ----------------------------
+ 4 files changed, 413 insertions(+), 408 deletions(-)
+
+diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
+index a7c646a..d85ea04 100644
+--- a/arch/powerpc/platforms/52xx/Makefile
++++ b/arch/powerpc/platforms/52xx/Makefile
+@@ -3,7 +3,7 @@
+ #
+ ifeq ($(CONFIG_PPC_MERGE),y)
+ obj-y                         += mpc52xx_pic.o mpc52xx_common.o
+-obj-$(CONFIG_PCI)             += pci.o
++obj-$(CONFIG_PCI)             += mpc52xx_pci.o
+ obj-$(CONFIG_PPC_BESTCOMM)    += bestcomm.o
+ obj-$(CONFIG_FEC_MPC52xx)     += sdma_fec_rx_task.o sdma_fec_tx_task.o fec.o
+ endif
+diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
+index f1bbe24..cdb16bf 100644
+--- a/arch/powerpc/platforms/52xx/lite5200.c
++++ b/arch/powerpc/platforms/52xx/lite5200.c
+@@ -111,9 +111,6 @@ static void __init lite52xx_setup_arch(void)
+       np = of_find_node_by_type(np, "pci");
+       if (np)
+               mpc52xx_add_bridge(np);
+-
+-      //ppc_md.pci_swizzle = common_swizzle;
+-      //ppc_md.pci_exclude_device = mpc52xx_exclude_device;
+ #endif
+ #ifdef CONFIG_BLK_DEV_INITRD
+diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+new file mode 100644
+index 0000000..faf161b
+--- /dev/null
++++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+@@ -0,0 +1,412 @@
++/*
++ * PCI code for the Freescale MPC52xx embedded CPU.
++ *
++ * Copyright (C) 2006 Secret Lab Technologies Ltd.
++ *                        Grant Likely <grant.likely@secretlab.ca>
++ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ */
++
++#undef DEBUG
++
++#include <asm/pci.h>
++#include <asm/mpc52xx.h>
++#include <asm/delay.h>
++#include <asm/machdep.h>
++#include <linux/kernel.h>
++
++
++/* ======================================================================== */
++/* PCI windows config                                                       */
++/* ======================================================================== */
++
++#define MPC52xx_PCI_TARGET_IO 0xf0000000
++#define MPC52xx_PCI_TARGET_MEM        0x00000000
++
++
++/* ======================================================================== */
++/* Structures mapping & Defines for PCI Unit                                */
++/* ======================================================================== */
++
++#define MPC52xx_PCI_GSCR_BM           0x40000000
++#define MPC52xx_PCI_GSCR_PE           0x20000000
++#define MPC52xx_PCI_GSCR_SE           0x10000000
++#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
++#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT        24
++#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
++#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT        16
++#define MPC52xx_PCI_GSCR_BME          0x00004000
++#define MPC52xx_PCI_GSCR_PEE          0x00002000
++#define MPC52xx_PCI_GSCR_SEE          0x00001000
++#define MPC52xx_PCI_GSCR_PR           0x00000001
++
++
++#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size)     \
++              ( ( (proc_ad) & 0xff000000 )                    | \
++                ( (((size) - 1) >> 8) & 0x00ff0000 )          | \
++                ( ((pci_ad) >> 16) & 0x0000ff00 ) )
++
++#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
++                                               ((win1) << 16) | \
++                                               ((win2) <<  8))
++
++#define MPC52xx_PCI_IWCR_DISABLE      0x0
++#define MPC52xx_PCI_IWCR_ENABLE               0x1
++#define MPC52xx_PCI_IWCR_READ         0x0
++#define MPC52xx_PCI_IWCR_READ_LINE    0x2
++#define MPC52xx_PCI_IWCR_READ_MULTI   0x4
++#define MPC52xx_PCI_IWCR_MEM          0x0
++#define MPC52xx_PCI_IWCR_IO           0x8
++
++#define MPC52xx_PCI_TCR_P             0x01000000
++#define MPC52xx_PCI_TCR_LD            0x00010000
++
++#define MPC52xx_PCI_TBATR_DISABLE     0x0
++#define MPC52xx_PCI_TBATR_ENABLE      0x1
++
++struct mpc52xx_pci {
++      u32     idr;            /* PCI + 0x00 */
++      u32     scr;            /* PCI + 0x04 */
++      u32     ccrir;          /* PCI + 0x08 */
++      u32     cr1;            /* PCI + 0x0C */
++      u32     bar0;           /* PCI + 0x10 */
++      u32     bar1;           /* PCI + 0x14 */
++      u8      reserved1[16];  /* PCI + 0x18 */
++      u32     ccpr;           /* PCI + 0x28 */
++      u32     sid;            /* PCI + 0x2C */
++      u32     erbar;          /* PCI + 0x30 */
++      u32     cpr;            /* PCI + 0x34 */
++      u8      reserved2[4];   /* PCI + 0x38 */
++      u32     cr2;            /* PCI + 0x3C */
++      u8      reserved3[32];  /* PCI + 0x40 */
++      u32     gscr;           /* PCI + 0x60 */
++      u32     tbatr0;         /* PCI + 0x64 */
++      u32     tbatr1;         /* PCI + 0x68 */
++      u32     tcr;            /* PCI + 0x6C */
++      u32     iw0btar;        /* PCI + 0x70 */
++      u32     iw1btar;        /* PCI + 0x74 */
++      u32     iw2btar;        /* PCI + 0x78 */
++      u8      reserved4[4];   /* PCI + 0x7C */
++      u32     iwcr;           /* PCI + 0x80 */
++      u32     icr;            /* PCI + 0x84 */
++      u32     isr;            /* PCI + 0x88 */
++      u32     arb;            /* PCI + 0x8C */
++      u8      reserved5[104]; /* PCI + 0x90 */
++      u32     car;            /* PCI + 0xF8 */
++      u8      reserved6[4];   /* PCI + 0xFC */
++};
++
++
++/* ======================================================================== */
++/* PCI configuration acess                                                  */
++/* ======================================================================== */
++
++static int
++mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
++                              int offset, int len, u32 *val)
++{
++      struct pci_controller *hose = bus->sysdata;
++      u32 value;
++
++      if (ppc_md.pci_exclude_device)
++              if (ppc_md.pci_exclude_device(bus->number, devfn))
++                      return PCIBIOS_DEVICE_NOT_FOUND;
++
++      out_be32(hose->cfg_addr,
++              (1 << 31) |
++              ((bus->number - hose->bus_offset) << 16) |
++              (devfn << 8) |
++              (offset & 0xfc));
++      mb();
++
++#if defined(CONFIG_PPC_MPC5200_BUGFIX)
++      if (bus->number != hose->bus_offset) {
++              /* workaround for the bug 435 of the MPC5200 (L25R);
++               * Don't do 32 bits config access during type-1 cycles */
++              switch (len) {
++                    case 1:
++                      value = in_8(((u8 __iomem *)hose->cfg_data) +
++                                   (offset & 3));
++                      break;
++                    case 2:
++                      value = in_le16(((u16 __iomem *)hose->cfg_data) +
++                                      ((offset>>1) & 1));
++                      break;
++
++                    default:
++                      value = in_le16((u16 __iomem *)hose->cfg_data) |
++                              (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
++                      break;
++              }
++      }
++      else
++#endif
++      {
++              value = in_le32(hose->cfg_data);
++
++              if (len != 4) {
++                      value >>= ((offset & 0x3) << 3);
++                      value &= 0xffffffff >> (32 - (len << 3));
++              }
++      }
++
++      *val = value;
++
++      out_be32(hose->cfg_addr, 0);
++      mb();
++
++      return PCIBIOS_SUCCESSFUL;
++}
++
++static int
++mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
++                              int offset, int len, u32 val)
++{
++      struct pci_controller *hose = bus->sysdata;
++      u32 value, mask;
++
++      if (ppc_md.pci_exclude_device)
++              if (ppc_md.pci_exclude_device(bus->number, devfn))
++                      return PCIBIOS_DEVICE_NOT_FOUND;
++
++      out_be32(hose->cfg_addr,
++              (1 << 31) |
++              ((bus->number - hose->bus_offset) << 16) |
++              (devfn << 8) |
++              (offset & 0xfc));
++      mb();
++
++#if defined(CONFIG_PPC_MPC5200_BUGFIX)
++      if (bus->number != hose->bus_offset) {
++              /* workaround for the bug 435 of the MPC5200 (L25R);
++               * Don't do 32 bits config access during type-1 cycles */
++              switch (len) {
++                    case 1:
++                      out_8(((u8 __iomem *)hose->cfg_data) +
++                              (offset & 3), val);
++                      break;
++                    case 2:
++                      out_le16(((u16 __iomem *)hose->cfg_data) +
++                              ((offset>>1) & 1), val);
++                      break;
++
++                    default:
++                      out_le16((u16 __iomem *)hose->cfg_data,
++                              (u16)val);
++                      out_le16(((u16 __iomem *)hose->cfg_data) + 1,
++                              (u16)(val>>16));
++                      break;
++              }
++      }
++      else
++#endif
++      {
++              if (len != 4) {
++                      value = in_le32(hose->cfg_data);
++
++                      offset = (offset & 0x3) << 3;
++                      mask = (0xffffffff >> (32 - (len << 3)));
++                      mask <<= offset;
++
++                      value &= ~mask;
++                      val = value | ((val << offset) & mask);
++              }
++
++              out_le32(hose->cfg_data, val);
++      }
++      mb();
++
++      out_be32(hose->cfg_addr, 0);
++      mb();
++
++      return PCIBIOS_SUCCESSFUL;
++}
++
++static struct pci_ops mpc52xx_pci_ops = {
++      .read  = mpc52xx_pci_read_config,
++      .write = mpc52xx_pci_write_config
++};
++
++
++/* ======================================================================== */
++/* PCI setup                                                                */
++/* ======================================================================== */
++
++static void __init
++mpc52xx_pci_setup(struct pci_controller *hose,
++                  struct mpc52xx_pci __iomem *pci_regs)
++{
++      struct resource *res;
++      u32 tmp;
++      int iwcr0 = 0, iwcr1 = 0, iwcr2 = 0;
++
++      pr_debug("mpc52xx_pci_setup(hose=%p, pci_regs=%p)\n", hose, pci_regs);
++
++      /* pci_process_bridge_OF_ranges() found all our addresses for us;
++       * now store them in the right places */
++      hose->cfg_addr = &pci_regs->car;
++      hose->cfg_data = hose->io_base_virt;
++
++      /* Control regs */
++      tmp = in_be32(&pci_regs->scr);
++      tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
++      out_be32(&pci_regs->scr, tmp);
++
++      /* Memory windows */
++      res = &hose->mem_resources[0];
++      if (res->flags) {
++              pr_debug("mem_resource[0] = {.start=%x, .end=%x, .flags=%lx}\n",
++                       res->start, res->end, res->flags);
++              out_be32(&pci_regs->iw0btar,
++                       MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
++                                res->end - res->start + 1));
++              iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
++              if (res->flags & IORESOURCE_PREFETCH)
++                      iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
++              else
++                      iwcr0 |= MPC52xx_PCI_IWCR_READ;
++      }
++
++      res = &hose->mem_resources[1];
++      if (res->flags) {
++              pr_debug("mem_resource[1] = {.start=%x, .end=%x, .flags=%lx}\n",
++                       res->start, res->end, res->flags);
++              out_be32(&pci_regs->iw1btar,
++                       MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
++                                res->end - res->start + 1));
++              iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
++              if (res->flags & IORESOURCE_PREFETCH)
++                      iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
++              else
++                      iwcr1 |= MPC52xx_PCI_IWCR_READ;
++      }
++
++      /* IO resources */
++      res = &hose->io_resource;
++      if (!res) {
++              printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__);
++              return;
++      }
++      pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
++               ".io_base_phys=0x%p\n",
++               res->start, res->end, res->flags, (void*)hose->io_base_phys);
++      out_be32(&pci_regs->iw2btar,
++               MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
++                                              res->start,
++                                              res->end - res->start + 1));
++      iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
++
++      /* Set all the IWCR fields at once; they're in the same reg */
++      out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2));
++
++      out_be32(&pci_regs->tbatr0,
++              MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
++      out_be32(&pci_regs->tbatr1,
++              MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
++
++      out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
++
++      tmp = in_be32(&pci_regs->gscr);
++#if 0
++      /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
++      /* Not necessary and can be a bad thing if for example the bootloader
++         is displaying a splash screen or ... Just left here for
++         documentation purpose if anyone need it */
++      out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
++      udelay(50);
++#endif
++
++      /* Make sure the PCI bridge is out of reset */
++      out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
++}
++
++static void
++mpc52xx_pci_fixup_resources(struct pci_dev *dev)
++{
++      int i;
++
++      pr_debug("mpc52xx_pci_fixup_resources() %.4x:%.4x\n",
++               dev->vendor, dev->device);
++
++      /* We don't rely on boot loader for PCI and resets all
++         devices */
++      for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++              struct resource *res = &dev->resource[i];
++              if (res->end > res->start) {    /* Only valid resources */
++                      res->end -= res->start;
++                      res->start = 0;
++                      res->flags |= IORESOURCE_UNSET;
++              }
++      }
++
++      /* The PCI Host bridge of MPC52xx has a prefetch memory resource
++         fixed to 1Gb. Doesn't fit in the resource system so we remove it */
++      if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
++           (   dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
++            || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
++              struct resource *res = &dev->resource[1];
++              res->start = res->end = res->flags = 0;
++      }
++}
++
++int __init
++mpc52xx_add_bridge(struct device_node *node)
++{
++      int len;
++      struct mpc52xx_pci __iomem *pci_regs;
++      struct pci_controller *hose;
++      const int *bus_range;
++      struct resource rsrc;
++
++      pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
++
++      pci_assign_all_buses = 1;
++
++      if (of_address_to_resource(node, 0, &rsrc) != 0) {
++              printk(KERN_ERR "Can't get %s resources\n", node->full_name);
++              return -EINVAL;
++      }
++
++      bus_range = get_property(node, "bus-range", &len);
++      if (bus_range == NULL || len < 2 * sizeof(int)) {
++              printk(KERN_WARNING "Can't get %s bus-range, assume bus 0\n",
++                     node->full_name);
++              bus_range = NULL;
++      }
++
++      /* There are some PCI quirks on the 52xx, register the hook to
++       * fix them. */
++      ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
++
++      /* Alloc and initialize the pci controller.  Values in the device
++       * tree are needed to configure the 52xx PCI controller.  Rather
++       * than parse the tree here, let pci_process_bridge_OF_ranges()
++       * do it for us and extract the values after the fact */
++      hose = pcibios_alloc_controller();
++      if (!hose)
++              return -ENOMEM;
++
++      hose->arch_data = node;
++      hose->set_cfg_type = 1;
++
++      hose->first_busno = bus_range ? bus_range[0] : 0;
++      hose->last_busno = bus_range ? bus_range[1] : 0xff;
++
++      hose->bus_offset = 0;
++      hose->ops = &mpc52xx_pci_ops;
++
++      pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
++      if (!pci_regs)
++              return -ENOMEM;
++
++      pci_process_bridge_OF_ranges(hose, node, 1);
++
++      /* Finish setting up PCI using values obtained by
++       * pci_proces_bridge_OF_ranges */
++      mpc52xx_pci_setup(hose, pci_regs);
++
++      return 0;
++}
+diff --git a/arch/powerpc/platforms/52xx/pci.c b/arch/powerpc/platforms/52xx/pci.c
+deleted file mode 100644
+index b732fdc..0000000
+--- a/arch/powerpc/platforms/52xx/pci.c
++++ /dev/null
+@@ -1,404 +0,0 @@
+-/*
+- * PCI code for the Freescale MPC52xx embedded CPU.
+- *
+- * Copyright (C) 2004 Secret Lab Technologies Ltd.
+- *                        Grant Likely <grant.likely@secretlab.ca>
+- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+- *
+- * This file is licensed under the terms of the GNU General Public License
+- * version 2. This program is licensed "as is" without any warranty of any
+- * kind, whether express or implied.
+- */
+-
+-#undef DEBUG
+-
+-#include <asm/pci.h>
+-#include <asm/mpc52xx.h>
+-#include <asm/delay.h>
+-#include <asm/machdep.h>
+-#include <linux/kernel.h>
+-
+-
+-/* ======================================================================== */
+-/* PCI windows config                                                       */
+-/* ======================================================================== */
+-
+-#define MPC52xx_PCI_TARGET_IO 0xf0000000
+-#define MPC52xx_PCI_TARGET_MEM        0x00000000
+-
+-/* ======================================================================== */
+-/* Structures mapping & Defines for PCI Unit                                */
+-/* ======================================================================== */
+-
+-#define MPC52xx_PCI_GSCR_BM           0x40000000
+-#define MPC52xx_PCI_GSCR_PE           0x20000000
+-#define MPC52xx_PCI_GSCR_SE           0x10000000
+-#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
+-#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT        24
+-#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
+-#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT        16
+-#define MPC52xx_PCI_GSCR_BME          0x00004000
+-#define MPC52xx_PCI_GSCR_PEE          0x00002000
+-#define MPC52xx_PCI_GSCR_SEE          0x00001000
+-#define MPC52xx_PCI_GSCR_PR           0x00000001
+-
+-
+-#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size)     \
+-              ( ( (proc_ad) & 0xff000000 )                    | \
+-                ( (((size) - 1) >> 8) & 0x00ff0000 )          | \
+-                ( ((pci_ad) >> 16) & 0x0000ff00 ) )
+-
+-#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
+-                                               ((win1) << 16) | \
+-                                               ((win2) <<  8))
+-
+-#define MPC52xx_PCI_IWCR_DISABLE      0x0
+-#define MPC52xx_PCI_IWCR_ENABLE               0x1
+-#define MPC52xx_PCI_IWCR_READ         0x0
+-#define MPC52xx_PCI_IWCR_READ_LINE    0x2
+-#define MPC52xx_PCI_IWCR_READ_MULTI   0x4
+-#define MPC52xx_PCI_IWCR_MEM          0x0
+-#define MPC52xx_PCI_IWCR_IO           0x8
+-
+-#define MPC52xx_PCI_TCR_P             0x01000000
+-#define MPC52xx_PCI_TCR_LD            0x00010000
+-
+-#define MPC52xx_PCI_TBATR_DISABLE     0x0
+-#define MPC52xx_PCI_TBATR_ENABLE      0x1
+-
+-struct mpc52xx_pci {
+-      u32     idr;            /* PCI + 0x00 */
+-      u32     scr;            /* PCI + 0x04 */
+-      u32     ccrir;          /* PCI + 0x08 */
+-      u32     cr1;            /* PCI + 0x0C */
+-      u32     bar0;           /* PCI + 0x10 */
+-      u32     bar1;           /* PCI + 0x14 */
+-      u8      reserved1[16];  /* PCI + 0x18 */
+-      u32     ccpr;           /* PCI + 0x28 */
+-      u32     sid;            /* PCI + 0x2C */
+-      u32     erbar;          /* PCI + 0x30 */
+-      u32     cpr;            /* PCI + 0x34 */
+-      u8      reserved2[4];   /* PCI + 0x38 */
+-      u32     cr2;            /* PCI + 0x3C */
+-      u8      reserved3[32];  /* PCI + 0x40 */
+-      u32     gscr;           /* PCI + 0x60 */
+-      u32     tbatr0;         /* PCI + 0x64 */
+-      u32     tbatr1;         /* PCI + 0x68 */
+-      u32     tcr;            /* PCI + 0x6C */
+-      u32     iw0btar;        /* PCI + 0x70 */
+-      u32     iw1btar;        /* PCI + 0x74 */
+-      u32     iw2btar;        /* PCI + 0x78 */
+-      u8      reserved4[4];   /* PCI + 0x7C */
+-      u32     iwcr;           /* PCI + 0x80 */
+-      u32     icr;            /* PCI + 0x84 */
+-      u32     isr;            /* PCI + 0x88 */
+-      u32     arb;            /* PCI + 0x8C */
+-      u8      reserved5[104]; /* PCI + 0x90 */
+-      u32     car;            /* PCI + 0xF8 */
+-      u8      reserved6[4];   /* PCI + 0xFC */
+-};
+-
+-static int
+-mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+-                              int offset, int len, u32 *val)
+-{
+-      struct pci_controller *hose = bus->sysdata;
+-      u32 value;
+-
+-      if (ppc_md.pci_exclude_device)
+-              if (ppc_md.pci_exclude_device(bus->number, devfn))
+-                      return PCIBIOS_DEVICE_NOT_FOUND;
+-
+-      out_be32(hose->cfg_addr,
+-              (1 << 31) |
+-              ((bus->number - hose->bus_offset) << 16) |
+-              (devfn << 8) |
+-              (offset & 0xfc));
+-      mb();
+-
+-#if defined(CONFIG_PPC_MPC5200_BUGFIX)
+-      if (bus->number != hose->bus_offset) {
+-              /* workaround for the bug 435 of the MPC5200 (L25R);
+-               * Don't do 32 bits config access during type-1 cycles */
+-              switch (len) {
+-                    case 1:
+-                      value = in_8(((u8 __iomem *)hose->cfg_data) +
+-                                   (offset & 3));
+-                      break;
+-                    case 2:
+-                      value = in_le16(((u16 __iomem *)hose->cfg_data) +
+-                                      ((offset>>1) & 1));
+-                      break;
+-
+-                    default:
+-                      value = in_le16((u16 __iomem *)hose->cfg_data) |
+-                              (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
+-                      break;
+-              }
+-      }
+-      else
+-#endif
+-      {
+-              value = in_le32(hose->cfg_data);
+-
+-              if (len != 4) {
+-                      value >>= ((offset & 0x3) << 3);
+-                      value &= 0xffffffff >> (32 - (len << 3));
+-              }
+-      }
+-
+-      *val = value;
+-
+-      out_be32(hose->cfg_addr, 0);
+-      mb();
+-
+-      return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static int
+-mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+-                              int offset, int len, u32 val)
+-{
+-      struct pci_controller *hose = bus->sysdata;
+-      u32 value, mask;
+-
+-      if (ppc_md.pci_exclude_device)
+-              if (ppc_md.pci_exclude_device(bus->number, devfn))
+-                      return PCIBIOS_DEVICE_NOT_FOUND;
+-
+-      out_be32(hose->cfg_addr,
+-              (1 << 31) |
+-              ((bus->number - hose->bus_offset) << 16) |
+-              (devfn << 8) |
+-              (offset & 0xfc));
+-      mb();
+-
+-#if defined(CONFIG_PPC_MPC5200_BUGFIX)
+-      if (bus->number != hose->bus_offset) {
+-              /* workaround for the bug 435 of the MPC5200 (L25R);
+-               * Don't do 32 bits config access during type-1 cycles */
+-              switch (len) {
+-                    case 1:
+-                      out_8(((u8 __iomem *)hose->cfg_data) +
+-                              (offset & 3), val);
+-                      break;
+-                    case 2:
+-                      out_le16(((u16 __iomem *)hose->cfg_data) +
+-                              ((offset>>1) & 1), val);
+-                      break;
+-
+-                    default:
+-                      out_le16((u16 __iomem *)hose->cfg_data,
+-                              (u16)val);
+-                      out_le16(((u16 __iomem *)hose->cfg_data) + 1,
+-                              (u16)(val>>16));
+-                      break;
+-              }
+-      }
+-      else
+-#endif
+-      {
+-              if (len != 4) {
+-                      value = in_le32(hose->cfg_data);
+-
+-                      offset = (offset & 0x3) << 3;
+-                      mask = (0xffffffff >> (32 - (len << 3)));
+-                      mask <<= offset;
+-
+-                      value &= ~mask;
+-                      val = value | ((val << offset) & mask);
+-              }
+-
+-              out_le32(hose->cfg_data, val);
+-      }
+-      mb();
+-
+-      out_be32(hose->cfg_addr, 0);
+-      mb();
+-
+-      return PCIBIOS_SUCCESSFUL;
+-}
+-
+-static struct pci_ops mpc52xx_pci_ops = {
+-      .read  = mpc52xx_pci_read_config,
+-      .write = mpc52xx_pci_write_config
+-};
+-
+-
+-static void __init
+-mpc52xx_pci_setup(struct pci_controller *hose,
+-                  struct mpc52xx_pci __iomem *pci_regs)
+-{
+-      struct resource *res;
+-      u32 tmp;
+-      int iwcr0 = 0, iwcr1 = 0, iwcr2 = 0;
+-
+-      pr_debug("mpc52xx_pci_setup(hose=%p, pci_regs=%p)\n", hose, pci_regs);
+-
+-      /* pci_process_bridge_OF_ranges() found all our addresses for us;
+-       * now store them in the right places */
+-      hose->cfg_addr = &pci_regs->car;
+-      hose->cfg_data = hose->io_base_virt;
+-      hose->io_base_virt = ioremap(hose->io_base_phys,
+-                                   hose->io_resource.end + 1 -
+-                                   hose->io_resource.start);
+-      isa_io_base = (unsigned long) hose->io_base_virt;
+-
+-      /* Control regs */
+-      tmp = in_be32(&pci_regs->scr);
+-      tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+-      out_be32(&pci_regs->scr, tmp);
+-
+-      /* Memory windows */
+-      res = &hose->mem_resources[0];
+-      if (res->flags) {
+-              pr_debug("mem_resource[0] = {.start=%x, .end=%x, .flags=%lx}\n",
+-                       res->start, res->end, res->flags);
+-              out_be32(&pci_regs->iw0btar,
+-                       MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
+-                                res->end - res->start + 1));
+-              iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
+-              if (res->flags & IORESOURCE_PREFETCH)
+-                      iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
+-              else
+-                      iwcr0 |= MPC52xx_PCI_IWCR_READ;
+-      }
+-
+-      res = &hose->mem_resources[1];
+-      if (res->flags) {
+-              pr_debug("mem_resource[1] = {.start=%x, .end=%x, .flags=%lx}\n",
+-                       res->start, res->end, res->flags);
+-              out_be32(&pci_regs->iw1btar,
+-                       MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
+-                                res->end - res->start + 1));
+-              iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
+-              if (res->flags & IORESOURCE_PREFETCH)
+-                      iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
+-              else
+-                      iwcr1 |= MPC52xx_PCI_IWCR_READ;
+-      }
+-
+-      /* IO resources */
+-      res = &hose->io_resource;
+-      if (!res) {
+-              printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__);
+-              return;
+-      }
+-      pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
+-               ".io_base_phys=0x%p\n",
+-               res->start, res->end, res->flags, (void*)hose->io_base_phys);
+-      out_be32(&pci_regs->iw2btar,
+-               MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
+-                                              res->start,
+-                                              res->end - res->start + 1));
+-      iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
+-
+-      /* Set all the IWCR fields at once; they're in the same reg */
+-      out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2));
+-
+-      out_be32(&pci_regs->tbatr0,
+-              MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
+-      out_be32(&pci_regs->tbatr1,
+-              MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
+-
+-      out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
+-
+-#if 0
+-      /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
+-      /* Not necessary and can be a bad thing if for example the bootloader
+-         is displaying a splash screen or ... Just left here for
+-         documentation purpose if anyone need it */
+-      tmp = in_be32(&pci_regs->gscr);
+-      out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
+-      udelay(50);
+-      out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
+-#endif
+-}
+-
+-static void
+-mpc52xx_pci_fixup_resources(struct pci_dev *dev)
+-{
+-      int i;
+-
+-      pr_debug("mpc52xx_pci_fixup_resources() %.4x:%.4x\n",
+-               dev->vendor, dev->device);
+-
+-      /* We don't rely on boot loader for PCI and resets all
+-         devices */
+-      for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+-              struct resource *res = &dev->resource[i];
+-              if (res->end > res->start) {    /* Only valid resources */
+-                      res->end -= res->start;
+-                      res->start = 0;
+-                      res->flags |= IORESOURCE_UNSET;
+-              }
+-      }
+-
+-      /* The PCI Host bridge of MPC52xx has a prefetch memory resource
+-         fixed to 1Gb. Doesn't fit in the resource system so we remove it */
+-      if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
+-           (   dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
+-            || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
+-              struct resource *res = &dev->resource[1];
+-              res->start = res->end = res->flags = 0;
+-      }
+-}
+-
+-int __init
+-mpc52xx_add_bridge(struct device_node *node)
+-{
+-      int len;
+-      struct mpc52xx_pci __iomem *pci_regs;
+-      struct pci_controller *hose;
+-      const int *bus_range;
+-      struct resource rsrc;
+-
+-      pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
+-
+-      pci_assign_all_buses = 1;
+-
+-      if (of_address_to_resource(node, 0, &rsrc) != 0) {
+-              printk(KERN_ERR "Can't get %s resources\n", node->full_name);
+-              return -EINVAL;
+-      }
+-
+-      bus_range = get_property(node, "bus-range", &len);
+-      if (bus_range == NULL || len < 2 * sizeof(int)) {
+-              printk(KERN_WARNING "Can't get %s bus-range, assume bus 0\n",
+-                     node->full_name);
+-              bus_range = NULL;
+-      }
+-
+-      /* There are some PCI quirks on the 52xx, register the hook to
+-       * fix them. */
+-      ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
+-
+-      /* Alloc and initialize the pci controller.  Values in the device
+-       * tree are needed to configure the 52xx PCI controller.  Rather
+-       * than parse the tree here, let pci_process_bridge_OF_ranges()
+-       * do it for us and extract the values after the fact */
+-      hose = pcibios_alloc_controller();
+-      if (!hose)
+-              return -ENOMEM;
+-
+-      hose->arch_data = node;
+-      hose->set_cfg_type = 1;
+-
+-      hose->first_busno = bus_range ? bus_range[0] : 0;
+-      hose->last_busno = bus_range ? bus_range[1] : 0xff;
+-
+-      hose->bus_offset = 0;
+-      hose->ops = &mpc52xx_pci_ops;
+-
+-      pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
+-      if (!pci_regs)
+-              return -ENOMEM;
+-
+-      pci_process_bridge_OF_ranges(hose, node, 0);
+-
+-      /* Finish setting up PCI using values obtained by
+-       * pci_proces_bridge_OF_ranges */
+-      mpc52xx_pci_setup(hose, pci_regs);
+-
+-      return 0;
+-}
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0031-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt b/packages/linux/linux-efika-2.6.20/0031-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt
new file mode 100644 (file)
index 0000000..5e8d5a2
--- /dev/null
@@ -0,0 +1,828 @@
+From 46e8903e34759728afd11dd11c481e6a94e6b06d Mon Sep 17 00:00:00 2001
+From: Sylvain Munaut <tnt@246tNt.com>
+Date: Mon, 18 Dec 2006 22:51:38 +0100
+Subject: [PATCH] [PATCH] sound: Add support for the MPC52xx PSC AC97 Link
+
+Messy driver, to be cleaned ... a lot ...
+
+Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
+---
+ include/asm-ppc/mpc52xx_psc.h |   10 +-
+ sound/ppc/Kconfig             |   16 +
+ sound/ppc/Makefile            |    3 +
+ sound/ppc/mpc52xx_ac97.c      |  738 +++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 765 insertions(+), 2 deletions(-)
+
+diff --git a/include/asm-ppc/mpc52xx_psc.h b/include/asm-ppc/mpc52xx_psc.h
+index 9d850b2..c82b8d4 100644
+--- a/include/asm-ppc/mpc52xx_psc.h
++++ b/include/asm-ppc/mpc52xx_psc.h
+@@ -28,6 +28,10 @@
+ #define MPC52xx_PSC_MAXNUM    6
+ /* Programmable Serial Controller (PSC) status register bits */
++#define MPC52xx_PSC_SR_UNEX_RX        0x0001
++#define MPC52xx_PSC_SR_DATA_VAL       0x0002
++#define MPC52xx_PSC_SR_DATA_OVR       0x0004
++#define MPC52xx_PSC_SR_CMDSEND        0x0008
+ #define MPC52xx_PSC_SR_CDE    0x0080
+ #define MPC52xx_PSC_SR_RXRDY  0x0100
+ #define MPC52xx_PSC_SR_RXFULL 0x0200
+@@ -132,8 +136,10 @@ struct mpc52xx_psc {
+       u8              reserved5[3];
+       u8              ctlr;           /* PSC + 0x1c */
+       u8              reserved6[3];
+-      u16             ccr;            /* PSC + 0x20 */
+-      u8              reserved7[14];
++      u32             ccr;            /* PSC + 0x20 */
++      u32             ac97_slots;     /* PSC + 0x24 */
++      u32             ac97_cmd;       /* PSC + 0x28 */
++      u32             ac97_data;      /* PSC + 0x2c */
+       u8              ivr;            /* PSC + 0x30 */
+       u8              reserved8[3];
+       u8              ip;             /* PSC + 0x34 */
+diff --git a/sound/ppc/Kconfig b/sound/ppc/Kconfig
+index a3fb149..afd58f7 100644
+--- a/sound/ppc/Kconfig
++++ b/sound/ppc/Kconfig
+@@ -33,3 +33,19 @@ config SND_POWERMAC_AUTO_DRC
+         option.
+ endmenu
++
++
++# ALSA ppc drivers
++
++menu "ALSA PPC devices"
++      depends on SND!=n && PPC
++
++config SND_PPC_MPC52xx_AC97
++      tristate "Freescale MPC52xx AC97 interface support"
++      depends on SND && PPC_MPC52xx
++      select SND_AC97_CODEC
++      help
++        Say Y or M if you want to support any AC97 codec attached to
++        the Freescqle MPC52xx AC97 interface.
++
++endmenu
+diff --git a/sound/ppc/Makefile b/sound/ppc/Makefile
+index 4d95c65..c29cb9b 100644
+--- a/sound/ppc/Makefile
++++ b/sound/ppc/Makefile
+@@ -4,6 +4,9 @@
+ #
+ snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
++snd-mpc52xx-ac97-objs := mpc52xx_ac97.o
+ # Toplevel Module Dependency
+ obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
++
++obj-$(CONFIG_SND_PPC_MPC52xx_AC97)    += snd-mpc52xx-ac97.o
+diff --git a/sound/ppc/mpc52xx_ac97.c b/sound/ppc/mpc52xx_ac97.c
+new file mode 100644
+index 0000000..a4f008e
+--- /dev/null
++++ b/sound/ppc/mpc52xx_ac97.c
+@@ -0,0 +1,738 @@
++/*
++ * Driver for the PSC of the Freescale MPC52xx configured as AC97 interface
++ *
++ *
++ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
++ *
++ * 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.
++ */
++
++#define DEBUG
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++
++#include <sound/driver.h>
++#include <sound/core.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/ac97_codec.h>
++
++#include <asm/of_platform.h>
++#include <asm/mpc52xx_psc.h>
++
++
++#define DRV_NAME "mpc52xx-psc-ac97"
++
++
++/* ======================================================================== */
++/* Structs / Defines                                                        */
++/* ======================================================================== */
++
++/* Private structure */
++struct mpc52xx_ac97_priv {
++      struct device *dev;
++      resource_size_t mem_start;
++      resource_size_t mem_len;
++      int irq;
++      struct mpc52xx_psc __iomem *psc;
++      struct snd_card *card;
++      struct snd_pcm *pcm;
++      struct snd_ac97 *ac97;
++
++      struct snd_pcm_substream *substream_playback;
++      unsigned int buf_pos;
++};
++
++/* Register bit definition (AC97 mode specific) */
++#define PSC_AC97_SLOT_BIT(n)          (1<<(12-n))
++#define PSC_AC97_SLOTS_XMIT_SHIFT     16
++#define PSC_AC97_SLOTS_RECV_SHIFT      0
++
++
++
++/* ======================================================================== */
++/* ISR routine                                                              */
++/* ======================================================================== */
++
++static irqreturn_t
++mpc52xx_ac97_irq(int irq, void *dev_id)
++{
++      struct mpc52xx_ac97_priv *priv = dev_id;
++
++      static int icnt = 0;
++      #if 0
++      {
++      unsigned int val;
++//    val = in_be32(&priv->psc->ac97_data);
++      printk(KERN_INFO "mpc52xx_ac97_irq fired (isr=%04x, status=%04x) %08x\n", in_be16(&priv->psc->mpc52xx_psc_imr), in_be16(&priv->psc->mpc52xx_psc_status), val);
++      out_8(&priv->psc->command,MPC52xx_PSC_RST_ERR_STAT);
++      }
++      #endif
++
++      /* Anti Crash during dev ;) */
++      #if 0
++      if ((icnt++) > 50000)
++              out_be16(&priv->psc->mpc52xx_psc_imr, 0);
++      #endif
++
++      /* Copy 64 data into the buffer */
++      if (in_be16(&priv->psc->mpc52xx_psc_imr) & 0x0100) {
++              if (priv->substream_playback) {
++                      struct snd_pcm_runtime *rt;
++
++                      rt = priv->substream_playback->runtime;
++
++                      if (snd_pcm_playback_hw_avail(rt) < bytes_to_frames(rt,128)) {
++                              int i;
++                              /* Push silence */
++                              for (i=0; i<64; i++)
++                                      out_be32(&priv->psc->mpc52xx_psc_buffer_32, 0x00000800);
++                              printk(KERN_DEBUG "pushed silence ...\n");
++                      } else {
++                              int i;
++                              unsigned short *data;
++
++                              data = (unsigned short *)
++                                      (&rt->dma_area[frames_to_bytes(rt, priv->buf_pos)]);
++
++                              for (i=0; i<64; i++)
++                                      out_be32(&priv->psc->mpc52xx_psc_buffer_32,
++                                              (((unsigned int)data[i]) << 16) | 0x00000000);
++                                                      /* Setting the sof bit looks useless */
++
++                              priv->buf_pos += bytes_to_frames(rt,128);;
++                              if (priv->buf_pos >= rt->buffer_size)
++                                      priv->buf_pos = 0;
++
++                              snd_pcm_period_elapsed(priv->substream_playback);
++                      }
++              } else {
++                      out_be16(&priv->psc->mpc52xx_psc_imr, 0);
++                      printk(KERN_DEBUG "Interrupt with no stream ...\n");
++              }
++      } else {
++              printk(KERN_ERR "Spurious int\n");
++      }
++
++      return IRQ_HANDLED;
++}
++
++
++/* ======================================================================== */
++/* PCM interface                                                            */
++/* ======================================================================== */
++
++/* HW desc */
++
++static struct snd_pcm_hardware mpc52xx_ac97_hw = {
++      .info                   = SNDRV_PCM_INFO_INTERLEAVED            |
++                                      SNDRV_PCM_INFO_MMAP             |
++                                      SNDRV_PCM_INFO_MMAP_VALID,
++      .formats                = SNDRV_PCM_FMTBIT_S16_BE,
++      .rates                  = SNDRV_PCM_RATE_8000_48000,
++      .rate_min               = 8000,
++      .rate_max               = 48000,
++      .channels_min           = 1,
++      .channels_max           = 2,    /* Support for more ? */
++      .buffer_bytes_max       = 128*1024,
++      .period_bytes_min       = 128, /* 32, */
++      .period_bytes_max       = 128, /* 16*1024, */
++      .periods_min            = 8,
++      .periods_max            = 256,
++      .fifo_size              = 512,
++};
++
++
++/* Playback */
++
++static int
++mpc52xx_ac97_playback_open(struct snd_pcm_substream *substream)
++{
++      struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++
++      dev_dbg(priv->dev, "mpc52xx_ac97_playback_open(%p)\n", substream);
++
++      substream->runtime->hw = mpc52xx_ac97_hw;
++
++      priv->substream_playback = substream;
++      priv->buf_pos = 0;      /* FIXME Do that where ? */
++
++      return 0;       /* FIXME */
++}
++
++static int
++mpc52xx_ac97_playback_close(struct snd_pcm_substream *substream)
++{
++      struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++      dev_dbg(priv->dev, "mpc52xx_ac97_playback_close(%p)\n", substream);
++      priv->substream_playback = NULL;
++      return 0;       /* FIXME */
++}
++
++static int
++mpc52xx_ac97_playback_prepare(struct snd_pcm_substream *substream)
++{
++      struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++
++      dev_dbg(priv->dev, "mpc52xx_ac97_playback_prepare(%p)\n", substream);
++
++      /* FIXME, need a spinlock to protect access */
++      if (substream->runtime->channels == 1)
++              out_be32(&priv->psc->ac97_slots, 0x01000000);
++      else
++              out_be32(&priv->psc->ac97_slots, 0x03000000);
++
++      snd_ac97_set_rate(priv->ac97, AC97_PCM_FRONT_DAC_RATE, substream->runtime->rate);
++
++      return 0;       /* FIXME */
++}
++
++
++/* Capture */
++
++static int
++mpc52xx_ac97_capture_open(struct snd_pcm_substream *substream)
++{
++      struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++      return 0;       /* FIXME */
++}
++
++static int
++mpc52xx_ac97_capture_close(struct snd_pcm_substream *substream)
++{
++      struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++      return 0;       /* FIXME */
++}
++
++static int
++mpc52xx_ac97_capture_prepare(struct snd_pcm_substream *substream)
++{
++      struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++      return 0;       /* FIXME */
++}
++
++
++/* Common */
++
++static int
++mpc52xx_ac97_hw_params(struct snd_pcm_substream *substream,
++                      struct snd_pcm_hw_params *params)
++{
++      struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++      int rv;
++
++      dev_dbg(priv->dev, "mpc52xx_ac97_hw_params(%p)\n", substream);
++
++      rv = snd_pcm_lib_malloc_pages(substream,
++                                      params_buffer_bytes(params));
++      if (rv < 0) {
++              printk(KERN_ERR "hw params failes\n");  /* FIXME */
++              return rv;
++      }
++
++      printk(KERN_DEBUG "%d %d %d\n", params_buffer_bytes(params), params_period_bytes(params), params_periods(params));
++
++
++      return 0;
++}
++
++static int
++mpc52xx_ac97_hw_free(struct snd_pcm_substream *substream)
++{
++      struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++
++      dev_dbg(priv->dev, "mpc52xx_ac97_hw_free(%p)\n", substream);
++
++      return snd_pcm_lib_free_pages(substream);
++}
++
++static int
++mpc52xx_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
++{
++      struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++      int rv = 0;
++
++      dev_dbg(priv->dev, "mpc52xx_ac97_trigger(%p,%d)\n", substream, cmd);
++
++      switch (cmd) {
++              case SNDRV_PCM_TRIGGER_START:
++                      /* Enable TX interrupt */
++                      out_be16(&priv->psc->mpc52xx_psc_imr, 0x0100); // 0x0100
++
++                      break;
++
++              case SNDRV_PCM_TRIGGER_STOP:
++                      /* Disable TX interrupt */
++                      out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
++
++                      break;
++
++              default:
++                      rv = -EINVAL;
++      }
++
++      /* FIXME */
++      return rv;
++}
++
++static snd_pcm_uframes_t
++mpc52xx_ac97_pointer(struct snd_pcm_substream *substream)
++{
++      struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
++
++//    dev_dbg(priv->dev, "mpc52xx_ac97_pointer(%p)\n", substream);
++
++      if (substream->runtime->channels == 1)
++              return priv->buf_pos;   /* FIXME */
++      else
++              return priv->buf_pos >> 1;      /* FIXME */
++}
++
++
++/* Ops */
++
++static struct snd_pcm_ops mpc52xx_ac97_playback_ops = {
++      .open           = mpc52xx_ac97_playback_open,
++      .close          = mpc52xx_ac97_playback_close,
++      .ioctl          = snd_pcm_lib_ioctl,
++      .hw_params      = mpc52xx_ac97_hw_params,
++      .hw_free        = mpc52xx_ac97_hw_free,
++      .prepare        = mpc52xx_ac97_playback_prepare,
++      .trigger        = mpc52xx_ac97_trigger,
++      .pointer        = mpc52xx_ac97_pointer,
++};
++
++static struct snd_pcm_ops mpc52xx_ac97_capture_ops = {
++      .open           = mpc52xx_ac97_capture_open,
++      .close          = mpc52xx_ac97_capture_close,
++      .ioctl          = snd_pcm_lib_ioctl,
++      .hw_params      = mpc52xx_ac97_hw_params,
++      .hw_free        = mpc52xx_ac97_hw_free,
++      .prepare        = mpc52xx_ac97_capture_prepare,
++      .trigger        = mpc52xx_ac97_trigger,
++      .pointer        = mpc52xx_ac97_pointer,
++};
++
++
++/* ======================================================================== */
++/* AC97 Bus interface                                                       */
++/* ======================================================================== */
++
++static unsigned short
++mpc52xx_ac97_bus_read(struct snd_ac97 *ac97, unsigned short reg)
++{
++      struct mpc52xx_ac97_priv *priv = ac97->private_data;
++      int timeout;
++      unsigned int val;
++
++      dev_dbg(priv->dev, "ac97 read: reg %04x\n", reg);
++
++      /* Wait for it to be ready */
++      timeout = 1000;
++      while ((--timeout) && (in_be16(&priv->psc->mpc52xx_psc_status) &
++                                              MPC52xx_PSC_SR_CMDSEND) )
++              udelay(10);
++
++      if (!timeout) {
++              printk(KERN_ERR DRV_NAME ": timeout on ac97 bus (rdy)\n");
++              return 0xffff;
++      }
++
++      /* Do the read */
++      out_be32(&priv->psc->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));
++
++      /* Wait for the answer */
++      timeout = 1000;
++      while ((--timeout) && !(in_be16(&priv->psc->mpc52xx_psc_status) &
++                                              MPC52xx_PSC_SR_DATA_VAL) )
++              udelay(10);
++
++      if (!timeout) {
++              printk(KERN_ERR DRV_NAME ": timeout on ac97 read (val)\n");
++              return 0xffff;
++      }
++
++      /* Get the data */
++      val = in_be32(&priv->psc->ac97_data);
++      if ( ((val>>24) & 0x7f) != reg ) {
++              printk(KERN_ERR DRV_NAME ": reg echo error on ac97 read\n");
++              return 0xffff;
++      }
++      val = (val >> 8) & 0xffff;
++
++      dev_dbg(priv->dev, "ac97 read ok: reg %04x  val %04x\n",
++                              reg, val);
++
++      return (unsigned short) val;
++}
++
++static void
++mpc52xx_ac97_bus_write(struct snd_ac97 *ac97,
++                      unsigned short reg, unsigned short val)
++{
++      struct mpc52xx_ac97_priv *priv = ac97->private_data;
++      int timeout;
++
++      dev_dbg(priv->dev, "ac97 write: reg %04x  val %04x\n",
++                              reg, val);
++
++      /* Wait for it to be ready */
++      timeout = 1000;
++      while ((--timeout) && (in_be16(&priv->psc->mpc52xx_psc_status) &
++                                              MPC52xx_PSC_SR_CMDSEND) )
++              udelay(10);
++
++      if (!timeout) {
++              printk(KERN_ERR DRV_NAME ": timeout on ac97 write\n");
++              return;
++      }
++
++      /* Write data */
++      out_be32(&priv->psc->ac97_cmd, ((reg & 0x7f) << 24) | (val << 8));
++}
++
++static void
++mpc52xx_ac97_bus_reset(struct snd_ac97 *ac97)
++{
++      struct mpc52xx_ac97_priv *priv = ac97->private_data;
++
++      dev_dbg(priv->dev, "ac97 codec reset\n");
++
++      /* Do a cold reset */
++      out_8(&priv->psc->op1, 0x03);
++      udelay(10);
++      out_8(&priv->psc->op0, 0x02);
++      udelay(50);
++
++      /* PSC recover from cold reset (cfr user manual, not sure if useful) */
++      out_be32(&priv->psc->sicr, in_be32(&priv->psc->sicr));
++}
++
++
++static struct snd_ac97_bus_ops mpc52xx_ac97_bus_ops = {
++      .read   = mpc52xx_ac97_bus_read,
++      .write  = mpc52xx_ac97_bus_write,
++      .reset  = mpc52xx_ac97_bus_reset,
++};
++
++
++/* ======================================================================== */
++/* Sound driver setup                                                       */
++/* ======================================================================== */
++
++static int
++mpc52xx_ac97_setup_pcm(struct mpc52xx_ac97_priv *priv)
++{
++      int rv;
++
++      rv = snd_pcm_new(priv->card, DRV_NAME "-pcm", 0, 1, 1, &priv->pcm);
++      if (rv) {
++              printk(KERN_ERR DRV_NAME ": snd_pcm_new failed\n");
++              return rv;
++      }
++
++      rv = snd_pcm_lib_preallocate_pages_for_all(priv->pcm,
++              SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL),
++              128*1024, 128*1024);
++      if (rv) {
++              printk(KERN_ERR DRV_NAME
++                      ": snd_pcm_lib_preallocate_pages_for_all  failed\n");
++              return rv;
++      }
++
++      snd_pcm_set_ops(priv->pcm, SNDRV_PCM_STREAM_PLAYBACK,
++                      &mpc52xx_ac97_playback_ops);
++      snd_pcm_set_ops(priv->pcm, SNDRV_PCM_STREAM_CAPTURE,
++                      &mpc52xx_ac97_capture_ops);
++
++      priv->pcm->private_data = priv;
++      priv->pcm->info_flags = 0;
++
++      strcpy(priv->pcm->name, "Freescale MPC52xx PSC-AC97 PCM");
++
++      return 0;
++}
++
++static int
++mpc52xx_ac97_setup_mixer(struct mpc52xx_ac97_priv *priv)
++{
++      struct snd_ac97_bus *ac97_bus;
++      struct snd_ac97_template ac97_template;
++      int rv;
++
++      rv = snd_ac97_bus(priv->card, 0, &mpc52xx_ac97_bus_ops, NULL, &ac97_bus);
++      if (rv) {
++              printk(KERN_ERR DRV_NAME ": snd_ac97_bus failed\n");
++              return rv;
++      }
++
++      memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
++      ac97_template.private_data = priv;
++
++      rv = snd_ac97_mixer(ac97_bus, &ac97_template, &priv->ac97);
++      if (rv) {
++              printk(KERN_ERR DRV_NAME ": snd_ac97_mixer failed\n");
++              return rv;
++      }
++
++      return 0;
++}
++
++
++static int
++mpc52xx_ac97_hwinit(struct mpc52xx_ac97_priv *priv)
++{
++      /* Reset everything first by safety */
++      out_8(&priv->psc->command,MPC52xx_PSC_RST_RX);
++      out_8(&priv->psc->command,MPC52xx_PSC_RST_TX);
++      out_8(&priv->psc->command,MPC52xx_PSC_RST_ERR_STAT);
++
++      /* Do a cold reset of codec */
++      out_8(&priv->psc->op1, 0x03);
++      udelay(10);
++      out_8(&priv->psc->op0, 0x02);
++      udelay(50);
++
++      /* Configure AC97 enhanced mode */
++      out_be32(&priv->psc->sicr, 0x03010000);
++
++      /* No slots active */
++      out_be32(&priv->psc->ac97_slots, 0x00000000);
++
++      /* No IRQ */
++      out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
++
++      /* FIFO levels */
++      out_8(&priv->psc->rfcntl, 0x07);
++      out_8(&priv->psc->tfcntl, 0x07);
++      out_be16(&priv->psc->rfalarm, 0x80);
++      out_be16(&priv->psc->tfalarm, 0x80);
++
++      /* Go */
++      out_8(&priv->psc->command,MPC52xx_PSC_TX_ENABLE);
++      out_8(&priv->psc->command,MPC52xx_PSC_RX_ENABLE);
++
++      return 0;
++}
++
++static int
++mpc52xx_ac97_hwshutdown(struct mpc52xx_ac97_priv *priv)
++{
++      /* No IRQ */
++      out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
++
++      /* Disable TB & RX */
++      out_8(&priv->psc->command,MPC52xx_PSC_RST_RX);
++      out_8(&priv->psc->command,MPC52xx_PSC_RST_TX);
++
++      /* FIXME : Reset or put codec in low power ? */
++
++      return 0;
++}
++
++
++/* ======================================================================== */
++/* OF Platform Driver                                                       */
++/* ======================================================================== */
++
++static int __devinit
++mpc52xx_ac97_probe(struct of_device *op, const struct of_device_id *match)
++{
++      struct device_node *dn = op->node;
++      struct mpc52xx_ac97_priv *priv;
++      struct snd_card *card;
++      struct resource res;
++      int rv;
++
++      dev_dbg(&op->dev, "probing MPC52xx PSC AC97 driver\n");
++
++      /* Get card structure */
++      rv = -ENOMEM;
++      card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
++                              THIS_MODULE, sizeof(struct mpc52xx_ac97_priv));
++      if (!card)
++              goto err_early;
++
++      priv = card->private_data;
++
++      /* Init our private structure */
++      priv->card = card;
++      priv->dev = &op->dev;
++
++      /* Get resources (mem,irq,...) */
++      rv = of_address_to_resource(dn, 0, &res);
++      if (rv)
++              goto err_early;
++
++      priv->mem_start = res.start;
++      priv->mem_len = res.end - res.start + 1;
++
++      if (!request_mem_region(priv->mem_start, priv->mem_len, DRV_NAME)) {
++              printk(KERN_ERR DRV_NAME ": request_mem_region failed\n");
++              rv = -EBUSY;
++              goto err_early;
++      }
++
++      priv->psc = ioremap(priv->mem_start, priv->mem_len);
++      if (!priv->psc) {
++              printk(KERN_ERR DRV_NAME ": ioremap failed\n");
++              rv = -ENOMEM;
++              goto err_iomap;
++      }
++
++      priv->irq = irq_of_parse_and_map(dn, 0);
++      if (priv->irq == NO_IRQ) {
++              printk(KERN_ERR DRV_NAME ": irq_of_parse_and_map failed\n");
++              rv = -EBUSY;
++              goto err_irqmap;
++      }
++
++      /* Low level HW Init */
++      mpc52xx_ac97_hwinit(priv);
++
++      /* Request IRQ now that we're 'stable' */
++      rv = request_irq(priv->irq, mpc52xx_ac97_irq, 0, DRV_NAME, priv);
++      if (rv < 0) {
++              printk(KERN_ERR DRV_NAME ": request_irq failed\n");
++              goto err_irqreq;
++      }
++
++      /* Prepare sound stuff */
++      rv = mpc52xx_ac97_setup_mixer(priv);
++      if (rv)
++              goto err_late;
++
++      rv = mpc52xx_ac97_setup_pcm(priv);
++      if (rv)
++              goto err_late;
++
++      /* Finally register the card */
++      snprintf(card->shortname, sizeof(card->shortname), DRV_NAME);
++      snprintf(card->longname, sizeof(card->longname),
++              "Freescale MPC52xx PSC-AC97 (%s)", card->mixername);
++
++      rv = snd_card_register(card);
++      if (rv) {
++              printk(KERN_ERR DRV_NAME ": snd_card_register failed\n");
++              goto err_late;
++      }
++
++      dev_set_drvdata(&op->dev, priv);
++
++      return 0;
++
++err_late:
++      free_irq(priv->irq, priv);
++err_irqreq:
++      mpc52xx_ac97_hwshutdown(priv);
++      irq_dispose_mapping(priv->irq);
++err_irqmap:
++      iounmap(priv->psc);
++err_iomap:
++      release_mem_region(priv->mem_start, priv->mem_len);
++err_early:
++      if (card)
++              snd_card_free(card);
++      return rv;
++}
++
++static int
++mpc52xx_ac97_remove(struct of_device *op)
++{
++      struct mpc52xx_ac97_priv *priv;
++
++      dev_dbg(&op->dev, "removing MPC52xx PSC AC97 driver\n");
++
++      priv = dev_get_drvdata(&op->dev);
++      if (priv) {
++              /* Sound subsys shutdown */
++              snd_card_free(priv->card);
++
++              /* Low level HW shutdown */
++              mpc52xx_ac97_hwshutdown(priv);
++
++              /* Release resources */
++              iounmap(priv->psc);
++              free_irq(priv->irq, priv);
++              irq_dispose_mapping(priv->irq);
++              release_mem_region(priv->mem_start, priv->mem_len);
++      }
++
++      dev_set_drvdata(&op->dev, NULL);
++
++      return 0;
++}
++
++
++static struct of_device_id mpc52xx_ac97_of_match[] = {
++      {
++/*            .type           = "ac97",       FIXME Efika ... */
++              .compatible     = "mpc5200b-psc-ac97",  /* B only for now */
++      },
++};
++/* Prevent autoload during developpment phase ... */
++/* MODULE_DEVICE_TABLE(of, mpc52xx_ac97_of_match); */
++
++
++static struct of_platform_driver mpc52xx_ac97_of_driver = {
++      .owner          = THIS_MODULE,
++      .name           = DRV_NAME,
++      .match_table    = mpc52xx_ac97_of_match,
++      .probe          = mpc52xx_ac97_probe,
++      .remove         = mpc52xx_ac97_remove,
++      .driver         = {
++              .name   = DRV_NAME,
++      },
++};
++
++
++/* ======================================================================== */
++/* Module                                                                   */
++/* ======================================================================== */
++
++static int __init
++mpc52xx_ac97_init(void)
++{
++      int rv;
++
++      /* FIXME BIG FAT EFIKA HACK */
++      {
++              void *mbar;
++              mbar = ioremap(0xf0000000, 0x100000);
++              printk(KERN_INFO "EFIKA HACK: port_config %08x\n", in_be32(mbar + 0xb00));
++              out_be32(mbar + 0xb00, 0x01051124);
++              printk(KERN_INFO "EFIKA HACK: port_config %08x\n", in_be32(mbar + 0xb00));
++              iounmap(mbar);
++      }
++      /* ------------------------ */
++
++      printk(KERN_INFO "Sound: MPC52xx PSC AC97 driver\n");
++
++      rv = of_register_platform_driver(&mpc52xx_ac97_of_driver);
++      if (rv) {
++              printk(KERN_ERR DRV_NAME ": "
++                      "of_register_platform_driver failed (%i)\n", rv);
++              return rv;
++      }
++
++      return 0;
++}
++
++static void __exit
++mpc52xx_ac97_exit(void)
++{
++      of_unregister_platform_driver(&mpc52xx_ac97_of_driver);
++}
++
++module_init(mpc52xx_ac97_init);
++module_exit(mpc52xx_ac97_exit);
++
++MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
++MODULE_DESCRIPTION(DRV_NAME ": Freescale MPC52xx PSC AC97 driver");
++MODULE_LICENSE("GPL");
++
+-- 
+1.4.4.2
+
diff --git a/packages/linux/linux-efika-2.6.20/0032-POWERPC-EFIKA-Adds-missing-interrupts-from-bestcomm-node.txt b/packages/linux/linux-efika-2.6.20/0032-POWERPC-EFIKA-Adds-missing-interrupts-from-bestcomm-node.txt
new file mode 100644 (file)
index 0000000..1e07358
--- /dev/null
@@ -0,0 +1,36 @@
+From: Grant Likely <grant.likely@secretlab.ca>
+Date: Tue, 9 Jan 2007 08:40:11 +0000 (-0700)
+Subject: [POWERPC] Efika: Add missing interrupts from bestcomm node
+X-Git-Url: http://git.secretlab.ca/cgi-bin/gitweb.cgi?p=linux-2.6.git;a=commitdiff;h=7eaf3ab60bdf3b8850f30916e06934f2e1437eb3
+
+[POWERPC] Efika: Add missing interrupts from bestcomm node
+
+The efika device tree does not have the list of bestcomm interrupts which
+are expected by the Linux 52xx bestcomm device driver.  This adds the
+expected properties
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+
+--- a/arch/powerpc/kernel/prom_init.c
++++ b/arch/powerpc/kernel/prom_init.c
+@@ -2136,11 +2136,17 @@ static void __init fixup_device_tree_efi
+       /* Substitution table */
+       #define prop_cstr(x) x, sizeof(x)
+       int prop_sound_irq[3] = { 2, 2, 0 };
++      int prop_bestcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
++                                      3,4,0, 3,5,0, 3,6,0, 3,7,0,
++                                      3,8,0, 3,9,0, 3,10,0, 3,11,0,
++                                      3,12,0, 3,13,0, 3,14,0, 3,15,0,
++                                    };
+       struct subst_entry efika_subst_table[] = {
+               { "/",                  "device_type",  prop_cstr("efika") },
+               { "/builtin",           "compatible",   prop_cstr("soc") },
+               { "/builtin/ata",       "compatible",   prop_cstr("mpc5200b-ata\0mpc52xx-ata"), },
+               { "/builtin/bestcomm",  "compatible",   prop_cstr("mpc5200b-bestcomm\0mpc52xx-bestcomm") },
++              { "/builtin/bestcomm",  "interrupts",   prop_bestcomm_irq, sizeof(prop_bestcomm_irq) },
+               { "/builtin/ethernet",  "compatible",   prop_cstr("mpc5200b-fec\0mpc52xx-fec") },
+               { "/builtin/pic",       "compatible",   prop_cstr("mpc5200b-pic\0mpc52xx-pic") },
+               { "/builtin/serial",    "compatible",   prop_cstr("mpc5200b-psc-uart\0mpc52xx-psc-uart") },
+--
+
diff --git a/packages/linux/linux-efika-2.6.20/defconfig b/packages/linux/linux-efika-2.6.20/defconfig
new file mode 100644 (file)
index 0000000..31908aa
--- /dev/null
@@ -0,0 +1,1621 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+# Mon Feb 19 13:47:40 2007
+#
+# 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_ARCH_HAS_ILOG2_U32=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=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_AUDIT_ARCH=y
+CONFIG_GENERIC_BUG=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+CONFIG_CLASSIC32=y
+# 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_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_PPC_DCR_NATIVE is not set
+# CONFIG_PPC_DCR_MMIO is not set
+# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+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="-efika"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+CONFIG_POSIX_MQUEUE=y
+# 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_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# 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 is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
+# Platform support
+#
+CONFIG_PPC_MULTIPLATFORM=y
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_APUS is not set
+CONFIG_PPC_CHRP=y
+CONFIG_PPC_MPC52xx=y
+CONFIG_PPC_MPC5200=y
+CONFIG_PPC_MPC5200_BUGFIX=y
+CONFIG_PPC_BESTCOMM=y
+CONFIG_PPC_EFIKA=y
+CONFIG_PPC_LITE5200=y
+# CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_CELL is not set
+# CONFIG_PPC_CELL_NATIVE is not set
+CONFIG_PPC_NATIVE=y
+CONFIG_UDBG_RTAS_CONSOLE=y
+CONFIG_PPC_RTAS=y
+# CONFIG_RTAS_ERROR_LOGGING is not set
+CONFIG_RTAS_PROC=y
+# CONFIG_MMIO_NVRAM is not set
+CONFIG_PPC_MPC106=y
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_PPC_INDIRECT_IO is not set
+# CONFIG_GENERIC_IOMAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_WANT_EARLY_SERIAL is not set
+CONFIG_MPIC=y
+CONFIG_USE_MDIO=y
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+# CONFIG_KEXEC is not set
+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=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,9600 console=ttyPSC0,115200"
+# CONFIG_PM is not set
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+# CONFIG_ISA is not set
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_MPIC_WEIRD is not set
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# 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_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# 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=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# 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 is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES 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=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+CONFIG_IRPORT_SIR=m
+
+#
+# Old Serial dongle support
+#
+# CONFIG_DONGLE_OLD is not set
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_NSC_FIR=m
+CONFIG_WINBOND_FIR=m
+CONFIG_TOSHIBA_FIR=m
+CONFIG_SMC_IRCC_FIR=m
+CONFIG_ALI_FIR=m
+CONFIG_VLSI_FIR=m
+CONFIG_VIA_FIR=m
+CONFIG_MCS_FIR=m
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+# CONFIG_IEEE80211_CRYPT_CCMP is not set
+# CONFIG_IEEE80211_CRYPT_TKIP is not set
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM 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_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_IDEDMA_IVB=y
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=y
+CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+# CONFIG_SATA_AHCI is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SX4 is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_CMD64X is not set
+# CONFIG_PATA_CS5520 is not set
+# CONFIG_PATA_CS5530 is not set
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+CONFIG_ATA_GENERIC=y
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_MARVELL is not set
+CONFIG_PATA_MPC52xx=y
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RZ1000 is not set
+# CONFIG_PATA_SC1200 is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_MAC_EMUMOUSEBTN is not set
+# 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
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# 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_BROADCOM_PHY is not set
+CONFIG_FIXED_PHY=m
+CONFIG_FIXED_MII_10_FDX=y
+CONFIG_FIXED_MII_100_FDX=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+CONFIG_NET_VENDOR_3COM=y
+CONFIG_VORTEX=m
+CONFIG_TYPHOON=m
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# MPC5200 Networking Options
+#
+CONFIG_FEC_MPC52xx=y
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=m
+# CONFIG_R8169_NAPI is not set
+CONFIG_SIS190=m
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+CONFIG_SK98LIN=m
+CONFIG_TIGON3=m
+# CONFIG_BNX2 is not set
+# CONFIG_MV643XX_ETH is not set
+# CONFIG_QLA3XXX is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_AIRO is not set
+# CONFIG_HERMES is not set
+CONFIG_ATMEL=m
+# CONFIG_PCI_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+CONFIG_USB_ZD1201=m
+CONFIG_HOSTAP=m
+# CONFIG_HOSTAP_FIRMWARE is not set
+CONFIG_HOSTAP_PLX=m
+CONFIG_HOSTAP_PCI=m
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLHC=m
+# CONFIG_SLIP_SMART is not set
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_NET_FC 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 is not set
+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=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# 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 is not set
+# 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=y
+# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_RAW=m
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=16
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_UARTLITE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_MPC52xx=y
+CONFIG_SERIAL_MPC52xx_CONSOLE=y
+CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_BRIQ_PANEL is not set
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_RTAS=y
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_WATCHDOG_RTAS=m
+
+#
+# PCI-based Watchdog Cards
+#
+CONFIG_PCIPCWATCHDOG=m
+CONFIG_WDTPCI=m
+CONFIG_WDT_501_PCI=y
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_HW_RANDOM=y
+CONFIG_NVRAM=y
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+CONFIG_AGP=m
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_HYDRA is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+CONFIG_I2C_OCORES=y
+CONFIG_I2C_PARPORT_LIGHT=y
+CONFIG_I2C_PROSAVAGE=m
+CONFIG_I2C_SAVAGE4=m
+CONFIG_I2C_SIS5595=m
+CONFIG_I2C_SIS630=m
+CONFIG_I2C_SIS96X=m
+# CONFIG_I2C_STUB is not set
+CONFIG_I2C_VIA=m
+CONFIG_I2C_VIAPRO=m
+CONFIG_I2C_VOODOO3=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+CONFIG_SENSORS_DS1337=m
+CONFIG_SENSORS_DS1374=m
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+CONFIG_SENSORS_PCA9539=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_SENSORS_M41T00=m
+CONFIG_SENSORS_MAX6875=m
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP 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 is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB=y
+CONFIG_FB_DDC=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_MACMODES=y
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+CONFIG_FB_RADEON=y
+CONFIG_FB_RADEON_I2C=y
+# CONFIG_FB_RADEON_DEBUG is not set
+CONFIG_FB_ATY128=y
+CONFIG_FB_ATY=y
+CONFIG_FB_ATY_CT=y
+CONFIG_FB_ATY_GENERIC_LCD=y
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_SAVAGE is not set
+CONFIG_FB_SIS=y
+CONFIG_FB_SIS_300=y
+CONFIG_FB_SIS_315=y
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_IBM_GXT4500 is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_BANDWIDTH=y
+CONFIG_USB_DYNAMIC_MINORS=y
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PPC_SOC=y
+CONFIG_USB_OHCI_HCD_PPC_OF=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
+CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
+CONFIG_USB_OHCI_HCD_PCI=y
+CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y
+CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=m
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+CONFIG_NEW_LEDS=y
+# CONFIG_LEDS_CLASS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# DMA Engine support
+#
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+CONFIG_NET_DMA=y
+
+#
+# DMA Devices
+#
+# CONFIG_INTEL_IOATDMA is not set
+
+#
+# Virtualization
+#
+
+#
+# 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=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+CONFIG_JFS_FS=y
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+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
+CONFIG_GENERIC_ACL=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# 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=y
+CONFIG_HFSPLUS_FS=y
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# 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=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# 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_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# 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=y
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# 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=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_BOOTX_TEXT=y
+CONFIG_SERIAL_TEXT_DEBUG=y
+# CONFIG_PPC_EARLY_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_MANAGER=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=m
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/packages/linux/linux-efika-2.6.20/v4l.diff b/packages/linux/linux-efika-2.6.20/v4l.diff
new file mode 100644 (file)
index 0000000..cf5643e
--- /dev/null
@@ -0,0 +1,28 @@
+diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
+index a00fe72..5b60c05 100644
+--- a/arch/powerpc/Makefile
++++ b/arch/powerpc/Makefile
+@@ -139,6 +139,8 @@ core-$(CONFIG_XMON)                += arch/powerpc/xmon/
+ drivers-$(CONFIG_OPROFILE)    += arch/powerpc/oprofile/
++libs-y                                += `$(CC) -print-libgcc-file-name`
++
+ # Default to zImage, override when needed
+ defaultimage-y                        := zImage
+ defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
+diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
+index 9179f07..dea8384 100644
+--- a/arch/powerpc/kernel/ppc_ksyms.c
++++ b/arch/powerpc/kernel/ppc_ksyms.c
+@@ -164,6 +164,9 @@ long long __lshrdi3(long long, int);
+ EXPORT_SYMBOL(__ashrdi3);
+ EXPORT_SYMBOL(__ashldi3);
+ EXPORT_SYMBOL(__lshrdi3);
++
++extern void __ucmpdi2(void);
++EXPORT_SYMBOL(__ucmpdi2);
+ #endif
+ EXPORT_SYMBOL(memcpy);
+
diff --git a/packages/linux/linux-efika_2.6.20.bb b/packages/linux/linux-efika_2.6.20.bb
new file mode 100644 (file)
index 0000000..79fa08e
--- /dev/null
@@ -0,0 +1,68 @@
+DESCRIPTION = "Linux Kernel for the EFIKA dev platform"
+SECTION = "kernel"
+LICENSE = "GPL"
+PR = "r0"
+
+COMPATIBLE_MACHINE = "efika"
+
+SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/linux-${PV}.tar.bz2 \
+           file://0001-powerpc-serial-Dispose-irq-mapping-when-done-in-mpc52xx_serial.c.txt;p=1;patch=1 \
+           file://0003-powerpc-Add-device-tree-fixups-for-the-EFIKA.txt;p=1;patch=1 \
+           file://0004-powerpc-Use-common-52xx-of_platform-probe-code-for-EFIKA.txt;p=1;patch=1 \
+           file://0005-powerpc-Restore-proper-link-order-in-platform.txt;p=1;patch=1 \
+           file://0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt;p=1;patch=1 \
+           file://0007-Implement-support-for-split-endian-OHCI.txt;p=1;patch=1 \
+           file://0008-ohci-Rework-bus-glue-integration-to-allow-several-at-once.txt;p=1;patch=1 \
+           file://0009-ohci-Add-support-for-OHCI-controller-on-the-of_platform-bus.txt;p=1;patch=1 \
+           file://0010-libata-Add-support-for-the-MPC52xx-ATA-controller.txt;p=1;patch=1 \
+           file://0011-ohci-Whitespace-and-typo-fix-in-ohci-ppc-of.c.txt;p=1;patch=1 \
+           file://0012-ata-Fix-pata_mpc52xx.c-compatible-list.txt;p=1;patch=1 \
+           file://0013-powerpc-serial-Fix-mpc52xx_uart.c-compatible-list.txt;p=1;patch=1 \
+           file://0014-powerpc-Small-cleanup-of-EFIKA-platform.txt;p=1;patch=1 \
+           file://0015-powerpc-Add-a-unified-uevent-handler-for-bus-based-on-of_device.txt;p=1;patch=1 \
+           file://0016-macintosh-Use-the-new-of_device-common-uevent-handler.txt;p=1;patch=1 \
+           file://0017-powerpc-Add-uevent-handler-for-of_platform_bus.txt;p=1;patch=1 \
+           file://0018-powerpc-Add-uevent-handler-for-ibmebus.txt;p=1;patch=1 \
+           file://0019-MPC5200-Bestcomm-platform-driver.txt;p=1;patch=1 \
+           file://0020-Fec-MPC5200-eth-driver.txt;p=1;patch=1 \
+           file://0021-POWERPC-Copy-bestcomm-support-files-into-arch-powerpc.txt;p=1;patch=1 \
+           file://0022-MPC52xx-PCI-now-working-on-lite5200.-ugly-but-working.txt;p=1;patch=1 \
+           file://0023-POWERPC-Make-FEC-work-on-the-lite5200.txt;p=1;patch=1 \
+           file://0024-Add-missing-function-prototype.txt;p=1;patch=1 \
+           file://0025-POWERPC-Misc-EFIKA-fixups-for-rtas-chrp.txt;p=1;patch=1 \
+           file://0026-POWERPC-Cleanup-mpc52xx-PCI-support.txt;p=1;patch=1 \
+           file://0027-POWERPC-Change-name-of-mpc52xx-pci-support-file-in-Makefile.txt;p=1;patch=1 \
+           file://0028-POWERPC-Change-link-order-so-mpc52xx-fec-always-shows-up-as-eth0.txt;p=1;patch=1 \
+           file://0029-POWERPC-Fixup-pr_print-format-for-mpc52xx-pci-support.txt;p=1;patch=1 \
+           file://0030-POWERPC-Add-mpc52xx-lite5200-PCI-support.txt;p=1;patch=1 \
+           file://0031-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt;p=1;patch=1 \
+           file://0032-POWERPC-EFIKA-Adds-missing-interrupts-from-bestcomm-node.txt;p=1;patch=1 \
+           file://v4l.diff;p=1;patch=1 \
+
+           file://defconfig \
+                  "
+
+
+S = "${WORKDIR}/linux-${PV}"
+
+inherit kernel
+
+export ARCH="powerpc"
+
+KERNEL_IMAGETYPE = "zImage"
+
+do_configure() {
+               install -m 644 ${WORKDIR}/defconfig ${S}/.config
+               make ARCH=${ARCH} oldconfig
+}
+
+do_deploy() {
+        install -d ${DEPLOY_DIR_IMAGE}
+        install -m 0644 arch/${ARCH}/boot/${KERNEL_IMAGETYPE} ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGETYPE}-${PV}-${MACHINE}-${DATETIME}
+}
+
+do_deploy[dirs] = "${S}"
+
+addtask deploy before do_build after do_compile
+
+