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 /* for ls1021a */ 85 #define LS1021_AHCI_VEND_AXICC 0xC0 86 #define LS1021_CEVA_PHY2_CFG 0x28183414 87 #define LS1021_CEVA_PHY3_CFG 0x0e080e06 88 #define LS1021_CEVA_PHY4_CFG 0x064a080b 89 #define LS1021_CEVA_PHY5_CFG 0x2aa86470 90 91 /* for ls1088a */ 92 #define LS1088_ECC_DIS_ADDR_CH2 0x100520 93 #define LS1088_ECC_DIS_VAL_CH2 0x40000000 94 95 /* ecc addr-val pair */ 96 #define ECC_DIS_ADDR_CH2 0x20140520 97 #define ECC_DIS_VAL_CH2 0x80000000 98 #define SATA_ECC_REG_ADDR 0x20220520 99 #define SATA_ECC_DISABLE 0x00020000 100 101 enum ceva_soc { 102 CEVA_1V84, 103 CEVA_LS1012A, 104 CEVA_LS1021A, 105 CEVA_LS1043A, 106 CEVA_LS1046A, 107 CEVA_LS1088A, 108 CEVA_LS2080A, 109 }; 110 111 struct ceva_sata_priv { 112 ulong base; 113 enum ceva_soc soc; 114 ulong flag; 115 }; 116 117 static int ceva_init_sata(struct ceva_sata_priv *priv) 118 { 119 ulong base = priv->base; 120 ulong tmp; 121 122 switch (priv->soc) { 123 case CEVA_1V84: 124 tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD | PAXIC_MARIDD | PAXIC_OTL; 125 writel(tmp, base + AHCI_VEND_PAXIC); 126 tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | PCFG_PAD_VAL; 127 writel(tmp, base + AHCI_VEND_PCFG); 128 tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN; 129 writel(tmp, base + AHCI_VEND_PPCFG); 130 tmp = PTC_RX_WM_VAL | PTC_RSVD; 131 writel(tmp, base + AHCI_VEND_PTC); 132 break; 133 134 case CEVA_LS1021A: 135 writel(SATA_ECC_DISABLE, SATA_ECC_REG_ADDR); 136 writel(CEVA_PHY1_CFG, base + AHCI_VEND_PPCFG); 137 writel(LS1021_CEVA_PHY2_CFG, base + AHCI_VEND_PP2C); 138 writel(LS1021_CEVA_PHY3_CFG, base + AHCI_VEND_PP3C); 139 writel(LS1021_CEVA_PHY4_CFG, base + AHCI_VEND_PP4C); 140 writel(LS1021_CEVA_PHY5_CFG, base + AHCI_VEND_PP5C); 141 writel(CEVA_TRANS_CFG, base + AHCI_VEND_PTC); 142 if (priv->flag & FLAG_COHERENT) 143 writel(CEVA_AXICC_CFG, base + LS1021_AHCI_VEND_AXICC); 144 break; 145 146 case CEVA_LS1012A: 147 case CEVA_LS1043A: 148 case CEVA_LS1046A: 149 writel(ECC_DIS_VAL_CH2, ECC_DIS_ADDR_CH2); 150 /* fallthrough */ 151 case CEVA_LS2080A: 152 writel(CEVA_PHY1_CFG, base + AHCI_VEND_PPCFG); 153 writel(CEVA_TRANS_CFG, base + AHCI_VEND_PTC); 154 if (priv->flag & FLAG_COHERENT) 155 writel(CEVA_AXICC_CFG, base + AHCI_VEND_AXICC); 156 break; 157 158 case CEVA_LS1088A: 159 writel(LS1088_ECC_DIS_VAL_CH2, LS1088_ECC_DIS_ADDR_CH2); 160 writel(CEVA_PHY1_CFG, base + AHCI_VEND_PPCFG); 161 writel(CEVA_TRANS_CFG, base + AHCI_VEND_PTC); 162 if (priv->flag & FLAG_COHERENT) 163 writel(CEVA_AXICC_CFG, base + AHCI_VEND_AXICC); 164 break; 165 } 166 167 return 0; 168 } 169 170 static int sata_ceva_bind(struct udevice *dev) 171 { 172 struct udevice *scsi_dev; 173 174 return ahci_bind_scsi(dev, &scsi_dev); 175 } 176 177 static int sata_ceva_probe(struct udevice *dev) 178 { 179 struct ceva_sata_priv *priv = dev_get_priv(dev); 180 181 ceva_init_sata(priv); 182 183 return ahci_probe_scsi(dev, priv->base); 184 } 185 186 static const struct udevice_id sata_ceva_ids[] = { 187 { .compatible = "ceva,ahci-1v84", .data = CEVA_1V84 }, 188 { .compatible = "fsl,ls1012a-ahci", .data = CEVA_LS1012A }, 189 { .compatible = "fsl,ls1021a-ahci", .data = CEVA_LS1021A }, 190 { .compatible = "fsl,ls1043a-ahci", .data = CEVA_LS1043A }, 191 { .compatible = "fsl,ls1046a-ahci", .data = CEVA_LS1046A }, 192 { .compatible = "fsl,ls1088a-ahci", .data = CEVA_LS1088A }, 193 { .compatible = "fsl,ls2080a-ahci", .data = CEVA_LS2080A }, 194 { } 195 }; 196 197 static int sata_ceva_ofdata_to_platdata(struct udevice *dev) 198 { 199 struct ceva_sata_priv *priv = dev_get_priv(dev); 200 201 if (dev_read_bool(dev, "dma-coherent")) 202 priv->flag |= FLAG_COHERENT; 203 204 priv->base = dev_read_addr(dev); 205 if (priv->base == FDT_ADDR_T_NONE) 206 return -EINVAL; 207 208 priv->soc = dev_get_driver_data(dev); 209 210 return 0; 211 } 212 213 U_BOOT_DRIVER(ceva_host_blk) = { 214 .name = "ceva_sata", 215 .id = UCLASS_AHCI, 216 .of_match = sata_ceva_ids, 217 .bind = sata_ceva_bind, 218 .ops = &scsi_ops, 219 .priv_auto_alloc_size = sizeof(struct ceva_sata_priv), 220 .probe = sata_ceva_probe, 221 .ofdata_to_platdata = sata_ceva_ofdata_to_platdata, 222 }; 223