0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/acpi.h>
0013 #include <linux/module.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/ahci_platform.h>
0016 #include <linux/of_address.h>
0017 #include <linux/of_device.h>
0018 #include <linux/of_irq.h>
0019 #include <linux/phy/phy.h>
0020 #include "ahci.h"
0021
0022 #define DRV_NAME "xgene-ahci"
0023
0024
0025 #define MAX_AHCI_CHN_PERCTR 2
0026
0027
0028 #define SATA_ENET_CONFIG_REG 0x00000000
0029 #define CFG_SATA_ENET_SELECT_MASK 0x00000001
0030
0031
0032 #define SLVRDERRATTRIBUTES 0x00000000
0033 #define SLVWRERRATTRIBUTES 0x00000004
0034 #define MSTRDERRATTRIBUTES 0x00000008
0035 #define MSTWRERRATTRIBUTES 0x0000000c
0036 #define BUSCTLREG 0x00000014
0037 #define IOFMSTRWAUX 0x00000018
0038 #define INTSTATUSMASK 0x0000002c
0039 #define ERRINTSTATUS 0x00000030
0040 #define ERRINTSTATUSMASK 0x00000034
0041
0042
0043 #define PORTCFG 0x000000a4
0044 #define PORTADDR_SET(dst, src) \
0045 (((dst) & ~0x0000003f) | (((u32)(src)) & 0x0000003f))
0046 #define PORTPHY1CFG 0x000000a8
0047 #define PORTPHY1CFG_FRCPHYRDY_SET(dst, src) \
0048 (((dst) & ~0x00100000) | (((u32)(src) << 0x14) & 0x00100000))
0049 #define PORTPHY2CFG 0x000000ac
0050 #define PORTPHY3CFG 0x000000b0
0051 #define PORTPHY4CFG 0x000000b4
0052 #define PORTPHY5CFG 0x000000b8
0053 #define SCTL0 0x0000012C
0054 #define PORTPHY5CFG_RTCHG_SET(dst, src) \
0055 (((dst) & ~0xfff00000) | (((u32)(src) << 0x14) & 0xfff00000))
0056 #define PORTAXICFG_EN_CONTEXT_SET(dst, src) \
0057 (((dst) & ~0x01000000) | (((u32)(src) << 0x18) & 0x01000000))
0058 #define PORTAXICFG 0x000000bc
0059 #define PORTAXICFG_OUTTRANS_SET(dst, src) \
0060 (((dst) & ~0x00f00000) | (((u32)(src) << 0x14) & 0x00f00000))
0061 #define PORTRANSCFG 0x000000c8
0062 #define PORTRANSCFG_RXWM_SET(dst, src) \
0063 (((dst) & ~0x0000007f) | (((u32)(src)) & 0x0000007f))
0064
0065
0066 #define INT_SLV_TMOMASK 0x00000010
0067
0068
0069 #define CFG_MEM_RAM_SHUTDOWN 0x00000070
0070 #define BLOCK_MEM_RDY 0x00000074
0071
0072
0073 #define MAX_LINK_DOWN_RETRY 3
0074
0075 enum xgene_ahci_version {
0076 XGENE_AHCI_V1 = 1,
0077 XGENE_AHCI_V2,
0078 };
0079
0080 struct xgene_ahci_context {
0081 struct ahci_host_priv *hpriv;
0082 struct device *dev;
0083 u8 last_cmd[MAX_AHCI_CHN_PERCTR];
0084 u32 class[MAX_AHCI_CHN_PERCTR];
0085 void __iomem *csr_core;
0086 void __iomem *csr_diag;
0087 void __iomem *csr_axi;
0088 void __iomem *csr_mux;
0089 };
0090
0091 static int xgene_ahci_init_memram(struct xgene_ahci_context *ctx)
0092 {
0093 dev_dbg(ctx->dev, "Release memory from shutdown\n");
0094 writel(0x0, ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN);
0095 readl(ctx->csr_diag + CFG_MEM_RAM_SHUTDOWN);
0096 msleep(1);
0097 if (readl(ctx->csr_diag + BLOCK_MEM_RDY) != 0xFFFFFFFF) {
0098 dev_err(ctx->dev, "failed to release memory from shutdown\n");
0099 return -ENODEV;
0100 }
0101 return 0;
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 static int xgene_ahci_poll_reg_val(struct ata_port *ap,
0113 void __iomem *reg, unsigned
0114 int val, unsigned long interval,
0115 unsigned long timeout)
0116 {
0117 unsigned long deadline;
0118 unsigned int tmp;
0119
0120 tmp = ioread32(reg);
0121 deadline = ata_deadline(jiffies, timeout);
0122
0123 while (tmp != val && time_before(jiffies, deadline)) {
0124 ata_msleep(ap, interval);
0125 tmp = ioread32(reg);
0126 }
0127
0128 return tmp;
0129 }
0130
0131
0132
0133
0134
0135
0136
0137
0138 static int xgene_ahci_restart_engine(struct ata_port *ap)
0139 {
0140 struct ahci_host_priv *hpriv = ap->host->private_data;
0141 struct ahci_port_priv *pp = ap->private_data;
0142 void __iomem *port_mmio = ahci_port_base(ap);
0143 u32 fbs;
0144
0145
0146
0147
0148
0149
0150
0151 if (xgene_ahci_poll_reg_val(ap, port_mmio +
0152 PORT_CMD_ISSUE, 0x0, 1, 100))
0153 return -EBUSY;
0154
0155 hpriv->stop_engine(ap);
0156 ahci_start_fis_rx(ap);
0157
0158
0159
0160
0161
0162 if (pp->fbs_supported) {
0163 fbs = readl(port_mmio + PORT_FBS);
0164 writel(fbs | PORT_FBS_EN, port_mmio + PORT_FBS);
0165 fbs = readl(port_mmio + PORT_FBS);
0166 }
0167
0168 hpriv->start_engine(ap);
0169
0170 return 0;
0171 }
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189 static unsigned int xgene_ahci_qc_issue(struct ata_queued_cmd *qc)
0190 {
0191 struct ata_port *ap = qc->ap;
0192 struct ahci_host_priv *hpriv = ap->host->private_data;
0193 struct xgene_ahci_context *ctx = hpriv->plat_data;
0194 int rc = 0;
0195 u32 port_fbs;
0196 void __iomem *port_mmio = ahci_port_base(ap);
0197
0198
0199
0200
0201
0202 if (ctx->class[ap->port_no] == ATA_DEV_PMP) {
0203 port_fbs = readl(port_mmio + PORT_FBS);
0204 port_fbs &= ~PORT_FBS_DEV_MASK;
0205 port_fbs |= qc->dev->link->pmp << PORT_FBS_DEV_OFFSET;
0206 writel(port_fbs, port_mmio + PORT_FBS);
0207 }
0208
0209 if (unlikely((ctx->last_cmd[ap->port_no] == ATA_CMD_ID_ATA) ||
0210 (ctx->last_cmd[ap->port_no] == ATA_CMD_PACKET) ||
0211 (ctx->last_cmd[ap->port_no] == ATA_CMD_SMART)))
0212 xgene_ahci_restart_engine(ap);
0213
0214 rc = ahci_qc_issue(qc);
0215
0216
0217 ctx->last_cmd[ap->port_no] = qc->tf.command;
0218
0219 return rc;
0220 }
0221
0222 static bool xgene_ahci_is_memram_inited(struct xgene_ahci_context *ctx)
0223 {
0224 void __iomem *diagcsr = ctx->csr_diag;
0225
0226 return (readl(diagcsr + CFG_MEM_RAM_SHUTDOWN) == 0 &&
0227 readl(diagcsr + BLOCK_MEM_RDY) == 0xFFFFFFFF);
0228 }
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239 static unsigned int xgene_ahci_read_id(struct ata_device *dev,
0240 struct ata_taskfile *tf, __le16 *id)
0241 {
0242 u32 err_mask;
0243
0244 err_mask = ata_do_dev_read_id(dev, tf, id);
0245 if (err_mask)
0246 return err_mask;
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262 id[ATA_ID_FEATURE_SUPP] &= cpu_to_le16(~(1 << 8));
0263
0264 return 0;
0265 }
0266
0267 static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel)
0268 {
0269 void __iomem *mmio = ctx->hpriv->mmio;
0270 u32 val;
0271
0272 dev_dbg(ctx->dev, "port configure mmio 0x%p channel %d\n",
0273 mmio, channel);
0274 val = readl(mmio + PORTCFG);
0275 val = PORTADDR_SET(val, channel == 0 ? 2 : 3);
0276 writel(val, mmio + PORTCFG);
0277 readl(mmio + PORTCFG);
0278
0279 writel(0x0001fffe, mmio + PORTPHY1CFG);
0280 readl(mmio + PORTPHY1CFG);
0281 writel(0x28183219, mmio + PORTPHY2CFG);
0282 readl(mmio + PORTPHY2CFG);
0283 writel(0x13081008, mmio + PORTPHY3CFG);
0284 readl(mmio + PORTPHY3CFG);
0285 writel(0x00480815, mmio + PORTPHY4CFG);
0286 readl(mmio + PORTPHY4CFG);
0287
0288 val = readl(mmio + PORTPHY5CFG);
0289 val = PORTPHY5CFG_RTCHG_SET(val, 0x300);
0290 writel(val, mmio + PORTPHY5CFG);
0291 readl(mmio + PORTPHY5CFG);
0292 val = readl(mmio + PORTAXICFG);
0293 val = PORTAXICFG_EN_CONTEXT_SET(val, 0x1);
0294 val = PORTAXICFG_OUTTRANS_SET(val, 0xe);
0295 writel(val, mmio + PORTAXICFG);
0296 readl(mmio + PORTAXICFG);
0297
0298 val = readl(mmio + PORTRANSCFG);
0299 val = PORTRANSCFG_RXWM_SET(val, 0x30);
0300 writel(val, mmio + PORTRANSCFG);
0301 }
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350 static int xgene_ahci_do_hardreset(struct ata_link *link,
0351 unsigned long deadline, bool *online)
0352 {
0353 const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
0354 struct ata_port *ap = link->ap;
0355 struct ahci_host_priv *hpriv = ap->host->private_data;
0356 struct xgene_ahci_context *ctx = hpriv->plat_data;
0357 struct ahci_port_priv *pp = ap->private_data;
0358 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
0359 void __iomem *port_mmio = ahci_port_base(ap);
0360 struct ata_taskfile tf;
0361 int link_down_retry = 0;
0362 int rc;
0363 u32 val, sstatus;
0364
0365 do {
0366
0367 ata_tf_init(link->device, &tf);
0368 tf.status = ATA_BUSY;
0369 ata_tf_to_fis(&tf, 0, 0, d2h_fis);
0370 rc = sata_link_hardreset(link, timing, deadline, online,
0371 ahci_check_ready);
0372 if (*online) {
0373 val = readl(port_mmio + PORT_SCR_ERR);
0374 if (val & (SERR_DISPARITY | SERR_10B_8B_ERR))
0375 dev_warn(ctx->dev, "link has error\n");
0376 break;
0377 }
0378
0379 sata_scr_read(link, SCR_STATUS, &sstatus);
0380 } while (link_down_retry++ < MAX_LINK_DOWN_RETRY &&
0381 (sstatus & 0xff) == 0x1);
0382
0383
0384 val = readl(port_mmio + PORT_SCR_ERR);
0385 writel(val, port_mmio + PORT_SCR_ERR);
0386
0387 return rc;
0388 }
0389
0390 static int xgene_ahci_hardreset(struct ata_link *link, unsigned int *class,
0391 unsigned long deadline)
0392 {
0393 struct ata_port *ap = link->ap;
0394 struct ahci_host_priv *hpriv = ap->host->private_data;
0395 void __iomem *port_mmio = ahci_port_base(ap);
0396 bool online;
0397 int rc;
0398 u32 portcmd_saved;
0399 u32 portclb_saved;
0400 u32 portclbhi_saved;
0401 u32 portrxfis_saved;
0402 u32 portrxfishi_saved;
0403
0404
0405 portcmd_saved = readl(port_mmio + PORT_CMD);
0406 portclb_saved = readl(port_mmio + PORT_LST_ADDR);
0407 portclbhi_saved = readl(port_mmio + PORT_LST_ADDR_HI);
0408 portrxfis_saved = readl(port_mmio + PORT_FIS_ADDR);
0409 portrxfishi_saved = readl(port_mmio + PORT_FIS_ADDR_HI);
0410
0411 hpriv->stop_engine(ap);
0412
0413 rc = xgene_ahci_do_hardreset(link, deadline, &online);
0414
0415
0416 writel(portcmd_saved, port_mmio + PORT_CMD);
0417 writel(portclb_saved, port_mmio + PORT_LST_ADDR);
0418 writel(portclbhi_saved, port_mmio + PORT_LST_ADDR_HI);
0419 writel(portrxfis_saved, port_mmio + PORT_FIS_ADDR);
0420 writel(portrxfishi_saved, port_mmio + PORT_FIS_ADDR_HI);
0421
0422 hpriv->start_engine(ap);
0423
0424 if (online)
0425 *class = ahci_dev_classify(ap);
0426
0427 return rc;
0428 }
0429
0430 static void xgene_ahci_host_stop(struct ata_host *host)
0431 {
0432 struct ahci_host_priv *hpriv = host->private_data;
0433
0434 ahci_platform_disable_resources(hpriv);
0435 }
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451 static int xgene_ahci_pmp_softreset(struct ata_link *link, unsigned int *class,
0452 unsigned long deadline)
0453 {
0454 int pmp = sata_srst_pmp(link);
0455 struct ata_port *ap = link->ap;
0456 u32 rc;
0457 void __iomem *port_mmio = ahci_port_base(ap);
0458 u32 port_fbs;
0459
0460
0461
0462
0463
0464 port_fbs = readl(port_mmio + PORT_FBS);
0465 port_fbs &= ~PORT_FBS_DEV_MASK;
0466 port_fbs |= pmp << PORT_FBS_DEV_OFFSET;
0467 writel(port_fbs, port_mmio + PORT_FBS);
0468
0469 rc = ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
0470
0471 return rc;
0472 }
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495 static int xgene_ahci_softreset(struct ata_link *link, unsigned int *class,
0496 unsigned long deadline)
0497 {
0498 int pmp = sata_srst_pmp(link);
0499 struct ata_port *ap = link->ap;
0500 struct ahci_host_priv *hpriv = ap->host->private_data;
0501 struct xgene_ahci_context *ctx = hpriv->plat_data;
0502 void __iomem *port_mmio = ahci_port_base(ap);
0503 u32 port_fbs;
0504 u32 port_fbs_save;
0505 u32 retry = 1;
0506 u32 rc;
0507
0508 port_fbs_save = readl(port_mmio + PORT_FBS);
0509
0510
0511
0512
0513
0514 port_fbs = readl(port_mmio + PORT_FBS);
0515 port_fbs &= ~PORT_FBS_DEV_MASK;
0516 port_fbs |= pmp << PORT_FBS_DEV_OFFSET;
0517 writel(port_fbs, port_mmio + PORT_FBS);
0518
0519 softreset_retry:
0520 rc = ahci_do_softreset(link, class, pmp,
0521 deadline, ahci_check_ready);
0522
0523 ctx->class[ap->port_no] = *class;
0524 if (*class != ATA_DEV_PMP) {
0525
0526
0527
0528
0529 if (retry--) {
0530 writel(port_fbs_save, port_mmio + PORT_FBS);
0531 goto softreset_retry;
0532 }
0533 }
0534
0535 return rc;
0536 }
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562 static int xgene_ahci_handle_broken_edge_irq(struct ata_host *host,
0563 u32 irq_masked)
0564 {
0565 struct ahci_host_priv *hpriv = host->private_data;
0566 void __iomem *port_mmio;
0567 int i;
0568
0569 if (!readl(hpriv->mmio + HOST_IRQ_STAT)) {
0570 for (i = 0; i < host->n_ports; i++) {
0571 if (irq_masked & (1 << i))
0572 continue;
0573
0574 port_mmio = ahci_port_base(host->ports[i]);
0575 if (readl(port_mmio + PORT_IRQ_STAT))
0576 irq_masked |= (1 << i);
0577 }
0578 }
0579
0580 return ahci_handle_port_intr(host, irq_masked);
0581 }
0582
0583 static irqreturn_t xgene_ahci_irq_intr(int irq, void *dev_instance)
0584 {
0585 struct ata_host *host = dev_instance;
0586 struct ahci_host_priv *hpriv;
0587 unsigned int rc = 0;
0588 void __iomem *mmio;
0589 u32 irq_stat, irq_masked;
0590
0591 hpriv = host->private_data;
0592 mmio = hpriv->mmio;
0593
0594
0595 irq_stat = readl(mmio + HOST_IRQ_STAT);
0596 if (!irq_stat)
0597 return IRQ_NONE;
0598
0599 irq_masked = irq_stat & hpriv->port_map;
0600
0601 spin_lock(&host->lock);
0602
0603
0604
0605
0606
0607 writel(irq_stat, mmio + HOST_IRQ_STAT);
0608
0609 rc = xgene_ahci_handle_broken_edge_irq(host, irq_masked);
0610
0611 spin_unlock(&host->lock);
0612
0613 return IRQ_RETVAL(rc);
0614 }
0615
0616 static struct ata_port_operations xgene_ahci_v1_ops = {
0617 .inherits = &ahci_ops,
0618 .host_stop = xgene_ahci_host_stop,
0619 .hardreset = xgene_ahci_hardreset,
0620 .read_id = xgene_ahci_read_id,
0621 .qc_issue = xgene_ahci_qc_issue,
0622 .softreset = xgene_ahci_softreset,
0623 .pmp_softreset = xgene_ahci_pmp_softreset
0624 };
0625
0626 static const struct ata_port_info xgene_ahci_v1_port_info = {
0627 .flags = AHCI_FLAG_COMMON | ATA_FLAG_PMP,
0628 .pio_mask = ATA_PIO4,
0629 .udma_mask = ATA_UDMA6,
0630 .port_ops = &xgene_ahci_v1_ops,
0631 };
0632
0633 static struct ata_port_operations xgene_ahci_v2_ops = {
0634 .inherits = &ahci_ops,
0635 .host_stop = xgene_ahci_host_stop,
0636 .hardreset = xgene_ahci_hardreset,
0637 .read_id = xgene_ahci_read_id,
0638 };
0639
0640 static const struct ata_port_info xgene_ahci_v2_port_info = {
0641 .flags = AHCI_FLAG_COMMON | ATA_FLAG_PMP,
0642 .pio_mask = ATA_PIO4,
0643 .udma_mask = ATA_UDMA6,
0644 .port_ops = &xgene_ahci_v2_ops,
0645 };
0646
0647 static int xgene_ahci_hw_init(struct ahci_host_priv *hpriv)
0648 {
0649 struct xgene_ahci_context *ctx = hpriv->plat_data;
0650 int i;
0651 int rc;
0652 u32 val;
0653
0654
0655 rc = xgene_ahci_init_memram(ctx);
0656 if (rc)
0657 return rc;
0658
0659 for (i = 0; i < MAX_AHCI_CHN_PERCTR; i++)
0660 xgene_ahci_set_phy_cfg(ctx, i);
0661
0662
0663 writel(0xffffffff, hpriv->mmio + HOST_IRQ_STAT);
0664 readl(hpriv->mmio + HOST_IRQ_STAT);
0665 writel(0, ctx->csr_core + INTSTATUSMASK);
0666 val = readl(ctx->csr_core + INTSTATUSMASK);
0667 dev_dbg(ctx->dev, "top level interrupt mask 0x%X value 0x%08X\n",
0668 INTSTATUSMASK, val);
0669
0670 writel(0x0, ctx->csr_core + ERRINTSTATUSMASK);
0671 readl(ctx->csr_core + ERRINTSTATUSMASK);
0672 writel(0x0, ctx->csr_axi + INT_SLV_TMOMASK);
0673 readl(ctx->csr_axi + INT_SLV_TMOMASK);
0674
0675
0676 writel(0xffffffff, ctx->csr_core + SLVRDERRATTRIBUTES);
0677 writel(0xffffffff, ctx->csr_core + SLVWRERRATTRIBUTES);
0678 writel(0xffffffff, ctx->csr_core + MSTRDERRATTRIBUTES);
0679 writel(0xffffffff, ctx->csr_core + MSTWRERRATTRIBUTES);
0680
0681
0682 val = readl(ctx->csr_core + BUSCTLREG);
0683 val &= ~0x00000002;
0684 val &= ~0x00000001;
0685 writel(val, ctx->csr_core + BUSCTLREG);
0686
0687 val = readl(ctx->csr_core + IOFMSTRWAUX);
0688 val |= (1 << 3);
0689 val |= (1 << 9);
0690 writel(val, ctx->csr_core + IOFMSTRWAUX);
0691 val = readl(ctx->csr_core + IOFMSTRWAUX);
0692 dev_dbg(ctx->dev, "coherency 0x%X value 0x%08X\n",
0693 IOFMSTRWAUX, val);
0694
0695 return rc;
0696 }
0697
0698 static int xgene_ahci_mux_select(struct xgene_ahci_context *ctx)
0699 {
0700 u32 val;
0701
0702
0703 if (!ctx->csr_mux)
0704 return 0;
0705
0706 val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG);
0707 val &= ~CFG_SATA_ENET_SELECT_MASK;
0708 writel(val, ctx->csr_mux + SATA_ENET_CONFIG_REG);
0709 val = readl(ctx->csr_mux + SATA_ENET_CONFIG_REG);
0710 return val & CFG_SATA_ENET_SELECT_MASK ? -1 : 0;
0711 }
0712
0713 static struct scsi_host_template ahci_platform_sht = {
0714 AHCI_SHT(DRV_NAME),
0715 };
0716
0717 #ifdef CONFIG_ACPI
0718 static const struct acpi_device_id xgene_ahci_acpi_match[] = {
0719 { "APMC0D0D", XGENE_AHCI_V1},
0720 { "APMC0D32", XGENE_AHCI_V2},
0721 {},
0722 };
0723 MODULE_DEVICE_TABLE(acpi, xgene_ahci_acpi_match);
0724 #endif
0725
0726 static const struct of_device_id xgene_ahci_of_match[] = {
0727 {.compatible = "apm,xgene-ahci", .data = (void *) XGENE_AHCI_V1},
0728 {.compatible = "apm,xgene-ahci-v2", .data = (void *) XGENE_AHCI_V2},
0729 { }
0730 };
0731 MODULE_DEVICE_TABLE(of, xgene_ahci_of_match);
0732
0733 static int xgene_ahci_probe(struct platform_device *pdev)
0734 {
0735 struct device *dev = &pdev->dev;
0736 struct ahci_host_priv *hpriv;
0737 struct xgene_ahci_context *ctx;
0738 struct resource *res;
0739 const struct of_device_id *of_devid;
0740 enum xgene_ahci_version version = XGENE_AHCI_V1;
0741 const struct ata_port_info *ppi[] = { &xgene_ahci_v1_port_info,
0742 &xgene_ahci_v2_port_info };
0743 int rc;
0744
0745 hpriv = ahci_platform_get_resources(pdev, 0);
0746 if (IS_ERR(hpriv))
0747 return PTR_ERR(hpriv);
0748
0749 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
0750 if (!ctx)
0751 return -ENOMEM;
0752
0753 hpriv->plat_data = ctx;
0754 ctx->hpriv = hpriv;
0755 ctx->dev = dev;
0756
0757
0758 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
0759 ctx->csr_core = devm_ioremap_resource(dev, res);
0760 if (IS_ERR(ctx->csr_core))
0761 return PTR_ERR(ctx->csr_core);
0762
0763
0764 res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
0765 ctx->csr_diag = devm_ioremap_resource(dev, res);
0766 if (IS_ERR(ctx->csr_diag))
0767 return PTR_ERR(ctx->csr_diag);
0768
0769
0770 res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
0771 ctx->csr_axi = devm_ioremap_resource(dev, res);
0772 if (IS_ERR(ctx->csr_axi))
0773 return PTR_ERR(ctx->csr_axi);
0774
0775
0776 res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
0777 if (res) {
0778 void __iomem *csr = devm_ioremap_resource(dev, res);
0779 if (IS_ERR(csr))
0780 return PTR_ERR(csr);
0781
0782 ctx->csr_mux = csr;
0783 }
0784
0785 of_devid = of_match_device(xgene_ahci_of_match, dev);
0786 if (of_devid) {
0787 if (of_devid->data)
0788 version = (enum xgene_ahci_version) of_devid->data;
0789 }
0790 #ifdef CONFIG_ACPI
0791 else {
0792 const struct acpi_device_id *acpi_id;
0793 struct acpi_device_info *info;
0794 acpi_status status;
0795
0796 acpi_id = acpi_match_device(xgene_ahci_acpi_match, &pdev->dev);
0797 if (!acpi_id) {
0798 dev_warn(&pdev->dev, "No node entry in ACPI table. Assume version1\n");
0799 version = XGENE_AHCI_V1;
0800 } else if (acpi_id->driver_data) {
0801 version = (enum xgene_ahci_version) acpi_id->driver_data;
0802 status = acpi_get_object_info(ACPI_HANDLE(&pdev->dev), &info);
0803 if (ACPI_FAILURE(status)) {
0804 dev_warn(&pdev->dev, "%s: Error reading device info. Assume version1\n",
0805 __func__);
0806 version = XGENE_AHCI_V1;
0807 } else {
0808 if (info->valid & ACPI_VALID_CID)
0809 version = XGENE_AHCI_V2;
0810 kfree(info);
0811 }
0812 }
0813 }
0814 #endif
0815
0816 dev_dbg(dev, "VAddr 0x%p Mmio VAddr 0x%p\n", ctx->csr_core,
0817 hpriv->mmio);
0818
0819
0820 if ((rc = xgene_ahci_mux_select(ctx))) {
0821 dev_err(dev, "SATA mux selection failed error %d\n", rc);
0822 return -ENODEV;
0823 }
0824
0825 if (xgene_ahci_is_memram_inited(ctx)) {
0826 dev_info(dev, "skip clock and PHY initialization\n");
0827 goto skip_clk_phy;
0828 }
0829
0830
0831 rc = ahci_platform_enable_clks(hpriv);
0832 if (rc)
0833 goto disable_resources;
0834 ahci_platform_disable_clks(hpriv);
0835
0836 rc = ahci_platform_enable_resources(hpriv);
0837 if (rc)
0838 goto disable_resources;
0839
0840
0841 xgene_ahci_hw_init(hpriv);
0842 skip_clk_phy:
0843
0844 switch (version) {
0845 case XGENE_AHCI_V1:
0846 hpriv->flags = AHCI_HFLAG_NO_NCQ;
0847 break;
0848 case XGENE_AHCI_V2:
0849 hpriv->flags |= AHCI_HFLAG_YES_FBS;
0850 hpriv->irq_handler = xgene_ahci_irq_intr;
0851 break;
0852 default:
0853 break;
0854 }
0855
0856 rc = ahci_platform_init_host(pdev, hpriv, ppi[version - 1],
0857 &ahci_platform_sht);
0858 if (rc)
0859 goto disable_resources;
0860
0861 dev_dbg(dev, "X-Gene SATA host controller initialized\n");
0862 return 0;
0863
0864 disable_resources:
0865 ahci_platform_disable_resources(hpriv);
0866 return rc;
0867 }
0868
0869 static struct platform_driver xgene_ahci_driver = {
0870 .probe = xgene_ahci_probe,
0871 .remove = ata_platform_remove_one,
0872 .driver = {
0873 .name = DRV_NAME,
0874 .of_match_table = xgene_ahci_of_match,
0875 .acpi_match_table = ACPI_PTR(xgene_ahci_acpi_match),
0876 },
0877 };
0878
0879 module_platform_driver(xgene_ahci_driver);
0880
0881 MODULE_DESCRIPTION("APM X-Gene AHCI SATA driver");
0882 MODULE_AUTHOR("Loc Ho <lho@apm.com>");
0883 MODULE_LICENSE("GPL");
0884 MODULE_VERSION("0.4");