ahci_platform: Drop unused ahci_platform_data members
[cascardo/linux.git] / drivers / ata / ahci_platform.c
1 /*
2  * AHCI SATA platform driver
3  *
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>
8  *
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)
12  * any later version.
13  */
14
15 #include <linux/clk.h>
16 #include <linux/kernel.h>
17 #include <linux/gfp.h>
18 #include <linux/module.h>
19 #include <linux/pm.h>
20 #include <linux/interrupt.h>
21 #include <linux/device.h>
22 #include <linux/platform_device.h>
23 #include <linux/libata.h>
24 #include <linux/ahci_platform.h>
25 #include <linux/phy/phy.h>
26 #include <linux/pm_runtime.h>
27 #include "ahci.h"
28
29 static void ahci_host_stop(struct ata_host *host);
30
31 struct ata_port_operations ahci_platform_ops = {
32         .inherits       = &ahci_ops,
33         .host_stop      = ahci_host_stop,
34 };
35 EXPORT_SYMBOL_GPL(ahci_platform_ops);
36
37 static const struct ata_port_info ahci_port_info = {
38         .flags          = AHCI_FLAG_COMMON,
39         .pio_mask       = ATA_PIO4,
40         .udma_mask      = ATA_UDMA6,
41         .port_ops       = &ahci_platform_ops,
42 };
43
44 static struct scsi_host_template ahci_platform_sht = {
45         AHCI_SHT("ahci_platform"),
46 };
47
48 /**
49  * ahci_platform_enable_clks - Enable platform clocks
50  * @hpriv: host private area to store config values
51  *
52  * This function enables all the clks found in hpriv->clks, starting at
53  * index 0. If any clk fails to enable it disables all the clks already
54  * enabled in reverse order, and then returns an error.
55  *
56  * RETURNS:
57  * 0 on success otherwise a negative error code
58  */
59 int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
60 {
61         int c, rc;
62
63         for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
64                 rc = clk_prepare_enable(hpriv->clks[c]);
65                 if (rc)
66                         goto disable_unprepare_clk;
67         }
68         return 0;
69
70 disable_unprepare_clk:
71         while (--c >= 0)
72                 clk_disable_unprepare(hpriv->clks[c]);
73         return rc;
74 }
75 EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
76
77 /**
78  * ahci_platform_disable_clks - Disable platform clocks
79  * @hpriv: host private area to store config values
80  *
81  * This function disables all the clks found in hpriv->clks, in reverse
82  * order of ahci_platform_enable_clks (starting at the end of the array).
83  */
84 void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
85 {
86         int c;
87
88         for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
89                 if (hpriv->clks[c])
90                         clk_disable_unprepare(hpriv->clks[c]);
91 }
92 EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
93
94 /**
95  * ahci_platform_enable_resources - Enable platform resources
96  * @hpriv: host private area to store config values
97  *
98  * This function enables all ahci_platform managed resources in the
99  * following order:
100  * 1) Regulator
101  * 2) Clocks (through ahci_platform_enable_clks)
102  * 3) Phy
103  *
104  * If resource enabling fails at any point the previous enabled resources
105  * are disabled in reverse order.
106  *
107  * RETURNS:
108  * 0 on success otherwise a negative error code
109  */
110 int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
111 {
112         int rc;
113
114         if (hpriv->target_pwr) {
115                 rc = regulator_enable(hpriv->target_pwr);
116                 if (rc)
117                         return rc;
118         }
119
120         rc = ahci_platform_enable_clks(hpriv);
121         if (rc)
122                 goto disable_regulator;
123
124         if (hpriv->phy) {
125                 rc = phy_init(hpriv->phy);
126                 if (rc)
127                         goto disable_clks;
128
129                 rc = phy_power_on(hpriv->phy);
130                 if (rc) {
131                         phy_exit(hpriv->phy);
132                         goto disable_clks;
133                 }
134         }
135
136         return 0;
137
138 disable_clks:
139         ahci_platform_disable_clks(hpriv);
140
141 disable_regulator:
142         if (hpriv->target_pwr)
143                 regulator_disable(hpriv->target_pwr);
144         return rc;
145 }
146 EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
147
148 /**
149  * ahci_platform_disable_resources - Disable platform resources
150  * @hpriv: host private area to store config values
151  *
152  * This function disables all ahci_platform managed resources in the
153  * following order:
154  * 1) Phy
155  * 2) Clocks (through ahci_platform_disable_clks)
156  * 3) Regulator
157  */
158 void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
159 {
160         if (hpriv->phy) {
161                 phy_power_off(hpriv->phy);
162                 phy_exit(hpriv->phy);
163         }
164
165         ahci_platform_disable_clks(hpriv);
166
167         if (hpriv->target_pwr)
168                 regulator_disable(hpriv->target_pwr);
169 }
170 EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
171
172 static void ahci_platform_put_resources(struct device *dev, void *res)
173 {
174         struct ahci_host_priv *hpriv = res;
175         int c;
176
177         if (hpriv->got_runtime_pm) {
178                 pm_runtime_put_sync(dev);
179                 pm_runtime_disable(dev);
180         }
181
182         for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
183                 clk_put(hpriv->clks[c]);
184 }
185
186 /**
187  * ahci_platform_get_resources - Get platform resources
188  * @pdev: platform device to get resources for
189  *
190  * This function allocates an ahci_host_priv struct, and gets the following
191  * resources, storing a reference to them inside the returned struct:
192  *
193  * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
194  * 2) regulator for controlling the targets power (optional)
195  * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
196  *    or for non devicetree enabled platforms a single clock
197  *      4) phy (optional)
198  *
199  * RETURNS:
200  * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
201  */
202 struct ahci_host_priv *ahci_platform_get_resources(
203         struct platform_device *pdev)
204 {
205         struct device *dev = &pdev->dev;
206         struct ahci_host_priv *hpriv;
207         struct clk *clk;
208         int i, rc = -ENOMEM;
209
210         if (!devres_open_group(dev, NULL, GFP_KERNEL))
211                 return ERR_PTR(-ENOMEM);
212
213         hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
214                              GFP_KERNEL);
215         if (!hpriv)
216                 goto err_out;
217
218         devres_add(dev, hpriv);
219
220         hpriv->mmio = devm_ioremap_resource(dev,
221                               platform_get_resource(pdev, IORESOURCE_MEM, 0));
222         if (!hpriv->mmio) {
223                 dev_err(dev, "no mmio space\n");
224                 goto err_out;
225         }
226
227         hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
228         if (IS_ERR(hpriv->target_pwr)) {
229                 rc = PTR_ERR(hpriv->target_pwr);
230                 if (rc == -EPROBE_DEFER)
231                         goto err_out;
232                 hpriv->target_pwr = NULL;
233         }
234
235         for (i = 0; i < AHCI_MAX_CLKS; i++) {
236                 /*
237                  * For now we must use clk_get(dev, NULL) for the first clock,
238                  * because some platforms (da850, spear13xx) are not yet
239                  * converted to use devicetree for clocks.  For new platforms
240                  * this is equivalent to of_clk_get(dev->of_node, 0).
241                  */
242                 if (i == 0)
243                         clk = clk_get(dev, NULL);
244                 else
245                         clk = of_clk_get(dev->of_node, i);
246
247                 if (IS_ERR(clk)) {
248                         rc = PTR_ERR(clk);
249                         if (rc == -EPROBE_DEFER)
250                                 goto err_out;
251                         break;
252                 }
253                 hpriv->clks[i] = clk;
254         }
255
256         hpriv->phy = devm_phy_get(dev, "sata-phy");
257         if (IS_ERR(hpriv->phy)) {
258                 rc = PTR_ERR(hpriv->phy);
259                 switch (rc) {
260                 case -ENODEV:
261                 case -ENOSYS:
262                         /* continue normally */
263                         hpriv->phy = NULL;
264                         break;
265
266                 case -EPROBE_DEFER:
267                         goto err_out;
268
269                 default:
270                         dev_err(dev, "couldn't get sata-phy\n");
271                         goto err_out;
272                 }
273         }
274
275         pm_runtime_enable(dev);
276         pm_runtime_get_sync(dev);
277         hpriv->got_runtime_pm = true;
278
279         devres_remove_group(dev, NULL);
280         return hpriv;
281
282 err_out:
283         devres_release_group(dev, NULL);
284         return ERR_PTR(rc);
285 }
286 EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
287
288 /**
289  * ahci_platform_init_host - Bring up an ahci-platform host
290  * @pdev: platform device pointer for the host
291  * @hpriv: ahci-host private data for the host
292  * @pi_template: template for the ata_port_info to use
293  * @force_port_map: param passed to ahci_save_initial_config
294  * @mask_port_map: param passed to ahci_save_initial_config
295  *
296  * This function does all the usual steps needed to bring up an
297  * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
298  * must be initialized / enabled before calling this.
299  *
300  * RETURNS:
301  * 0 on success otherwise a negative error code
302  */
303 int ahci_platform_init_host(struct platform_device *pdev,
304                             struct ahci_host_priv *hpriv,
305                             const struct ata_port_info *pi_template,
306                             unsigned int force_port_map,
307                             unsigned int mask_port_map)
308 {
309         struct device *dev = &pdev->dev;
310         struct ata_port_info pi = *pi_template;
311         const struct ata_port_info *ppi[] = { &pi, NULL };
312         struct ata_host *host;
313         int i, irq, n_ports, rc;
314
315         irq = platform_get_irq(pdev, 0);
316         if (irq <= 0) {
317                 dev_err(dev, "no irq\n");
318                 return -EINVAL;
319         }
320
321         /* prepare host */
322         hpriv->flags |= (unsigned long)pi.private_data;
323
324         ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
325
326         if (hpriv->cap & HOST_CAP_NCQ)
327                 pi.flags |= ATA_FLAG_NCQ;
328
329         if (hpriv->cap & HOST_CAP_PMP)
330                 pi.flags |= ATA_FLAG_PMP;
331
332         ahci_set_em_messages(hpriv, &pi);
333
334         /* CAP.NP sometimes indicate the index of the last enabled
335          * port, at other times, that of the last possible port, so
336          * determining the maximum port number requires looking at
337          * both CAP.NP and port_map.
338          */
339         n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
340
341         host = ata_host_alloc_pinfo(dev, ppi, n_ports);
342         if (!host)
343                 return -ENOMEM;
344
345         host->private_data = hpriv;
346
347         if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
348                 host->flags |= ATA_HOST_PARALLEL_SCAN;
349         else
350                 dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
351
352         if (pi.flags & ATA_FLAG_EM)
353                 ahci_reset_em(host);
354
355         for (i = 0; i < host->n_ports; i++) {
356                 struct ata_port *ap = host->ports[i];
357
358                 ata_port_desc(ap, "mmio %pR",
359                               platform_get_resource(pdev, IORESOURCE_MEM, 0));
360                 ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
361
362                 /* set enclosure management message type */
363                 if (ap->flags & ATA_FLAG_EM)
364                         ap->em_message_type = hpriv->em_msg_type;
365
366                 /* disabled/not-implemented port */
367                 if (!(hpriv->port_map & (1 << i)))
368                         ap->ops = &ata_dummy_port_ops;
369         }
370
371         rc = ahci_reset_controller(host);
372         if (rc)
373                 return rc;
374
375         ahci_init_controller(host);
376         ahci_print_info(host, "platform");
377
378         return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
379                                  &ahci_platform_sht);
380 }
381 EXPORT_SYMBOL_GPL(ahci_platform_init_host);
382
383 static int ahci_probe(struct platform_device *pdev)
384 {
385         struct device *dev = &pdev->dev;
386         struct ahci_platform_data *pdata = dev_get_platdata(dev);
387         struct ahci_host_priv *hpriv;
388         int rc;
389
390         hpriv = ahci_platform_get_resources(pdev);
391         if (IS_ERR(hpriv))
392                 return PTR_ERR(hpriv);
393
394         rc = ahci_platform_enable_resources(hpriv);
395         if (rc)
396                 return rc;
397
398         /*
399          * Some platforms might need to prepare for mmio region access,
400          * which could be done in the following init call. So, the mmio
401          * region shouldn't be accessed before init (if provided) has
402          * returned successfully.
403          */
404         if (pdata && pdata->init) {
405                 rc = pdata->init(dev, hpriv->mmio);
406                 if (rc)
407                         goto disable_resources;
408         }
409
410         rc = ahci_platform_init_host(pdev, hpriv, &ahci_port_info, 0, 0);
411         if (rc)
412                 goto pdata_exit;
413
414         return 0;
415 pdata_exit:
416         if (pdata && pdata->exit)
417                 pdata->exit(dev);
418 disable_resources:
419         ahci_platform_disable_resources(hpriv);
420         return rc;
421 }
422
423 static void ahci_host_stop(struct ata_host *host)
424 {
425         struct device *dev = host->dev;
426         struct ahci_platform_data *pdata = dev_get_platdata(dev);
427         struct ahci_host_priv *hpriv = host->private_data;
428
429         if (pdata && pdata->exit)
430                 pdata->exit(dev);
431
432         ahci_platform_disable_resources(hpriv);
433 }
434
435 #ifdef CONFIG_PM_SLEEP
436 /**
437  * ahci_platform_suspend_host - Suspend an ahci-platform host
438  * @dev: device pointer for the host
439  *
440  * This function does all the usual steps needed to suspend an
441  * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
442  * must be disabled after calling this.
443  *
444  * RETURNS:
445  * 0 on success otherwise a negative error code
446  */
447 int ahci_platform_suspend_host(struct device *dev)
448 {
449         struct ata_host *host = dev_get_drvdata(dev);
450         struct ahci_host_priv *hpriv = host->private_data;
451         void __iomem *mmio = hpriv->mmio;
452         u32 ctl;
453
454         if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
455                 dev_err(dev, "firmware update required for suspend/resume\n");
456                 return -EIO;
457         }
458
459         /*
460          * AHCI spec rev1.1 section 8.3.3:
461          * Software must disable interrupts prior to requesting a
462          * transition of the HBA to D3 state.
463          */
464         ctl = readl(mmio + HOST_CTL);
465         ctl &= ~HOST_IRQ_EN;
466         writel(ctl, mmio + HOST_CTL);
467         readl(mmio + HOST_CTL); /* flush */
468
469         return ata_host_suspend(host, PMSG_SUSPEND);
470 }
471 EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
472
473 /**
474  * ahci_platform_resume_host - Resume an ahci-platform host
475  * @dev: device pointer for the host
476  *
477  * This function does all the usual steps needed to resume an ahci-platform
478  * host, note any necessary resources (ie clks, phy, etc.)  must be
479  * initialized / enabled before calling this.
480  *
481  * RETURNS:
482  * 0 on success otherwise a negative error code
483  */
484 int ahci_platform_resume_host(struct device *dev)
485 {
486         struct ata_host *host = dev_get_drvdata(dev);
487         int rc;
488
489         if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
490                 rc = ahci_reset_controller(host);
491                 if (rc)
492                         return rc;
493
494                 ahci_init_controller(host);
495         }
496
497         ata_host_resume(host);
498
499         return 0;
500 }
501 EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
502
503 /**
504  * ahci_platform_suspend - Suspend an ahci-platform device
505  * @dev: the platform device to suspend
506  *
507  * This function suspends the host associated with the device, followed by
508  * disabling all the resources of the device.
509  *
510  * RETURNS:
511  * 0 on success otherwise a negative error code
512  */
513 int ahci_platform_suspend(struct device *dev)
514 {
515         struct ahci_platform_data *pdata = dev_get_platdata(dev);
516         struct ata_host *host = dev_get_drvdata(dev);
517         struct ahci_host_priv *hpriv = host->private_data;
518         int rc;
519
520         rc = ahci_platform_suspend_host(dev);
521         if (rc)
522                 return rc;
523
524         if (pdata && pdata->suspend)
525                 return pdata->suspend(dev);
526
527         ahci_platform_disable_resources(hpriv);
528
529         return 0;
530 }
531 EXPORT_SYMBOL_GPL(ahci_platform_suspend);
532
533 /**
534  * ahci_platform_resume - Resume an ahci-platform device
535  * @dev: the platform device to resume
536  *
537  * This function enables all the resources of the device followed by
538  * resuming the host associated with the device.
539  *
540  * RETURNS:
541  * 0 on success otherwise a negative error code
542  */
543 int ahci_platform_resume(struct device *dev)
544 {
545         struct ahci_platform_data *pdata = dev_get_platdata(dev);
546         struct ata_host *host = dev_get_drvdata(dev);
547         struct ahci_host_priv *hpriv = host->private_data;
548         int rc;
549
550         rc = ahci_platform_enable_resources(hpriv);
551         if (rc)
552                 return rc;
553
554         if (pdata && pdata->resume) {
555                 rc = pdata->resume(dev);
556                 if (rc)
557                         goto disable_resources;
558         }
559
560         rc = ahci_platform_resume_host(dev);
561         if (rc)
562                 goto disable_resources;
563
564         /* We resumed so update PM runtime state */
565         pm_runtime_disable(dev);
566         pm_runtime_set_active(dev);
567         pm_runtime_enable(dev);
568
569         return 0;
570
571 disable_resources:
572         ahci_platform_disable_resources(hpriv);
573
574         return rc;
575 }
576 EXPORT_SYMBOL_GPL(ahci_platform_resume);
577 #endif
578
579 static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
580                          ahci_platform_resume);
581
582 static const struct of_device_id ahci_of_match[] = {
583         { .compatible = "snps,spear-ahci", },
584         { .compatible = "snps,exynos5440-ahci", },
585         { .compatible = "ibm,476gtr-ahci", },
586         { .compatible = "snps,dwc-ahci", },
587         {},
588 };
589 MODULE_DEVICE_TABLE(of, ahci_of_match);
590
591 static struct platform_driver ahci_driver = {
592         .probe = ahci_probe,
593         .remove = ata_platform_remove_one,
594         .driver = {
595                 .name = "ahci",
596                 .owner = THIS_MODULE,
597                 .of_match_table = ahci_of_match,
598                 .pm = &ahci_pm_ops,
599         },
600 };
601 module_platform_driver(ahci_driver);
602
603 MODULE_DESCRIPTION("AHCI SATA platform driver");
604 MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
605 MODULE_LICENSE("GPL");
606 MODULE_ALIAS("platform:ahci");