18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * AHCI SATA platform driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2004-2005 Red Hat, Inc. 68c2ecf20Sopenharmony_ci * Jeff Garzik <jgarzik@pobox.com> 78c2ecf20Sopenharmony_ci * Copyright 2010 MontaVista Software, LLC. 88c2ecf20Sopenharmony_ci * Anton Vorontsov <avorontsov@ru.mvista.com> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/pm.h> 148c2ecf20Sopenharmony_ci#include <linux/device.h> 158c2ecf20Sopenharmony_ci#include <linux/of_device.h> 168c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 178c2ecf20Sopenharmony_ci#include <linux/libata.h> 188c2ecf20Sopenharmony_ci#include <linux/ahci_platform.h> 198c2ecf20Sopenharmony_ci#include <linux/acpi.h> 208c2ecf20Sopenharmony_ci#include <linux/pci_ids.h> 218c2ecf20Sopenharmony_ci#include "ahci.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define DRV_NAME "ahci" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic const struct ata_port_info ahci_port_info = { 268c2ecf20Sopenharmony_ci .flags = AHCI_FLAG_COMMON, 278c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 288c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA6, 298c2ecf20Sopenharmony_ci .port_ops = &ahci_platform_ops, 308c2ecf20Sopenharmony_ci}; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic const struct ata_port_info ahci_port_info_nolpm = { 338c2ecf20Sopenharmony_ci .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_LPM, 348c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 358c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA6, 368c2ecf20Sopenharmony_ci .port_ops = &ahci_platform_ops, 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic struct scsi_host_template ahci_platform_sht = { 408c2ecf20Sopenharmony_ci AHCI_SHT(DRV_NAME), 418c2ecf20Sopenharmony_ci}; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic int ahci_probe(struct platform_device *pdev) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 468c2ecf20Sopenharmony_ci struct ahci_host_priv *hpriv; 478c2ecf20Sopenharmony_ci const struct ata_port_info *port; 488c2ecf20Sopenharmony_ci int rc; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci hpriv = ahci_platform_get_resources(pdev, 518c2ecf20Sopenharmony_ci AHCI_PLATFORM_GET_RESETS); 528c2ecf20Sopenharmony_ci if (IS_ERR(hpriv)) 538c2ecf20Sopenharmony_ci return PTR_ERR(hpriv); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci rc = ahci_platform_enable_resources(hpriv); 568c2ecf20Sopenharmony_ci if (rc) 578c2ecf20Sopenharmony_ci return rc; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci of_property_read_u32(dev->of_node, 608c2ecf20Sopenharmony_ci "ports-implemented", &hpriv->force_port_map); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci")) 638c2ecf20Sopenharmony_ci hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci port = acpi_device_get_match_data(dev); 668c2ecf20Sopenharmony_ci if (!port) 678c2ecf20Sopenharmony_ci port = &ahci_port_info; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci rc = ahci_platform_init_host(pdev, hpriv, port, 708c2ecf20Sopenharmony_ci &ahci_platform_sht); 718c2ecf20Sopenharmony_ci if (rc) 728c2ecf20Sopenharmony_ci goto disable_resources; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci return 0; 758c2ecf20Sopenharmony_cidisable_resources: 768c2ecf20Sopenharmony_ci ahci_platform_disable_resources(hpriv); 778c2ecf20Sopenharmony_ci return rc; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, 818c2ecf20Sopenharmony_ci ahci_platform_resume); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic const struct of_device_id ahci_of_match[] = { 848c2ecf20Sopenharmony_ci { .compatible = "generic-ahci", }, 858c2ecf20Sopenharmony_ci /* Keep the following compatibles for device tree compatibility */ 868c2ecf20Sopenharmony_ci { .compatible = "snps,spear-ahci", }, 878c2ecf20Sopenharmony_ci { .compatible = "ibm,476gtr-ahci", }, 888c2ecf20Sopenharmony_ci { .compatible = "snps,dwc-ahci", }, 898c2ecf20Sopenharmony_ci { .compatible = "hisilicon,hisi-ahci", }, 908c2ecf20Sopenharmony_ci { .compatible = "cavium,octeon-7130-ahci", }, 918c2ecf20Sopenharmony_ci {}, 928c2ecf20Sopenharmony_ci}; 938c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, ahci_of_match); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic const struct acpi_device_id ahci_acpi_match[] = { 968c2ecf20Sopenharmony_ci { "APMC0D33", (unsigned long)&ahci_port_info_nolpm }, 978c2ecf20Sopenharmony_ci { ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) }, 988c2ecf20Sopenharmony_ci {}, 998c2ecf20Sopenharmony_ci}; 1008c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, ahci_acpi_match); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic struct platform_driver ahci_driver = { 1038c2ecf20Sopenharmony_ci .probe = ahci_probe, 1048c2ecf20Sopenharmony_ci .remove = ata_platform_remove_one, 1058c2ecf20Sopenharmony_ci .shutdown = ahci_platform_shutdown, 1068c2ecf20Sopenharmony_ci .driver = { 1078c2ecf20Sopenharmony_ci .name = DRV_NAME, 1088c2ecf20Sopenharmony_ci .of_match_table = ahci_of_match, 1098c2ecf20Sopenharmony_ci .acpi_match_table = ahci_acpi_match, 1108c2ecf20Sopenharmony_ci .pm = &ahci_pm_ops, 1118c2ecf20Sopenharmony_ci }, 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_cimodule_platform_driver(ahci_driver); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("AHCI SATA platform driver"); 1168c2ecf20Sopenharmony_ciMODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); 1178c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1188c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:ahci"); 119