diff options
author | Stelios Koroneos <skoroneos@digital-opsis.com> | 2007-02-19 20:18:25 +0000 |
---|---|---|
committer | Stelios Koroneos <skoroneos@digital-opsis.com> | 2007-02-19 20:18:25 +0000 |
commit | 7ed9ddb3fed7b3d38613644df734cedb887502d1 (patch) | |
tree | 27760c6f9b0fe1fa8e426e0e7215640a1babff17 /packages/linux | |
parent | f692fd835e0716ac90c1c2d93fa7d800099715af (diff) |
/packages/linux: Add kernel 2.6.20 for efika
Diffstat (limited to 'packages/linux')
35 files changed, 13230 insertions, 0 deletions
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 index 0000000000..e69de29bb2 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/.mtn2git_empty 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 index 0000000000..ef3c42dc30 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0001-powerpc-serial-Dispose-irq-mapping-when-done-in-mpc52xx_serial.c.txt @@ -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 index 0000000000..eddebfe2e7 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0003-powerpc-Add-device-tree-fixups-for-the-EFIKA.txt @@ -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 index 0000000000..763d53208f --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0004-powerpc-Use-common-52xx-of_platform-probe-code-for-EFIKA.txt @@ -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 index 0000000000..0b4bbe3376 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0005-powerpc-Restore-proper-link-order-in-platform.txt @@ -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 index 0000000000..39f6fef607 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt @@ -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 index 0000000000..f49e0cfa7d --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0007-Implement-support-for-split-endian-OHCI.txt @@ -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 index 0000000000..c209ee035b --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0008-ohci-Rework-bus-glue-integration-to-allow-several-at-once.txt @@ -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 index 0000000000..2b53e487f8 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0009-ohci-Add-support-for-OHCI-controller-on-the-of_platform-bus.txt @@ -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 index 0000000000..4a69da5c2c --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0010-libata-Add-support-for-the-MPC52xx-ATA-controller.txt @@ -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(®s->pio1, timing->pio1); ++ out_be32(®s->pio2, timing->pio2); ++ out_be32(®s->mdma1, 0); ++ out_be32(®s->mdma2, 0); ++ out_be32(®s->udma1, 0); ++ out_be32(®s->udma2, 0); ++ out_be32(®s->udma3, 0); ++ out_be32(®s->udma4, 0); ++ out_be32(®s->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(®s->share_cnt, 0); ++ ++ /* Configure and reset host */ ++ out_be32(®s->config, ++ MPC52xx_ATA_HOSTCONF_IE | ++ MPC52xx_ATA_HOSTCONF_IORDY | ++ MPC52xx_ATA_HOSTCONF_SMR | ++ MPC52xx_ATA_HOSTCONF_FR); ++ ++ udelay(10); ++ ++ out_be32(®s->config, ++ MPC52xx_ATA_HOSTCONF_IE | ++ MPC52xx_ATA_HOSTCONF_IORDY); ++ ++ /* Set the time slot to 1us */ ++ tslot = CALC_CLKCYC(priv->ipb_period, 1000000); ++ out_be32(®s->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 index 0000000000..2228fa06b3 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0011-ohci-Whitespace-and-typo-fix-in-ohci-ppc-of.c.txt @@ -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 index 0000000000..33f2ffcad0 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0012-ata-Fix-pata_mpc52xx.c-compatible-list.txt @@ -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 index 0000000000..d0c5a4647a --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0013-powerpc-serial-Fix-mpc52xx_uart.c-compatible-list.txt @@ -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 index 0000000000..a373e9703d --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0014-powerpc-Small-cleanup-of-EFIKA-platform.txt @@ -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 index 0000000000..6de1fd28f8 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0015-powerpc-Add-a-unified-uevent-handler-for-bus-based-on-of_device.txt @@ -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 index 0000000000..93859bdebd --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0016-macintosh-Use-the-new-of_device-common-uevent-handler.txt @@ -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 index 0000000000..303cf6ba01 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0017-powerpc-Add-uevent-handler-for-of_platform_bus.txt @@ -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 index 0000000000..39392a6060 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0018-powerpc-Add-uevent-handler-for-ibmebus.txt @@ -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 index 0000000000..74bfbf9b39 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0019-MPC5200-Bestcomm-platform-driver.txt @@ -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 index 0000000000..6c9ab0ebeb --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0020-Fec-MPC5200-eth-driver.txt @@ -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(ðcmd, 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 index 0000000000..958ca7f20b --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0021-POWERPC-Copy-bestcomm-support-files-into-arch-powerpc.txt @@ -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 index 0000000000..dbf61629fc --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0022-MPC52xx-PCI-now-working-on-lite5200.-ugly-but-working.txt @@ -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 index 0000000000..bdbafcb30d --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0023-POWERPC-Make-FEC-work-on-the-lite5200.txt @@ -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 index 0000000000..2fb1a495bc --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0024-Add-missing-function-prototype.txt @@ -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 index 0000000000..8f39c3a3d6 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0025-POWERPC-Misc-EFIKA-fixups-for-rtas-chrp.txt @@ -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 index 0000000000..3119060f2b --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0026-POWERPC-Cleanup-mpc52xx-PCI-support.txt @@ -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 index 0000000000..80a769b9bf --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0027-POWERPC-Change-name-of-mpc52xx-pci-support-file-in-Makefile.txt @@ -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 index 0000000000..0761bea354 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0028-POWERPC-Change-link-order-so-mpc52xx-fec-always-shows-up-as-eth0.txt @@ -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 index 0000000000..3a1793924f --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0029-POWERPC-Fixup-pr_print-format-for-mpc52xx-pci-support.txt @@ -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 index 0000000000..dae76e0d75 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0030-POWERPC-Add-mpc52xx-lite5200-PCI-support.txt @@ -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 index 0000000000..5e8d5a268c --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0031-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt @@ -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 index 0000000000..1e0735849d --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0032-POWERPC-EFIKA-Adds-missing-interrupts-from-bestcomm-node.txt @@ -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 index 0000000000..31908aa9e5 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/defconfig @@ -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 index 0000000000..cf5643e30d --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/v4l.diff @@ -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 index 0000000000..79fa08e5fe --- /dev/null +++ b/packages/linux/linux-efika_2.6.20.bb @@ -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 + + |