^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Synopsys DesignWare Multimedia Card PCI Interface driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2012 Vayavya Labs Pvt. Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/mmc/host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mmc/mmc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "dw_mmc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define PCI_BAR_NO 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define SYNOPSYS_DW_MCI_VENDOR_ID 0x700
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define SYNOPSYS_DW_MCI_DEVICE_ID 0x1107
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* Defining the Capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define DW_MCI_CAPABILITIES (MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) MMC_CAP_SD_HIGHSPEED | MMC_CAP_8_BIT_DATA |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) MMC_CAP_SDIO_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static struct dw_mci_board pci_board_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) .caps = DW_MCI_CAPABILITIES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) .bus_hz = 33 * 1000 * 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) .detect_delay_ms = 200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) .fifo_depth = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int dw_mci_pci_probe(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) const struct pci_device_id *entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct dw_mci *host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) ret = pcim_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (!host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) host->irq = pdev->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) host->irq_flags = IRQF_SHARED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) host->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) host->pdata = &pci_board_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ret = pcim_iomap_regions(pdev, 1 << PCI_BAR_NO, pci_name(pdev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) host->regs = pcim_iomap_table(pdev)[PCI_BAR_NO];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) pci_set_master(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ret = dw_mci_probe(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) pci_set_drvdata(pdev, host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static void dw_mci_pci_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct dw_mci *host = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) dw_mci_remove(host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static const struct dev_pm_ops dw_mci_pci_dev_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) pm_runtime_force_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) dw_mci_runtime_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static const struct pci_device_id dw_mci_pci_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) { PCI_DEVICE(SYNOPSYS_DW_MCI_VENDOR_ID, SYNOPSYS_DW_MCI_DEVICE_ID) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) MODULE_DEVICE_TABLE(pci, dw_mci_pci_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static struct pci_driver dw_mci_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .name = "dw_mmc_pci",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .id_table = dw_mci_pci_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .probe = dw_mci_pci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .remove = dw_mci_pci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .pm = &dw_mci_pci_dev_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) module_pci_driver(dw_mci_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) MODULE_DESCRIPTION("DW Multimedia Card PCI Interface driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) MODULE_AUTHOR("Shashidhar Hiremath <shashidharh@vayavyalabs.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) MODULE_LICENSE("GPL v2");