Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/ata/ahci_brcm.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Broadcom SATA3 AHCI Controller Driver
4
*
5
* Copyright © 2009-2015 Broadcom Corporation
6
*/
7
8
#include <linux/ahci_platform.h>
9
#include <linux/compiler.h>
10
#include <linux/device.h>
11
#include <linux/init.h>
12
#include <linux/interrupt.h>
13
#include <linux/io.h>
14
#include <linux/kernel.h>
15
#include <linux/libata.h>
16
#include <linux/module.h>
17
#include <linux/of.h>
18
#include <linux/platform_device.h>
19
#include <linux/reset.h>
20
#include <linux/string.h>
21
22
#include "ahci.h"
23
24
#define DRV_NAME "brcm-ahci"
25
26
#define SATA_TOP_CTRL_VERSION 0x0
27
#define SATA_TOP_CTRL_BUS_CTRL 0x4
28
#define MMIO_ENDIAN_SHIFT 0 /* CPU->AHCI */
29
#define DMADESC_ENDIAN_SHIFT 2 /* AHCI->DDR */
30
#define DMADATA_ENDIAN_SHIFT 4 /* AHCI->DDR */
31
#define PIODATA_ENDIAN_SHIFT 6
32
#define ENDIAN_SWAP_NONE 0
33
#define ENDIAN_SWAP_FULL 2
34
#define SATA_TOP_CTRL_TP_CTRL 0x8
35
#define SATA_TOP_CTRL_PHY_CTRL 0xc
36
#define SATA_TOP_CTRL_PHY_CTRL_1 0x0
37
#define SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE BIT(14)
38
#define SATA_TOP_CTRL_PHY_CTRL_2 0x4
39
#define SATA_TOP_CTRL_2_SW_RST_MDIOREG BIT(0)
40
#define SATA_TOP_CTRL_2_SW_RST_OOB BIT(1)
41
#define SATA_TOP_CTRL_2_SW_RST_RX BIT(2)
42
#define SATA_TOP_CTRL_2_SW_RST_TX BIT(3)
43
#define SATA_TOP_CTRL_2_PHY_GLOBAL_RESET BIT(14)
44
#define SATA_TOP_CTRL_PHY_OFFS 0x8
45
#define SATA_TOP_MAX_PHYS 2
46
47
#define SATA_FIRST_PORT_CTRL 0x700
48
#define SATA_NEXT_PORT_CTRL_OFFSET 0x80
49
#define SATA_PORT_PCTRL6(reg_base) (reg_base + 0x18)
50
51
/* On big-endian MIPS, buses are reversed to big endian, so switch them back */
52
#if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN)
53
#define DATA_ENDIAN 2 /* AHCI->DDR inbound accesses */
54
#define MMIO_ENDIAN 2 /* CPU->AHCI outbound accesses */
55
#else
56
#define DATA_ENDIAN 0
57
#define MMIO_ENDIAN 0
58
#endif
59
60
#define BUS_CTRL_ENDIAN_CONF \
61
((DATA_ENDIAN << DMADATA_ENDIAN_SHIFT) | \
62
(DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) | \
63
(MMIO_ENDIAN << MMIO_ENDIAN_SHIFT))
64
65
#define BUS_CTRL_ENDIAN_NSP_CONF \
66
(0x02 << DMADATA_ENDIAN_SHIFT | 0x02 << DMADESC_ENDIAN_SHIFT)
67
68
#define BUS_CTRL_ENDIAN_CONF_MASK \
69
(0x3 << MMIO_ENDIAN_SHIFT | 0x3 << DMADESC_ENDIAN_SHIFT | \
70
0x3 << DMADATA_ENDIAN_SHIFT | 0x3 << PIODATA_ENDIAN_SHIFT)
71
72
enum brcm_ahci_version {
73
BRCM_SATA_BCM7425 = 1,
74
BRCM_SATA_BCM7445,
75
BRCM_SATA_NSP,
76
BRCM_SATA_BCM7216,
77
};
78
79
enum brcm_ahci_quirks {
80
BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(0),
81
};
82
83
struct brcm_ahci_priv {
84
struct device *dev;
85
void __iomem *top_ctrl;
86
u32 port_mask;
87
u32 quirks;
88
enum brcm_ahci_version version;
89
struct reset_control *rcdev_rescal;
90
struct reset_control *rcdev_ahci;
91
};
92
93
static inline u32 brcm_sata_readreg(void __iomem *addr)
94
{
95
/*
96
* MIPS endianness is configured by boot strap, which also reverses all
97
* bus endianness (i.e., big-endian CPU + big endian bus ==> native
98
* endian I/O).
99
*
100
* Other architectures (e.g., ARM) either do not support big endian, or
101
* else leave I/O in little endian mode.
102
*/
103
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
104
return __raw_readl(addr);
105
else
106
return readl_relaxed(addr);
107
}
108
109
static inline void brcm_sata_writereg(u32 val, void __iomem *addr)
110
{
111
/* See brcm_sata_readreg() comments */
112
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
113
__raw_writel(val, addr);
114
else
115
writel_relaxed(val, addr);
116
}
117
118
static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv)
119
{
120
struct brcm_ahci_priv *priv = hpriv->plat_data;
121
u32 port_ctrl, host_caps;
122
int i;
123
124
/* Enable support for ALPM */
125
host_caps = readl(hpriv->mmio + HOST_CAP);
126
if (!(host_caps & HOST_CAP_ALPM))
127
hpriv->flags |= AHCI_HFLAG_YES_ALPM;
128
129
/*
130
* Adjust timeout to allow PLL sufficient time to lock while waking
131
* up from slumber mode.
132
*/
133
for (i = 0, port_ctrl = SATA_FIRST_PORT_CTRL;
134
i < SATA_TOP_MAX_PHYS;
135
i++, port_ctrl += SATA_NEXT_PORT_CTRL_OFFSET) {
136
if (priv->port_mask & BIT(i))
137
writel(0xff1003fc,
138
hpriv->mmio + SATA_PORT_PCTRL6(port_ctrl));
139
}
140
}
141
142
static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port)
143
{
144
void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +
145
(port * SATA_TOP_CTRL_PHY_OFFS);
146
void __iomem *p;
147
u32 reg;
148
149
if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)
150
return;
151
152
/* clear PHY_DEFAULT_POWER_STATE */
153
p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;
154
reg = brcm_sata_readreg(p);
155
reg &= ~SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;
156
brcm_sata_writereg(reg, p);
157
158
/* reset the PHY digital logic */
159
p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;
160
reg = brcm_sata_readreg(p);
161
reg &= ~(SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |
162
SATA_TOP_CTRL_2_SW_RST_RX);
163
reg |= SATA_TOP_CTRL_2_SW_RST_TX;
164
brcm_sata_writereg(reg, p);
165
reg = brcm_sata_readreg(p);
166
reg |= SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;
167
brcm_sata_writereg(reg, p);
168
reg = brcm_sata_readreg(p);
169
reg &= ~SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;
170
brcm_sata_writereg(reg, p);
171
(void)brcm_sata_readreg(p);
172
}
173
174
static void brcm_sata_phy_disable(struct brcm_ahci_priv *priv, int port)
175
{
176
void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +
177
(port * SATA_TOP_CTRL_PHY_OFFS);
178
void __iomem *p;
179
u32 reg;
180
181
if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)
182
return;
183
184
/* power-off the PHY digital logic */
185
p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;
186
reg = brcm_sata_readreg(p);
187
reg |= (SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |
188
SATA_TOP_CTRL_2_SW_RST_RX | SATA_TOP_CTRL_2_SW_RST_TX |
189
SATA_TOP_CTRL_2_PHY_GLOBAL_RESET);
190
brcm_sata_writereg(reg, p);
191
192
/* set PHY_DEFAULT_POWER_STATE */
193
p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;
194
reg = brcm_sata_readreg(p);
195
reg |= SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;
196
brcm_sata_writereg(reg, p);
197
}
198
199
static void brcm_sata_phys_enable(struct brcm_ahci_priv *priv)
200
{
201
int i;
202
203
for (i = 0; i < SATA_TOP_MAX_PHYS; i++)
204
if (priv->port_mask & BIT(i))
205
brcm_sata_phy_enable(priv, i);
206
}
207
208
static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv)
209
{
210
int i;
211
212
for (i = 0; i < SATA_TOP_MAX_PHYS; i++)
213
if (priv->port_mask & BIT(i))
214
brcm_sata_phy_disable(priv, i);
215
}
216
217
static u32 brcm_ahci_get_portmask(struct ahci_host_priv *hpriv,
218
struct brcm_ahci_priv *priv)
219
{
220
u32 impl;
221
222
impl = readl(hpriv->mmio + HOST_PORTS_IMPL);
223
224
if (fls(impl) > SATA_TOP_MAX_PHYS)
225
dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n",
226
impl);
227
else if (!impl)
228
dev_info(priv->dev, "no ports found\n");
229
230
return impl;
231
}
232
233
static void brcm_sata_init(struct brcm_ahci_priv *priv)
234
{
235
void __iomem *ctrl = priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL;
236
u32 data;
237
238
/* Configure endianness */
239
data = brcm_sata_readreg(ctrl);
240
data &= ~BUS_CTRL_ENDIAN_CONF_MASK;
241
if (priv->version == BRCM_SATA_NSP)
242
data |= BUS_CTRL_ENDIAN_NSP_CONF;
243
else
244
data |= BUS_CTRL_ENDIAN_CONF;
245
brcm_sata_writereg(data, ctrl);
246
}
247
248
static unsigned int brcm_ahci_read_id(struct ata_device *dev,
249
struct ata_taskfile *tf, __le16 *id)
250
{
251
struct ata_port *ap = dev->link->ap;
252
struct ata_host *host = ap->host;
253
struct ahci_host_priv *hpriv = host->private_data;
254
struct brcm_ahci_priv *priv = hpriv->plat_data;
255
void __iomem *mmio = hpriv->mmio;
256
unsigned int err_mask;
257
unsigned long flags;
258
int i, rc;
259
u32 ctl;
260
261
/* Try to read the device ID and, if this fails, proceed with the
262
* recovery sequence below
263
*/
264
err_mask = ata_do_dev_read_id(dev, tf, id);
265
if (likely(!err_mask))
266
return err_mask;
267
268
/* Disable host interrupts */
269
spin_lock_irqsave(&host->lock, flags);
270
ctl = readl(mmio + HOST_CTL);
271
ctl &= ~HOST_IRQ_EN;
272
writel(ctl, mmio + HOST_CTL);
273
readl(mmio + HOST_CTL); /* flush */
274
spin_unlock_irqrestore(&host->lock, flags);
275
276
/* Perform the SATA PHY reset sequence */
277
brcm_sata_phy_disable(priv, ap->port_no);
278
279
/* Reset the SATA clock */
280
ahci_platform_disable_clks(hpriv);
281
msleep(10);
282
283
ahci_platform_enable_clks(hpriv);
284
msleep(10);
285
286
/* Bring the PHY back on */
287
brcm_sata_phy_enable(priv, ap->port_no);
288
289
/* Re-initialize and calibrate the PHY */
290
for (i = 0; i < hpriv->nports; i++) {
291
if (ahci_ignore_port(hpriv, i))
292
continue;
293
294
rc = phy_init(hpriv->phys[i]);
295
if (rc)
296
goto disable_phys;
297
298
rc = phy_calibrate(hpriv->phys[i]);
299
if (rc) {
300
phy_exit(hpriv->phys[i]);
301
goto disable_phys;
302
}
303
}
304
305
/* Re-enable host interrupts */
306
spin_lock_irqsave(&host->lock, flags);
307
ctl = readl(mmio + HOST_CTL);
308
ctl |= HOST_IRQ_EN;
309
writel(ctl, mmio + HOST_CTL);
310
readl(mmio + HOST_CTL); /* flush */
311
spin_unlock_irqrestore(&host->lock, flags);
312
313
return ata_do_dev_read_id(dev, tf, id);
314
315
disable_phys:
316
while (--i >= 0) {
317
phy_power_off(hpriv->phys[i]);
318
phy_exit(hpriv->phys[i]);
319
}
320
321
return AC_ERR_OTHER;
322
}
323
324
static void brcm_ahci_host_stop(struct ata_host *host)
325
{
326
struct ahci_host_priv *hpriv = host->private_data;
327
328
ahci_platform_disable_resources(hpriv);
329
}
330
331
static struct ata_port_operations ahci_brcm_platform_ops = {
332
.inherits = &ahci_ops,
333
.host_stop = brcm_ahci_host_stop,
334
.read_id = brcm_ahci_read_id,
335
};
336
337
static const struct ata_port_info ahci_brcm_port_info = {
338
.flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
339
.link_flags = ATA_LFLAG_NO_DEBOUNCE_DELAY,
340
.pio_mask = ATA_PIO4,
341
.udma_mask = ATA_UDMA6,
342
.port_ops = &ahci_brcm_platform_ops,
343
};
344
345
static int brcm_ahci_suspend(struct device *dev)
346
{
347
struct ata_host *host = dev_get_drvdata(dev);
348
struct ahci_host_priv *hpriv = host->private_data;
349
struct brcm_ahci_priv *priv = hpriv->plat_data;
350
int ret;
351
352
brcm_sata_phys_disable(priv);
353
354
if (IS_ENABLED(CONFIG_PM_SLEEP))
355
ret = ahci_platform_suspend(dev);
356
else
357
ret = 0;
358
359
reset_control_assert(priv->rcdev_ahci);
360
reset_control_rearm(priv->rcdev_rescal);
361
362
return ret;
363
}
364
365
static int __maybe_unused brcm_ahci_resume(struct device *dev)
366
{
367
struct ata_host *host = dev_get_drvdata(dev);
368
struct ahci_host_priv *hpriv = host->private_data;
369
struct brcm_ahci_priv *priv = hpriv->plat_data;
370
int ret = 0;
371
372
ret = reset_control_deassert(priv->rcdev_ahci);
373
if (ret)
374
return ret;
375
ret = reset_control_reset(priv->rcdev_rescal);
376
if (ret)
377
return ret;
378
379
/* Make sure clocks are turned on before re-configuration */
380
ret = ahci_platform_enable_clks(hpriv);
381
if (ret)
382
return ret;
383
384
ret = ahci_platform_enable_regulators(hpriv);
385
if (ret)
386
goto out_disable_clks;
387
388
brcm_sata_init(priv);
389
brcm_sata_phys_enable(priv);
390
brcm_sata_alpm_init(hpriv);
391
392
/* Since we had to enable clocks earlier on, we cannot use
393
* ahci_platform_resume() as-is since a second call to
394
* ahci_platform_enable_resources() would bump up the resources
395
* (regulators, clocks, PHYs) count artificially so we copy the part
396
* after ahci_platform_enable_resources().
397
*/
398
ret = ahci_platform_enable_phys(hpriv);
399
if (ret)
400
goto out_disable_phys;
401
402
ret = ahci_platform_resume_host(dev);
403
if (ret)
404
goto out_disable_platform_phys;
405
406
/* We resumed so update PM runtime state */
407
pm_runtime_disable(dev);
408
pm_runtime_set_active(dev);
409
pm_runtime_enable(dev);
410
411
return 0;
412
413
out_disable_platform_phys:
414
ahci_platform_disable_phys(hpriv);
415
out_disable_phys:
416
brcm_sata_phys_disable(priv);
417
ahci_platform_disable_regulators(hpriv);
418
out_disable_clks:
419
ahci_platform_disable_clks(hpriv);
420
return ret;
421
}
422
423
static const struct scsi_host_template ahci_platform_sht = {
424
AHCI_SHT(DRV_NAME),
425
};
426
427
static const struct of_device_id ahci_of_match[] = {
428
{.compatible = "brcm,bcm7425-ahci", .data = (void *)BRCM_SATA_BCM7425},
429
{.compatible = "brcm,bcm7445-ahci", .data = (void *)BRCM_SATA_BCM7445},
430
{.compatible = "brcm,bcm63138-ahci", .data = (void *)BRCM_SATA_BCM7445},
431
{.compatible = "brcm,bcm-nsp-ahci", .data = (void *)BRCM_SATA_NSP},
432
{.compatible = "brcm,bcm7216-ahci", .data = (void *)BRCM_SATA_BCM7216},
433
{ /* sentinel */ }
434
};
435
MODULE_DEVICE_TABLE(of, ahci_of_match);
436
437
static int brcm_ahci_probe(struct platform_device *pdev)
438
{
439
const struct of_device_id *of_id;
440
struct device *dev = &pdev->dev;
441
struct brcm_ahci_priv *priv;
442
struct ahci_host_priv *hpriv;
443
int ret;
444
445
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
446
if (!priv)
447
return -ENOMEM;
448
449
of_id = of_match_node(ahci_of_match, pdev->dev.of_node);
450
if (!of_id)
451
return -ENODEV;
452
453
priv->version = (unsigned long)of_id->data;
454
priv->dev = dev;
455
456
priv->top_ctrl = devm_platform_ioremap_resource_byname(pdev, "top-ctrl");
457
if (IS_ERR(priv->top_ctrl))
458
return PTR_ERR(priv->top_ctrl);
459
460
if (priv->version == BRCM_SATA_BCM7216) {
461
priv->rcdev_rescal = devm_reset_control_get_optional_shared(
462
&pdev->dev, "rescal");
463
if (IS_ERR(priv->rcdev_rescal))
464
return PTR_ERR(priv->rcdev_rescal);
465
}
466
priv->rcdev_ahci = devm_reset_control_get_optional(&pdev->dev, "ahci");
467
if (IS_ERR(priv->rcdev_ahci))
468
return PTR_ERR(priv->rcdev_ahci);
469
470
hpriv = ahci_platform_get_resources(pdev, 0);
471
if (IS_ERR(hpriv))
472
return PTR_ERR(hpriv);
473
474
hpriv->plat_data = priv;
475
hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP | AHCI_HFLAG_NO_WRITE_TO_RO;
476
477
switch (priv->version) {
478
case BRCM_SATA_BCM7425:
479
hpriv->flags |= AHCI_HFLAG_DELAY_ENGINE;
480
fallthrough;
481
case BRCM_SATA_NSP:
482
hpriv->flags |= AHCI_HFLAG_NO_NCQ;
483
priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;
484
break;
485
default:
486
break;
487
}
488
489
ret = reset_control_reset(priv->rcdev_rescal);
490
if (ret)
491
return ret;
492
ret = reset_control_deassert(priv->rcdev_ahci);
493
if (ret)
494
return ret;
495
496
ret = ahci_platform_enable_clks(hpriv);
497
if (ret)
498
goto out_reset;
499
500
ret = ahci_platform_enable_regulators(hpriv);
501
if (ret)
502
goto out_disable_clks;
503
504
/* Must be first so as to configure endianness including that
505
* of the standard AHCI register space.
506
*/
507
brcm_sata_init(priv);
508
509
/* Initializes priv->port_mask which is used below */
510
priv->port_mask = brcm_ahci_get_portmask(hpriv, priv);
511
if (!priv->port_mask) {
512
ret = -ENODEV;
513
goto out_disable_regulators;
514
}
515
516
/* Must be done before ahci_platform_enable_phys() */
517
brcm_sata_phys_enable(priv);
518
519
brcm_sata_alpm_init(hpriv);
520
521
ret = ahci_platform_enable_phys(hpriv);
522
if (ret)
523
goto out_disable_phys;
524
525
ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
526
&ahci_platform_sht);
527
if (ret)
528
goto out_disable_platform_phys;
529
530
dev_info(dev, "Broadcom AHCI SATA3 registered\n");
531
532
return 0;
533
534
out_disable_platform_phys:
535
ahci_platform_disable_phys(hpriv);
536
out_disable_phys:
537
brcm_sata_phys_disable(priv);
538
out_disable_regulators:
539
ahci_platform_disable_regulators(hpriv);
540
out_disable_clks:
541
ahci_platform_disable_clks(hpriv);
542
out_reset:
543
reset_control_assert(priv->rcdev_ahci);
544
reset_control_rearm(priv->rcdev_rescal);
545
return ret;
546
}
547
548
static void brcm_ahci_remove(struct platform_device *pdev)
549
{
550
struct ata_host *host = dev_get_drvdata(&pdev->dev);
551
struct ahci_host_priv *hpriv = host->private_data;
552
struct brcm_ahci_priv *priv = hpriv->plat_data;
553
554
brcm_sata_phys_disable(priv);
555
556
ata_platform_remove_one(pdev);
557
}
558
559
static void brcm_ahci_shutdown(struct platform_device *pdev)
560
{
561
int ret;
562
563
/* All resources releasing happens via devres, but our device, unlike a
564
* proper remove is not disappearing, therefore using
565
* brcm_ahci_suspend() here which does explicit power management is
566
* appropriate.
567
*/
568
ret = brcm_ahci_suspend(&pdev->dev);
569
if (ret)
570
dev_err(&pdev->dev, "failed to shutdown\n");
571
}
572
573
static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume);
574
575
static struct platform_driver brcm_ahci_driver = {
576
.probe = brcm_ahci_probe,
577
.remove = brcm_ahci_remove,
578
.shutdown = brcm_ahci_shutdown,
579
.driver = {
580
.name = DRV_NAME,
581
.of_match_table = ahci_of_match,
582
.pm = &ahci_brcm_pm_ops,
583
},
584
};
585
module_platform_driver(brcm_ahci_driver);
586
587
MODULE_DESCRIPTION("Broadcom SATA3 AHCI Controller Driver");
588
MODULE_AUTHOR("Brian Norris");
589
MODULE_LICENSE("GPL");
590
MODULE_ALIAS("platform:sata-brcmstb");
591
592