Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/ata/libahci_platform.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* AHCI SATA platform library
4
*
5
* Copyright 2004-2005 Red Hat, Inc.
6
* Jeff Garzik <[email protected]>
7
* Copyright 2010 MontaVista Software, LLC.
8
* Anton Vorontsov <[email protected]>
9
*/
10
11
#include <linux/clk.h>
12
#include <linux/kernel.h>
13
#include <linux/gfp.h>
14
#include <linux/module.h>
15
#include <linux/pm.h>
16
#include <linux/interrupt.h>
17
#include <linux/device.h>
18
#include <linux/platform_device.h>
19
#include <linux/libata.h>
20
#include <linux/ahci_platform.h>
21
#include <linux/phy/phy.h>
22
#include <linux/pm_runtime.h>
23
#include <linux/of.h>
24
#include <linux/of_platform.h>
25
#include <linux/reset.h>
26
#include "ahci.h"
27
28
static void ahci_host_stop(struct ata_host *host);
29
30
struct ata_port_operations ahci_platform_ops = {
31
.inherits = &ahci_ops,
32
.host_stop = ahci_host_stop,
33
};
34
EXPORT_SYMBOL_GPL(ahci_platform_ops);
35
36
/**
37
* ahci_platform_enable_phys - Enable PHYs
38
* @hpriv: host private area to store config values
39
*
40
* This function enables all the PHYs found in hpriv->phys, if any.
41
* If a PHY fails to be enabled, it disables all the PHYs already
42
* enabled in reverse order and returns an error.
43
*
44
* RETURNS:
45
* 0 on success otherwise a negative error code
46
*/
47
int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
48
{
49
int rc, i;
50
51
for (i = 0; i < hpriv->nports; i++) {
52
if (ahci_ignore_port(hpriv, i))
53
continue;
54
55
rc = phy_init(hpriv->phys[i]);
56
if (rc)
57
goto disable_phys;
58
59
rc = phy_set_mode(hpriv->phys[i], PHY_MODE_SATA);
60
if (rc) {
61
phy_exit(hpriv->phys[i]);
62
goto disable_phys;
63
}
64
65
rc = phy_power_on(hpriv->phys[i]);
66
if (rc) {
67
phy_exit(hpriv->phys[i]);
68
goto disable_phys;
69
}
70
}
71
72
return 0;
73
74
disable_phys:
75
while (--i >= 0) {
76
if (ahci_ignore_port(hpriv, i))
77
continue;
78
79
phy_power_off(hpriv->phys[i]);
80
phy_exit(hpriv->phys[i]);
81
}
82
return rc;
83
}
84
EXPORT_SYMBOL_GPL(ahci_platform_enable_phys);
85
86
/**
87
* ahci_platform_disable_phys - Disable PHYs
88
* @hpriv: host private area to store config values
89
*
90
* This function disables all PHYs found in hpriv->phys.
91
*/
92
void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
93
{
94
int i;
95
96
for (i = 0; i < hpriv->nports; i++) {
97
if (ahci_ignore_port(hpriv, i))
98
continue;
99
100
phy_power_off(hpriv->phys[i]);
101
phy_exit(hpriv->phys[i]);
102
}
103
}
104
EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
105
106
/**
107
* ahci_platform_find_clk - Find platform clock
108
* @hpriv: host private area to store config values
109
* @con_id: clock connection ID
110
*
111
* This function returns a pointer to the clock descriptor of the clock with
112
* the passed ID.
113
*
114
* RETURNS:
115
* Pointer to the clock descriptor on success otherwise NULL
116
*/
117
struct clk *ahci_platform_find_clk(struct ahci_host_priv *hpriv, const char *con_id)
118
{
119
int i;
120
121
for (i = 0; i < hpriv->n_clks; i++) {
122
if (hpriv->clks[i].id && !strcmp(hpriv->clks[i].id, con_id))
123
return hpriv->clks[i].clk;
124
}
125
126
return NULL;
127
}
128
EXPORT_SYMBOL_GPL(ahci_platform_find_clk);
129
130
/**
131
* ahci_platform_enable_clks - Enable platform clocks
132
* @hpriv: host private area to store config values
133
*
134
* This function enables all the clks found for the AHCI device.
135
*
136
* RETURNS:
137
* 0 on success otherwise a negative error code
138
*/
139
int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
140
{
141
return clk_bulk_prepare_enable(hpriv->n_clks, hpriv->clks);
142
}
143
EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
144
145
/**
146
* ahci_platform_disable_clks - Disable platform clocks
147
* @hpriv: host private area to store config values
148
*
149
* This function disables all the clocks enabled before
150
* (bulk-clocks-disable function is supposed to do that in reverse
151
* from the enabling procedure order).
152
*/
153
void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
154
{
155
clk_bulk_disable_unprepare(hpriv->n_clks, hpriv->clks);
156
}
157
EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
158
159
/**
160
* ahci_platform_deassert_rsts - Deassert/trigger platform resets
161
* @hpriv: host private area to store config values
162
*
163
* This function deasserts or triggers all the reset lines found for
164
* the AHCI device.
165
*
166
* RETURNS:
167
* 0 on success otherwise a negative error code
168
*/
169
int ahci_platform_deassert_rsts(struct ahci_host_priv *hpriv)
170
{
171
if (hpriv->f_rsts & AHCI_PLATFORM_RST_TRIGGER)
172
return reset_control_reset(hpriv->rsts);
173
174
return reset_control_deassert(hpriv->rsts);
175
}
176
EXPORT_SYMBOL_GPL(ahci_platform_deassert_rsts);
177
178
/**
179
* ahci_platform_assert_rsts - Assert/rearm platform resets
180
* @hpriv: host private area to store config values
181
*
182
* This function asserts or rearms (for self-deasserting resets) all
183
* the reset controls found for the AHCI device.
184
*
185
* RETURNS:
186
* 0 on success otherwise a negative error code
187
*/
188
int ahci_platform_assert_rsts(struct ahci_host_priv *hpriv)
189
{
190
if (hpriv->f_rsts & AHCI_PLATFORM_RST_TRIGGER)
191
return reset_control_rearm(hpriv->rsts);
192
193
return reset_control_assert(hpriv->rsts);
194
}
195
EXPORT_SYMBOL_GPL(ahci_platform_assert_rsts);
196
197
/**
198
* ahci_platform_enable_regulators - Enable regulators
199
* @hpriv: host private area to store config values
200
*
201
* This function enables all the regulators found in controller and
202
* hpriv->target_pwrs, if any. If a regulator fails to be enabled, it
203
* disables all the regulators already enabled in reverse order and
204
* returns an error.
205
*
206
* RETURNS:
207
* 0 on success otherwise a negative error code
208
*/
209
int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv)
210
{
211
int rc, i;
212
213
rc = regulator_enable(hpriv->ahci_regulator);
214
if (rc)
215
return rc;
216
217
rc = regulator_enable(hpriv->phy_regulator);
218
if (rc)
219
goto disable_ahci_pwrs;
220
221
for (i = 0; i < hpriv->nports; i++) {
222
if (!hpriv->target_pwrs[i])
223
continue;
224
225
rc = regulator_enable(hpriv->target_pwrs[i]);
226
if (rc)
227
goto disable_target_pwrs;
228
}
229
230
return 0;
231
232
disable_target_pwrs:
233
while (--i >= 0)
234
if (hpriv->target_pwrs[i])
235
regulator_disable(hpriv->target_pwrs[i]);
236
237
regulator_disable(hpriv->phy_regulator);
238
disable_ahci_pwrs:
239
regulator_disable(hpriv->ahci_regulator);
240
return rc;
241
}
242
EXPORT_SYMBOL_GPL(ahci_platform_enable_regulators);
243
244
/**
245
* ahci_platform_disable_regulators - Disable regulators
246
* @hpriv: host private area to store config values
247
*
248
* This function disables all regulators found in hpriv->target_pwrs and
249
* AHCI controller.
250
*/
251
void ahci_platform_disable_regulators(struct ahci_host_priv *hpriv)
252
{
253
int i;
254
255
for (i = 0; i < hpriv->nports; i++) {
256
if (!hpriv->target_pwrs[i])
257
continue;
258
regulator_disable(hpriv->target_pwrs[i]);
259
}
260
261
regulator_disable(hpriv->ahci_regulator);
262
regulator_disable(hpriv->phy_regulator);
263
}
264
EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators);
265
/**
266
* ahci_platform_enable_resources - Enable platform resources
267
* @hpriv: host private area to store config values
268
*
269
* This function enables all ahci_platform managed resources in the
270
* following order:
271
* 1) Regulator
272
* 2) Clocks (through ahci_platform_enable_clks)
273
* 3) Resets
274
* 4) Phys
275
*
276
* If resource enabling fails at any point the previous enabled resources
277
* are disabled in reverse order.
278
*
279
* RETURNS:
280
* 0 on success otherwise a negative error code
281
*/
282
int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
283
{
284
int rc;
285
286
rc = ahci_platform_enable_regulators(hpriv);
287
if (rc)
288
return rc;
289
290
rc = ahci_platform_enable_clks(hpriv);
291
if (rc)
292
goto disable_regulator;
293
294
rc = ahci_platform_deassert_rsts(hpriv);
295
if (rc)
296
goto disable_clks;
297
298
rc = ahci_platform_enable_phys(hpriv);
299
if (rc)
300
goto disable_rsts;
301
302
return 0;
303
304
disable_rsts:
305
ahci_platform_assert_rsts(hpriv);
306
307
disable_clks:
308
ahci_platform_disable_clks(hpriv);
309
310
disable_regulator:
311
ahci_platform_disable_regulators(hpriv);
312
313
return rc;
314
}
315
EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
316
317
/**
318
* ahci_platform_disable_resources - Disable platform resources
319
* @hpriv: host private area to store config values
320
*
321
* This function disables all ahci_platform managed resources in the
322
* following order:
323
* 1) Phys
324
* 2) Resets
325
* 3) Clocks (through ahci_platform_disable_clks)
326
* 4) Regulator
327
*/
328
void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
329
{
330
ahci_platform_disable_phys(hpriv);
331
332
ahci_platform_assert_rsts(hpriv);
333
334
ahci_platform_disable_clks(hpriv);
335
336
ahci_platform_disable_regulators(hpriv);
337
}
338
EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
339
340
static void ahci_platform_put_resources(struct device *dev, void *res)
341
{
342
struct ahci_host_priv *hpriv = res;
343
int c;
344
345
if (hpriv->got_runtime_pm) {
346
pm_runtime_put_sync(dev);
347
pm_runtime_disable(dev);
348
}
349
350
/*
351
* The regulators are tied to child node device and not to the
352
* SATA device itself. So we can't use devm for automatically
353
* releasing them. We have to do it manually here.
354
*/
355
for (c = 0; c < hpriv->nports; c++)
356
if (hpriv->target_pwrs && hpriv->target_pwrs[c])
357
regulator_put(hpriv->target_pwrs[c]);
358
359
kfree(hpriv->target_pwrs);
360
}
361
362
static int ahci_platform_get_phy(struct ahci_host_priv *hpriv, u32 port,
363
struct device *dev, struct device_node *node)
364
{
365
int rc;
366
367
hpriv->phys[port] = devm_of_phy_get(dev, node, NULL);
368
369
if (!IS_ERR(hpriv->phys[port]))
370
return 0;
371
372
rc = PTR_ERR(hpriv->phys[port]);
373
switch (rc) {
374
case -ENOSYS:
375
/* No PHY support. Check if PHY is required. */
376
if (of_property_present(node, "phys")) {
377
dev_err(dev,
378
"couldn't get PHY in node %pOFn: ENOSYS\n",
379
node);
380
break;
381
}
382
fallthrough;
383
case -ENODEV:
384
/* continue normally */
385
hpriv->phys[port] = NULL;
386
rc = 0;
387
break;
388
case -EPROBE_DEFER:
389
/* Do not complain yet */
390
break;
391
392
default:
393
dev_err(dev,
394
"couldn't get PHY in node %pOFn: %d\n",
395
node, rc);
396
397
break;
398
}
399
400
return rc;
401
}
402
403
static int ahci_platform_get_regulator(struct ahci_host_priv *hpriv, u32 port,
404
struct device *dev)
405
{
406
struct regulator *target_pwr;
407
int rc = 0;
408
409
target_pwr = regulator_get(dev, "target");
410
411
if (!IS_ERR(target_pwr))
412
hpriv->target_pwrs[port] = target_pwr;
413
else
414
rc = PTR_ERR(target_pwr);
415
416
return rc;
417
}
418
419
static int ahci_platform_get_firmware(struct ahci_host_priv *hpriv,
420
struct device *dev)
421
{
422
u32 port;
423
424
if (!of_property_read_u32(dev->of_node, "hba-cap", &hpriv->saved_cap))
425
hpriv->saved_cap &= (HOST_CAP_SSS | HOST_CAP_MPS);
426
427
of_property_read_u32(dev->of_node,
428
"ports-implemented", &hpriv->saved_port_map);
429
430
for_each_child_of_node_scoped(dev->of_node, child) {
431
if (!of_device_is_available(child))
432
continue;
433
434
if (of_property_read_u32(child, "reg", &port))
435
return -EINVAL;
436
437
if (!of_property_read_u32(child, "hba-port-cap", &hpriv->saved_port_cap[port]))
438
hpriv->saved_port_cap[port] &= PORT_CMD_CAP;
439
}
440
441
return 0;
442
}
443
444
static u32 ahci_platform_find_max_port_id(struct device *dev)
445
{
446
u32 max_port = 0;
447
448
for_each_child_of_node_scoped(dev->of_node, child) {
449
u32 port;
450
451
if (!of_property_read_u32(child, "reg", &port))
452
max_port = max(max_port, port);
453
}
454
455
return max_port;
456
}
457
458
/**
459
* ahci_platform_get_resources - Get platform resources
460
* @pdev: platform device to get resources for
461
* @flags: bitmap representing the resource to get
462
*
463
* This function allocates an ahci_host_priv struct, and gets the following
464
* resources, storing a reference to them inside the returned struct:
465
*
466
* 1) mmio registers (IORESOURCE_MEM 0, mandatory)
467
* 2) regulator for controlling the targets power (optional)
468
* regulator for controlling the AHCI controller (optional)
469
* 3) all clocks specified in the devicetree node, or a single
470
* clock for non-OF platforms (optional)
471
* 4) resets, if flags has AHCI_PLATFORM_GET_RESETS (optional)
472
* 5) phys (optional)
473
*
474
* RETURNS:
475
* The allocated ahci_host_priv on success, otherwise an ERR_PTR value
476
*/
477
struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,
478
unsigned int flags)
479
{
480
int child_nodes, rc = -ENOMEM, enabled_ports = 0;
481
struct device *dev = &pdev->dev;
482
struct ahci_host_priv *hpriv;
483
u32 mask_port_map = 0;
484
u32 max_port;
485
486
if (!devres_open_group(dev, NULL, GFP_KERNEL))
487
return ERR_PTR(-ENOMEM);
488
489
hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
490
GFP_KERNEL);
491
if (!hpriv)
492
goto err_out;
493
494
devres_add(dev, hpriv);
495
496
/*
497
* If the DT provided an "ahci" named resource, use it. Otherwise,
498
* fallback to using the default first resource for the device node.
499
*/
500
if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci"))
501
hpriv->mmio = devm_platform_ioremap_resource_byname(pdev, "ahci");
502
else
503
hpriv->mmio = devm_platform_ioremap_resource(pdev, 0);
504
if (IS_ERR(hpriv->mmio)) {
505
rc = PTR_ERR(hpriv->mmio);
506
goto err_out;
507
}
508
509
/*
510
* Bulk clocks getting procedure can fail to find any clock due to
511
* running on a non-OF platform or due to the clocks being defined in
512
* bypass of the DT firmware (like da850, spear13xx). In that case we
513
* fallback to getting a single clock source right from the dev clocks
514
* list.
515
*/
516
rc = devm_clk_bulk_get_all(dev, &hpriv->clks);
517
if (rc < 0)
518
goto err_out;
519
520
if (rc > 0) {
521
/* Got clocks in bulk */
522
hpriv->n_clks = rc;
523
} else {
524
/*
525
* No clock bulk found: fallback to manually getting
526
* the optional clock.
527
*/
528
hpriv->clks = devm_kzalloc(dev, sizeof(*hpriv->clks), GFP_KERNEL);
529
if (!hpriv->clks) {
530
rc = -ENOMEM;
531
goto err_out;
532
}
533
hpriv->clks->clk = devm_clk_get_optional(dev, NULL);
534
if (IS_ERR(hpriv->clks->clk)) {
535
rc = PTR_ERR(hpriv->clks->clk);
536
goto err_out;
537
} else if (hpriv->clks->clk) {
538
hpriv->clks->id = "ahci";
539
hpriv->n_clks = 1;
540
}
541
}
542
543
hpriv->ahci_regulator = devm_regulator_get(dev, "ahci");
544
if (IS_ERR(hpriv->ahci_regulator)) {
545
rc = PTR_ERR(hpriv->ahci_regulator);
546
if (rc != 0)
547
goto err_out;
548
}
549
550
hpriv->phy_regulator = devm_regulator_get(dev, "phy");
551
if (IS_ERR(hpriv->phy_regulator)) {
552
rc = PTR_ERR(hpriv->phy_regulator);
553
goto err_out;
554
}
555
556
if (flags & AHCI_PLATFORM_GET_RESETS) {
557
hpriv->rsts = devm_reset_control_array_get_optional_shared(dev);
558
if (IS_ERR(hpriv->rsts)) {
559
rc = PTR_ERR(hpriv->rsts);
560
goto err_out;
561
}
562
563
hpriv->f_rsts = flags & AHCI_PLATFORM_RST_TRIGGER;
564
}
565
566
/*
567
* Too many sub-nodes most likely means having something wrong with
568
* the firmware.
569
*/
570
child_nodes = of_get_child_count(dev->of_node);
571
if (child_nodes > AHCI_MAX_PORTS) {
572
rc = -EINVAL;
573
goto err_out;
574
}
575
576
/* find maximum port id for allocating structures */
577
max_port = ahci_platform_find_max_port_id(dev);
578
/*
579
* Set nports according to maximum port id. Clamp at
580
* AHCI_MAX_PORTS, warning message for invalid port id
581
* is generated later.
582
* When DT has no sub-nodes max_port is 0, nports is 1,
583
* in order to be able to use the
584
* ahci_platform_[en|dis]able_[phys|regulators] functions.
585
*/
586
hpriv->nports = min(AHCI_MAX_PORTS, max_port + 1);
587
588
hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
589
if (!hpriv->phys) {
590
rc = -ENOMEM;
591
goto err_out;
592
}
593
/*
594
* We cannot use devm_ here, since ahci_platform_put_resources() uses
595
* target_pwrs after devm_ have freed memory
596
*/
597
hpriv->target_pwrs = kcalloc(hpriv->nports, sizeof(*hpriv->target_pwrs), GFP_KERNEL);
598
if (!hpriv->target_pwrs) {
599
rc = -ENOMEM;
600
goto err_out;
601
}
602
603
if (child_nodes) {
604
for_each_child_of_node_scoped(dev->of_node, child) {
605
u32 port;
606
struct platform_device *port_dev __maybe_unused;
607
608
if (!of_device_is_available(child))
609
continue;
610
611
if (of_property_read_u32(child, "reg", &port)) {
612
rc = -EINVAL;
613
goto err_out;
614
}
615
616
if (port >= hpriv->nports) {
617
dev_warn(dev, "invalid port number %d\n", port);
618
continue;
619
}
620
mask_port_map |= BIT(port);
621
622
#ifdef CONFIG_OF_ADDRESS
623
of_platform_device_create(child, NULL, NULL);
624
625
port_dev = of_find_device_by_node(child);
626
627
if (port_dev) {
628
rc = ahci_platform_get_regulator(hpriv, port,
629
&port_dev->dev);
630
if (rc == -EPROBE_DEFER)
631
goto err_out;
632
}
633
#endif
634
635
rc = ahci_platform_get_phy(hpriv, port, dev, child);
636
if (rc)
637
goto err_out;
638
639
enabled_ports++;
640
}
641
if (!enabled_ports) {
642
dev_warn(dev, "No port enabled\n");
643
rc = -ENODEV;
644
goto err_out;
645
}
646
647
if (!hpriv->mask_port_map)
648
hpriv->mask_port_map = mask_port_map;
649
} else {
650
/*
651
* If no sub-node was found, keep this for device tree
652
* compatibility
653
*/
654
rc = ahci_platform_get_phy(hpriv, 0, dev, dev->of_node);
655
if (rc)
656
goto err_out;
657
658
rc = ahci_platform_get_regulator(hpriv, 0, dev);
659
if (rc == -EPROBE_DEFER)
660
goto err_out;
661
}
662
663
/*
664
* Retrieve firmware-specific flags which then will be used to set
665
* the HW-init fields of HBA and its ports
666
*/
667
rc = ahci_platform_get_firmware(hpriv, dev);
668
if (rc)
669
goto err_out;
670
671
pm_runtime_enable(dev);
672
pm_runtime_get_sync(dev);
673
hpriv->got_runtime_pm = true;
674
675
devres_remove_group(dev, NULL);
676
return hpriv;
677
678
err_out:
679
devres_release_group(dev, NULL);
680
return ERR_PTR(rc);
681
}
682
EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
683
684
/**
685
* ahci_platform_init_host - Bring up an ahci-platform host
686
* @pdev: platform device pointer for the host
687
* @hpriv: ahci-host private data for the host
688
* @pi_template: template for the ata_port_info to use
689
* @sht: scsi_host_template to use when registering
690
*
691
* This function does all the usual steps needed to bring up an
692
* ahci-platform host, note any necessary resources (ie clks, phys, etc.)
693
* must be initialized / enabled before calling this.
694
*
695
* RETURNS:
696
* 0 on success otherwise a negative error code
697
*/
698
int ahci_platform_init_host(struct platform_device *pdev,
699
struct ahci_host_priv *hpriv,
700
const struct ata_port_info *pi_template,
701
const struct scsi_host_template *sht)
702
{
703
struct device *dev = &pdev->dev;
704
struct ata_port_info pi = *pi_template;
705
const struct ata_port_info *ppi[] = { &pi, NULL };
706
struct ata_host *host;
707
int i, irq, n_ports, rc;
708
709
irq = platform_get_irq(pdev, 0);
710
if (irq < 0)
711
return irq;
712
if (!irq)
713
return -EINVAL;
714
715
hpriv->irq = irq;
716
717
/* prepare host */
718
pi.private_data = (void *)(unsigned long)hpriv->flags;
719
720
ahci_save_initial_config(dev, hpriv);
721
722
if (hpriv->cap & HOST_CAP_NCQ)
723
pi.flags |= ATA_FLAG_NCQ;
724
725
if (hpriv->cap & HOST_CAP_PMP)
726
pi.flags |= ATA_FLAG_PMP;
727
728
ahci_set_em_messages(hpriv, &pi);
729
730
/* CAP.NP sometimes indicate the index of the last enabled
731
* port, at other times, that of the last possible port, so
732
* determining the maximum port number requires looking at
733
* both CAP.NP and port_map.
734
*/
735
n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
736
737
host = ata_host_alloc_pinfo(dev, ppi, n_ports);
738
if (!host)
739
return -ENOMEM;
740
741
host->private_data = hpriv;
742
743
if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
744
host->flags |= ATA_HOST_PARALLEL_SCAN;
745
else
746
dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
747
748
if (pi.flags & ATA_FLAG_EM)
749
ahci_reset_em(host);
750
751
for (i = 0; i < host->n_ports; i++) {
752
struct ata_port *ap = host->ports[i];
753
754
ata_port_desc(ap, "mmio %pR",
755
platform_get_resource(pdev, IORESOURCE_MEM, 0));
756
ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
757
758
/* set enclosure management message type */
759
if (ap->flags & ATA_FLAG_EM)
760
ap->em_message_type = hpriv->em_msg_type;
761
762
/* disabled/not-implemented port */
763
if (!(hpriv->port_map & (1 << i)))
764
ap->ops = &ata_dummy_port_ops;
765
}
766
767
if (hpriv->cap & HOST_CAP_64) {
768
rc = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
769
if (rc) {
770
dev_err(dev, "Failed to enable 64-bit DMA.\n");
771
return rc;
772
}
773
}
774
775
rc = ahci_reset_controller(host);
776
if (rc)
777
return rc;
778
779
ahci_init_controller(host);
780
ahci_print_info(host, "platform");
781
782
return ahci_host_activate(host, sht);
783
}
784
EXPORT_SYMBOL_GPL(ahci_platform_init_host);
785
786
static void ahci_host_stop(struct ata_host *host)
787
{
788
struct ahci_host_priv *hpriv = host->private_data;
789
790
ahci_platform_disable_resources(hpriv);
791
}
792
793
/**
794
* ahci_platform_shutdown - Disable interrupts and stop DMA for host ports
795
* @pdev: platform device pointer for the host
796
*
797
* This function is called during system shutdown and performs the minimal
798
* deconfiguration required to ensure that an ahci_platform host cannot
799
* corrupt or otherwise interfere with a new kernel being started with kexec.
800
*/
801
void ahci_platform_shutdown(struct platform_device *pdev)
802
{
803
struct ata_host *host = platform_get_drvdata(pdev);
804
struct ahci_host_priv *hpriv = host->private_data;
805
void __iomem *mmio = hpriv->mmio;
806
int i;
807
808
for (i = 0; i < host->n_ports; i++) {
809
struct ata_port *ap = host->ports[i];
810
811
/* Disable port interrupts */
812
if (ap->ops->freeze)
813
ap->ops->freeze(ap);
814
815
/* Stop the port DMA engines */
816
if (ap->ops->port_stop)
817
ap->ops->port_stop(ap);
818
}
819
820
/* Disable and clear host interrupts */
821
writel(readl(mmio + HOST_CTL) & ~HOST_IRQ_EN, mmio + HOST_CTL);
822
readl(mmio + HOST_CTL); /* flush */
823
writel(GENMASK(host->n_ports, 0), mmio + HOST_IRQ_STAT);
824
}
825
EXPORT_SYMBOL_GPL(ahci_platform_shutdown);
826
827
#ifdef CONFIG_PM_SLEEP
828
/**
829
* ahci_platform_suspend_host - Suspend an ahci-platform host
830
* @dev: device pointer for the host
831
*
832
* This function does all the usual steps needed to suspend an
833
* ahci-platform host, note any necessary resources (ie clks, phys, etc.)
834
* must be disabled after calling this.
835
*
836
* RETURNS:
837
* 0 on success otherwise a negative error code
838
*/
839
int ahci_platform_suspend_host(struct device *dev)
840
{
841
struct ata_host *host = dev_get_drvdata(dev);
842
struct ahci_host_priv *hpriv = host->private_data;
843
void __iomem *mmio = hpriv->mmio;
844
u32 ctl;
845
846
if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
847
dev_err(dev, "firmware update required for suspend/resume\n");
848
return -EIO;
849
}
850
851
/*
852
* AHCI spec rev1.1 section 8.3.3:
853
* Software must disable interrupts prior to requesting a
854
* transition of the HBA to D3 state.
855
*/
856
ctl = readl(mmio + HOST_CTL);
857
ctl &= ~HOST_IRQ_EN;
858
writel(ctl, mmio + HOST_CTL);
859
readl(mmio + HOST_CTL); /* flush */
860
861
if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
862
ahci_platform_disable_phys(hpriv);
863
864
ata_host_suspend(host, PMSG_SUSPEND);
865
return 0;
866
}
867
EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
868
869
/**
870
* ahci_platform_resume_host - Resume an ahci-platform host
871
* @dev: device pointer for the host
872
*
873
* This function does all the usual steps needed to resume an ahci-platform
874
* host, note any necessary resources (ie clks, phys, etc.) must be
875
* initialized / enabled before calling this.
876
*
877
* RETURNS:
878
* 0 on success otherwise a negative error code
879
*/
880
int ahci_platform_resume_host(struct device *dev)
881
{
882
struct ata_host *host = dev_get_drvdata(dev);
883
struct ahci_host_priv *hpriv = host->private_data;
884
int rc;
885
886
if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
887
rc = ahci_reset_controller(host);
888
if (rc)
889
return rc;
890
891
ahci_init_controller(host);
892
}
893
894
if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
895
ahci_platform_enable_phys(hpriv);
896
897
ata_host_resume(host);
898
899
return 0;
900
}
901
EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
902
903
/**
904
* ahci_platform_suspend - Suspend an ahci-platform device
905
* @dev: the platform device to suspend
906
*
907
* This function suspends the host associated with the device, followed by
908
* disabling all the resources of the device.
909
*
910
* RETURNS:
911
* 0 on success otherwise a negative error code
912
*/
913
int ahci_platform_suspend(struct device *dev)
914
{
915
struct ata_host *host = dev_get_drvdata(dev);
916
struct ahci_host_priv *hpriv = host->private_data;
917
int rc;
918
919
rc = ahci_platform_suspend_host(dev);
920
if (rc)
921
return rc;
922
923
ahci_platform_disable_resources(hpriv);
924
925
return 0;
926
}
927
EXPORT_SYMBOL_GPL(ahci_platform_suspend);
928
929
/**
930
* ahci_platform_resume - Resume an ahci-platform device
931
* @dev: the platform device to resume
932
*
933
* This function enables all the resources of the device followed by
934
* resuming the host associated with the device.
935
*
936
* RETURNS:
937
* 0 on success otherwise a negative error code
938
*/
939
int ahci_platform_resume(struct device *dev)
940
{
941
struct ata_host *host = dev_get_drvdata(dev);
942
struct ahci_host_priv *hpriv = host->private_data;
943
int rc;
944
945
rc = ahci_platform_enable_resources(hpriv);
946
if (rc)
947
return rc;
948
949
rc = ahci_platform_resume_host(dev);
950
if (rc)
951
goto disable_resources;
952
953
/* We resumed so update PM runtime state */
954
pm_runtime_disable(dev);
955
pm_runtime_set_active(dev);
956
pm_runtime_enable(dev);
957
958
return 0;
959
960
disable_resources:
961
ahci_platform_disable_resources(hpriv);
962
963
return rc;
964
}
965
EXPORT_SYMBOL_GPL(ahci_platform_resume);
966
#endif
967
968
MODULE_DESCRIPTION("AHCI SATA platform library");
969
MODULE_AUTHOR("Anton Vorontsov <[email protected]>");
970
MODULE_LICENSE("GPL");
971
972