From 7ed9ddb3fed7b3d38613644df734cedb887502d1 Mon Sep 17 00:00:00 2001 From: Stelios Koroneos Date: Mon, 19 Feb 2007 20:18:25 +0000 Subject: /packages/linux: Add kernel 2.6.20 for efika --- packages/linux/linux-efika-2.6.20/.mtn2git_empty | 0 ...e-irq-mapping-when-done-in-mpc52xx_serial.c.txt | 27 + ...owerpc-Add-device-tree-fixups-for-the-EFIKA.txt | 110 ++ ...ommon-52xx-of_platform-probe-code-for-EFIKA.txt | 106 ++ ...werpc-Restore-proper-link-order-in-platform.txt | 33 + ...e-OHCI-quirk-mecanism-as-suggested-by-David.txt | 236 +++ ...007-Implement-support-for-split-endian-OHCI.txt | 367 ++++ ...s-glue-integration-to-allow-several-at-once.txt | 470 ++++++ ...-for-OHCI-controller-on-the-of_platform-bus.txt | 349 ++++ ...-Add-support-for-the-MPC52xx-ATA-controller.txt | 620 +++++++ ...ci-Whitespace-and-typo-fix-in-ohci-ppc-of.c.txt | 38 + ...0012-ata-Fix-pata_mpc52xx.c-compatible-list.txt | 31 + ...c-serial-Fix-mpc52xx_uart.c-compatible-list.txt | 28 + ...014-powerpc-Small-cleanup-of-EFIKA-platform.txt | 144 ++ ...d-uevent-handler-for-bus-based-on-of_device.txt | 116 ++ ...Use-the-new-of_device-common-uevent-handler.txt | 130 ++ ...erpc-Add-uevent-handler-for-of_platform_bus.txt | 29 + ...0018-powerpc-Add-uevent-handler-for-ibmebus.txt | 50 + .../0019-MPC5200-Bestcomm-platform-driver.txt | 1439 ++++++++++++++++ .../0020-Fec-MPC5200-eth-driver.txt | 1783 ++++++++++++++++++++ ...py-bestcomm-support-files-into-arch-powerpc.txt | 1335 +++++++++++++++ ...I-now-working-on-lite5200.-ugly-but-working.txt | 464 +++++ .../0023-POWERPC-Make-FEC-work-on-the-lite5200.txt | 700 ++++++++ .../0024-Add-missing-function-prototype.txt | 26 + ...025-POWERPC-Misc-EFIKA-fixups-for-rtas-chrp.txt | 133 ++ .../0026-POWERPC-Cleanup-mpc52xx-PCI-support.txt | 911 ++++++++++ ...ame-of-mpc52xx-pci-support-file-in-Makefile.txt | 28 + ...rder-so-mpc52xx-fec-always-shows-up-as-eth0.txt | 47 + ...xup-pr_print-format-for-mpc52xx-pci-support.txt | 28 + ...30-POWERPC-Add-mpc52xx-lite5200-PCI-support.txt | 871 ++++++++++ ...d-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt | 828 +++++++++ ...-Adds-missing-interrupts-from-bestcomm-node.txt | 36 + packages/linux/linux-efika-2.6.20/defconfig | 1621 ++++++++++++++++++ packages/linux/linux-efika-2.6.20/v4l.diff | 28 + packages/linux/linux-efika_2.6.20.bb | 68 + 35 files changed, 13230 insertions(+) create mode 100644 packages/linux/linux-efika-2.6.20/.mtn2git_empty create mode 100644 packages/linux/linux-efika-2.6.20/0001-powerpc-serial-Dispose-irq-mapping-when-done-in-mpc52xx_serial.c.txt create mode 100644 packages/linux/linux-efika-2.6.20/0003-powerpc-Add-device-tree-fixups-for-the-EFIKA.txt create mode 100644 packages/linux/linux-efika-2.6.20/0004-powerpc-Use-common-52xx-of_platform-probe-code-for-EFIKA.txt create mode 100644 packages/linux/linux-efika-2.6.20/0005-powerpc-Restore-proper-link-order-in-platform.txt create mode 100644 packages/linux/linux-efika-2.6.20/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt create mode 100644 packages/linux/linux-efika-2.6.20/0007-Implement-support-for-split-endian-OHCI.txt create mode 100644 packages/linux/linux-efika-2.6.20/0008-ohci-Rework-bus-glue-integration-to-allow-several-at-once.txt create mode 100644 packages/linux/linux-efika-2.6.20/0009-ohci-Add-support-for-OHCI-controller-on-the-of_platform-bus.txt create mode 100644 packages/linux/linux-efika-2.6.20/0010-libata-Add-support-for-the-MPC52xx-ATA-controller.txt create mode 100644 packages/linux/linux-efika-2.6.20/0011-ohci-Whitespace-and-typo-fix-in-ohci-ppc-of.c.txt create mode 100644 packages/linux/linux-efika-2.6.20/0012-ata-Fix-pata_mpc52xx.c-compatible-list.txt create mode 100644 packages/linux/linux-efika-2.6.20/0013-powerpc-serial-Fix-mpc52xx_uart.c-compatible-list.txt create mode 100644 packages/linux/linux-efika-2.6.20/0014-powerpc-Small-cleanup-of-EFIKA-platform.txt create mode 100644 packages/linux/linux-efika-2.6.20/0015-powerpc-Add-a-unified-uevent-handler-for-bus-based-on-of_device.txt create mode 100644 packages/linux/linux-efika-2.6.20/0016-macintosh-Use-the-new-of_device-common-uevent-handler.txt create mode 100644 packages/linux/linux-efika-2.6.20/0017-powerpc-Add-uevent-handler-for-of_platform_bus.txt create mode 100644 packages/linux/linux-efika-2.6.20/0018-powerpc-Add-uevent-handler-for-ibmebus.txt create mode 100644 packages/linux/linux-efika-2.6.20/0019-MPC5200-Bestcomm-platform-driver.txt create mode 100644 packages/linux/linux-efika-2.6.20/0020-Fec-MPC5200-eth-driver.txt create mode 100644 packages/linux/linux-efika-2.6.20/0021-POWERPC-Copy-bestcomm-support-files-into-arch-powerpc.txt create mode 100644 packages/linux/linux-efika-2.6.20/0022-MPC52xx-PCI-now-working-on-lite5200.-ugly-but-working.txt create mode 100644 packages/linux/linux-efika-2.6.20/0023-POWERPC-Make-FEC-work-on-the-lite5200.txt create mode 100644 packages/linux/linux-efika-2.6.20/0024-Add-missing-function-prototype.txt create mode 100644 packages/linux/linux-efika-2.6.20/0025-POWERPC-Misc-EFIKA-fixups-for-rtas-chrp.txt create mode 100644 packages/linux/linux-efika-2.6.20/0026-POWERPC-Cleanup-mpc52xx-PCI-support.txt create mode 100644 packages/linux/linux-efika-2.6.20/0027-POWERPC-Change-name-of-mpc52xx-pci-support-file-in-Makefile.txt create mode 100644 packages/linux/linux-efika-2.6.20/0028-POWERPC-Change-link-order-so-mpc52xx-fec-always-shows-up-as-eth0.txt create mode 100644 packages/linux/linux-efika-2.6.20/0029-POWERPC-Fixup-pr_print-format-for-mpc52xx-pci-support.txt create mode 100644 packages/linux/linux-efika-2.6.20/0030-POWERPC-Add-mpc52xx-lite5200-PCI-support.txt create mode 100644 packages/linux/linux-efika-2.6.20/0031-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt create mode 100644 packages/linux/linux-efika-2.6.20/0032-POWERPC-EFIKA-Adds-missing-interrupts-from-bestcomm-node.txt create mode 100644 packages/linux/linux-efika-2.6.20/defconfig create mode 100644 packages/linux/linux-efika-2.6.20/v4l.diff create mode 100644 packages/linux/linux-efika_2.6.20.bb (limited to 'packages/linux') 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 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +Acked-by: David Brownell + + 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 +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 +Acked-by: David Brownell + + 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 +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 +Acked-by: David Brownell +Signed-off-by: Greg Kroah-Hartman +--- + 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 +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 +Acked-by: David Brownell +Signed-off-by: Greg Kroah-Hartman +--- + 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 ++ * (C) Copyright 2000-2002 David Brownell ++ * (C) Copyright 2002 Hewlett-Packard Company ++ * (C) Copyright 2006 Sylvain Munaut ++ * ++ * 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 ++ ++#include ++#include ++ ++ ++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 +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 +Signed-off-by: Jeff Garzik +--- + 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 ++ * 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define DRV_NAME "mpc52xx_ata" ++#define DRV_VERSION "0.1.0" ++ ++ ++/* Private struct