Skip to content

Commit 8167e6f

Browse files
fltorobclark
authored andcommitted
drm/msm/a6xx: HFI v2 for A640 and A650
Add HFI v2 code paths required by Adreno 640 and 650 GPUs. Signed-off-by: Jonathan Marek <[email protected]> Reviewed-by: Jordan Crouse <[email protected]> Signed-off-by: Rob Clark <[email protected]>
1 parent a83366e commit 8167e6f

File tree

5 files changed

+222
-24
lines changed

5 files changed

+222
-24
lines changed

drivers/gpu/drm/msm/adreno/a6xx_gmu.c

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,6 @@ static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
136136
if (ret)
137137
dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret);
138138

139-
gmu->freq = gmu->gpu_freqs[index];
140-
141139
/*
142140
* Eventually we will want to scale the path vote with the frequency but
143141
* for now leave it at max so that the performance is nominal.
@@ -162,7 +160,12 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq)
162160

163161
gmu->current_perf_index = perf_index;
164162

165-
__a6xx_gmu_set_freq(gmu, perf_index);
163+
if (gmu->legacy)
164+
__a6xx_gmu_set_freq(gmu, perf_index);
165+
else
166+
a6xx_hfi_set_freq(gmu, perf_index);
167+
168+
gmu->freq = gmu->gpu_freqs[perf_index];
166169
}
167170

168171
unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu)
@@ -242,8 +245,13 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
242245

243246
switch (state) {
244247
case GMU_OOB_GPU_SET:
245-
request = GMU_OOB_GPU_SET_REQUEST;
246-
ack = GMU_OOB_GPU_SET_ACK;
248+
if (gmu->legacy) {
249+
request = GMU_OOB_GPU_SET_REQUEST;
250+
ack = GMU_OOB_GPU_SET_ACK;
251+
} else {
252+
request = GMU_OOB_GPU_SET_REQUEST_NEW;
253+
ack = GMU_OOB_GPU_SET_ACK_NEW;
254+
}
247255
name = "GPU_SET";
248256
break;
249257
case GMU_OOB_BOOT_SLUMBER:
@@ -282,6 +290,13 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
282290
/* Clear a pending OOB state in the GMU */
283291
void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
284292
{
293+
if (!gmu->legacy) {
294+
WARN_ON(state != GMU_OOB_GPU_SET);
295+
gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
296+
1 << GMU_OOB_GPU_SET_CLEAR_NEW);
297+
return;
298+
}
299+
285300
switch (state) {
286301
case GMU_OOB_GPU_SET:
287302
gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET,
@@ -304,6 +319,9 @@ static int a6xx_sptprac_enable(struct a6xx_gmu *gmu)
304319
int ret;
305320
u32 val;
306321

322+
if (!gmu->legacy)
323+
return 0;
324+
307325
gmu_write(gmu, REG_A6XX_GMU_GX_SPTPRAC_POWER_CONTROL, 0x778000);
308326

309327
ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS, val,
@@ -323,6 +341,9 @@ static void a6xx_sptprac_disable(struct a6xx_gmu *gmu)
323341
u32 val;
324342
int ret;
325343

344+
if (!gmu->legacy)
345+
return;
346+
326347
/* Make sure retention is on */
327348
gmu_rmw(gmu, REG_A6XX_GPU_CC_GX_GDSCR, 0, (1 << 11));
328349

@@ -366,6 +387,11 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu)
366387
if (gmu->idle_level < GMU_IDLE_STATE_SPTP)
367388
a6xx_sptprac_disable(gmu);
368389

390+
if (!gmu->legacy) {
391+
ret = a6xx_hfi_send_prep_slumber(gmu);
392+
goto out;
393+
}
394+
369395
/* Tell the GMU to get ready to slumber */
370396
gmu_write(gmu, REG_A6XX_GMU_BOOT_SLUMBER_OPTION, 1);
371397

