1
2
3
4
5
6
7
8
9
10
11
12#include <linux/acpi.h>
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/ahci_platform.h>
16#include <linux/of_address.h>
17#include <linux/of_device.h>
18#include <linux/of_irq.h>
19#include <linux/phy/phy.h>
20#include "ahci.h"
21
22#define DRV_NAME "xgene-ahci"
23
24
25#define MAX_AHCI_CHN_PERCTR 2
26
27
28#define SATA_ENET_CONFIG_REG 0x00000000
29#define CFG_SATA_ENET_SELECT_MASK 0x00000001
30
31
32#define SLVRDERRATTRIBUTES 0x00000000
33#define SLVWRERRATTRIBUTES 0x00000004
34#define MSTRDERRATTRIBUTES 0x00000008
35#define MSTWRERRATTRIBUTES 0x0000000c
36#define BUSCTLREG 0x00000014
37#define IOFMSTRWAUX 0x00000018
38#define INTSTATUSMASK 0x0000002c
39#define ERRINTSTATUS 0x00000030
40#define ERRINTSTATUSMASK 0x00000034
41
42
43#define PORTCFG 0x000000a4
44#define PORTADDR_SET(dst, src) \
45 (((dst) & ~0x0000003f) | (((u32)(src)) & 0x0000003f))
46#define PORTPHY1CFG 0x000000a8
47#define PORTPHY1CFG_FRCPHYRDY_SET(dst, src) \
48 (((dst) & ~0x00100000) | (((u32)(src) << 0x14) & 0x00100000))
49#define PORTPHY2CFG 0x000000ac
50#define PORTPHY3CFG 0x000000b0
51#define PORTPHY4CFG 0x000000b4
52#define PORTPHY5CFG 0x000000b8
53#define SCTL0 0x0000012C
54#define PORTPHY5CFG_RTCHG_SET(dst, src) \
55 (((dst) & ~0xfff00000) | (((u32)(src) << 0x14) & 0xfff00000))
56#define PORTAXICFG_EN_CONTEXT_SET(dst, src) \
57 (((dst) & ~0x01000000) | (((u32)(src) << 0x18) & 0x01000000))
58#define PORTAXICFG 0x000000bc
59#define PORTAXICFG_OUTTRANS_SET(dst, src) \
60 (((dst) & ~0x00f00000) | (((u32)(src) << 0x14) & 0x00f00000))
61#define PORTRANSCFG 0x000000c8
62#define PORTRANSCFG_RXWM_SET(dst, src) \
63 (((dst) & ~0x0000007f) | (((u32)(src)) & 0x0000007f))
64
65
66#define INT_SLV_TMOMASK 0x00000010
67
68
69#define CFG_MEM_RAM_SHUTDOWN 0x00000070
70#define BLOCK_MEM_RDY 0x00000074
71
72
73#define MAX_LINK_DOWN_RETRY 3
74
75enum xgene_ahci_version {
76 XGENE_AHCI_V1 = 1,
77 XGENE_AHCI_V2,
78};
79
80struct xgene_ahci_context {
81 struct ahci_host_priv *hpriv;
82 struct device *dev;
83 u8 last_cmd[MAX_AHCI_CHN_PERCTR];
84 u32 class[MAX_AHCI_CHN_PERCTR];
85 void __iomem *csr_core;
86 void __iomem *csr_diag;
87 void __iomem *csr_axi;
88 void __iomem *csr_mux;
89};
90
91static int xgene_ahci_init_memram(struct xgene_ahci_context *ctx)
92{
93 dev_dbg(ctx->dev, "Release memory from shutdown\n");
94 writel(0x0, ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN);
95 readl(ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN);
96 msleep(1);
97 if (readl(ctx->csr_diag + BLOCK_MEM_RDY) != 0xFFFFFFFF) {
98 dev_err(ctx->dev, "failed to release memory from shutdown\n");
99 return -ENODEV;
100 }
101 return 0;
102}
103
104
105
106
107
108
109
110
111
112static int xgene_ahci_poll_reg_val(struct ata_port *ap,
113 void __iomem *reg, unsigned
114 int val, unsigned long interval,
115 unsigned long timeout)
116{
117 unsigned long deadline;
118 unsigned int tmp;
119
120 tmp = ioread32(reg);
121 deadline = ata_deadline(jiffies, timeout);
122
123 while (tmp != val && time_before(jiffies, deadline)) {
124 ata_msleep(ap, interval);
125 tmp = ioread32(reg);
126 }
127
128 return tmp;
129}
130
131
132
133
134
135
136
137
138static int xgene_ahci_restart_engine(struct ata_port *ap)
139{
140 struct ahci_host_priv *hpriv = ap->host->private_data;
141 struct ahci_port_priv *pp = ap->private_data;
142 void __iomem *port_mmio = ahci_port_base(ap);
143 u32 fbs;
144
145
146
147
148
149
150
151 if (xgene_ahci_poll_reg_val(ap, port_mmio +
152 PORT_CMD_ISSUE, 0x0, 1, 100))
153 return -EBUSY;
154
155 hpriv->stop_engine(ap);
156 ahci_start_fis_rx(ap);
157
158
159
160
161
162 if (pp->fbs_supported) {
163 fbs = readl(port_mmio + PORT_FBS);
164 writel(fbs | PORT_FBS_EN, port_mmio + PORT_FBS);
165 fbs = readl(port_mmio + PORT_FBS);
166 }
167
168 hpriv->start_engine(ap);
169
170 return 0;
171}
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189static unsigned int xgene_ahci_qc_issue(struct ata_queued_cmd *qc)
190{
191 struct ata_port *ap = qc->ap;
192 struct ahci_host_priv *hpriv = ap->host->private_data;
193 struct xgene_ahci_context *ctx = hpriv->plat_data;
194 int rc = 0;
195 u32 port_fbs;
196 void __iomem *port_mmio = ahci_port_base(ap);
197
198
199
200
201
202 if (ctx->class[ap->port_no] == ATA_DEV_PMP) {
203 port_fbs = readl(port_mmio + PORT_FBS);
204 port_fbs &= ~PORT_FBS_DEV_MASK;
205 port_fbs |= qc->dev->link->pmp << PORT_FBS_DEV_OFFSET;
206 writel(port_fbs, port_mmio + PORT_FBS);
207 }
208
209 if (unlikely((ctx->last_cmd[ap->port_no] == ATA_CMD_ID_ATA) ||
210 (ctx->last_cmd[ap->port_no] == ATA_CMD_PACKET) ||
211 (ctx->last_cmd[ap->port_no] == ATA_CMD_SMART)))
212 xgene_ahci_restart_engine(ap);
213
214 rc = ahci_qc_issue(qc);
215
216
217 ctx->last_cmd[ap->port_no] = qc->tf.command;
218
219 return rc;
220}
221
222static bool xgene_ahci_is_memram_inited(struct xgene_ahci_context *ctx)
223{
224 void __iomem *diagcsr = ctx->csr_diag;
225
226 return (readl(diagcsr + CFG_MEM_RAM_SHUTDOWN) == 0 &&
227 readl(diagcsr + BLOCK_MEM_RDY) == 0xFFFFFFFF);
228}
229
230
231
232
233
234
235
236
237
238
239static unsigned int xgene_ahci_read_id(struct ata_device *dev,
240 struct ata_taskfile *tf, __le16 *id)
241{
242 u32 err_mask;
243
244 err_mask = ata_do_dev_read_id(dev, tf, id);
245 if (err_mask)
246 return err_mask;
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262 id[ATA_ID_FEATURE_SUPP] &= cpu_to_le16(~(1 << 8));
263
264 return 0;
265}
266
267static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel)
268{
269 void __iomem *mmio = ctx->hpriv->mmio;
270 u32 val;
271
272 dev_dbg(ctx->dev, "port configure mmio 0x%p channel %d\n",
273 mmio, channel);
274 val = readl(mmio + PORTCFG);
275 val = PORTADDR_SET(val, channel == 0 ? 2 : 3);
276 writel(val, mmio + PORTCFG);
277 readl(mmio + PORTCFG);
278
279 writel(0x0001fffe, mmio + PORTPHY1CFG);
280 readl(mmio + PORTPHY1CFG);
281 writel(0x28183219, mmio + PORTPHY2CFG);
282 readl(mmio + PORTPHY2CFG);
283 writel(0x13081008, mmio + PORTPHY3CFG);
284 readl(mmio + PORTPHY3CFG);
285 writel(0x00480815, mmio + PORTPHY4CFG);
286 readl(mmio + PORTPHY4CFG);
287
288 val = readl(mmio + PORTPHY5CFG);
289 val = PORTPHY5CFG_RTCHG_SET(val, 0x300);
290 writel(val, mmio + PORTPHY5CFG);
291 readl(mmio + PORTPHY5CFG);
292 val = readl(mmio + PORTAXICFG);
293 val = PORTAXICFG_EN_CONTEXT_SET(val, 0x1);
294 val = PORTAXICFG_OUTTRANS_SET(val, 0xe);
295 writel(val, mmio + PORTAXICFG);
296 readl(mmio + PORTAXICFG);
297
298 val = readl(mmio + PORTRANSCFG);
299 val = PORTRANSCFG_RXWM_SET(val, 0x30);
300 writel(val, mmio + PORTRANSCFG);
301}
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350static int xgene_ahci_do_hardreset(struct ata_link *link,
351 unsigned long deadline, bool *online)
352{
353 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
354 struct ata_port *ap = link->ap;
355 struct ahci_host_priv *hpriv = ap->host->private_data;
356 struct xgene_ahci_context *ctx = hpriv->plat_data;
357 struct ahci_port_priv *pp = ap->private_data;
358 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
359 void __iomem *port_mmio = ahci_port_base(ap);
360 struct ata_taskfile tf;
361 int link_down_retry = 0;
362 int rc;
363 u32 val, sstatus;
364
365 do {
366
367 ata_tf_init(link->device, &tf);
368 tf.command = ATA_BUSY;
369 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
370 rc = sata_link_hardreset(link, timing, deadline, online,
371 ahci_check_ready);
372 if (*online) {
373 val = readl(port_mmio + PORT_SCR_ERR);
374 if (val & (SERR_DISPARITY | SERR_10B_8B_ERR))
375 dev_warn(ctx->dev, "link has error\n");
376 break;
377 }
378
379 sata_scr_read(link, SCR_STATUS, &sstatus);
380 } while (link_down_retry++ < MAX_LINK_DOWN_RETRY &&
381 (sstatus & 0xff) == 0x1);
382
383
384 val = readl(port_mmio + PORT_SCR_ERR);
385 writel(val, port_mmio + PORT_SCR_ERR);
386
387 return rc;
388}
389
390static int xgene_ahci_hardreset(struct ata_link *link, unsigned int *class,
391 unsigned long deadline)
392{
393 struct ata_port *ap = link->ap;
394 struct ahci_host_priv *hpriv = ap->host->private_data;
395 void __iomem *port_mmio = ahci_port_base(ap);
396 bool online;
397 int rc;
398 u32 portcmd_saved;
399 u32 portclb_saved;
400 u32 portclbhi_saved;
401 u32 portrxfis_saved;
402 u32 portrxfishi_saved;
403
404
405 portcmd_saved = readl(port_mmio + PORT_CMD);
406 portclb_saved = readl(port_mmio + PORT_LST_ADDR);
407 portclbhi_saved = readl(port_mmio + PORT_LST_ADDR_HI);
408 portrxfis_saved = readl(port_mmio + PORT_FIS_ADDR);
409 portrxfishi_saved = readl(port_mmio + PORT_FIS_ADDR_HI);
410
411 hpriv->stop_engine(ap);
412
413 rc = xgene_ahci_do_hardreset(link, deadline, &online);
414
415
416 writel(portcmd_saved, port_mmio + PORT_CMD);
417 writel(portclb_saved, port_mmio + PORT_LST_ADDR);
418 writel(portclbhi_saved, port_mmio + PORT_LST_ADDR_HI);
419 writel(portrxfis_saved, port_mmio + PORT_FIS_ADDR);
420 writel(portrxfishi_saved, port_mmio + PORT_FIS_ADDR_HI);
421
422 hpriv->start_engine(ap);
423
424 if (online)
425 *class = ahci_dev_classify(ap);
426
427 return rc;
428}
429
430static void xgene_ahci_host_stop(struct ata_host *host)
431{
432 struct ahci_host_priv *hpriv = host->private_data;
433
434 ahci_platform_disable_resources(hpriv);
435}
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451static int xgene_ahci_pmp_softreset(struct ata_link *link, unsigned int *class,
452 unsigned long deadline)
453{
454 int pmp = sata_srst_pmp(link);
455 struct ata_port *ap = link->ap;
456 u32 rc;
457 void __iomem *port_mmio = ahci_port_base(ap);
458 u32 port_fbs;
459
460
461
462
463
464 port_fbs = readl(port_mmio + PORT_FBS);
465 port_fbs &= ~PORT_FBS_DEV_MASK;
466 port_fbs |= pmp << PORT_FBS_DEV_OFFSET;
467 writel(port_fbs, port_mmio + PORT_FBS);
468
469 rc = ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
470
471 return rc;
472}
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495static int xgene_ahci_softreset(struct ata_link *link, unsigned int *class,
496 unsigned long deadline)
497{
498 int pmp = sata_srst_pmp(link);
499 struct ata_port *ap = link->ap;
500 struct ahci_host_priv *hpriv = ap->host->private_data;
501 struct xgene_ahci_context *ctx = hpriv->plat_data;
502 void __iomem *port_mmio = ahci_port_base(ap);
503 u32 port_fbs;
504 u32 port_fbs_save;
505 u32 retry = 1;
506 u32 rc;
507
508 port_fbs_save = readl(port_mmio + PORT_FBS);
509
510
511
512
513
514 port_fbs = readl(port_mmio + PORT_FBS);
515 port_fbs &= ~PORT_FBS_DEV_MASK;
516 port_fbs |= pmp << PORT_FBS_DEV_OFFSET;
517 writel(port_fbs, port_mmio + PORT_FBS);
518
519softreset_retry:
520 rc = ahci_do_softreset(link, class, pmp,
521 deadline, ahci_check_ready);
522
523 ctx->class[ap->port_no] = *class;
524 if (*class != ATA_DEV_PMP) {
525
526
527
528
529 if (retry--) {
530 writel(port_fbs_save, port_mmio + PORT_FBS);
531 goto softreset_retry;
532 }
533 }
534
535 return rc;
536}
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562static int xgene_ahci_handle_broken_edge_irq(struct ata_host *host,
563 u32 irq_masked)
564{
565 struct ahci_host_priv *hpriv = host->private_data;
566 void __iomem *port_mmio;
567 int i;
568
569 if (!readl(hpriv->mmio + HOST_IRQ_STAT)) {
570 for (i = 0; i < host->n_ports; i++) {
571 if (irq_masked & (1 << i))
572 continue;
573
574 port_mmio = ahci_port_base(host->ports[i]);
575 if (readl(port_mmio + PORT_IRQ_STAT))
576 irq_masked |= (1 << i);
577 }
578 }
579
580 return ahci_handle_port_intr(host, irq_masked);
581}
582
583static irqreturn_t xgene_ahci_irq_intr(int irq, void *dev_instance)
584{
585 struct ata_host *host = dev_instance;
586 struct ahci_host_priv *hpriv;
587 unsigned int rc = 0;
588 void __iomem *mmio;
589 u32 irq_stat, irq_masked;
590
591 hpriv = host->private_data;
592 mmio = hpriv->mmio;
593
594
595 irq_stat = readl(mmio + HOST_IRQ_STAT);
596 if (!irq_stat)
597 return IRQ_NONE;
598
599 irq_masked = irq_stat & hpriv->port_map;
600
601 spin_lock(&host->lock);
602
603
604
605
606
607 writel(irq_stat, mmio + HOST_IRQ_STAT);
608
609 rc = xgene_ahci_handle_broken_edge_irq(host, irq_masked);
610
611 spin_unlock(&host->lock);
612
613 return IRQ_RETVAL(rc);
614}
615
616static struct ata_port_operations xgene_ahci_v1_ops = {
617 .inherits = &ahci_ops,
618 .host_stop = xgene_ahci_host_stop,
619 .hardreset = xgene_ahci_hardreset,
620 .read_id = xgene_ahci_read_id,
621 .qc_issue = xgene_ahci_qc_issue,
622 .softreset = xgene_ahci_softreset,
623 .pmp_softreset = xgene_ahci_pmp_softreset
624};
625
626static const struct ata_port_info xgene_ahci_v1_port_info = {
627 .flags = AHCI_FLAG_COMMON | ATA_FLAG_PMP,
628 .pio_mask = ATA_PIO4,
629 .udma_mask = ATA_UDMA6,
630 .port_ops = &xgene_ahci_v1_ops,
631};
632
633static struct ata_port_operations xgene_ahci_v2_ops = {
634 .inherits = &ahci_ops,
635 .host_stop = xgene_ahci_host_stop,
636 .hardreset = xgene_ahci_hardreset,
637 .read_id = xgene_ahci_read_id,
638};
639
640static const struct ata_port_info xgene_ahci_v2_port_info = {
641 .flags = AHCI_FLAG_COMMON | ATA_FLAG_PMP,
642 .pio_mask = ATA_PIO4,
643 .udma_mask = ATA_UDMA6,
644 .port_ops = &xgene_ahci_v2_ops,
645};
646
647static int xgene_ahci_hw_init(struct ahci_host_priv *hpriv)
648{
649 struct xgene_ahci_context *ctx = hpriv->plat_data;
650 int i;
651 int rc;
652 u32 val;
653
654
655 rc = xgene_ahci_init_memram(ctx);
656 if (rc)
657 return rc;
658
659 for (i = 0; i < MAX_AHCI_CHN_PERCTR; i++)
660 xgene_ahci_set_phy_cfg(ctx, i);
661
662
663 writel(0xffffffff, hpriv->mmio + HOST_IRQ_STAT);
664 readl(hpriv->mmio + HOST_IRQ_STAT);
665 writel(0, ctx->csr_core + INTSTATUSMASK);
666 val = readl(ctx->csr_core + INTSTATUSMASK);
667 dev_dbg(ctx->dev, "top level interrupt mask 0x%X value 0x%08X\n",
668 INTSTATUSMASK, val);
669
670 writel(0x0, ctx->csr_core + ERRINTSTATUSMASK);
671 readl(ctx->csr_core + ERRINTSTATUSMASK);
672 writel(0x0, ctx->csr_axi + INT_SLV_TMOMASK);
673 readl(ctx->csr_axi + INT_SLV_TMOMASK);
674
675
676 writel(0xffffffff, ctx->csr_core + SLVRDERRATTRIBUTES);
677 writel(0xffffffff, ctx->csr_core + SLVWRERRATTRIBUTES);
678 writel(0xffffffff, ctx->csr_core + MSTRDERRATTRIBUTES);
679 writel(0xffffffff, ctx->csr_core + MSTWRERRATTRIBUTES);
680
681
682 val = readl(ctx->csr_core + BUSCTLREG);
683 val &= ~0x00000002;
684 val &= ~0x00000001;
685 writel(val, ctx->csr_core + BUSCTLREG);
686
687 val = readl(ctx->csr_core + IOFMSTRWAUX);
688 val |= (1 << 3);
689 val |= (1 << 9);
690 writel(val, ctx->csr_core + IOFMSTRWAUX);
691 val = readl(ctx->csr_core + IOFMSTRWAUX);
692 dev_dbg(ctx->dev, "coherency 0x%X value 0x%08X\n",
693 IOFMSTRWAUX, val);
694
695 return rc;
696}
697
698static int xgene_ahci_mux_select(struct xgene_ahci_context *ctx)
699{
700 u32 val;
701
702
703 if (!ctx->csr_mux)
704 return 0;
705
706 val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG);
707 val &= ~CFG_SATA_ENET_SELECT_MASK;
708 writel(val, ctx->csr_mux + SATA_ENET_CONFIG_REG);
709 val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG);
710 return val & CFG_SATA_ENET_SELECT_MASK ? -1 : 0;
711}
712
713static struct scsi_host_template ahci_platform_sht = {
714 AHCI_SHT(DRV_NAME),
715};
716
717#ifdef CONFIG_ACPI
718static const struct acpi_device_id xgene_ahci_acpi_match[] = {
719 { "APMC0D0D", XGENE_AHCI_V1},
720 { "APMC0D32", XGENE_AHCI_V2},
721 {},
722};
723MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match);
724#endif
725
726static const struct of_device_id xgene_ahci_of_match[] = {
727 {.compatible = "apm,xgene-ahci", .data = (void *) XGENE_AHCI_V1},
728 {.compatible = "apm,xgene-ahci-v2", .data = (void *) XGENE_AHCI_V2},
729 {},
730};
731MODULE_DEVICE_TABLE(of, xgene_ahci_of_match);
732
733static int xgene_ahci_probe(struct platform_device *pdev)
734{
735 struct device *dev = &pdev->dev;
736 struct ahci_host_priv *hpriv;
737 struct xgene_ahci_context *ctx;
738 struct resource *res;
739 const struct of_device_id *of_devid;
740 enum xgene_ahci_version version = XGENE_AHCI_V1;
741 const struct ata_port_info *ppi[] = { &xgene_ahci_v1_port_info,
742 &xgene_ahci_v2_port_info };
743 int rc;
744
745 hpriv = ahci_platform_get_resources(pdev, 0);
746 if (IS_ERR(hpriv))
747 return PTR_ERR(hpriv);
748
749 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
750 if (!ctx)
751 return -ENOMEM;
752
753 hpriv->plat_data = ctx;
754 ctx->hpriv = hpriv;
755 ctx->dev = dev;
756
757
758 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
759 ctx->csr_core = devm_ioremap_resource(dev, res);
760 if (IS_ERR(ctx->csr_core))
761 return PTR_ERR(ctx->csr_core);
762
763
764 res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
765 ctx->csr_diag = devm_ioremap_resource(dev, res);
766 if (IS_ERR(ctx->csr_diag))
767 return PTR_ERR(ctx->csr_diag);
768
769
770 res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
771 ctx->csr_axi = devm_ioremap_resource(dev, res);
772 if (IS_ERR(ctx->csr_axi))
773 return PTR_ERR(ctx->csr_axi);
774
775
776 res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
777 if (res) {
778 void __iomem *csr = devm_ioremap_resource(dev, res);
779 if (IS_ERR(csr))
780 return PTR_ERR(csr);
781
782 ctx->csr_mux = csr;
783 }
784
785 of_devid = of_match_device(xgene_ahci_of_match, dev);
786 if (of_devid) {
787 if (of_devid->data)
788 version = (enum xgene_ahci_version) of_devid->data;
789 }
790#ifdef CONFIG_ACPI
791 else {
792 const struct acpi_device_id *acpi_id;
793 struct acpi_device_info *info;
794 acpi_status status;
795
796 acpi_id = acpi_match_device(xgene_ahci_acpi_match, &pdev->dev);
797 if (!acpi_id) {
798 dev_warn(&pdev->dev, "No node entry in ACPI table. Assume version1\n");
799 version = XGENE_AHCI_V1;
800 } else if (acpi_id->driver_data) {
801 version = (enum xgene_ahci_version) acpi_id->driver_data;
802 status = acpi_get_object_info(ACPI_HANDLE(&pdev->dev), &info);
803 if (ACPI_FAILURE(status)) {
804 dev_warn(&pdev->dev, "%s: Error reading device info. Assume version1\n",
805 __func__);
806 version = XGENE_AHCI_V1;
807 } else {
808 if (info->valid & ACPI_VALID_CID)
809 version = XGENE_AHCI_V2;
810 kfree(info);
811 }
812 }
813 }
814#endif
815
816 dev_dbg(dev, "VAddr 0x%p Mmio VAddr 0x%p\n", ctx->csr_core,
817 hpriv->mmio);
818
819
820 if ((rc = xgene_ahci_mux_select(ctx))) {
821 dev_err(dev, "SATA mux selection failed error %d\n", rc);
822 return -ENODEV;
823 }
824
825 if (xgene_ahci_is_memram_inited(ctx)) {
826 dev_info(dev, "skip clock and PHY initialization\n");
827 goto skip_clk_phy;
828 }
829
830
831 rc = ahci_platform_enable_clks(hpriv);
832 if (rc)
833 goto disable_resources;
834 ahci_platform_disable_clks(hpriv);
835
836 rc = ahci_platform_enable_resources(hpriv);
837 if (rc)
838 goto disable_resources;
839
840
841 xgene_ahci_hw_init(hpriv);
842skip_clk_phy:
843
844 switch (version) {
845 case XGENE_AHCI_V1:
846 hpriv->flags = AHCI_HFLAG_NO_NCQ;
847 break;
848 case XGENE_AHCI_V2:
849 hpriv->flags |= AHCI_HFLAG_YES_FBS;
850 hpriv->irq_handler = xgene_ahci_irq_intr;
851 break;
852 default:
853 break;
854 }
855
856 rc = ahci_platform_init_host(pdev, hpriv, ppi[version - 1],
857 &ahci_platform_sht);
858 if (rc)
859 goto disable_resources;
860
861 dev_dbg(dev, "X-Gene SATA host controller initialized\n");
862 return 0;
863
864disable_resources:
865 ahci_platform_disable_resources(hpriv);
866 return rc;
867}
868
869static struct platform_driver xgene_ahci_driver = {
870 .probe = xgene_ahci_probe,
871 .remove = ata_platform_remove_one,
872 .driver = {
873 .name = DRV_NAME,
874 .of_match_table = xgene_ahci_of_match,
875 .acpi_match_table = ACPI_PTR(xgene_ahci_acpi_match),
876 },
877};
878
879module_platform_driver(xgene_ahci_driver);
880
881MODULE_DESCRIPTION("APM X-Gene AHCI SATA driver");
882MODULE_AUTHOR("Loc Ho <lho@apm.com>");
883MODULE_LICENSE("GPL");
884MODULE_VERSION("0.4");
885