162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * AHCI SATA platform driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2004-2005 Red Hat, Inc. 662306a36Sopenharmony_ci * Jeff Garzik <jgarzik@pobox.com> 762306a36Sopenharmony_ci * Copyright 2010 MontaVista Software, LLC. 862306a36Sopenharmony_ci * Anton Vorontsov <avorontsov@ru.mvista.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/pm.h> 1562306a36Sopenharmony_ci#include <linux/device.h> 1662306a36Sopenharmony_ci#include <linux/platform_device.h> 1762306a36Sopenharmony_ci#include <linux/property.h> 1862306a36Sopenharmony_ci#include <linux/libata.h> 1962306a36Sopenharmony_ci#include <linux/ahci_platform.h> 2062306a36Sopenharmony_ci#include <linux/pci_ids.h> 2162306a36Sopenharmony_ci#include "ahci.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define DRV_NAME "ahci" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic const struct ata_port_info ahci_port_info = { 2662306a36Sopenharmony_ci .flags = AHCI_FLAG_COMMON, 2762306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 2862306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 2962306a36Sopenharmony_ci .port_ops = &ahci_platform_ops, 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic const struct ata_port_info ahci_port_info_nolpm = { 3362306a36Sopenharmony_ci .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_LPM, 3462306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 3562306a36Sopenharmony_ci .udma_mask = ATA_UDMA6, 3662306a36Sopenharmony_ci .port_ops = &ahci_platform_ops, 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic const struct scsi_host_template ahci_platform_sht = { 4062306a36Sopenharmony_ci AHCI_SHT(DRV_NAME), 4162306a36Sopenharmony_ci}; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic int ahci_probe(struct platform_device *pdev) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci struct device *dev = &pdev->dev; 4662306a36Sopenharmony_ci struct ahci_host_priv *hpriv; 4762306a36Sopenharmony_ci const struct ata_port_info *port; 4862306a36Sopenharmony_ci int rc; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci hpriv = ahci_platform_get_resources(pdev, 5162306a36Sopenharmony_ci AHCI_PLATFORM_GET_RESETS); 5262306a36Sopenharmony_ci if (IS_ERR(hpriv)) 5362306a36Sopenharmony_ci return PTR_ERR(hpriv); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci rc = ahci_platform_enable_resources(hpriv); 5662306a36Sopenharmony_ci if (rc) 5762306a36Sopenharmony_ci return rc; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci if (device_is_compatible(dev, "hisilicon,hisi-ahci")) 6062306a36Sopenharmony_ci hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci port = device_get_match_data(dev); 6362306a36Sopenharmony_ci if (!port) 6462306a36Sopenharmony_ci port = &ahci_port_info; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci rc = ahci_platform_init_host(pdev, hpriv, port, 6762306a36Sopenharmony_ci &ahci_platform_sht); 6862306a36Sopenharmony_ci if (rc) 6962306a36Sopenharmony_ci goto disable_resources; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci return 0; 7262306a36Sopenharmony_cidisable_resources: 7362306a36Sopenharmony_ci ahci_platform_disable_resources(hpriv); 7462306a36Sopenharmony_ci return rc; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend, 7862306a36Sopenharmony_ci ahci_platform_resume); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic const struct of_device_id ahci_of_match[] = { 8162306a36Sopenharmony_ci { .compatible = "generic-ahci", }, 8262306a36Sopenharmony_ci /* Keep the following compatibles for device tree compatibility */ 8362306a36Sopenharmony_ci { .compatible = "ibm,476gtr-ahci", }, 8462306a36Sopenharmony_ci { .compatible = "hisilicon,hisi-ahci", }, 8562306a36Sopenharmony_ci { .compatible = "cavium,octeon-7130-ahci", }, 8662306a36Sopenharmony_ci { /* sentinel */ } 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ahci_of_match); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic const struct acpi_device_id ahci_acpi_match[] = { 9162306a36Sopenharmony_ci { "APMC0D33", (unsigned long)&ahci_port_info_nolpm }, 9262306a36Sopenharmony_ci { ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) }, 9362306a36Sopenharmony_ci {}, 9462306a36Sopenharmony_ci}; 9562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, ahci_acpi_match); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic struct platform_driver ahci_driver = { 9862306a36Sopenharmony_ci .probe = ahci_probe, 9962306a36Sopenharmony_ci .remove_new = ata_platform_remove_one, 10062306a36Sopenharmony_ci .shutdown = ahci_platform_shutdown, 10162306a36Sopenharmony_ci .driver = { 10262306a36Sopenharmony_ci .name = DRV_NAME, 10362306a36Sopenharmony_ci .of_match_table = ahci_of_match, 10462306a36Sopenharmony_ci .acpi_match_table = ahci_acpi_match, 10562306a36Sopenharmony_ci .pm = &ahci_pm_ops, 10662306a36Sopenharmony_ci }, 10762306a36Sopenharmony_ci}; 10862306a36Sopenharmony_cimodule_platform_driver(ahci_driver); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ciMODULE_DESCRIPTION("AHCI SATA platform driver"); 11162306a36Sopenharmony_ciMODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); 11262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 11362306a36Sopenharmony_ciMODULE_ALIAS("platform:ahci"); 114