aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/host1x
diff options
context:
space:
mode:
authorArto Merilainen <amerilainen@nvidia.com>2013-10-14 08:21:53 -0400
committerThierry Reding <treding@nvidia.com>2013-10-31 04:55:48 -0400
commitf5a954fed9b3eb04973ede72c50c66157fa9e15b (patch)
treed9d6faeb5b2bafbc5a4143feb10e27d975ec1da4 /drivers/gpu/host1x
parent8736fe81532182ba0086a371fae0708ea42a2cdf (diff)
gpu: host1x: Add syncpoint base support
This patch adds support for hardware syncpoint bases. This creates a simple mechanism to stall the command FIFO until an operation is completed. Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/host1x')
-rw-r--r--drivers/gpu/host1x/dev.h2
-rw-r--r--drivers/gpu/host1x/hw/channel_hw.c20
-rw-r--r--drivers/gpu/host1x/hw/hw_host1x01_uclass.h6
-rw-r--r--drivers/gpu/host1x/syncpt.c55
-rw-r--r--drivers/gpu/host1x/syncpt.h6
5 files changed, 87 insertions, 2 deletions
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index 6cf689b9e17b..a61a976e7a42 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -27,6 +27,7 @@
27#include "job.h" 27#include "job.h"
28 28
29struct host1x_syncpt; 29struct host1x_syncpt;
30struct host1x_syncpt_base;
30struct host1x_channel; 31struct host1x_channel;
31struct host1x_cdma; 32struct host1x_cdma;
32struct host1x_job; 33struct host1x_job;
@@ -102,6 +103,7 @@ struct host1x {
102 103
103 void __iomem *regs; 104 void __iomem *regs;
104 struct host1x_syncpt *syncpt; 105 struct host1x_syncpt *syncpt;
106 struct host1x_syncpt_base *bases;
105 struct device *dev; 107 struct device *dev;
106 struct clk *clk; 108 struct clk *clk;
107 109
diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c
index 3be0cd296d3a..4608257ab656 100644
--- a/drivers/gpu/host1x/hw/channel_hw.c
+++ b/drivers/gpu/host1x/hw/channel_hw.c
@@ -67,6 +67,22 @@ static void submit_gathers(struct host1x_job *job)
67 } 67 }
68} 68}
69 69
70static inline void synchronize_syncpt_base(struct host1x_job *job)
71{
72 struct host1x *host = dev_get_drvdata(job->channel->dev->parent);
73 struct host1x_syncpt *sp = host->syncpt + job->syncpt_id;
74 u32 id, value;
75
76 value = host1x_syncpt_read_max(sp);
77 id = sp->base->id;
78
79 host1x_cdma_push(&job->channel->cdma,
80 host1x_opcode_setclass(HOST1X_CLASS_HOST1X,
81 HOST1X_UCLASS_LOAD_SYNCPT_BASE, 1),
82 HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(id) |
83 HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(value));
84}
85
70static int channel_submit(struct host1x_job *job) 86static int channel_submit(struct host1x_job *job)
71{ 87{
72 struct host1x_channel *ch = job->channel; 88 struct host1x_channel *ch = job->channel;
@@ -118,6 +134,10 @@ static int channel_submit(struct host1x_job *job)
118 host1x_syncpt_read_max(sp))); 134 host1x_syncpt_read_max(sp)));
119 } 135 }
120 136
137 /* Synchronize base register to allow using it for relative waiting */
138 if (sp->base)
139 synchronize_syncpt_base(job);
140
121 syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs); 141 syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs);
122 142
123 job->syncpt_end = syncval; 143 job->syncpt_end = syncval;
diff --git a/drivers/gpu/host1x/hw/hw_host1x01_uclass.h b/drivers/gpu/host1x/hw/hw_host1x01_uclass.h
index 42f3ce19ca32..f7553599ee27 100644
--- a/drivers/gpu/host1x/hw/hw_host1x01_uclass.h
+++ b/drivers/gpu/host1x/hw/hw_host1x01_uclass.h
@@ -111,6 +111,12 @@ static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v)
111} 111}
112#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \ 112#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \
113 host1x_uclass_wait_syncpt_base_offset_f(v) 113 host1x_uclass_wait_syncpt_base_offset_f(v)
114static inline u32 host1x_uclass_load_syncpt_base_r(void)
115{
116 return 0xb;
117}
118#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \
119 host1x_uclass_load_syncpt_base_r()
114static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v) 120static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)
115{ 121{
116 return (v & 0xff) << 24; 122 return (v & 0xff) << 24;
diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c
index 5b88ba4c974e..159c479829c9 100644
--- a/drivers/gpu/host1x/syncpt.c
+++ b/drivers/gpu/host1x/syncpt.c
@@ -30,6 +30,29 @@
30#define SYNCPT_CHECK_PERIOD (2 * HZ) 30#define SYNCPT_CHECK_PERIOD (2 * HZ)
31#define MAX_STUCK_CHECK_COUNT 15 31#define MAX_STUCK_CHECK_COUNT 15
32 32
33static struct host1x_syncpt_base *
34host1x_syncpt_base_request(struct host1x *host)
35{
36 struct host1x_syncpt_base *bases = host->bases;
37 unsigned int i;
38
39 for (i = 0; i < host->info->nb_bases; i++)
40 if (!bases[i].requested)
41 break;
42
43 if (i >= host->info->nb_bases)
44 return NULL;
45
46 bases[i].requested = true;
47 return &bases[i];
48}
49
50static void host1x_syncpt_base_free(struct host1x_syncpt_base *base)
51{
52 if (base)
53 base->requested = false;
54}
55
33static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host, 56static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
34 struct device *dev, 57 struct device *dev,
35 unsigned long flags) 58 unsigned long flags)
@@ -44,6 +67,12 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host,
44 if (i >= host->info->nb_pts) 67 if (i >= host->info->nb_pts)
45 return NULL; 68 return NULL;
46 69
70 if (flags & HOST1X_SYNCPT_HAS_BASE) {
71 sp->base = host1x_syncpt_base_request(host);
72 if (!sp->base)
73 return NULL;
74 }
75
47 name = kasprintf(GFP_KERNEL, "%02d-%s", sp->id, 76 name = kasprintf(GFP_KERNEL, "%02d-%s", sp->id,
48 dev ? dev_name(dev) : NULL); 77 dev ? dev_name(dev) : NULL);
49 if (!name) 78 if (!name)
@@ -307,20 +336,30 @@ int host1x_syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr)
307 336
308int host1x_syncpt_init(struct host1x *host) 337int host1x_syncpt_init(struct host1x *host)
309{ 338{
339 struct host1x_syncpt_base *bases;
310 struct host1x_syncpt *syncpt; 340 struct host1x_syncpt *syncpt;
311 int i; 341 int i;
312 342
313 syncpt = devm_kzalloc(host->dev, sizeof(*syncpt) * host->info->nb_pts, 343 syncpt = devm_kzalloc(host->dev, sizeof(*syncpt) * host->info->nb_pts,
314 GFP_KERNEL); 344 GFP_KERNEL);
315 if (!syncpt) 345 if (!syncpt)
316 return -ENOMEM; 346 return -ENOMEM;
317 347
318 for (i = 0; i < host->info->nb_pts; ++i) { 348 bases = devm_kzalloc(host->dev, sizeof(*bases) * host->info->nb_bases,
349 GFP_KERNEL);
350 if (!bases)
351 return -ENOMEM;
352
353 for (i = 0; i < host->info->nb_pts; i++) {
319 syncpt[i].id = i; 354 syncpt[i].id = i;
320 syncpt[i].host = host; 355 syncpt[i].host = host;
321 } 356 }
322 357
358 for (i = 0; i < host->info->nb_bases; i++)
359 bases[i].id = i;
360
323 host->syncpt = syncpt; 361 host->syncpt = syncpt;
362 host->bases = bases;
324 363
325 host1x_syncpt_restore(host); 364 host1x_syncpt_restore(host);
326 365
@@ -344,7 +383,9 @@ void host1x_syncpt_free(struct host1x_syncpt *sp)
344 if (!sp) 383 if (!sp)
345 return; 384 return;
346 385
386 host1x_syncpt_base_free(sp->base);
347 kfree(sp->name); 387 kfree(sp->name);
388 sp->base = NULL;
348 sp->dev = NULL; 389 sp->dev = NULL;
349 sp->name = NULL; 390 sp->name = NULL;
350 sp->client_managed = false; 391 sp->client_managed = false;
@@ -398,3 +439,13 @@ struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id)
398 return NULL; 439 return NULL;
399 return host->syncpt + id; 440 return host->syncpt + id;
400} 441}
442
443struct host1x_syncpt_base *host1x_syncpt_get_base(struct host1x_syncpt *sp)
444{
445 return sp ? sp->base : NULL;
446}
447
448u32 host1x_syncpt_base_id(struct host1x_syncpt_base *base)
449{
450 return base->id;
451}
diff --git a/drivers/gpu/host1x/syncpt.h b/drivers/gpu/host1x/syncpt.h
index 4eb933a497fd..9056465ecd3f 100644
--- a/drivers/gpu/host1x/syncpt.h
+++ b/drivers/gpu/host1x/syncpt.h
@@ -31,6 +31,11 @@ struct host1x;
31/* Reserved for replacing an expired wait with a NOP */ 31/* Reserved for replacing an expired wait with a NOP */
32#define HOST1X_SYNCPT_RESERVED 0 32#define HOST1X_SYNCPT_RESERVED 0
33 33
34struct host1x_syncpt_base {
35 unsigned int id;
36 bool requested;
37};
38
34struct host1x_syncpt { 39struct host1x_syncpt {
35 int id; 40 int id;
36 atomic_t min_val; 41 atomic_t min_val;
@@ -40,6 +45,7 @@ struct host1x_syncpt {
40 bool client_managed; 45 bool client_managed;
41 struct host1x *host; 46 struct host1x *host;
42 struct device *dev; 47 struct device *dev;
48 struct host1x_syncpt_base *base;
43 49
44 /* interrupt data */ 50 /* interrupt data */
45 struct host1x_syncpt_intr intr; 51 struct host1x_syncpt_intr intr;