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 of_device *ofdev, 18 const struct of_device_id *match) 19 { 20 int ret; 21 struct device_node *dn = ofdev->node; 22 struct resource io_res; 23 struct resource ctl_res; 24 struct resource irq_res; 25 unsigned int reg_shift = 0; 26 int pio_mode = 0; 27 int pio_mask; 28 const u32 *prop; 29 30 ret = of_address_to_resource(dn, 0, &io_res); 31 if (ret) { 32 dev_err(&ofdev->dev, "can't get IO address from " 33 "device tree\n"); 34 return -EINVAL; 35 } 36 37 if (of_device_is_compatible(dn, "electra-ide")) { 38 /* Altstatus is really at offset 0x3f6 from the primary window 39 * on electra-ide. Adjust ctl_res and io_res accordingly. 40 */ 41 ctl_res = io_res; 42 ctl_res.start = ctl_res.start+0x3f6; 43 io_res.end = ctl_res.start-1; 44 } else { 45 ret = of_address_to_resource(dn, 1, &ctl_res); 46 if (ret) { 47 dev_err(&ofdev->dev, "can't get CTL address from " 48 "device tree\n"); 49 return -EINVAL; 50 } 51 } 52 53 ret = of_irq_to_resource(dn, 0, &irq_res); 54 if (ret == NO_IRQ) 55 irq_res.start = irq_res.end = -1; 56 else 57 irq_res.flags = 0; 58 59 prop = of_get_property(dn, "reg-shift", NULL); 60 if (prop) 61 reg_shift = *prop; 62 63 prop = of_get_property(dn, "pio-mode", NULL); 64 if (prop) { 65 pio_mode = *prop; 66 if (pio_mode > 6) { 67 dev_err(&ofdev->dev, "invalid pio-mode\n"); 68 return -EINVAL; 69 } 70 } else { 71 dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n"); 72 } 73 74 pio_mask = 1 << pio_mode; 75 pio_mask |= (1 << pio_mode) - 1; 76 77 return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res, 78 reg_shift, pio_mask); 79 } 80 81 static int __devexit pata_of_platform_remove(struct of_device *ofdev) 82 { 83 return __pata_platform_remove(&ofdev->dev); 84 } 85 86 static struct of_device_id pata_of_platform_match[] = { 87 { .compatible = "ata-generic", }, 88 { .compatible = "electra-ide", }, 89 {}, 90 }; 91 MODULE_DEVICE_TABLE(of, pata_of_platform_match); 92 93 static struct of_platform_driver pata_of_platform_driver = { 94 .name = "pata_of_platform", 95 .match_table = pata_of_platform_match, 96 .probe = pata_of_platform_probe, 97 .remove = __devexit_p(pata_of_platform_remove), 98 }; 99 100 static int __init pata_of_platform_init(void) 101 { 102 return of_register_platform_driver(&pata_of_platform_driver); 103 } 104 module_init(pata_of_platform_init); 105 106 static void __exit pata_of_platform_exit(void) 107 { 108 of_unregister_platform_driver(&pata_of_platform_driver); 109 } 110 module_exit(pata_of_platform_exit); 111 112 MODULE_DESCRIPTION("OF-platform PATA driver"); 113 MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); 114 MODULE_LICENSE("GPL"); 115