1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Freescale QorIQ AHCI SATA platform driver 4 * 5 * Copyright 2015 Freescale, Inc. 6 * Tang Yuantian <Yuantian.Tang@freescale.com> 7 */ 8 9 #include <linux/acpi.h> 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 #include <linux/pm.h> 13 #include <linux/ahci_platform.h> 14 #include <linux/device.h> 15 #include <linux/of.h> 16 #include <linux/platform_device.h> 17 #include <linux/libata.h> 18 #include "ahci.h" 19 20 #define DRV_NAME "ahci-qoriq" 21 22 /* port register definition */ 23 #define PORT_PHY1 0xA8 24 #define PORT_PHY2 0xAC 25 #define PORT_PHY3 0xB0 26 #define PORT_PHY4 0xB4 27 #define PORT_PHY5 0xB8 28 #define PORT_AXICC 0xBC 29 #define PORT_TRANS 0xC8 30 31 /* port register default value */ 32 #define AHCI_PORT_PHY_1_CFG 0xa003fffe 33 #define AHCI_PORT_PHY2_CFG 0x28184d1f 34 #define AHCI_PORT_PHY3_CFG 0x0e081509 35 #define AHCI_PORT_TRANS_CFG 0x08000029 36 #define AHCI_PORT_AXICC_CFG 0x3fffffff 37 38 /* for ls1021a */ 39 #define LS1021A_PORT_PHY2 0x28183414 40 #define LS1021A_PORT_PHY3 0x0e080e06 41 #define LS1021A_PORT_PHY4 0x064a080b 42 #define LS1021A_PORT_PHY5 0x2aa86470 43 #define LS1021A_AXICC_ADDR 0xC0 44 45 #define SATA_ECC_DISABLE 0x00020000 46 #define ECC_DIS_ARMV8_CH2 0x80000000 47 #define ECC_DIS_LS1088A 0x40000000 48 49 enum ahci_qoriq_type { 50 AHCI_LS1021A, 51 AHCI_LS1028A, 52 AHCI_LS1043A, 53 AHCI_LS2080A, 54 AHCI_LS1046A, 55 AHCI_LS1088A, 56 AHCI_LS2088A, 57 AHCI_LX2160A, 58 }; 59 60 struct ahci_qoriq_priv { 61 struct ccsr_ahci *reg_base; 62 enum ahci_qoriq_type type; 63 void __iomem *ecc_addr; 64 bool is_dmacoherent; 65 }; 66 67 static bool ecc_initialized; 68 69 static const struct of_device_id ahci_qoriq_of_match[] = { 70 { .compatible = "fsl,ls1021a-ahci", .data = (void *)AHCI_LS1021A}, 71 { .compatible = "fsl,ls1028a-ahci", .data = (void *)AHCI_LS1028A}, 72 { .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A}, 73 { .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A}, 74 { .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A}, 75 { .compatible = "fsl,ls1088a-ahci", .data = (void *)AHCI_LS1088A}, 76 { .compatible = "fsl,ls2088a-ahci", .data = (void *)AHCI_LS2088A}, 77 { .compatible = "fsl,lx2160a-ahci", .data = (void *)AHCI_LX2160A}, 78 { /* sentinel */ } 79 }; 80 MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match); 81 82 static const struct acpi_device_id ahci_qoriq_acpi_match[] = { 83 {"NXP0004", .driver_data = (kernel_ulong_t)AHCI_LX2160A}, 84 { } 85 }; 86 MODULE_DEVICE_TABLE(acpi, ahci_qoriq_acpi_match); 87 88 static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class, 89 unsigned long deadline) 90 { 91 const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context); 92 void __iomem *port_mmio = ahci_port_base(link->ap); 93 u32 px_cmd, px_is, px_val; 94 struct ata_port *ap = link->ap; 95 struct ahci_port_priv *pp = ap->private_data; 96 struct ahci_host_priv *hpriv = ap->host->private_data; 97 struct ahci_qoriq_priv *qoriq_priv = hpriv->plat_data; 98 u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; 99 struct ata_taskfile tf; 100 bool online; 101 int rc; 102 bool ls1021a_workaround = (qoriq_priv->type == AHCI_LS1021A); 103 104 hpriv->stop_engine(ap); 105 106 /* 107 * There is a errata on ls1021a Rev1.0 and Rev2.0 which is: 108 * A-009042: The device detection initialization sequence 109 * mistakenly resets some registers. 110 * 111 * Workaround for this is: 112 * The software should read and store PxCMD and PxIS values 113 * before issuing the device detection initialization sequence. 114 * After the sequence is complete, software should restore the 115 * PxCMD and PxIS with the stored values. 116 */ 117 if (ls1021a_workaround) { 118 px_cmd = readl(port_mmio + PORT_CMD); 119 px_is = readl(port_mmio + PORT_IRQ_STAT); 120 } 121 122 /* clear D2H reception area to properly wait for D2H FIS */ 123 ata_tf_init(link->device, &tf); 124 tf.status = ATA_BUSY; 125 ata_tf_to_fis(&tf, 0, 0, d2h_fis); 126 127 rc = sata_link_hardreset(link, timing, deadline, &online, 128 ahci_check_ready); 129 130 /* restore the PxCMD and PxIS on ls1021 */ 131 if (ls1021a_workaround) { 132 px_val = readl(port_mmio + PORT_CMD); 133 if (px_val != px_cmd) 134 writel(px_cmd, port_mmio + PORT_CMD); 135 136 px_val = readl(port_mmio + PORT_IRQ_STAT); 137 if (px_val != px_is) 138 writel(px_is, port_mmio + PORT_IRQ_STAT); 139 } 140 141 hpriv->start_engine(ap); 142 143 if (online) 144 *class = ahci_dev_classify(ap); 145 return rc; 146 } 147 148 static struct ata_port_operations ahci_qoriq_ops = { 149 .inherits = &ahci_ops, 150 .hardreset = ahci_qoriq_hardreset, 151 }; 152 153 static const struct ata_port_info ahci_qoriq_port_info = { 154 .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ, 155 .pio_mask = ATA_PIO4, 156 .udma_mask = ATA_UDMA6, 157 .port_ops = &ahci_qoriq_ops, 158 }; 159 160 static const struct scsi_host_template ahci_qoriq_sht = { 161 AHCI_SHT(DRV_NAME), 162 }; 163 164 static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv) 165 { 166 struct ahci_qoriq_priv *qpriv = hpriv->plat_data; 167 void __iomem *reg_base = hpriv->mmio; 168 169 switch (qpriv->type) { 170 case AHCI_LS1021A: 171 if (!(qpriv->ecc_addr || ecc_initialized)) 172 return -EINVAL; 173 else if (qpriv->ecc_addr && !ecc_initialized) 174 writel(SATA_ECC_DISABLE, qpriv->ecc_addr); 175 writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); 176 writel(LS1021A_PORT_PHY2, reg_base + PORT_PHY2); 177 writel(LS1021A_PORT_PHY3, reg_base + PORT_PHY3); 178 writel(LS1021A_PORT_PHY4, reg_base + PORT_PHY4); 179 writel(LS1021A_PORT_PHY5, reg_base + PORT_PHY5); 180 writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); 181 if (qpriv->is_dmacoherent) 182 writel(AHCI_PORT_AXICC_CFG, 183 reg_base + LS1021A_AXICC_ADDR); 184 break; 185 186 case AHCI_LS1043A: 187 if (!(qpriv->ecc_addr || ecc_initialized)) 188 return -EINVAL; 189 else if (qpriv->ecc_addr && !ecc_initialized) 190 writel(readl(qpriv->ecc_addr) | 191 ECC_DIS_ARMV8_CH2, 192 qpriv->ecc_addr); 193 writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); 194 writel(AHCI_PORT_PHY2_CFG, reg_base + PORT_PHY2); 195 writel(AHCI_PORT_PHY3_CFG, reg_base + PORT_PHY3); 196 writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); 197 if (qpriv->is_dmacoherent) 198 writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); 199 break; 200 201 case AHCI_LS2080A: 202 writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); 203 writel(AHCI_PORT_PHY2_CFG, reg_base + PORT_PHY2); 204 writel(AHCI_PORT_PHY3_CFG, reg_base + PORT_PHY3); 205 writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); 206 if (qpriv->is_dmacoherent) 207 writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); 208 break; 209 210 case AHCI_LS1046A: 211 if (!(qpriv->ecc_addr || ecc_initialized)) 212 return -EINVAL; 213 else if (qpriv->ecc_addr && !ecc_initialized) 214 writel(readl(qpriv->ecc_addr) | 215 ECC_DIS_ARMV8_CH2, 216 qpriv->ecc_addr); 217 writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); 218 writel(AHCI_PORT_PHY2_CFG, reg_base + PORT_PHY2); 219 writel(AHCI_PORT_PHY3_CFG, reg_base + PORT_PHY3); 220 writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); 221 if (qpriv->is_dmacoherent) 222 writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); 223 break; 224 225 case AHCI_LS1028A: 226 case AHCI_LS1088A: 227 case AHCI_LX2160A: 228 if (!(qpriv->ecc_addr || ecc_initialized)) 229 return -EINVAL; 230 else if (qpriv->ecc_addr && !ecc_initialized) 231 writel(readl(qpriv->ecc_addr) | 232 ECC_DIS_LS1088A, 233 qpriv->ecc_addr); 234 writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); 235 writel(AHCI_PORT_PHY2_CFG, reg_base + PORT_PHY2); 236 writel(AHCI_PORT_PHY3_CFG, reg_base + PORT_PHY3); 237 writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); 238 if (qpriv->is_dmacoherent) 239 writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); 240 break; 241 242 case AHCI_LS2088A: 243 writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1); 244 writel(AHCI_PORT_PHY2_CFG, reg_base + PORT_PHY2); 245 writel(AHCI_PORT_PHY3_CFG, reg_base + PORT_PHY3); 246 writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS); 247 if (qpriv->is_dmacoherent) 248 writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC); 249 break; 250 } 251 252 ecc_initialized = true; 253 return 0; 254 } 255 256 static int ahci_qoriq_probe(struct platform_device *pdev) 257 { 258 struct device_node *np = pdev->dev.of_node; 259 const struct acpi_device_id *acpi_id; 260 struct device *dev = &pdev->dev; 261 struct ahci_host_priv *hpriv; 262 struct ahci_qoriq_priv *qoriq_priv; 263 const struct of_device_id *of_id; 264 struct resource *res; 265 int rc; 266 267 hpriv = ahci_platform_get_resources(pdev, 0); 268 if (IS_ERR(hpriv)) 269 return PTR_ERR(hpriv); 270 271 of_id = of_match_node(ahci_qoriq_of_match, np); 272 acpi_id = acpi_match_device(ahci_qoriq_acpi_match, &pdev->dev); 273 if (!(of_id || acpi_id)) 274 return -ENODEV; 275 276 qoriq_priv = devm_kzalloc(dev, sizeof(*qoriq_priv), GFP_KERNEL); 277 if (!qoriq_priv) 278 return -ENOMEM; 279 280 if (of_id) 281 qoriq_priv->type = (unsigned long)of_id->data; 282 else 283 qoriq_priv->type = (enum ahci_qoriq_type)acpi_id->driver_data; 284 285 if (unlikely(!ecc_initialized)) { 286 res = platform_get_resource_byname(pdev, 287 IORESOURCE_MEM, 288 "sata-ecc"); 289 if (res) { 290 qoriq_priv->ecc_addr = 291 devm_ioremap_resource(dev, res); 292 if (IS_ERR(qoriq_priv->ecc_addr)) 293 return PTR_ERR(qoriq_priv->ecc_addr); 294 } 295 } 296 297 if (device_get_dma_attr(&pdev->dev) == DEV_DMA_COHERENT) 298 qoriq_priv->is_dmacoherent = true; 299 300 rc = ahci_platform_enable_resources(hpriv); 301 if (rc) 302 return rc; 303 304 hpriv->plat_data = qoriq_priv; 305 rc = ahci_qoriq_phy_init(hpriv); 306 if (rc) 307 goto disable_resources; 308 309 rc = ahci_platform_init_host(pdev, hpriv, &ahci_qoriq_port_info, 310 &ahci_qoriq_sht); 311 if (rc) 312 goto disable_resources; 313 314 return 0; 315 316 disable_resources: 317 ahci_platform_disable_resources(hpriv); 318 319 return rc; 320 } 321 322 #ifdef CONFIG_PM_SLEEP 323 static int ahci_qoriq_resume(struct device *dev) 324 { 325 struct ata_host *host = dev_get_drvdata(dev); 326 struct ahci_host_priv *hpriv = host->private_data; 327 int rc; 328 329 rc = ahci_platform_enable_resources(hpriv); 330 if (rc) 331 return rc; 332 333 rc = ahci_qoriq_phy_init(hpriv); 334 if (rc) 335 goto disable_resources; 336 337 rc = ahci_platform_resume_host(dev); 338 if (rc) 339 goto disable_resources; 340 341 /* We resumed so update PM runtime state */ 342 pm_runtime_disable(dev); 343 pm_runtime_set_active(dev); 344 pm_runtime_enable(dev); 345 346 return 0; 347 348 disable_resources: 349 ahci_platform_disable_resources(hpriv); 350 351 return rc; 352 } 353 #endif 354 355 static SIMPLE_DEV_PM_OPS(ahci_qoriq_pm_ops, ahci_platform_suspend, 356 ahci_qoriq_resume); 357 358 static struct platform_driver ahci_qoriq_driver = { 359 .probe = ahci_qoriq_probe, 360 .remove_new = ata_platform_remove_one, 361 .driver = { 362 .name = DRV_NAME, 363 .of_match_table = ahci_qoriq_of_match, 364 .acpi_match_table = ahci_qoriq_acpi_match, 365 .pm = &ahci_qoriq_pm_ops, 366 }, 367 }; 368 module_platform_driver(ahci_qoriq_driver); 369 370 MODULE_DESCRIPTION("Freescale QorIQ AHCI SATA platform driver"); 371 MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>"); 372 MODULE_LICENSE("GPL"); 373