1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2015 Xilinx, Inc. 4 * CEVA AHCI SATA platform driver 5 * 6 * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov 7 */ 8 9 #include <linux/ahci_platform.h> 10 #include <linux/kernel.h> 11 #include <linux/libata.h> 12 #include <linux/module.h> 13 #include <linux/of_device.h> 14 #include <linux/platform_device.h> 15 #include "ahci.h" 16 17 /* Vendor Specific Register Offsets */ 18 #define AHCI_VEND_PCFG 0xA4 19 #define AHCI_VEND_PPCFG 0xA8 20 #define AHCI_VEND_PP2C 0xAC 21 #define AHCI_VEND_PP3C 0xB0 22 #define AHCI_VEND_PP4C 0xB4 23 #define AHCI_VEND_PP5C 0xB8 24 #define AHCI_VEND_AXICC 0xBC 25 #define AHCI_VEND_PAXIC 0xC0 26 #define AHCI_VEND_PTC 0xC8 27 28 /* Vendor Specific Register bit definitions */ 29 #define PAXIC_ADBW_BW64 0x1 30 #define PAXIC_MAWID(i) (((i) * 2) << 4) 31 #define PAXIC_MARID(i) (((i) * 2) << 12) 32 #define PAXIC_MARIDD(i) ((((i) * 2) + 1) << 16) 33 #define PAXIC_MAWIDD(i) ((((i) * 2) + 1) << 8) 34 #define PAXIC_OTL (0x4 << 20) 35 36 /* Register bit definitions for cache control */ 37 #define AXICC_ARCA_VAL (0xF << 0) 38 #define AXICC_ARCF_VAL (0xF << 4) 39 #define AXICC_ARCH_VAL (0xF << 8) 40 #define AXICC_ARCP_VAL (0xF << 12) 41 #define AXICC_AWCFD_VAL (0xF << 16) 42 #define AXICC_AWCD_VAL (0xF << 20) 43 #define AXICC_AWCF_VAL (0xF << 24) 44 45 #define PCFG_TPSS_VAL (0x32 << 16) 46 #define PCFG_TPRS_VAL (0x2 << 12) 47 #define PCFG_PAD_VAL 0x2 48 49 #define PPCFG_TTA 0x1FFFE 50 #define PPCFG_PSSO_EN (1 << 28) 51 #define PPCFG_PSS_EN (1 << 29) 52 #define PPCFG_ESDF_EN (1 << 31) 53 54 #define PP5C_RIT 0x60216 55 #define PP5C_RCT (0x7f0 << 20) 56 57 #define PTC_RX_WM_VAL 0x40 58 #define PTC_RSVD (1 << 27) 59 60 #define PORT0_BASE 0x100 61 #define PORT1_BASE 0x180 62 63 /* Port Control Register Bit Definitions */ 64 #define PORT_SCTL_SPD_GEN3 (0x3 << 4) 65 #define PORT_SCTL_SPD_GEN2 (0x2 << 4) 66 #define PORT_SCTL_SPD_GEN1 (0x1 << 4) 67 #define PORT_SCTL_IPM (0x3 << 8) 68 69 #define PORT_BASE 0x100 70 #define PORT_OFFSET 0x80 71 #define NR_PORTS 2 72 #define DRV_NAME "ahci-ceva" 73 #define CEVA_FLAG_BROKEN_GEN2 1 74 75 static unsigned int rx_watermark = PTC_RX_WM_VAL; 76 module_param(rx_watermark, uint, 0644); 77 MODULE_PARM_DESC(rx_watermark, "RxWaterMark value (0 - 0x80)"); 78 79 struct ceva_ahci_priv { 80 struct platform_device *ahci_pdev; 81 /* Port Phy2Cfg Register */ 82 u32 pp2c[NR_PORTS]; 83 u32 pp3c[NR_PORTS]; 84 u32 pp4c[NR_PORTS]; 85 u32 pp5c[NR_PORTS]; 86 /* Axi Cache Control Register */ 87 u32 axicc; 88 bool is_cci_enabled; 89 int flags; 90 }; 91 92 static unsigned int ceva_ahci_read_id(struct ata_device *dev, 93 struct ata_taskfile *tf, u16 *id) 94 { 95 u32 err_mask; 96 97 err_mask = ata_do_dev_read_id(dev, tf, id); 98 if (err_mask) 99 return err_mask; 100 /* 101 * Since CEVA controller does not support device sleep feature, we 102 * need to clear DEVSLP (bit 8) in word78 of the IDENTIFY DEVICE data. 103 */ 104 id[ATA_ID_FEATURE_SUPP] &= cpu_to_le16(~(1 << 8)); 105 106 return 0; 107 } 108 109 static struct ata_port_operations ahci_ceva_ops = { 110 .inherits = &ahci_platform_ops, 111 .read_id = ceva_ahci_read_id, 112 }; 113 114 static const struct ata_port_info ahci_ceva_port_info = { 115 .flags = AHCI_FLAG_COMMON, 116 .pio_mask = ATA_PIO4, 117 .udma_mask = ATA_UDMA6, 118 .port_ops = &ahci_ceva_ops, 119 }; 120 121 static void ahci_ceva_setup(struct ahci_host_priv *hpriv) 122 { 123 void __iomem *mmio = hpriv->mmio; 124 struct ceva_ahci_priv *cevapriv = hpriv->plat_data; 125 u32 tmp; 126 int i; 127 128 /* Set AHCI Enable */ 129 tmp = readl(mmio + HOST_CTL); 130 tmp |= HOST_AHCI_EN; 131 writel(tmp, mmio + HOST_CTL); 132 133 for (i = 0; i < NR_PORTS; i++) { 134 /* TPSS TPRS scalars, CISE and Port Addr */ 135 tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | (PCFG_PAD_VAL + i); 136 writel(tmp, mmio + AHCI_VEND_PCFG); 137 138 /* 139 * AXI Data bus width to 64 140 * Set Mem Addr Read, Write ID for data transfers 141 * Set Mem Addr Read ID, Write ID for non-data transfers 142 * Transfer limit to 72 DWord 143 */ 144 tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD(i) | PAXIC_MARIDD(i) | 145 PAXIC_MAWID(i) | PAXIC_MARID(i) | PAXIC_OTL; 146 writel(tmp, mmio + AHCI_VEND_PAXIC); 147 148 /* Set AXI cache control register if CCi is enabled */ 149 if (cevapriv->is_cci_enabled) { 150 tmp = readl(mmio + AHCI_VEND_AXICC); 151 tmp |= AXICC_ARCA_VAL | AXICC_ARCF_VAL | 152 AXICC_ARCH_VAL | AXICC_ARCP_VAL | 153 AXICC_AWCFD_VAL | AXICC_AWCD_VAL | 154 AXICC_AWCF_VAL; 155 writel(tmp, mmio + AHCI_VEND_AXICC); 156 } 157 158 /* Port Phy Cfg register enables */ 159 tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN; 160 writel(tmp, mmio + AHCI_VEND_PPCFG); 161 162 /* Phy Control OOB timing parameters COMINIT */ 163 writel(cevapriv->pp2c[i], mmio + AHCI_VEND_PP2C); 164 165 /* Phy Control OOB timing parameters COMWAKE */ 166 writel(cevapriv->pp3c[i], mmio + AHCI_VEND_PP3C); 167 168 /* Phy Control Burst timing setting */ 169 writel(cevapriv->pp4c[i], mmio + AHCI_VEND_PP4C); 170 171 /* Rate Change Timer and Retry Interval Timer setting */ 172 writel(cevapriv->pp5c[i], mmio + AHCI_VEND_PP5C); 173 174 /* Rx Watermark setting */ 175 tmp = rx_watermark | PTC_RSVD; 176 writel(tmp, mmio + AHCI_VEND_PTC); 177 178 /* Default to Gen 3 Speed and Gen 1 if Gen2 is broken */ 179 tmp = PORT_SCTL_SPD_GEN3 | PORT_SCTL_IPM; 180 if (cevapriv->flags & CEVA_FLAG_BROKEN_GEN2) 181 tmp = PORT_SCTL_SPD_GEN1 | PORT_SCTL_IPM; 182 writel(tmp, mmio + PORT_SCR_CTL + PORT_BASE + PORT_OFFSET * i); 183 } 184 } 185 186 static struct scsi_host_template ahci_platform_sht = { 187 AHCI_SHT(DRV_NAME), 188 }; 189 190 static int ceva_ahci_probe(struct platform_device *pdev) 191 { 192 struct device_node *np = pdev->dev.of_node; 193 struct device *dev = &pdev->dev; 194 struct ahci_host_priv *hpriv; 195 struct ceva_ahci_priv *cevapriv; 196 enum dev_dma_attr attr; 197 int rc; 198 199 cevapriv = devm_kzalloc(dev, sizeof(*cevapriv), GFP_KERNEL); 200 if (!cevapriv) 201 return -ENOMEM; 202 203 cevapriv->ahci_pdev = pdev; 204 205 hpriv = ahci_platform_get_resources(pdev, 0); 206 if (IS_ERR(hpriv)) 207 return PTR_ERR(hpriv); 208 209 rc = ahci_platform_enable_resources(hpriv); 210 if (rc) 211 return rc; 212 213 if (of_property_read_bool(np, "ceva,broken-gen2")) 214 cevapriv->flags = CEVA_FLAG_BROKEN_GEN2; 215 216 /* Read OOB timing value for COMINIT from device-tree */ 217 if (of_property_read_u8_array(np, "ceva,p0-cominit-params", 218 (u8 *)&cevapriv->pp2c[0], 4) < 0) { 219 dev_warn(dev, "ceva,p0-cominit-params property not defined\n"); 220 return -EINVAL; 221 } 222 223 if (of_property_read_u8_array(np, "ceva,p1-cominit-params", 224 (u8 *)&cevapriv->pp2c[1], 4) < 0) { 225 dev_warn(dev, "ceva,p1-cominit-params property not defined\n"); 226 return -EINVAL; 227 } 228 229 /* Read OOB timing value for COMWAKE from device-tree*/ 230 if (of_property_read_u8_array(np, "ceva,p0-comwake-params", 231 (u8 *)&cevapriv->pp3c[0], 4) < 0) { 232 dev_warn(dev, "ceva,p0-comwake-params property not defined\n"); 233 return -EINVAL; 234 } 235 236 if (of_property_read_u8_array(np, "ceva,p1-comwake-params", 237 (u8 *)&cevapriv->pp3c[1], 4) < 0) { 238 dev_warn(dev, "ceva,p1-comwake-params property not defined\n"); 239 return -EINVAL; 240 } 241 242 /* Read phy BURST timing value from device-tree */ 243 if (of_property_read_u8_array(np, "ceva,p0-burst-params", 244 (u8 *)&cevapriv->pp4c[0], 4) < 0) { 245 dev_warn(dev, "ceva,p0-burst-params property not defined\n"); 246 return -EINVAL; 247 } 248 249 if (of_property_read_u8_array(np, "ceva,p1-burst-params", 250 (u8 *)&cevapriv->pp4c[1], 4) < 0) { 251 dev_warn(dev, "ceva,p1-burst-params property not defined\n"); 252 return -EINVAL; 253 } 254 255 /* Read phy RETRY interval timing value from device-tree */ 256 if (of_property_read_u16_array(np, "ceva,p0-retry-params", 257 (u16 *)&cevapriv->pp5c[0], 2) < 0) { 258 dev_warn(dev, "ceva,p0-retry-params property not defined\n"); 259 return -EINVAL; 260 } 261 262 if (of_property_read_u16_array(np, "ceva,p1-retry-params", 263 (u16 *)&cevapriv->pp5c[1], 2) < 0) { 264 dev_warn(dev, "ceva,p1-retry-params property not defined\n"); 265 return -EINVAL; 266 } 267 268 /* 269 * Check if CCI is enabled for SATA. The DEV_DMA_COHERENT is returned 270 * if CCI is enabled, so check for DEV_DMA_COHERENT. 271 */ 272 attr = device_get_dma_attr(dev); 273 cevapriv->is_cci_enabled = (attr == DEV_DMA_COHERENT); 274 275 hpriv->plat_data = cevapriv; 276 277 /* CEVA specific initialization */ 278 ahci_ceva_setup(hpriv); 279 280 rc = ahci_platform_init_host(pdev, hpriv, &ahci_ceva_port_info, 281 &ahci_platform_sht); 282 if (rc) 283 goto disable_resources; 284 285 return 0; 286 287 disable_resources: 288 ahci_platform_disable_resources(hpriv); 289 return rc; 290 } 291 292 static int __maybe_unused ceva_ahci_suspend(struct device *dev) 293 { 294 return ahci_platform_suspend(dev); 295 } 296 297 static int __maybe_unused ceva_ahci_resume(struct device *dev) 298 { 299 struct ata_host *host = dev_get_drvdata(dev); 300 struct ahci_host_priv *hpriv = host->private_data; 301 int rc; 302 303 rc = ahci_platform_enable_resources(hpriv); 304 if (rc) 305 return rc; 306 307 /* Configure CEVA specific config before resuming HBA */ 308 ahci_ceva_setup(hpriv); 309 310 rc = ahci_platform_resume_host(dev); 311 if (rc) 312 goto disable_resources; 313 314 /* We resumed so update PM runtime state */ 315 pm_runtime_disable(dev); 316 pm_runtime_set_active(dev); 317 pm_runtime_enable(dev); 318 319 return 0; 320 321 disable_resources: 322 ahci_platform_disable_resources(hpriv); 323 324 return rc; 325 } 326 327 static SIMPLE_DEV_PM_OPS(ahci_ceva_pm_ops, ceva_ahci_suspend, ceva_ahci_resume); 328 329 static const struct of_device_id ceva_ahci_of_match[] = { 330 { .compatible = "ceva,ahci-1v84" }, 331 {}, 332 }; 333 MODULE_DEVICE_TABLE(of, ceva_ahci_of_match); 334 335 static struct platform_driver ceva_ahci_driver = { 336 .probe = ceva_ahci_probe, 337 .remove = ata_platform_remove_one, 338 .driver = { 339 .name = DRV_NAME, 340 .of_match_table = ceva_ahci_of_match, 341 .pm = &ahci_ceva_pm_ops, 342 }, 343 }; 344 module_platform_driver(ceva_ahci_driver); 345 346 MODULE_DESCRIPTION("CEVA AHCI SATA platform driver"); 347 MODULE_AUTHOR("Xilinx Inc."); 348 MODULE_LICENSE("GPL v2"); 349