2 * AHCI SATA platform driver
4 * Copyright 2004-2005 Red Hat, Inc.
5 * Jeff Garzik <jgarzik@pobox.com>
6 * Copyright 2010 MontaVista Software, LLC.
7 * Anton Vorontsov <avorontsov@ru.mvista.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
15 #include <linux/kernel.h>
16 #include <linux/gfp.h>
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include <linux/interrupt.h>
20 #include <linux/device.h>
21 #include <linux/platform_device.h>
22 #include <linux/libata.h>
23 #include <linux/ahci_platform.h>
26 static int __init
ahci_probe(struct platform_device
*pdev
)
28 struct device
*dev
= &pdev
->dev
;
29 struct ahci_platform_data
*pdata
= dev
->platform_data
;
30 struct ata_port_info pi
= {
31 .flags
= AHCI_FLAG_COMMON
,
33 .udma_mask
= ATA_UDMA6
,
34 .port_ops
= &ahci_ops
,
36 const struct ata_port_info
*ppi
[] = { &pi
, NULL
};
37 struct ahci_host_priv
*hpriv
;
38 struct ata_host
*host
;
45 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
47 dev_err(dev
, "no mmio space\n");
51 irq
= platform_get_irq(pdev
, 0);
53 dev_err(dev
, "no irq\n");
57 if (pdata
&& pdata
->ata_port_info
)
58 pi
= *pdata
->ata_port_info
;
60 hpriv
= devm_kzalloc(dev
, sizeof(*hpriv
), GFP_KERNEL
);
62 dev_err(dev
, "can't alloc ahci_host_priv\n");
66 hpriv
->flags
|= (unsigned long)pi
.private_data
;
68 hpriv
->mmio
= devm_ioremap(dev
, mem
->start
, resource_size(mem
));
70 dev_err(dev
, "can't map %pR\n", mem
);
75 * Some platforms might need to prepare for mmio region access,
76 * which could be done in the following init call. So, the mmio
77 * region shouldn't be accessed before init (if provided) has
78 * returned successfully.
80 if (pdata
&& pdata
->init
) {
81 rc
= pdata
->init(dev
, hpriv
->mmio
);
86 ahci_save_initial_config(dev
, hpriv
,
87 pdata
? pdata
->force_port_map
: 0,
88 pdata
? pdata
->mask_port_map
: 0);
91 if (hpriv
->cap
& HOST_CAP_NCQ
)
92 pi
.flags
|= ATA_FLAG_NCQ
;
94 if (hpriv
->cap
& HOST_CAP_PMP
)
95 pi
.flags
|= ATA_FLAG_PMP
;
97 ahci_set_em_messages(hpriv
, &pi
);
99 /* CAP.NP sometimes indicate the index of the last enabled
100 * port, at other times, that of the last possible port, so
101 * determining the maximum port number requires looking at
102 * both CAP.NP and port_map.
104 n_ports
= max(ahci_nr_ports(hpriv
->cap
), fls(hpriv
->port_map
));
106 host
= ata_host_alloc_pinfo(dev
, ppi
, n_ports
);
112 host
->private_data
= hpriv
;
114 if (!(hpriv
->cap
& HOST_CAP_SSS
) || ahci_ignore_sss
)
115 host
->flags
|= ATA_HOST_PARALLEL_SCAN
;
117 printk(KERN_INFO
"ahci: SSS flag set, parallel bus scan disabled\n");
119 if (pi
.flags
& ATA_FLAG_EM
)
122 for (i
= 0; i
< host
->n_ports
; i
++) {
123 struct ata_port
*ap
= host
->ports
[i
];
125 ata_port_desc(ap
, "mmio %pR", mem
);
126 ata_port_desc(ap
, "port 0x%x", 0x100 + ap
->port_no
* 0x80);
128 /* set initial link pm policy */
129 ap
->pm_policy
= NOT_AVAILABLE
;
131 /* set enclosure management message type */
132 if (ap
->flags
& ATA_FLAG_EM
)
133 ap
->em_message_type
= hpriv
->em_msg_type
;
135 /* disabled/not-implemented port */
136 if (!(hpriv
->port_map
& (1 << i
)))
137 ap
->ops
= &ata_dummy_port_ops
;
140 rc
= ahci_reset_controller(host
);
144 ahci_init_controller(host
);
145 ahci_print_info(host
, "platform");
147 rc
= ata_host_activate(host
, irq
, ahci_interrupt
, IRQF_SHARED
,
154 if (pdata
&& pdata
->exit
)
159 static int __devexit
ahci_remove(struct platform_device
*pdev
)
161 struct device
*dev
= &pdev
->dev
;
162 struct ahci_platform_data
*pdata
= dev
->platform_data
;
163 struct ata_host
*host
= dev_get_drvdata(dev
);
165 ata_host_detach(host
);
167 if (pdata
&& pdata
->exit
)
173 static struct platform_driver ahci_driver
= {
174 .remove
= __devexit_p(ahci_remove
),
177 .owner
= THIS_MODULE
,
181 static int __init
ahci_init(void)
183 return platform_driver_probe(&ahci_driver
, ahci_probe
);
185 module_init(ahci_init
);
187 static void __exit
ahci_exit(void)
189 platform_driver_unregister(&ahci_driver
);
191 module_exit(ahci_exit
);
193 MODULE_DESCRIPTION("AHCI SATA platform driver");
194 MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
195 MODULE_LICENSE("GPL");
196 MODULE_ALIAS("platform:ahci");