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