162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Synopsys DesignWare Multimedia Card PCI Interface driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2012 Vayavya Labs Pvt. Ltd. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/interrupt.h> 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/io.h> 1162306a36Sopenharmony_ci#include <linux/irq.h> 1262306a36Sopenharmony_ci#include <linux/pci.h> 1362306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include <linux/mmc/host.h> 1662306a36Sopenharmony_ci#include <linux/mmc/mmc.h> 1762306a36Sopenharmony_ci#include "dw_mmc.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define PCI_BAR_NO 2 2062306a36Sopenharmony_ci#define SYNOPSYS_DW_MCI_VENDOR_ID 0x700 2162306a36Sopenharmony_ci#define SYNOPSYS_DW_MCI_DEVICE_ID 0x1107 2262306a36Sopenharmony_ci/* Defining the Capabilities */ 2362306a36Sopenharmony_ci#define DW_MCI_CAPABILITIES (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED |\ 2462306a36Sopenharmony_ci MMC_CAP_SD_HIGHSPEED | MMC_CAP_8_BIT_DATA |\ 2562306a36Sopenharmony_ci MMC_CAP_SDIO_IRQ) 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic struct dw_mci_board pci_board_data = { 2862306a36Sopenharmony_ci .caps = DW_MCI_CAPABILITIES, 2962306a36Sopenharmony_ci .bus_hz = 33 * 1000 * 1000, 3062306a36Sopenharmony_ci .detect_delay_ms = 200, 3162306a36Sopenharmony_ci .fifo_depth = 32, 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic int dw_mci_pci_probe(struct pci_dev *pdev, 3562306a36Sopenharmony_ci const struct pci_device_id *entries) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci struct dw_mci *host; 3862306a36Sopenharmony_ci int ret; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci ret = pcim_enable_device(pdev); 4162306a36Sopenharmony_ci if (ret) 4262306a36Sopenharmony_ci return ret; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL); 4562306a36Sopenharmony_ci if (!host) 4662306a36Sopenharmony_ci return -ENOMEM; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci host->irq = pdev->irq; 4962306a36Sopenharmony_ci host->irq_flags = IRQF_SHARED; 5062306a36Sopenharmony_ci host->dev = &pdev->dev; 5162306a36Sopenharmony_ci host->pdata = &pci_board_data; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci ret = pcim_iomap_regions(pdev, 1 << PCI_BAR_NO, pci_name(pdev)); 5462306a36Sopenharmony_ci if (ret) 5562306a36Sopenharmony_ci return ret; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci host->regs = pcim_iomap_table(pdev)[PCI_BAR_NO]; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci pci_set_master(pdev); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci ret = dw_mci_probe(host); 6262306a36Sopenharmony_ci if (ret) 6362306a36Sopenharmony_ci return ret; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci pci_set_drvdata(pdev, host); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci return 0; 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic void dw_mci_pci_remove(struct pci_dev *pdev) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci struct dw_mci *host = pci_get_drvdata(pdev); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci dw_mci_remove(host); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic const struct dev_pm_ops dw_mci_pci_dev_pm_ops = { 7862306a36Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 7962306a36Sopenharmony_ci pm_runtime_force_resume) 8062306a36Sopenharmony_ci SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend, 8162306a36Sopenharmony_ci dw_mci_runtime_resume, 8262306a36Sopenharmony_ci NULL) 8362306a36Sopenharmony_ci}; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic const struct pci_device_id dw_mci_pci_id[] = { 8662306a36Sopenharmony_ci { PCI_DEVICE(SYNOPSYS_DW_MCI_VENDOR_ID, SYNOPSYS_DW_MCI_DEVICE_ID) }, 8762306a36Sopenharmony_ci {} 8862306a36Sopenharmony_ci}; 8962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, dw_mci_pci_id); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cistatic struct pci_driver dw_mci_pci_driver = { 9262306a36Sopenharmony_ci .name = "dw_mmc_pci", 9362306a36Sopenharmony_ci .id_table = dw_mci_pci_id, 9462306a36Sopenharmony_ci .probe = dw_mci_pci_probe, 9562306a36Sopenharmony_ci .remove = dw_mci_pci_remove, 9662306a36Sopenharmony_ci .driver = { 9762306a36Sopenharmony_ci .pm = &dw_mci_pci_dev_pm_ops, 9862306a36Sopenharmony_ci }, 9962306a36Sopenharmony_ci}; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cimodule_pci_driver(dw_mci_pci_driver); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciMODULE_DESCRIPTION("DW Multimedia Card PCI Interface driver"); 10462306a36Sopenharmony_ciMODULE_AUTHOR("Shashidhar Hiremath <shashidharh@vayavyalabs.com>"); 10562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 106