hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
....@@ -24,6 +24,7 @@
2424 */
2525
2626 #include <linux/irqdomain.h>
27
+#include <linux/pci.h>
2728 #include <linux/pm_domain.h>
2829 #include <linux/platform_device.h>
2930 #include <sound/designware_i2s.h>
....@@ -116,151 +117,71 @@
116117 return 0;
117118 }
118119
119
-/* power off a tile/block within ACP */
120
-static int acp_suspend_tile(void *cgs_dev, int tile)
121
-{
122
- u32 val = 0;
123
- u32 count = 0;
124
-
125
- if ((tile < ACP_TILE_P1) || (tile > ACP_TILE_DSP2)) {
126
- pr_err("Invalid ACP tile : %d to suspend\n", tile);
127
- return -1;
128
- }
129
-
130
- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0 + tile);
131
- val &= ACP_TILE_ON_MASK;
132
-
133
- if (val == 0x0) {
134
- val = cgs_read_register(cgs_dev, mmACP_PGFSM_RETAIN_REG);
135
- val = val | (1 << tile);
136
- cgs_write_register(cgs_dev, mmACP_PGFSM_RETAIN_REG, val);
137
- cgs_write_register(cgs_dev, mmACP_PGFSM_CONFIG_REG,
138
- 0x500 + tile);
139
-
140
- count = ACP_TIMEOUT_LOOP;
141
- while (true) {
142
- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0
143
- + tile);
144
- val = val & ACP_TILE_ON_MASK;
145
- if (val == ACP_TILE_OFF_MASK)
146
- break;
147
- if (--count == 0) {
148
- pr_err("Timeout reading ACP PGFSM status\n");
149
- return -ETIMEDOUT;
150
- }
151
- udelay(100);
152
- }
153
-
154
- val = cgs_read_register(cgs_dev, mmACP_PGFSM_RETAIN_REG);
155
-
156
- val |= ACP_TILE_OFF_RETAIN_REG_MASK;
157
- cgs_write_register(cgs_dev, mmACP_PGFSM_RETAIN_REG, val);
158
- }
159
- return 0;
160
-}
161
-
162
-/* power on a tile/block within ACP */
163
-static int acp_resume_tile(void *cgs_dev, int tile)
164
-{
165
- u32 val = 0;
166
- u32 count = 0;
167
-
168
- if ((tile < ACP_TILE_P1) || (tile > ACP_TILE_DSP2)) {
169
- pr_err("Invalid ACP tile to resume\n");
170
- return -1;
171
- }
172
-
173
- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0 + tile);
174
- val = val & ACP_TILE_ON_MASK;
175
-
176
- if (val != 0x0) {
177
- cgs_write_register(cgs_dev, mmACP_PGFSM_CONFIG_REG,
178
- 0x600 + tile);
179
- count = ACP_TIMEOUT_LOOP;
180
- while (true) {
181
- val = cgs_read_register(cgs_dev, mmACP_PGFSM_READ_REG_0
182
- + tile);
183
- val = val & ACP_TILE_ON_MASK;
184
- if (val == 0x0)
185
- break;
186
- if (--count == 0) {
187
- pr_err("Timeout reading ACP PGFSM status\n");
188
- return -ETIMEDOUT;
189
- }
190
- udelay(100);
191
- }
192
- val = cgs_read_register(cgs_dev, mmACP_PGFSM_RETAIN_REG);
193
- if (tile == ACP_TILE_P1)
194
- val = val & (ACP_TILE_P1_MASK);
195
- else if (tile == ACP_TILE_P2)
196
- val = val & (ACP_TILE_P2_MASK);
197
-
198
- cgs_write_register(cgs_dev, mmACP_PGFSM_RETAIN_REG, val);
199
- }
200
- return 0;
201
-}
202
-
203120 struct acp_pm_domain {
204
- void *cgs_dev;
121
+ void *adev;
205122 struct generic_pm_domain gpd;
206123 };
207124
208125 static int acp_poweroff(struct generic_pm_domain *genpd)
209126 {
210
- int i, ret;
211127 struct acp_pm_domain *apd;
128
+ struct amdgpu_device *adev;
212129
213130 apd = container_of(genpd, struct acp_pm_domain, gpd);
214131 if (apd != NULL) {
215
- /* Donot return abruptly if any of power tile fails to suspend.
216
- * Log it and continue powering off other tile
217
- */
218
- for (i = 4; i >= 0 ; i--) {
219
- ret = acp_suspend_tile(apd->cgs_dev, ACP_TILE_P1 + i);
220
- if (ret)
221
- pr_err("ACP tile %d tile suspend failed\n", i);
222
- }
132
+ adev = apd->adev;
133
+ /* call smu to POWER GATE ACP block
134
+ * smu will
135
+ * 1. turn off the acp clock
136
+ * 2. power off the acp tiles
137
+ * 3. check and enter ulv state
138
+ */
139
+ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true);
223140 }
224141 return 0;
225142 }
226143
227144 static int acp_poweron(struct generic_pm_domain *genpd)
228145 {
229
- int i, ret;
230146 struct acp_pm_domain *apd;
147
+ struct amdgpu_device *adev;
231148
232149 apd = container_of(genpd, struct acp_pm_domain, gpd);
233150 if (apd != NULL) {
234
- for (i = 0; i < 2; i++) {
235
- ret = acp_resume_tile(apd->cgs_dev, ACP_TILE_P1 + i);
236
- if (ret) {
237
- pr_err("ACP tile %d resume failed\n", i);
238
- break;
239
- }
240
- }
241
-
242
- /* Disable DSPs which are not going to be used */
243
- for (i = 0; i < 3; i++) {
244
- ret = acp_suspend_tile(apd->cgs_dev, ACP_TILE_DSP0 + i);
245
- /* Continue suspending other DSP, even if one fails */
246
- if (ret)
247
- pr_err("ACP DSP %d suspend failed\n", i);
248
- }
151
+ adev = apd->adev;
152
+ /* call smu to UNGATE ACP block
153
+ * smu will
154
+ * 1. exit ulv
155
+ * 2. turn on acp clock
156
+ * 3. power on acp tiles
157
+ */
158
+ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false);
249159 }
250160 return 0;
251161 }
252162
253
-static struct device *get_mfd_cell_dev(const char *device_name, int r)
163
+static int acp_genpd_add_device(struct device *dev, void *data)
254164 {
255
- char auto_dev_name[25];
256
- struct device *dev;
165
+ struct generic_pm_domain *gpd = data;
166
+ int ret;
257167
258
- snprintf(auto_dev_name, sizeof(auto_dev_name),
259
- "%s.%d.auto", device_name, r);
260
- dev = bus_find_device_by_name(&platform_bus_type, NULL, auto_dev_name);
261
- dev_info(dev, "device %s added to pm domain\n", auto_dev_name);
168
+ ret = pm_genpd_add_device(gpd, dev);
169
+ if (ret)
170
+ dev_err(dev, "Failed to add dev to genpd %d\n", ret);
262171
263
- return dev;
172
+ return ret;
173
+}
174
+
175
+static int acp_genpd_remove_device(struct device *dev, void *data)
176
+{
177
+ int ret;
178
+
179
+ ret = pm_genpd_remove_device(dev);
180
+ if (ret)
181
+ dev_err(dev, "Failed to remove dev from genpd %d\n", ret);
182
+
183
+ /* Continue to remove */
184
+ return 0;
264185 }
265186
266187 /**
....@@ -271,11 +192,10 @@
271192 */
272193 static int acp_hw_init(void *handle)
273194 {
274
- int r, i;
195
+ int r;
275196 uint64_t acp_base;
276197 u32 val = 0;
277198 u32 count = 0;
278
- struct device *dev;
279199 struct i2s_platform_data *i2s_pdata = NULL;
280200
281201 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
....@@ -289,30 +209,31 @@
289209 r = amd_acp_hw_init(adev->acp.cgs_device,
290210 ip_block->version->major, ip_block->version->minor);
291211 /* -ENODEV means board uses AZ rather than ACP */
292
- if (r == -ENODEV)
212
+ if (r == -ENODEV) {
213
+ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true);
293214 return 0;
294
- else if (r)
215
+ } else if (r) {
295216 return r;
217
+ }
296218
297219 if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
298220 return -EINVAL;
299221
300222 acp_base = adev->rmmio_base;
301223
302
- if (adev->asic_type != CHIP_STONEY) {
303
- adev->acp.acp_genpd = kzalloc(sizeof(struct acp_pm_domain), GFP_KERNEL);
304
- if (adev->acp.acp_genpd == NULL)
305
- return -ENOMEM;
306224
307
- adev->acp.acp_genpd->gpd.name = "ACP_AUDIO";
308
- adev->acp.acp_genpd->gpd.power_off = acp_poweroff;
309
- adev->acp.acp_genpd->gpd.power_on = acp_poweron;
225
+ adev->acp.acp_genpd = kzalloc(sizeof(struct acp_pm_domain), GFP_KERNEL);
226
+ if (adev->acp.acp_genpd == NULL)
227
+ return -ENOMEM;
228
+
229
+ adev->acp.acp_genpd->gpd.name = "ACP_AUDIO";
230
+ adev->acp.acp_genpd->gpd.power_off = acp_poweroff;
231
+ adev->acp.acp_genpd->gpd.power_on = acp_poweron;
310232
311233
312
- adev->acp.acp_genpd->cgs_dev = adev->acp.cgs_device;
234
+ adev->acp.acp_genpd->adev = adev;
313235
314
- pm_genpd_init(&adev->acp.acp_genpd->gpd, NULL, false);
315
- }
236
+ pm_genpd_init(&adev->acp.acp_genpd->gpd, NULL, false);
316237
317238 adev->acp.acp_cell = kcalloc(ACP_DEVS, sizeof(struct mfd_cell),
318239 GFP_KERNEL);
....@@ -430,16 +351,10 @@
430351 if (r)
431352 goto failure;
432353
433
- if (adev->asic_type != CHIP_STONEY) {
434
- for (i = 0; i < ACP_DEVS ; i++) {
435
- dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i);
436
- r = pm_genpd_add_device(&adev->acp.acp_genpd->gpd, dev);
437
- if (r) {
438
- dev_err(dev, "Failed to add dev to genpd\n");
439
- goto failure;
440
- }
441
- }
442
- }
354
+ r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
355
+ acp_genpd_add_device);
356
+ if (r)
357
+ goto failure;
443358
444359 /* Assert Soft reset of ACP */
445360 val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
....@@ -500,15 +415,15 @@
500415 */
501416 static int acp_hw_fini(void *handle)
502417 {
503
- int i, ret;
504418 u32 val = 0;
505419 u32 count = 0;
506
- struct device *dev;
507420 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
508421
509422 /* return early if no ACP */
510
- if (!adev->acp.acp_cell)
423
+ if (!adev->acp.acp_genpd) {
424
+ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false);
511425 return 0;
426
+ }
512427
513428 /* Assert Soft reset of ACP */
514429 val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
....@@ -546,19 +461,12 @@
546461 udelay(100);
547462 }
548463
549
- if (adev->acp.acp_genpd) {
550
- for (i = 0; i < ACP_DEVS ; i++) {
551
- dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i);
552
- ret = pm_genpd_remove_device(dev);
553
- /* If removal fails, dont giveup and try rest */
554
- if (ret)
555
- dev_err(dev, "remove dev from genpd failed\n");
556
- }
557
- kfree(adev->acp.acp_genpd);
558
- }
464
+ device_for_each_child(adev->acp.parent, NULL,
465
+ acp_genpd_remove_device);
559466
560467 mfd_remove_devices(adev->acp.parent);
561468 kfree(adev->acp.acp_res);
469
+ kfree(adev->acp.acp_genpd);
562470 kfree(adev->acp.acp_cell);
563471
564472 return 0;
....@@ -566,11 +474,21 @@
566474
567475 static int acp_suspend(void *handle)
568476 {
477
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
478
+
479
+ /* power up on suspend */
480
+ if (!adev->acp.acp_cell)
481
+ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false);
569482 return 0;
570483 }
571484
572485 static int acp_resume(void *handle)
573486 {
487
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
488
+
489
+ /* power down again on resume */
490
+ if (!adev->acp.acp_cell)
491
+ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true);
574492 return 0;
575493 }
576494
....@@ -603,6 +521,11 @@
603521 static int acp_set_powergating_state(void *handle,
604522 enum amd_powergating_state state)
605523 {
524
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
525
+ bool enable = (state == AMD_PG_STATE_GATE);
526
+
527
+ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable);
528
+
606529 return 0;
607530 }
608531