Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Synopsys G210 Test Chip driver
  4 *
  5 * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
  6 *
  7 * Authors: Joao Pinto <jpinto@synopsys.com>
  8 */
  9
 10#include "ufshcd.h"
 11#include "ufshcd-dwc.h"
 12#include "tc-dwc-g210.h"
 13
 14#include <linux/pci.h>
 15#include <linux/pm_runtime.h>
 16
 17/* Test Chip type expected values */
 18#define TC_G210_20BIT 20
 19#define TC_G210_40BIT 40
 20#define TC_G210_INV 0
 21
 22static int tc_type = TC_G210_INV;
 23module_param(tc_type, int, 0);
 24MODULE_PARM_DESC(tc_type, "Test Chip Type (20 = 20-bit, 40 = 40-bit)");
 25
 26static int tc_dwc_g210_pci_suspend(struct device *dev)
 27{
 28	return ufshcd_system_suspend(dev_get_drvdata(dev));
 29}
 30
 31static int tc_dwc_g210_pci_resume(struct device *dev)
 32{
 33	return ufshcd_system_resume(dev_get_drvdata(dev));
 34}
 35
 36static int tc_dwc_g210_pci_runtime_suspend(struct device *dev)
 37{
 38	return ufshcd_runtime_suspend(dev_get_drvdata(dev));
 39}
 40
 41static int tc_dwc_g210_pci_runtime_resume(struct device *dev)
 42{
 43	return ufshcd_runtime_resume(dev_get_drvdata(dev));
 44}
 45
 46static int tc_dwc_g210_pci_runtime_idle(struct device *dev)
 47{
 48	return ufshcd_runtime_idle(dev_get_drvdata(dev));
 49}
 50
 51/*
 52 * struct ufs_hba_dwc_vops - UFS DWC specific variant operations
 53 */
 54static struct ufs_hba_variant_ops tc_dwc_g210_pci_hba_vops = {
 55	.name                   = "tc-dwc-g210-pci",
 56	.link_startup_notify	= ufshcd_dwc_link_startup_notify,
 57};
 58
 59/**
 60 * tc_dwc_g210_pci_shutdown - main function to put the controller in reset state
 61 * @pdev: pointer to PCI device handle
 62 */
 63static void tc_dwc_g210_pci_shutdown(struct pci_dev *pdev)
 64{
 65	ufshcd_shutdown((struct ufs_hba *)pci_get_drvdata(pdev));
 66}
 67
 68/**
 69 * tc_dwc_g210_pci_remove - de-allocate PCI/SCSI host and host memory space
 70 *		data structure memory
 71 * @pdev: pointer to PCI handle
 72 */
 73static void tc_dwc_g210_pci_remove(struct pci_dev *pdev)
 74{
 75	struct ufs_hba *hba = pci_get_drvdata(pdev);
 76
 77	pm_runtime_forbid(&pdev->dev);
 78	pm_runtime_get_noresume(&pdev->dev);
 79	ufshcd_remove(hba);
 80}
 81
 82/**
 83 * tc_dwc_g210_pci_probe - probe routine of the driver
 84 * @pdev: pointer to PCI device handle
 85 * @id: PCI device id
 86 *
 87 * Returns 0 on success, non-zero value on failure
 88 */
 89static int
 90tc_dwc_g210_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 91{
 92	struct ufs_hba *hba;
 93	void __iomem *mmio_base;
 94	int err;
 95
 96	/* Check Test Chip type and set the specific setup routine */
 97	if (tc_type == TC_G210_20BIT) {
 98		tc_dwc_g210_pci_hba_vops.phy_initialization =
 99						tc_dwc_g210_config_20_bit;
100	} else if (tc_type == TC_G210_40BIT) {
101		tc_dwc_g210_pci_hba_vops.phy_initialization =
102						tc_dwc_g210_config_40_bit;
103	} else {
104		dev_err(&pdev->dev, "test chip version not specified\n");
105		return -EPERM;
106	}
107
108	err = pcim_enable_device(pdev);
109	if (err) {
110		dev_err(&pdev->dev, "pcim_enable_device failed\n");
111		return err;
112	}
113
114	pci_set_master(pdev);
115
116	err = pcim_iomap_regions(pdev, 1 << 0, UFSHCD);
117	if (err < 0) {
118		dev_err(&pdev->dev, "request and iomap failed\n");
119		return err;
120	}
121
122	mmio_base = pcim_iomap_table(pdev)[0];
123
124	err = ufshcd_alloc_host(&pdev->dev, &hba);
125	if (err) {
126		dev_err(&pdev->dev, "Allocation failed\n");
127		return err;
128	}
129
130	hba->vops = &tc_dwc_g210_pci_hba_vops;
131
132	err = ufshcd_init(hba, mmio_base, pdev->irq);
133	if (err) {
134		dev_err(&pdev->dev, "Initialization failed\n");
135		return err;
136	}
137
138	pci_set_drvdata(pdev, hba);
139	pm_runtime_put_noidle(&pdev->dev);
140	pm_runtime_allow(&pdev->dev);
141
142	return 0;
143}
144
145static const struct dev_pm_ops tc_dwc_g210_pci_pm_ops = {
146	.suspend	= tc_dwc_g210_pci_suspend,
147	.resume		= tc_dwc_g210_pci_resume,
148	.runtime_suspend = tc_dwc_g210_pci_runtime_suspend,
149	.runtime_resume  = tc_dwc_g210_pci_runtime_resume,
150	.runtime_idle    = tc_dwc_g210_pci_runtime_idle,
151};
152
153static const struct pci_device_id tc_dwc_g210_pci_tbl[] = {
154	{ PCI_VENDOR_ID_SYNOPSYS, 0xB101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
155	{ PCI_VENDOR_ID_SYNOPSYS, 0xB102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
156	{ }	/* terminate list */
157};
158
159MODULE_DEVICE_TABLE(pci, tc_dwc_g210_pci_tbl);
160
161static struct pci_driver tc_dwc_g210_pci_driver = {
162	.name = "tc-dwc-g210-pci",
163	.id_table = tc_dwc_g210_pci_tbl,
164	.probe = tc_dwc_g210_pci_probe,
165	.remove = tc_dwc_g210_pci_remove,
166	.shutdown = tc_dwc_g210_pci_shutdown,
167	.driver = {
168		.pm = &tc_dwc_g210_pci_pm_ops
169	},
170};
171
172module_pci_driver(tc_dwc_g210_pci_driver);
173
174MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
175MODULE_DESCRIPTION("Synopsys Test Chip G210 PCI glue driver");
176MODULE_LICENSE("Dual BSD/GPL");