diff options
Diffstat (limited to 'drivers/scsi/ufs/ufshcd-pci.c')
-rw-r--r-- | drivers/scsi/ufs/ufshcd-pci.c | 99 |
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 | */ |
47 | static int ufshcd_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 48 | static 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 | */ |
64 | static int ufshcd_pci_resume(struct pci_dev *pdev) | 65 | static 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 | ||
81 | static 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 | } | ||
90 | static 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 | } | ||
99 | static 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 | |||
174 | out_iounmap: | ||
175 | iounmap(mmio_base); | ||
176 | out_release_regions: | ||
177 | pci_release_regions(pdev); | ||
178 | out_disable: | ||
179 | pci_clear_master(pdev); | ||
180 | pci_disable_device(pdev); | ||
181 | out_error: | ||
182 | return err; | ||
183 | } | 205 | } |
184 | 206 | ||
207 | static 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 | |||
185 | static DEFINE_PCI_DEVICE_TABLE(ufshcd_pci_tbl) = { | 215 | static 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 | ||
204 | module_pci_driver(ufshcd_pci_driver); | 233 | module_pci_driver(ufshcd_pci_driver); |