1 /* 2 * OF-platform PATA driver 3 * 4 * Copyright (c) 2007 MontaVista Software, Inc. 5 * Anton Vorontsov <avorontsov@ru.mvista.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License (Version 2) as 9 * published by the Free Software Foundation. 10 */ 11 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/of_platform.h> 15 #include <linux/ata_platform.h> 16 17 static int __devinit pata_of_platform_probe(struct platform_device *ofdev) 18 { 19 int ret; 20 struct device_node *dn = ofdev->dev.of_node; 21 struct resource io_res; 22 struct resource ctl_res; 23 struct resource irq_res; 24 unsigned int reg_shift = 0; 25 int pio_mode = 0; 26 int pio_mask; 27 const u32 *prop; 28 29 ret = of_address_to_resource(dn, 0, &io_res); 30 if (ret) { 31 dev_err(&ofdev->dev, "can't get IO address from " 32 "device tree\n"); 33 return -EINVAL; 34 } 35 36 if (of_device_is_compatible(dn, "electra-ide")) { 37 /* Altstatus is really at offset 0x3f6 from the primary window 38 * on electra-ide. Adjust ctl_res and io_res accordingly. 39 */ 40 ctl_res = io_res; 41 ctl_res.start = ctl_res.start+0x3f6; 42 io_res.end = ctl_res.start-1; 43 } else { 44 ret = of_address_to_resource(dn, 1, &ctl_res); 45 if (ret) { 46 dev_err(&ofdev->dev, "can't get CTL address from " 47 "device tree\n"); 48 return -EINVAL; 49 } 50 } 51 52 ret = of_irq_to_resource(dn, 0, &irq_res); 53 if (ret == NO_IRQ) 54 irq_res.start = irq_res.end = 0; 55 else 56 irq_res.flags = 0; 57 58 prop = of_get_property(dn, "reg-shift", NULL); 59 if (prop) 60 reg_shift = *prop; 61 62 prop = of_get_property(dn, "pio-mode", NULL); 63 if (prop) { 64 pio_mode = *prop; 65 if (pio_mode > 6) { 66 dev_err(&ofdev->dev, "invalid pio-mode\n"); 67 return -EINVAL; 68 } 69 } else { 70 dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n"); 71 } 72 73 pio_mask = 1 << pio_mode; 74 pio_mask |= (1 << pio_mode) - 1; 75 76 return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res, 77 reg_shift, pio_mask); 78 } 79 80 static int __devexit pata_of_platform_remove(struct platform_device *ofdev) 81 { 82 return __pata_platform_remove(&ofdev->dev); 83 } 84 85 static struct of_device_id pata_of_platform_match[] = { 86 { .compatible = "ata-generic", }, 87 { .compatible = "electra-ide", }, 88 {}, 89 }; 90 MODULE_DEVICE_TABLE(of, pata_of_platform_match); 91 92 static struct platform_driver pata_of_platform_driver = { 93 .driver = { 94 .name = "pata_of_platform", 95 .owner = THIS_MODULE, 96 .of_match_table = pata_of_platform_match, 97 }, 98 .probe = pata_of_platform_probe, 99 .remove = __devexit_p(pata_of_platform_remove), 100 }; 101 102 static int __init pata_of_platform_init(void) 103 { 104 return platform_driver_register(&pata_of_platform_driver); 105 } 106 module_init(pata_of_platform_init); 107 108 static void __exit pata_of_platform_exit(void) 109 { 110 platform_driver_unregister(&pata_of_platform_driver); 111 } 112 module_exit(pata_of_platform_exit); 113 114 MODULE_DESCRIPTION("OF-platform PATA driver"); 115 MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); 116 MODULE_LICENSE("GPL"); 117