Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.24 169 lines 4.0 kB view raw
1/* 2 * Platform IDE driver 3 * 4 * Copyright (C) 2007 MontaVista Software 5 * 6 * Maintainer: Kumar Gala <galak@kernel.crashing.org> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 */ 13 14#include <linux/types.h> 15#include <linux/init.h> 16#include <linux/kernel.h> 17#include <linux/ide.h> 18#include <linux/ioport.h> 19#include <linux/module.h> 20#include <linux/pata_platform.h> 21#include <linux/platform_device.h> 22#include <linux/io.h> 23 24static struct { 25 void __iomem *plat_ide_mapbase; 26 void __iomem *plat_ide_alt_mapbase; 27 ide_hwif_t *hwif; 28 int index; 29} hwif_prop; 30 31static ide_hwif_t *__devinit plat_ide_locate_hwif(void __iomem *base, 32 void __iomem *ctrl, struct pata_platform_info *pdata, int irq, 33 int mmio) 34{ 35 unsigned long port = (unsigned long)base; 36 ide_hwif_t *hwif = ide_find_port(port); 37 int i; 38 39 if (hwif == NULL) 40 goto out; 41 42 hwif->io_ports[IDE_DATA_OFFSET] = port; 43 44 port += (1 << pdata->ioport_shift); 45 for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET; 46 i++, port += (1 << pdata->ioport_shift)) 47 hwif->io_ports[i] = port; 48 49 hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; 50 51 hwif->irq = irq; 52 53 hwif->chipset = ide_generic; 54 55 if (mmio) { 56 hwif->mmio = 1; 57 default_hwif_mmiops(hwif); 58 } 59 60 hwif_prop.hwif = hwif; 61 hwif_prop.index = hwif->index; 62out: 63 return hwif; 64} 65 66static int __devinit plat_ide_probe(struct platform_device *pdev) 67{ 68 struct resource *res_base, *res_alt, *res_irq; 69 ide_hwif_t *hwif; 70 struct pata_platform_info *pdata; 71 u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; 72 int ret = 0; 73 int mmio = 0; 74 75 pdata = pdev->dev.platform_data; 76 77 /* get a pointer to the register memory */ 78 res_base = platform_get_resource(pdev, IORESOURCE_IO, 0); 79 res_alt = platform_get_resource(pdev, IORESOURCE_IO, 1); 80 81 if (!res_base || !res_alt) { 82 res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); 83 res_alt = platform_get_resource(pdev, IORESOURCE_MEM, 1); 84 if (!res_base || !res_alt) { 85 ret = -ENOMEM; 86 goto out; 87 } 88 mmio = 1; 89 } 90 91 res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 92 if (!res_irq) { 93 ret = -EINVAL; 94 goto out; 95 } 96 97 if (mmio) { 98 hwif_prop.plat_ide_mapbase = devm_ioremap(&pdev->dev, 99 res_base->start, res_base->end - res_base->start + 1); 100 hwif_prop.plat_ide_alt_mapbase = devm_ioremap(&pdev->dev, 101 res_alt->start, res_alt->end - res_alt->start + 1); 102 } else { 103 hwif_prop.plat_ide_mapbase = devm_ioport_map(&pdev->dev, 104 res_base->start, res_base->end - res_base->start + 1); 105 hwif_prop.plat_ide_alt_mapbase = devm_ioport_map(&pdev->dev, 106 res_alt->start, res_alt->end - res_alt->start + 1); 107 } 108 109 hwif = plat_ide_locate_hwif(hwif_prop.plat_ide_mapbase, 110 hwif_prop.plat_ide_alt_mapbase, pdata, res_irq->start, mmio); 111 112 if (!hwif) { 113 ret = -ENODEV; 114 goto out; 115 } 116 hwif->gendev.parent = &pdev->dev; 117 hwif->noprobe = 0; 118 119 idx[0] = hwif->index; 120 121 ide_device_add(idx); 122 123 platform_set_drvdata(pdev, hwif); 124 125 return 0; 126 127out: 128 return ret; 129} 130 131static int __devexit plat_ide_remove(struct platform_device *pdev) 132{ 133 ide_hwif_t *hwif = pdev->dev.driver_data; 134 135 if (hwif != hwif_prop.hwif) { 136 dev_printk(KERN_DEBUG, &pdev->dev, "%s: hwif value error", 137 pdev->name); 138 } else { 139 ide_unregister(hwif_prop.index); 140 hwif_prop.index = 0; 141 hwif_prop.hwif = NULL; 142 } 143 144 return 0; 145} 146 147static struct platform_driver platform_ide_driver = { 148 .driver = { 149 .name = "pata_platform", 150 }, 151 .probe = plat_ide_probe, 152 .remove = __devexit_p(plat_ide_remove), 153}; 154 155static int __init platform_ide_init(void) 156{ 157 return platform_driver_register(&platform_ide_driver); 158} 159 160static void __exit platform_ide_exit(void) 161{ 162 platform_driver_unregister(&platform_ide_driver); 163} 164 165MODULE_DESCRIPTION("Platform IDE driver"); 166MODULE_LICENSE("GPL"); 167 168module_init(platform_ide_init); 169module_exit(platform_ide_exit);