aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ufs/ufshcd-pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ufs/ufshcd-pci.c')
-rw-r--r--drivers/scsi/ufs/ufshcd-pci.c99
1 files changed, 64 insertions, 35 deletions
diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c
index 48be39a6f6d7..a823cf44e949 100644
--- a/drivers/scsi/ufs/ufshcd-pci.c
+++ b/drivers/scsi/ufs/ufshcd-pci.c
@@ -35,6 +35,7 @@
35 35
36#include "ufshcd.h" 36#include "ufshcd.h"
37#include <linux/pci.h> 37#include <linux/pci.h>
38#include <linux/pm_runtime.h>
38 39
39#ifdef CONFIG_PM 40#ifdef CONFIG_PM
40/** 41/**
@@ -44,7 +45,7 @@
44 * 45 *
45 * Returns -ENOSYS 46 * Returns -ENOSYS
46 */ 47 */
47static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state) 48static int ufshcd_pci_suspend(struct device *dev)
48{ 49{
49 /* 50 /*
50 * TODO: 51 * TODO:
@@ -61,7 +62,7 @@ static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state)
61 * 62 *
62 * Returns -ENOSYS 63 * Returns -ENOSYS
63 */ 64 */
64static int ufshcd_pci_resume(struct pci_dev *pdev) 65static int ufshcd_pci_resume(struct device *dev)
65{ 66{
66 /* 67 /*
67 * TODO: 68 * TODO:
@@ -71,8 +72,45 @@ static int ufshcd_pci_resume(struct pci_dev *pdev)
71 72
72 return -ENOSYS; 73 return -ENOSYS;
73} 74}
75#else
76#define ufshcd_pci_suspend NULL
77#define ufshcd_pci_resume NULL
74#endif /* CONFIG_PM */ 78#endif /* CONFIG_PM */
75 79
80#ifdef CONFIG_PM_RUNTIME
81static int ufshcd_pci_runtime_suspend(struct device *dev)
82{
83 struct ufs_hba *hba = dev_get_drvdata(dev);
84
85 if (!hba)
86 return 0;
87
88 return ufshcd_runtime_suspend(hba);
89}
90static int ufshcd_pci_runtime_resume(struct device *dev)
91{
92 struct ufs_hba *hba = dev_get_drvdata(dev);
93
94 if (!hba)
95 return 0;
96
97 return ufshcd_runtime_resume(hba);
98}
99static int ufshcd_pci_runtime_idle(struct device *dev)
100{
101 struct ufs_hba *hba = dev_get_drvdata(dev);
102
103 if (!hba)
104 return 0;
105
106 return ufshcd_runtime_idle(hba);
107}
108#else /* !CONFIG_PM_RUNTIME */
109#define ufshcd_pci_runtime_suspend NULL
110#define ufshcd_pci_runtime_resume NULL
111#define ufshcd_pci_runtime_idle NULL
112#endif /* CONFIG_PM_RUNTIME */
113
76/** 114/**
77 * ufshcd_pci_shutdown - main function to put the controller in reset state 115 * ufshcd_pci_shutdown - main function to put the controller in reset state
78 * @pdev: pointer to PCI device handle 116 * @pdev: pointer to PCI device handle
@@ -91,12 +129,10 @@ static void ufshcd_pci_remove(struct pci_dev *pdev)
91{ 129{
92 struct ufs_hba *hba = pci_get_drvdata(pdev); 130 struct ufs_hba *hba = pci_get_drvdata(pdev);
93 131
94 disable_irq(pdev->irq); 132 pm_runtime_forbid(&pdev->dev);
133 pm_runtime_get_noresume(&pdev->dev);
95 ufshcd_remove(hba); 134 ufshcd_remove(hba);
96 pci_release_regions(pdev);
97 pci_set_drvdata(pdev, NULL); 135 pci_set_drvdata(pdev, NULL);
98 pci_clear_master(pdev);
99 pci_disable_device(pdev);
100} 136}
101 137
102/** 138/**
@@ -133,55 +169,49 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
133 void __iomem *mmio_base; 169 void __iomem *mmio_base;
134 int err; 170 int err;
135 171
136 err = pci_enable_device(pdev); 172 err = pcim_enable_device(pdev);
137 if (err) { 173 if (err) {
138 dev_err(&pdev->dev, "pci_enable_device failed\n"); 174 dev_err(&pdev->dev, "pcim_enable_device failed\n");
139 goto out_error; 175 return err;
140 } 176 }
141 177
142 pci_set_master(pdev); 178 pci_set_master(pdev);
143 179
144 180 err = pcim_iomap_regions(pdev, 1 << 0, UFSHCD);
145 err = pci_request_regions(pdev, UFSHCD);
146 if (err < 0) { 181 if (err < 0) {
147 dev_err(&pdev->dev, "request regions failed\n"); 182 dev_err(&pdev->dev, "request and iomap failed\n");
148 goto out_disable; 183 return err;
149 } 184 }
150 185
151 mmio_base = pci_ioremap_bar(pdev, 0); 186 mmio_base = pcim_iomap_table(pdev)[0];
152 if (!mmio_base) {
153 dev_err(&pdev->dev, "memory map failed\n");
154 err = -ENOMEM;
155 goto out_release_regions;
156 }
157 187
158 err = ufshcd_set_dma_mask(pdev); 188 err = ufshcd_set_dma_mask(pdev);
159 if (err) { 189 if (err) {
160 dev_err(&pdev->dev, "set dma mask failed\n"); 190 dev_err(&pdev->dev, "set dma mask failed\n");
161 goto out_iounmap; 191 return err;
162 } 192 }
163 193
164 err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq); 194 err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq);
165 if (err) { 195 if (err) {
166 dev_err(&pdev->dev, "Initialization failed\n"); 196 dev_err(&pdev->dev, "Initialization failed\n");
167 goto out_iounmap; 197 return err;
168 } 198 }
169 199
170 pci_set_drvdata(pdev, hba); 200 pci_set_drvdata(pdev, hba);
201 pm_runtime_put_noidle(&pdev->dev);
202 pm_runtime_allow(&pdev->dev);
171 203
172 return 0; 204 return 0;
173
174out_iounmap:
175 iounmap(mmio_base);
176out_release_regions:
177 pci_release_regions(pdev);
178out_disable:
179 pci_clear_master(pdev);
180 pci_disable_device(pdev);
181out_error:
182 return err;
183} 205}
184 206
207static const struct dev_pm_ops ufshcd_pci_pm_ops = {
208 .suspend = ufshcd_pci_suspend,
209 .resume = ufshcd_pci_resume,
210 .runtime_suspend = ufshcd_pci_runtime_suspend,
211 .runtime_resume = ufshcd_pci_runtime_resume,
212 .runtime_idle = ufshcd_pci_runtime_idle,
213};
214
185static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = { 215static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = {
186 { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 216 { PCI_VENDOR_ID_SAMSUNG, 0xC00C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
187 { } /* terminate list */ 217 { } /* terminate list */
@@ -195,10 +225,9 @@ static struct pci_driver ufshcd_pci_driver = {
195 .probe = ufshcd_pci_probe, 225 .probe = ufshcd_pci_probe,
196 .remove = ufshcd_pci_remove, 226 .remove = ufshcd_pci_remove,
197 .shutdown = ufshcd_pci_shutdown, 227 .shutdown = ufshcd_pci_shutdown,
198#ifdef CONFIG_PM 228 .driver = {
199 .suspend = ufshcd_pci_suspend, 229 .pm = &ufshcd_pci_pm_ops
200 .resume = ufshcd_pci_resume, 230 },
201#endif
202}; 231};
203 232
204module_pci_driver(ufshcd_pci_driver); 233module_pci_driver(ufshcd_pci_driver);