18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Macintosh IDE Driver 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 1998 by Michael Schmitz 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This driver was written based on information obtained from the MacOS IDE 78c2ecf20Sopenharmony_ci * driver binary by Mikael Forselius 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 108c2ecf20Sopenharmony_ci * License. See the file COPYING in the main directory of this archive for 118c2ecf20Sopenharmony_ci * more details. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/types.h> 158c2ecf20Sopenharmony_ci#include <linux/mm.h> 168c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 178c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 188c2ecf20Sopenharmony_ci#include <linux/delay.h> 198c2ecf20Sopenharmony_ci#include <linux/ide.h> 208c2ecf20Sopenharmony_ci#include <linux/module.h> 218c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <asm/macintosh.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define DRV_NAME "mac_ide" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define IDE_BASE 0x50F1A000 /* Base address of IDE controller */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* 308c2ecf20Sopenharmony_ci * Generic IDE registers as offsets from the base 318c2ecf20Sopenharmony_ci * These match MkLinux so they should be correct. 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define IDE_CONTROL 0x38 /* control/altstatus */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/* 378c2ecf20Sopenharmony_ci * Mac-specific registers 388c2ecf20Sopenharmony_ci */ 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci * this register is odd; it doesn't seem to do much and it's 428c2ecf20Sopenharmony_ci * not word-aligned like virtually every other hardware register 438c2ecf20Sopenharmony_ci * on the Mac... 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define IDE_IFR 0x101 /* (0x101) IDE interrupt flags on Quadra: 478c2ecf20Sopenharmony_ci * 488c2ecf20Sopenharmony_ci * Bit 0+1: some interrupt flags 498c2ecf20Sopenharmony_ci * Bit 2+3: some interrupt enable 508c2ecf20Sopenharmony_ci * Bit 4: ?? 518c2ecf20Sopenharmony_ci * Bit 5: IDE interrupt flag (any hwif) 528c2ecf20Sopenharmony_ci * Bit 6: maybe IDE interrupt enable (any hwif) ?? 538c2ecf20Sopenharmony_ci * Bit 7: Any interrupt condition 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_civolatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ciint macide_test_irq(ide_hwif_t *hwif) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci if (*ide_ifr & 0x20) 618c2ecf20Sopenharmony_ci return 1; 628c2ecf20Sopenharmony_ci return 0; 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic void macide_clear_irq(ide_drive_t *drive) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci *ide_ifr &= ~0x20; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistatic void __init macide_setup_ports(struct ide_hw *hw, unsigned long base, 718c2ecf20Sopenharmony_ci int irq) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci int i; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci memset(hw, 0, sizeof(*hw)); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) 788c2ecf20Sopenharmony_ci hw->io_ports_array[i] = base + i * 4; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci hw->io_ports.ctl_addr = base + IDE_CONTROL; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci hw->irq = irq; 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic const struct ide_port_ops macide_port_ops = { 868c2ecf20Sopenharmony_ci .clear_irq = macide_clear_irq, 878c2ecf20Sopenharmony_ci .test_irq = macide_test_irq, 888c2ecf20Sopenharmony_ci}; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic const struct ide_port_info macide_port_info = { 918c2ecf20Sopenharmony_ci .port_ops = &macide_port_ops, 928c2ecf20Sopenharmony_ci .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA, 938c2ecf20Sopenharmony_ci .irq_flags = IRQF_SHARED, 948c2ecf20Sopenharmony_ci .chipset = ide_generic, 958c2ecf20Sopenharmony_ci}; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic const char *mac_ide_name[] = 988c2ecf20Sopenharmony_ci { "Quadra", "Powerbook", "Powerbook Baboon" }; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* 1018c2ecf20Sopenharmony_ci * Probe for a Macintosh IDE interface 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic int mac_ide_probe(struct platform_device *pdev) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci struct resource *mem, *irq; 1078c2ecf20Sopenharmony_ci struct ide_hw hw, *hws[] = { &hw }; 1088c2ecf20Sopenharmony_ci struct ide_port_info d = macide_port_info; 1098c2ecf20Sopenharmony_ci struct ide_host *host; 1108c2ecf20Sopenharmony_ci int rc; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci if (!MACH_IS_MAC) 1138c2ecf20Sopenharmony_ci return -ENODEV; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1168c2ecf20Sopenharmony_ci if (!mem) 1178c2ecf20Sopenharmony_ci return -ENODEV; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1208c2ecf20Sopenharmony_ci if (!irq) 1218c2ecf20Sopenharmony_ci return -ENODEV; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (!devm_request_mem_region(&pdev->dev, mem->start, 1248c2ecf20Sopenharmony_ci resource_size(mem), DRV_NAME)) { 1258c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "resources busy\n"); 1268c2ecf20Sopenharmony_ci return -EBUSY; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci printk(KERN_INFO "ide: Macintosh %s IDE controller\n", 1308c2ecf20Sopenharmony_ci mac_ide_name[macintosh_config->ide_type - 1]); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci macide_setup_ports(&hw, mem->start, irq->start); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci rc = ide_host_add(&d, hws, 1, &host); 1358c2ecf20Sopenharmony_ci if (rc) 1368c2ecf20Sopenharmony_ci return rc; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, host); 1398c2ecf20Sopenharmony_ci return 0; 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic int mac_ide_remove(struct platform_device *pdev) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci struct ide_host *host = platform_get_drvdata(pdev); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci ide_host_remove(host); 1478c2ecf20Sopenharmony_ci return 0; 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic struct platform_driver mac_ide_driver = { 1518c2ecf20Sopenharmony_ci .driver = { 1528c2ecf20Sopenharmony_ci .name = DRV_NAME, 1538c2ecf20Sopenharmony_ci }, 1548c2ecf20Sopenharmony_ci .probe = mac_ide_probe, 1558c2ecf20Sopenharmony_ci .remove = mac_ide_remove, 1568c2ecf20Sopenharmony_ci}; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cimodule_platform_driver(mac_ide_driver); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:" DRV_NAME); 1618c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 162