@@ -381,6 +407,7 @@ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu)
381407
}
382408
}
383409

410+
out:
384411
/* Put fence into allow mode */
385412
gmu_write(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0);
386413
return ret;
@@ -650,9 +677,11 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
650677
if (ret)
651678
return ret;
652679

653-
ret = a6xx_gmu_gfx_rail_on(gmu);
654-
if (ret)
655-
return ret;
680+
if (gmu->legacy) {
681+
ret = a6xx_gmu_gfx_rail_on(gmu);
682+
if (ret)
683+
return ret;
684+
}
656685

657686
/* Enable SPTP_PC if the CPU is responsible for it */
658687
if (gmu->idle_level < GMU_IDLE_STATE_SPTP) {
@@ -771,7 +800,10 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
771800
enable_irq(gmu->hfi_irq);
772801

773802
/* Set the GPU to the current freq */
774-
__a6xx_gmu_set_freq(gmu, gmu->current_perf_index);
803+
if (gmu->legacy)
804+
__a6xx_gmu_set_freq(gmu, gmu->current_perf_index);
805+
else
806+
a6xx_hfi_set_freq(gmu, gmu->current_perf_index);
775807

776808
/*
777809
* "enable" the GX power domain which won't actually do anything but it
@@ -1270,6 +1302,7 @@ void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu)
12701302

12711303
int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
12721304
{
1305+
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
12731306
struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
12741307
struct platform_device *pdev = of_find_device_by_node(node);
12751308
int ret;
@@ -1295,16 +1328,21 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
12951328
if (ret)
12961329
goto err_put_device;
12971330

1331+
if (!adreno_is_a640(adreno_gpu) && !adreno_is_a650(adreno_gpu)) {
1332+
/* HFI v1, has sptprac */
1333+
gmu->legacy = true;
1334+
1335+
/* Allocate memory for the GMU debug region */
1336+
ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_16K, 0);
1337+
if (ret)
1338+
goto err_memory;
1339+
}
1340+
12981341
/* Allocate memory for for the HFI queues */
12991342
ret = a6xx_gmu_memory_alloc(gmu, &gmu->hfi, SZ_16K, 0);
13001343
if (ret)
13011344
goto err_memory;
13021345

1303-
/* Allocate memory for the GMU debug region */
1304-
ret = a6xx_gmu_memory_alloc(gmu, &gmu->debug, SZ_16K, 0);
1305-
if (ret)
1306-
goto err_memory;
1307-
13081346
/* Map the GMU registers */
13091347
gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
13101348
if (IS_ERR(gmu->mmio)) {

drivers/gpu/drm/msm/adreno/a6xx_gmu.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ struct a6xx_gmu {
7979

8080
bool initialized;
8181
bool hung;
82+
bool legacy; /* a618 or a630 */
8283
};
8384

8485
static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset)
@@ -159,10 +160,16 @@ enum a6xx_gmu_oob_state {
159160
#define GMU_OOB_GPU_SET_ACK 24
160161
#define GMU_OOB_GPU_SET_CLEAR 24
161162

163+
#define GMU_OOB_GPU_SET_REQUEST_NEW 30
164+
#define GMU_OOB_GPU_SET_ACK_NEW 31
165+
#define GMU_OOB_GPU_SET_CLEAR_NEW 31
166+
162167

163168
void a6xx_hfi_init(struct a6xx_gmu *gmu);
164169
int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
165170
void a6xx_hfi_stop(struct a6xx_gmu *gmu);
171+
int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu);
172+
int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index);
166173

167174
bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu);
168175
bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu);

drivers/gpu/drm/msm/adreno/a6xx_gpu.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,10 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
566566
*/
567567
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
568568

569-
/* Take the GMU out of its special boot mode */
570-
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);
569+
if (a6xx_gpu->gmu.legacy) {
570+
/* Take the GMU out of its special boot mode */
571+
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_BOOT_SLUMBER);
572+
}
571573

