diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/pci.c | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/drivers/gpu/nvgpu/pci.c b/drivers/gpu/nvgpu/pci.c index 01c7a2dc..90a54570 100644 --- a/drivers/gpu/nvgpu/pci.c +++ b/drivers/gpu/nvgpu/pci.c | |||
@@ -38,25 +38,15 @@ static bool nvgpu_pci_tegra_is_railgated(struct device *pdev) | |||
38 | return false; | 38 | return false; |
39 | } | 39 | } |
40 | 40 | ||
41 | static int nvgpu_pci_busy(struct device *dev) | ||
42 | { | ||
43 | struct gk20a *g = get_gk20a(dev); | ||
44 | int err = 0; | ||
45 | |||
46 | if (!g->power_on) | ||
47 | err = gk20a_pm_finalize_poweron(dev); | ||
48 | |||
49 | return err; | ||
50 | } | ||
51 | |||
52 | static struct gk20a_platform nvgpu_pci_device = { | 41 | static struct gk20a_platform nvgpu_pci_device = { |
53 | /* ptimer src frequency in hz */ | 42 | /* ptimer src frequency in hz */ |
54 | .ptimer_src_freq = 31250000, | 43 | .ptimer_src_freq = 31250000, |
55 | 44 | ||
56 | .probe = nvgpu_pci_tegra_probe, | 45 | .probe = nvgpu_pci_tegra_probe, |
57 | .remove = nvgpu_pci_tegra_remove, | 46 | .remove = nvgpu_pci_tegra_remove, |
58 | .busy = nvgpu_pci_busy, | ||
59 | 47 | ||
48 | /* power management configuration */ | ||
49 | .railgate_delay = 500, | ||
60 | .can_elpg = false, | 50 | .can_elpg = false, |
61 | 51 | ||
62 | /* power management callbacks */ | 52 | /* power management callbacks */ |
@@ -148,6 +138,45 @@ static struct class nvgpu_pci_class = { | |||
148 | .devnode = nvgpu_pci_devnode, | 138 | .devnode = nvgpu_pci_devnode, |
149 | }; | 139 | }; |
150 | 140 | ||
141 | #ifdef CONFIG_PM | ||
142 | static int nvgpu_pci_pm_runtime_resume(struct device *dev) | ||
143 | { | ||
144 | return gk20a_pm_finalize_poweron(dev); | ||
145 | } | ||
146 | |||
147 | static int nvgpu_pci_pm_runtime_suspend(struct device *dev) | ||
148 | { | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static const struct dev_pm_ops nvgpu_pci_pm_ops = { | ||
153 | .runtime_resume = nvgpu_pci_pm_runtime_resume, | ||
154 | .runtime_suspend = nvgpu_pci_pm_runtime_suspend, | ||
155 | .resume = nvgpu_pci_pm_runtime_resume, | ||
156 | .suspend = nvgpu_pci_pm_runtime_suspend, | ||
157 | }; | ||
158 | #endif | ||
159 | |||
160 | int nvgpu_pci_pm_init(struct device *dev) | ||
161 | { | ||
162 | #ifdef CONFIG_PM | ||
163 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
164 | |||
165 | if (platform->railgate_delay) | ||
166 | pm_runtime_set_autosuspend_delay(dev, | ||
167 | platform->railgate_delay); | ||
168 | |||
169 | /* | ||
170 | * Runtime PM for PCI devices is disabled by default, | ||
171 | * so we need to enable it first | ||
172 | */ | ||
173 | pm_runtime_use_autosuspend(dev); | ||
174 | pm_runtime_put_noidle(dev); | ||
175 | pm_runtime_allow(dev); | ||
176 | #endif | ||
177 | return 0; | ||
178 | } | ||
179 | |||
151 | static int nvgpu_pci_probe(struct pci_dev *pdev, | 180 | static int nvgpu_pci_probe(struct pci_dev *pdev, |
152 | const struct pci_device_id *pent) | 181 | const struct pci_device_id *pent) |
153 | { | 182 | { |
@@ -252,6 +281,12 @@ static int nvgpu_pci_probe(struct pci_dev *pdev, | |||
252 | 281 | ||
253 | gk20a_init_gr(g); | 282 | gk20a_init_gr(g); |
254 | 283 | ||
284 | err = nvgpu_pci_pm_init(&pdev->dev); | ||
285 | if (err) { | ||
286 | gk20a_err(&pdev->dev, "pm init failed"); | ||
287 | return err; | ||
288 | } | ||
289 | |||
255 | return 0; | 290 | return 0; |
256 | } | 291 | } |
257 | 292 | ||
@@ -281,6 +316,9 @@ static struct pci_driver nvgpu_pci_driver = { | |||
281 | .id_table = nvgpu_pci_table, | 316 | .id_table = nvgpu_pci_table, |
282 | .probe = nvgpu_pci_probe, | 317 | .probe = nvgpu_pci_probe, |
283 | .remove = nvgpu_pci_remove, | 318 | .remove = nvgpu_pci_remove, |
319 | #ifdef CONFIG_PM | ||
320 | .driver.pm = &nvgpu_pci_pm_ops, | ||
321 | #endif | ||
284 | }; | 322 | }; |
285 | 323 | ||
286 | int __init nvgpu_pci_init(void) | 324 | int __init nvgpu_pci_init(void) |