diff --git a/arch/powerpc/configs/pasemi_defconfig b/arch/powerpc/configs/pasemi_defconfig index 9d21b083ae12afb319fadcaeda06358877e760ed..797f0dfebde242dbe3ba7954996da8a5cac8764e 100644 --- a/arch/powerpc/configs/pasemi_defconfig +++ b/arch/powerpc/configs/pasemi_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.24-rc6 -# Fri Dec 28 11:01:53 2007 +# Tue Jan 15 10:26:10 2008 # CONFIG_PPC64=y @@ -152,7 +152,6 @@ CONFIG_PPC_PASEMI=y CONFIG_PPC_PASEMI_IOMMU=y # CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set CONFIG_PPC_PASEMI_MDIO=y -CONFIG_ELECTRA_IDE=y # CONFIG_PPC_CELLEB is not set # CONFIG_PPC_PS3 is not set # CONFIG_PPC_CELL is not set @@ -663,6 +662,7 @@ CONFIG_PATA_PCMCIA=y # CONFIG_PATA_VIA is not set # CONFIG_PATA_WINBOND is not set CONFIG_PATA_PLATFORM=y +CONFIG_PATA_OF_PLATFORM=y CONFIG_MD=y CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=y diff --git a/arch/powerpc/platforms/pasemi/Kconfig b/arch/powerpc/platforms/pasemi/Kconfig index b3458a181a150cb93277b5cf09e85cfd13722e76..348e0619e3e53cd085e37c820b9732fde2e7ab94 100644 --- a/arch/powerpc/platforms/pasemi/Kconfig +++ b/arch/powerpc/platforms/pasemi/Kconfig @@ -37,13 +37,4 @@ config PPC_PASEMI_MDIO help Driver for MDIO via GPIO on PWRficient platforms -config ELECTRA_IDE - tristate "Electra IDE driver" - default y - depends on PPC_PASEMI && ATA - select PATA_PLATFORM - help - This includes driver support for the Electra on-board IDE - interface. - endmenu diff --git a/arch/powerpc/platforms/pasemi/Makefile b/arch/powerpc/platforms/pasemi/Makefile index f47fcac7e5812d6270f388bf0f893cbe177b4ca8..2cd2a4f26a48cfd29c2ab32f44e23fb28b836902 100644 --- a/arch/powerpc/platforms/pasemi/Makefile +++ b/arch/powerpc/platforms/pasemi/Makefile @@ -1,4 +1,3 @@ obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o -obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o diff --git a/arch/powerpc/platforms/pasemi/electra_ide.c b/arch/powerpc/platforms/pasemi/electra_ide.c deleted file mode 100644 index 12fb0c9492636178fd832f13cebf52e74ed0f3ff..0000000000000000000000000000000000000000 --- a/arch/powerpc/platforms/pasemi/electra_ide.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2007 PA Semi, Inc - * - * Maintained by: Olof Johansson - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include - -#include -#include - -/* The electra IDE interface is incredibly simple: Just a device on the localbus - * with interrupts hooked up to one of the GPIOs. The device tree contains the - * address window and interrupt mappings already, and the pata_platform driver handles - * the rest. We just need to hook the two up. - */ - -#define MAX_IFS 4 /* really, we have only one */ - -static struct platform_device *pdevs[MAX_IFS]; - -static int __devinit electra_ide_init(void) -{ - struct device_node *np; - struct resource r[3]; - int ret = 0; - int i; - - np = of_find_compatible_node(NULL, "ide", "electra-ide"); - i = 0; - - while (np && i < MAX_IFS) { - memset(r, 0, sizeof(r)); - - /* pata_platform wants two address ranges: one for the base registers, - * another for the control (altstatus). It's located at offset 0x3f6 in - * the window, but the device tree only has one large register window - * that covers both ranges. So we need to split it up by hand here: - */ - - ret = of_address_to_resource(np, 0, &r[0]); - if (ret) - goto out; - ret = of_address_to_resource(np, 0, &r[1]); - if (ret) - goto out; - - r[1].start += 0x3f6; - r[0].end = r[1].start-1; - - r[2].start = irq_of_parse_and_map(np, 0); - r[2].end = irq_of_parse_and_map(np, 0); - r[2].flags = IORESOURCE_IRQ; - - pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n", - r[0].start, r[1].start, r[2].start); - pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3); - if (IS_ERR(pdevs[i])) { - ret = PTR_ERR(pdevs[i]); - pdevs[i] = NULL; - goto out; - } - np = of_find_compatible_node(np, "ide", "electra-ide"); - } -out: - return ret; -} -module_init(electra_ide_init); - -static void __devexit electra_ide_exit(void) -{ - int i; - - for (i = 0; i < MAX_IFS; i++) - if (pdevs[i]) - platform_device_unregister(pdevs[i]); -} -module_exit(electra_ide_exit); - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Olof Johansson "); -MODULE_DESCRIPTION("PA Semi Electra IDE driver"); diff --git a/arch/powerpc/platforms/pasemi/idle.c b/arch/powerpc/platforms/pasemi/idle.c index d8e1fcc7851388b51c84b20f77f62638e4189fab..43911d8b0206bb9e3d423ca4e9c12901634ad6b8 100644 --- a/arch/powerpc/platforms/pasemi/idle.c +++ b/arch/powerpc/platforms/pasemi/idle.c @@ -74,9 +74,6 @@ static int pasemi_system_reset_exception(struct pt_regs *regs) static int __init pasemi_idle_init(void) { - if (!machine_is(pasemi)) - return -ENODEV; - #ifndef CONFIG_PPC_PASEMI_CPUFREQ printk(KERN_WARNING "No cpufreq driver, powersavings modes disabled\n"); current_mode = 0; @@ -88,7 +85,7 @@ static int __init pasemi_idle_init(void) return 0; } -late_initcall(pasemi_idle_init); +machine_late_initcall(pasemi, pasemi_idle_init); static int __init idle_param(char *p) { diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 1940e678878ef0e6d0adf324f1b3c5111d308116..c64fb5bfb37e3598ea6b44a64332210bc0bf5c8a 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -135,9 +135,6 @@ static int __init pas_setup_mce_regs(void) struct pci_dev *dev; int reg; - if (!machine_is(pasemi)) - return -ENODEV; - /* Remap various SoC status registers for use by the MCE handler */ reg = 0; @@ -181,7 +178,7 @@ static int __init pas_setup_mce_regs(void) return 0; } -device_initcall(pas_setup_mce_regs); +machine_device_initcall(pasemi, pas_setup_mce_regs); static __init void pas_init_IRQ(void) { @@ -264,7 +261,7 @@ static int pas_machine_check_handler(struct pt_regs *regs) srr0 = regs->nip; srr1 = regs->msr; - if (mpic_get_mcirq() == nmi_virq) { + if (nmi_virq != NO_IRQ && mpic_get_mcirq() == nmi_virq) { printk(KERN_ERR "NMI delivered\n"); debugger(regs); mpic_end_irq(nmi_virq); @@ -405,9 +402,6 @@ static struct of_device_id pasemi_bus_ids[] = { static int __init pasemi_publish_devices(void) { - if (!machine_is(pasemi)) - return 0; - pasemi_pcmcia_init(); /* Publish OF platform devices for SDC and other non-PCI devices */ @@ -415,7 +409,7 @@ static int __init pasemi_publish_devices(void) return 0; } -device_initcall(pasemi_publish_devices); +machine_device_initcall(pasemi, pasemi_publish_devices); /* diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index ba63619ae5df20623ec530cc6eb7188da0b0c1df..64b4964d57e7f808376999ef6916b9c94251a088 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -607,13 +607,23 @@ config PATA_WINBOND_VLB config PATA_PLATFORM tristate "Generic platform device PATA support" - depends on EMBEDDED || ARCH_RPC + depends on EMBEDDED || ARCH_RPC || PPC help This option enables support for generic directly connected ATA devices commonly found on embedded systems. If unsure, say N. +config PATA_OF_PLATFORM + tristate "OpenFirmware platform device PATA support" + depends on PATA_PLATFORM && PPC_OF + help + This option enables support for generic directly connected ATA + devices commonly found on embedded systems with OpenFirmware + bindings. + + If unsure, say N. + config PATA_ICSIDE tristate "Acorn ICS PATA support" depends on ARM && ARCH_ACORN diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index b13feb2c5dae02cf934e1447b743a396749113fe..ebcee64dd5e2fa73f66c23cadde08c8d2a8210e0 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o obj-$(CONFIG_PATA_SCC) += pata_scc.o obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o +obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o # Should be last but two libata driver obj-$(CONFIG_PATA_ACPI) += pata_acpi.o diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c new file mode 100644 index 0000000000000000000000000000000000000000..938f48a807ebf5369d089b12300b3b7d1644a7ed --- /dev/null +++ b/drivers/ata/pata_of_platform.c @@ -0,0 +1,114 @@ +/* + * OF-platform PATA driver + * + * Copyright (c) 2007 MontaVista Software, Inc. + * Anton Vorontsov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +static int __devinit pata_of_platform_probe(struct of_device *ofdev, + const struct of_device_id *match) +{ + int ret; + struct device_node *dn = ofdev->node; + struct resource io_res; + struct resource ctl_res; + struct resource irq_res; + unsigned int reg_shift = 0; + int pio_mode = 0; + int pio_mask; + const u32 *prop; + + ret = of_address_to_resource(dn, 0, &io_res); + if (ret) { + dev_err(&ofdev->dev, "can't get IO address from " + "device tree\n"); + return -EINVAL; + } + + if (of_device_is_compatible(dn, "electra-ide")) { + /* Altstatus is really at offset 0x3f6 from the primary window + * on electra-ide. Adjust ctl_res and io_res accordingly. + */ + ctl_res = io_res; + ctl_res.start = ctl_res.start+0x3f6; + io_res.end = ctl_res.start-1; + } else { + ret = of_address_to_resource(dn, 1, &ctl_res); + if (ret) { + dev_err(&ofdev->dev, "can't get CTL address from " + "device tree\n"); + return -EINVAL; + } + } + + ret = of_irq_to_resource(dn, 0, &irq_res); + if (ret == NO_IRQ) + irq_res.start = irq_res.end = -1; + else + irq_res.flags = 0; + + prop = of_get_property(dn, "reg-shift", NULL); + if (prop) + reg_shift = *prop; + + prop = of_get_property(dn, "pio-mode", NULL); + if (prop) { + pio_mode = *prop; + if (pio_mode > 6) { + dev_err(&ofdev->dev, "invalid pio-mode\n"); + return -EINVAL; + } + } else { + dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n"); + } + + pio_mask = 1 << pio_mode; + pio_mask |= (1 << pio_mode) - 1; + + return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res, + reg_shift, pio_mask); +} + +static int __devexit pata_of_platform_remove(struct of_device *ofdev) +{ + return __pata_platform_remove(&ofdev->dev); +} + +static struct of_device_id pata_of_platform_match[] = { + { .compatible = "ata-generic", }, + { .compatible = "electra-ide", }, + {}, +}; +MODULE_DEVICE_TABLE(of, pata_of_platform_match); + +static struct of_platform_driver pata_of_platform_driver = { + .name = "pata_of_platform", + .match_table = pata_of_platform_match, + .probe = pata_of_platform_probe, + .remove = __devexit_p(pata_of_platform_remove), +}; + +static int __init pata_of_platform_init(void) +{ + return of_register_platform_driver(&pata_of_platform_driver); +} +module_init(pata_of_platform_init); + +static void __exit pata_of_platform_exit(void) +{ + of_unregister_platform_driver(&pata_of_platform_driver); +} +module_exit(pata_of_platform_exit); + +MODULE_DESCRIPTION("OF-platform PATA driver"); +MODULE_AUTHOR("Anton Vorontsov "); +MODULE_LICENSE("GPL"); diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index ac03a90a616829cc1b04d58f8b624caddff070f4..224bb6c2030a3e33fd129f4bf92b59fa661517f3 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -93,14 +93,9 @@ static struct ata_port_operations pata_platform_port_ops = { }; static void pata_platform_setup_port(struct ata_ioports *ioaddr, - struct pata_platform_info *info) + unsigned int shift) { - unsigned int shift = 0; - /* Fixup the port shift for platforms that need it */ - if (info && info->ioport_shift) - shift = info->ioport_shift; - ioaddr->data_addr = ioaddr->cmd_addr + (ATA_REG_DATA << shift); ioaddr->error_addr = ioaddr->cmd_addr + (ATA_REG_ERR << shift); ioaddr->feature_addr = ioaddr->cmd_addr + (ATA_REG_FEATURE << shift); @@ -114,8 +109,13 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr, } /** - * pata_platform_probe - attach a platform interface - * @pdev: platform device + * __pata_platform_probe - attach a platform interface + * @dev: device + * @io_res: Resource representing I/O base + * @ctl_res: Resource representing CTL base + * @irq_res: Resource representing IRQ and its flags + * @ioport_shift: I/O port shift + * @__pio_mask: PIO mask * * Register a platform bus IDE interface. Such interfaces are PIO and we * assume do not support IRQ sharing. @@ -135,42 +135,18 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr, * * If no IRQ resource is present, PIO polling mode is used instead. */ -static int __devinit pata_platform_probe(struct platform_device *pdev) +int __devinit __pata_platform_probe(struct device *dev, + struct resource *io_res, + struct resource *ctl_res, + struct resource *irq_res, + unsigned int ioport_shift, + int __pio_mask) { - struct resource *io_res, *ctl_res; struct ata_host *host; struct ata_port *ap; - struct pata_platform_info *pp_info; unsigned int mmio; - int irq; - - /* - * Simple resource validation .. - */ - if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) { - dev_err(&pdev->dev, "invalid number of resources\n"); - return -EINVAL; - } - - /* - * Get the I/O base first - */ - io_res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (io_res == NULL) { - io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(io_res == NULL)) - return -EINVAL; - } - - /* - * Then the CTL base - */ - ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1); - if (ctl_res == NULL) { - ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (unlikely(ctl_res == NULL)) - return -EINVAL; - } + int irq = 0; + int irq_flags = 0; /* * Check for MMIO @@ -181,20 +157,21 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) /* * And the IRQ */ - irq = platform_get_irq(pdev, 0); - if (irq < 0) - irq = 0; /* no irq */ + if (irq_res && irq_res->start > 0) { + irq = irq_res->start; + irq_flags = irq_res->flags; + } /* * Now that that's out of the way, wire up the port.. */ - host = ata_host_alloc(&pdev->dev, 1); + host = ata_host_alloc(dev, 1); if (!host) return -ENOMEM; ap = host->ports[0]; ap->ops = &pata_platform_port_ops; - ap->pio_mask = pio_mask; + ap->pio_mask = __pio_mask; ap->flags |= ATA_FLAG_SLAVE_POSS; /* @@ -209,25 +186,24 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) * Handle the MMIO case */ if (mmio) { - ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, io_res->start, + ap->ioaddr.cmd_addr = devm_ioremap(dev, io_res->start, io_res->end - io_res->start + 1); - ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start, + ap->ioaddr.ctl_addr = devm_ioremap(dev, ctl_res->start, ctl_res->end - ctl_res->start + 1); } else { - ap->ioaddr.cmd_addr = devm_ioport_map(&pdev->dev, io_res->start, + ap->ioaddr.cmd_addr = devm_ioport_map(dev, io_res->start, io_res->end - io_res->start + 1); - ap->ioaddr.ctl_addr = devm_ioport_map(&pdev->dev, ctl_res->start, + ap->ioaddr.ctl_addr = devm_ioport_map(dev, ctl_res->start, ctl_res->end - ctl_res->start + 1); } if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) { - dev_err(&pdev->dev, "failed to map IO/CTL base\n"); + dev_err(dev, "failed to map IO/CTL base\n"); return -ENOMEM; } ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr; - pp_info = pdev->dev.platform_data; - pata_platform_setup_port(&ap->ioaddr, pp_info); + pata_platform_setup_port(&ap->ioaddr, ioport_shift); ata_port_desc(ap, "%s cmd 0x%llx ctl 0x%llx", mmio ? "mmio" : "ioport", (unsigned long long)io_res->start, @@ -235,26 +211,78 @@ static int __devinit pata_platform_probe(struct platform_device *pdev) /* activate */ return ata_host_activate(host, irq, irq ? ata_interrupt : NULL, - pp_info ? pp_info->irq_flags : 0, - &pata_platform_sht); + irq_flags, &pata_platform_sht); } +EXPORT_SYMBOL_GPL(__pata_platform_probe); /** - * pata_platform_remove - unplug a platform interface - * @pdev: platform device + * __pata_platform_remove - unplug a platform interface + * @dev: device * * A platform bus ATA device has been unplugged. Perform the needed * cleanup. Also called on module unload for any active devices. */ -static int __devexit pata_platform_remove(struct platform_device *pdev) +int __devexit __pata_platform_remove(struct device *dev) { - struct device *dev = &pdev->dev; struct ata_host *host = dev_get_drvdata(dev); ata_host_detach(host); return 0; } +EXPORT_SYMBOL_GPL(__pata_platform_remove); + +static int __devinit pata_platform_probe(struct platform_device *pdev) +{ + struct resource *io_res; + struct resource *ctl_res; + struct resource *irq_res; + struct pata_platform_info *pp_info = pdev->dev.platform_data; + + /* + * Simple resource validation .. + */ + if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) { + dev_err(&pdev->dev, "invalid number of resources\n"); + return -EINVAL; + } + + /* + * Get the I/O base first + */ + io_res = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (io_res == NULL) { + io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(io_res == NULL)) + return -EINVAL; + } + + /* + * Then the CTL base + */ + ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1); + if (ctl_res == NULL) { + ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (unlikely(ctl_res == NULL)) + return -EINVAL; + } + + /* + * And the IRQ + */ + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (irq_res) + irq_res->flags = pp_info ? pp_info->irq_flags : 0; + + return __pata_platform_probe(&pdev->dev, io_res, ctl_res, irq_res, + pp_info ? pp_info->ioport_shift : 0, + pio_mask); +} + +static int __devexit pata_platform_remove(struct platform_device *pdev) +{ + return __pata_platform_remove(&pdev->dev); +} static struct platform_driver pata_platform_driver = { .probe = pata_platform_probe, diff --git a/include/linux/pata_platform.h b/include/linux/pata_platform.h index 5799e8d50623fb18af175b7cef1ac968949d2482..6a7a92db294c03d92fb1174cff79a6fcdd65b0c3 100644 --- a/include/linux/pata_platform.h +++ b/include/linux/pata_platform.h @@ -15,4 +15,13 @@ struct pata_platform_info { unsigned int irq_flags; }; +extern int __devinit __pata_platform_probe(struct device *dev, + struct resource *io_res, + struct resource *ctl_res, + struct resource *irq_res, + unsigned int ioport_shift, + int __pio_mask); + +extern int __devexit __pata_platform_remove(struct device *dev); + #endif /* __LINUX_PATA_PLATFORM_H */