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