572574
return ret;
573575
}

drivers/gpu/drm/msm/adreno/a6xx_hfi.c

Lines changed: 111 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@ static const char * const a6xx_hfi_msg_id[] = {
1717
HFI_MSG_ID(HFI_H2F_MSG_BW_TABLE),
1818
HFI_MSG_ID(HFI_H2F_MSG_PERF_TABLE),
1919
HFI_MSG_ID(HFI_H2F_MSG_TEST),
20+
HFI_MSG_ID(HFI_H2F_MSG_START),
21+
HFI_MSG_ID(HFI_H2F_MSG_CORE_FW_START),
22+
HFI_MSG_ID(HFI_H2F_MSG_GX_BW_PERF_VOTE),
23+
HFI_MSG_ID(HFI_H2F_MSG_PREPARE_SLUMBER),
2024
};
2125

22-
static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data,
23-
u32 dwords)
26+
static int a6xx_hfi_queue_read(struct a6xx_gmu *gmu,
27+
struct a6xx_hfi_queue *queue, u32 *data, u32 dwords)
2428
{
2529
struct a6xx_hfi_queue_header *header = queue->header;
2630
u32 i, hdr, index = header->read_index;
@@ -48,6 +52,9 @@ static int a6xx_hfi_queue_read(struct a6xx_hfi_queue *queue, u32 *data,
4852
index = (index + 1) % header->size;
4953
}
5054

55+
if (!gmu->legacy)
56+
index = ALIGN(index, 4) % header->size;
57+
5158
header->read_index = index;
5259
return HFI_HEADER_SIZE(hdr);
5360
}
@@ -73,6 +80,12 @@ static int a6xx_hfi_queue_write(struct a6xx_gmu *gmu,
7380
index = (index + 1) % header->size;
7481
}
7582

83+
/* Cookify any non used data at the end of the write buffer */
84+
if (!gmu->legacy) {
85+
for (; index % 4; index = (index + 1) % header->size)
86+
queue->data[index] = 0xfafafafa;
87+
}
88+
7689
header->write_index = index;
7790
spin_unlock(&queue->lock);
7891

@@ -106,7 +119,7 @@ static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum,
106119
struct a6xx_hfi_msg_response resp;
107120

108121
/* Get the next packet */
109-
ret = a6xx_hfi_queue_read(queue, (u32 *) &resp,
122+
ret = a6xx_hfi_queue_read(gmu, queue, (u32 *) &resp,
110123
sizeof(resp) >> 2);
111124

112125
/* If the queue is empty our response never made it */
@@ -195,6 +208,28 @@ static int a6xx_hfi_get_fw_version(struct a6xx_gmu *gmu, u32 *version)
195208
version, sizeof(*version));
196209
}
197210

211+
static int a6xx_hfi_send_perf_table_v1(struct a6xx_gmu *gmu)
212+
{
213+
struct a6xx_hfi_msg_perf_table_v1 msg = { 0 };
214+
int i;
215+
216+
msg.num_gpu_levels = gmu->nr_gpu_freqs;
217+
msg.num_gmu_levels = gmu->nr_gmu_freqs;
218+
219+
for (i = 0; i < gmu->nr_gpu_freqs; i++) {
220+
msg.gx_votes[i].vote = gmu->gx_arc_votes[i];
221+
msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
222+
}
223+
224+
for (i = 0; i < gmu->nr_gmu_freqs; i++) {
225+
msg.cx_votes[i].vote = gmu->cx_arc_votes[i];
226+
msg.cx_votes[i].freq = gmu->gmu_freqs[i] / 1000;
227+
}
228+
229+
return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PERF_TABLE, &msg, sizeof(msg),
230+
NULL, 0);
231+
}
232+
198233
static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
199234
{
200235
struct a6xx_hfi_msg_perf_table msg = { 0 };
@@ -205,6 +240,7 @@ static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
205240

206241
for (i = 0; i < gmu->nr_gpu_freqs; i++) {
207242
msg.gx_votes[i].vote = gmu->gx_arc_votes[i];
243+
msg.gx_votes[i].acd = 0xffffffff;
208244
msg.gx_votes[i].freq = gmu->gpu_freqs[i] / 1000;
209245
}
210246

@@ -306,7 +342,45 @@ static int a6xx_hfi_send_test(struct a6xx_gmu *gmu)
306342
NULL, 0);
307343
}
308344

