1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2015 - 2016 Xilinx, Inc. 4 * Michal Simek <michal.simek@xilinx.com> 5 */ 6 #include <common.h> 7 #include <dm.h> 8 #include <ahci.h> 9 #include <scsi.h> 10 #include <asm/io.h> 11 12 /* Vendor Specific Register Offsets */ 13 #define AHCI_VEND_PCFG 0xA4 14 #define AHCI_VEND_PPCFG 0xA8 15 #define AHCI_VEND_PP2C 0xAC 16 #define AHCI_VEND_PP3C 0xB0 17 #define AHCI_VEND_PP4C 0xB4 18 #define AHCI_VEND_PP5C 0xB8 19 #define AHCI_VEND_AXICC 0xBc 20 #define AHCI_VEND_PAXIC 0xC0 21 #define AHCI_VEND_PTC 0xC8 22 23 /* Vendor Specific Register bit definitions */ 24 #define PAXIC_ADBW_BW64 0x1 25 #define PAXIC_MAWIDD (1 << 8) 26 #define PAXIC_MARIDD (1 << 16) 27 #define PAXIC_OTL (0x4 << 20) 28 29 #define PCFG_TPSS_VAL (0x32 << 16) 30 #define PCFG_TPRS_VAL (0x2 << 12) 31 #define PCFG_PAD_VAL 0x2 32 33 #define PPCFG_TTA 0x1FFFE 34 #define PPCFG_PSSO_EN (1 << 28) 35 #define PPCFG_PSS_EN (1 << 29) 36 #define PPCFG_ESDF_EN (1 << 31) 37 38 #define PP2C_CIBGMN 0x0F 39 #define PP2C_CIBGMX (0x25 << 8) 40 #define PP2C_CIBGN (0x18 << 16) 41 #define PP2C_CINMP (0x29 << 24) 42 43 #define PP3C_CWBGMN 0x04 44 #define PP3C_CWBGMX (0x0B << 8) 45 #define PP3C_CWBGN (0x08 << 16) 46 #define PP3C_CWNMP (0x0F << 24) 47 48 #define PP4C_BMX 0x0a 49 #define PP4C_BNM (0x08 << 8) 50 #define PP4C_SFD (0x4a << 16) 51 #define PP4C_PTST (0x06 << 24) 52 53 #define PP5C_RIT 0x60216 54 #define PP5C_RCT (0x7f0 << 20) 55 56 #define PTC_RX_WM_VAL 0x40 57 #define PTC_RSVD (1 << 27) 58 59 #define PORT0_BASE 0x100 60 #define PORT1_BASE 0x180 61 62 /* Port Control Register Bit Definitions */ 63 #define PORT_SCTL_SPD_GEN3 (0x3 << 4) 64 #define PORT_SCTL_SPD_GEN2 (0x2 << 4) 65 #define PORT_SCTL_SPD_GEN1 (0x1 << 4) 66 #define PORT_SCTL_IPM (0x3 << 8) 67 68 #define PORT_BASE 0x100 69 #define PORT_OFFSET 0x80 70 #define NR_PORTS 2 71 #define DRV_NAME "ahci-ceva" 72 #define CEVA_FLAG_BROKEN_GEN2 1 73 74 /* flag bit definition */ 75 #define FLAG_COHERENT 1 76 77 /* register config value */ 78 #define CEVA_PHY1_CFG 0xa003fffe 79 #define CEVA_PHY2_CFG 0x28184d1f 80 #define CEVA_PHY3_CFG 0x0e081509 81 #define CEVA_TRANS_CFG 0x08000029 82 #define CEVA_AXICC_CFG 0x3fffffff 83 84 /* ecc addr-val pair */ 85 #define ECC_DIS_ADDR_CH2 0x80000000 86 #define ECC_DIS_VAL_CH2 0x20140520 87 88 enum ceva_soc { 89 CEVA_1V84, 90 CEVA_LS1012A, 91 }; 92 93 struct ceva_sata_priv { 94 ulong base; 95 enum ceva_soc soc; 96 ulong flag; 97 }; 98 99 static int ceva_init_sata(struct ceva_sata_priv *priv) 100 { 101 ulong base = priv->base; 102 ulong tmp; 103 104 switch (priv->soc) { 105 case CEVA_1V84: 106 tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD | PAXIC_MARIDD | PAXIC_OTL; 107 writel(tmp, base + AHCI_VEND_PAXIC); 108 tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | PCFG_PAD_VAL; 109 writel(tmp, base + AHCI_VEND_PCFG); 110 tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN; 111 writel(tmp, base + AHCI_VEND_PPCFG); 112 tmp = PTC_RX_WM_VAL | PTC_RSVD; 113 writel(tmp, base + AHCI_VEND_PTC); 114 break; 115 116 case CEVA_LS1012A: 117 writel(ECC_DIS_ADDR_CH2, ECC_DIS_VAL_CH2); 118 writel(CEVA_PHY1_CFG, base + AHCI_VEND_PPCFG); 119 writel(CEVA_TRANS_CFG, base + AHCI_VEND_PTC); 120 if (priv->flag & FLAG_COHERENT) 121 writel(CEVA_AXICC_CFG, base + AHCI_VEND_AXICC); 122 break; 123 } 124 125 return 0; 126 } 127 128 static int sata_ceva_bind(struct udevice *dev) 129 { 130 struct udevice *scsi_dev; 131 132 return ahci_bind_scsi(dev, &scsi_dev); 133 } 134 135 static int sata_ceva_probe(struct udevice *dev) 136 { 137 struct ceva_sata_priv *priv = dev_get_priv(dev); 138 139 ceva_init_sata(priv); 140 141 return ahci_probe_scsi(dev, priv->base); 142 } 143 144 static const struct udevice_id sata_ceva_ids[] = { 145 { .compatible = "ceva,ahci-1v84", .data = CEVA_1V84 }, 146 { .compatible = "fsl,ls1012a-ahci", .data = CEVA_LS1012A }, 147 { } 148 }; 149 150 static int sata_ceva_ofdata_to_platdata(struct udevice *dev) 151 { 152 struct ceva_sata_priv *priv = dev_get_priv(dev); 153 154 if (dev_read_bool(dev, "dma-coherent")) 155 priv->flag |= FLAG_COHERENT; 156 157 priv->base = dev_read_addr(dev); 158 if (priv->base == FDT_ADDR_T_NONE) 159 return -EINVAL; 160 161 priv->soc = dev_get_driver_data(dev); 162 163 return 0; 164 } 165 166 U_BOOT_DRIVER(ceva_host_blk) = { 167 .name = "ceva_sata", 168 .id = UCLASS_AHCI, 169 .of_match = sata_ceva_ids, 170 .bind = sata_ceva_bind, 171 .ops = &scsi_ops, 172 .priv_auto_alloc_size = sizeof(struct ceva_sata_priv), 173 .probe = sata_ceva_probe, 174 .ofdata_to_platdata = sata_ceva_ofdata_to_platdata, 175 }; 176