309-
int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
345+
int a6xx_hfi_send_start(struct a6xx_gmu *gmu)
346+
{
347+
struct a6xx_hfi_msg_start msg = { 0 };
348+
349+
return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_START, &msg, sizeof(msg),
350+
NULL, 0);
351+
}
352+
353+
int a6xx_hfi_send_core_fw_start(struct a6xx_gmu *gmu)
354+
{
355+
struct a6xx_hfi_msg_core_fw_start msg = { 0 };
356+
357+
return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_CORE_FW_START, &msg,
358+
sizeof(msg), NULL, 0);
359+
}
360+
361+
int a6xx_hfi_set_freq(struct a6xx_gmu *gmu, int index)
362+
{
363+
struct a6xx_hfi_gx_bw_perf_vote_cmd msg = { 0 };
364+
365+
msg.ack_type = 1; /* blocking */
366+
msg.freq = index;
367+
msg.bw = 0; /* TODO: bus scaling */
368+
369+
return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_GX_BW_PERF_VOTE, &msg,
370+
sizeof(msg), NULL, 0);
371+
}
372+
373+
int a6xx_hfi_send_prep_slumber(struct a6xx_gmu *gmu)
374+
{
375+
struct a6xx_hfi_prep_slumber_cmd msg = { 0 };
376+
377+
/* TODO: should freq and bw fields be non-zero ? */
378+
379+
return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_PREPARE_SLUMBER, &msg,
380+
sizeof(msg), NULL, 0);
381+
}
382+
383+
static int a6xx_hfi_start_v1(struct a6xx_gmu *gmu, int boot_state)
310384
{
311385
int ret;
312386

@@ -324,7 +398,7 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
324398
* the GMU firmware
325399
*/
326400

327-
ret = a6xx_hfi_send_perf_table(gmu);
401+
ret = a6xx_hfi_send_perf_table_v1(gmu);
328402
if (ret)
329403
return ret;
330404

@@ -341,6 +415,37 @@ int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
341415
return 0;
342416
}
343417

418+
int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state)
419+
{
420+
int ret;
421+
422+
if (gmu->legacy)
423+
return a6xx_hfi_start_v1(gmu, boot_state);
424+
425+
426+
ret = a6xx_hfi_send_perf_table(gmu);
427+
if (ret)
428+
return ret;
429+
430+
ret = a6xx_hfi_send_bw_table(gmu);
431+
if (ret)
432+
return ret;
433+
434+
ret = a6xx_hfi_send_core_fw_start(gmu);
435+
if (ret)
436+
return ret;
437+
438+
/*
439+
* Downstream driver sends this in its "a6xx_hw_init" equivalent,
440+
* but seems to be no harm in sending it here
441+
*/
442+
ret = a6xx_hfi_send_start(gmu);
443+
if (ret)
444+
return ret;
445+
446+
return 0;
447+
}
448+
344449
void a6xx_hfi_stop(struct a6xx_gmu *gmu)
345450
{
346451
int i;
@@ -415,5 +520,5 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu)
415520
/* GMU response queue */
416521
offset += SZ_4K;
417522
a6xx_hfi_queue_init(&gmu->queues[1], &headers[1], hfi->virt + offset,
418-
hfi->iova + offset, 4);
523+
hfi->iova + offset, gmu->legacy ? 4 : 1);
419524
}

0 commit comments

Comments
 (0)