[PATCHv3 2/7] gpu: host1x: Add syncpoint wait and interrupts

2012-12-13 Thread Terje Bergstrom
Add support for sync point interrupts, and sync point wait. Sync
point wait used interrupts for unblocking wait.

Signed-off-by: Terje Bergstrom 
---
 drivers/gpu/host1x/Makefile  |3 +-
 drivers/gpu/host1x/dev.c |   44 
 drivers/gpu/host1x/dev.h |   15 ++
 drivers/gpu/host1x/hw/host1x01.c |2 +
 drivers/gpu/host1x/hw/hw_host1x01_sync.h |   30 ++-
 drivers/gpu/host1x/hw/intr_hw.c  |  175 +++
 drivers/gpu/host1x/intr.c|  350 ++
 drivers/gpu/host1x/intr.h|  100 +
 drivers/gpu/host1x/syncpt.c  |  161 ++
 drivers/gpu/host1x/syncpt.h  |4 +
 include/linux/host1x.h   |1 +
 11 files changed, 883 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/host1x/hw/intr_hw.c
 create mode 100644 drivers/gpu/host1x/intr.c
 create mode 100644 drivers/gpu/host1x/intr.h

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index a4adcc6..9d00b62 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -2,7 +2,8 @@ ccflags-y = -Idrivers/gpu/host1x

 host1x-objs = \
syncpt.o \
-   dev.o
+   dev.o \
+   intr.o

 obj-$(CONFIG_TEGRA_HOST1X) += hw/
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index b0d630d..9255a49 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include "dev.h"
+#include "intr.h"
 #include "hw/host1x01.h"

 #define CREATE_TRACE_POINTS
@@ -48,6 +49,19 @@ u32 host1x_syncpt_read_byid(u32 id)
 }
 EXPORT_SYMBOL(host1x_syncpt_read_byid);

+int host1x_syncpt_wait_byid(u32 id, u32 thresh, long timeout, u32 *value)
+{
+   struct host1x_syncpt *sp = host1x->syncpt + id;
+   return host1x_syncpt_wait(sp, thresh, timeout, value);
+}
+EXPORT_SYMBOL(host1x_syncpt_wait_byid);
+
+static void host1x_free_resources(struct host1x *host)
+{
+   kfree(host->intr.syncpt);
+   host->intr.syncpt = 0;
+}
+
 void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
 {
void __iomem *sync_regs = host1x->regs + host1x->info.sync_offset;
@@ -62,6 +76,21 @@ u32 host1x_sync_readl(struct host1x *host1x, u32 r)
return readl(sync_regs + r);
 }

+static int host1x_alloc_resources(struct host1x *host)
+{
+   host->intr.syncpt = devm_kzalloc(&host->dev->dev,
+   sizeof(struct host1x_intr_syncpt) *
+   host->info.nb_pts,
+   GFP_KERNEL);
+
+   if (!host->intr.syncpt) {
+   /* frees happen in the support removal phase */
+   return -ENOMEM;
+   }
+
+   return 0;
+}
+
 static struct host1x_device_info host1x_info = {
.nb_channels= 8,
.nb_pts = 32,
@@ -118,6 +147,12 @@ static int host1x_probe(struct platform_device *dev)
goto fail;
}

+   err = host1x_alloc_resources(host);
+   if (err) {
+   dev_err(&dev->dev, "failed to init chip support\n");
+   goto fail;
+   }
+
if (host->info.init) {
err = host->info.init(host);
if (err)
@@ -132,6 +167,10 @@ static int host1x_probe(struct platform_device *dev)
if (!host->nop_sp)
goto fail;

+   err = host1x_intr_init(&host->intr, syncpt_irq);
+   if (err)
+   goto fail;
+
host->clk = devm_clk_get(&dev->dev, NULL);
if (IS_ERR(host->clk)) {
dev_err(&dev->dev, "failed to get clock\n");
@@ -145,6 +184,8 @@ static int host1x_probe(struct platform_device *dev)

host1x_syncpt_reset(host);

+   host1x_intr_start(&host->intr, clk_get_rate(host->clk));
+
host1x = host;

dev_info(&dev->dev, "initialized\n");
@@ -153,6 +194,7 @@ static int host1x_probe(struct platform_device *dev)

 fail:
host1x_syncpt_free(host->nop_sp);
+   host1x_free_resources(host);
kfree(host);
return err;
 }
@@ -160,8 +202,10 @@ fail:
 static int __exit host1x_remove(struct platform_device *dev)
 {
struct host1x *host = platform_get_drvdata(dev);
+   host1x_intr_deinit(&host->intr);
host1x_syncpt_deinit(host);
clk_disable_unprepare(host->clk);
+   host1x_free_resources(host);
return 0;
 }

diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index 8245e24..a1622bb 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -20,6 +20,7 @@
 #include 

 #include "syncpt.h"
+#include "intr.h"

 struct host1x;
 struct host1x_syncpt;
@@ -36,6 +37,18 @@ struct host1x_syncpt_ops {
const char * (*name)(struct host1x_syncpt *);
 };

+struct host1x_intr_ops {
+   void (*init_host_sync)(struct host1x_intr *);
+   void (*set_host_clocks_per_usec)(
+   struct host1x_intr *, u32 clocks);
+   void

[PATCHv3 2/7] gpu: host1x: Add syncpoint wait and interrupts

2012-12-13 Thread Terje Bergstrom
Add support for sync point interrupts, and sync point wait. Sync
point wait used interrupts for unblocking wait.

Signed-off-by: Terje Bergstrom 
---
 drivers/gpu/host1x/Makefile  |3 +-
 drivers/gpu/host1x/dev.c |   44 
 drivers/gpu/host1x/dev.h |   15 ++
 drivers/gpu/host1x/hw/host1x01.c |2 +
 drivers/gpu/host1x/hw/hw_host1x01_sync.h |   30 ++-
 drivers/gpu/host1x/hw/intr_hw.c  |  175 +++
 drivers/gpu/host1x/intr.c|  350 ++
 drivers/gpu/host1x/intr.h|  100 +
 drivers/gpu/host1x/syncpt.c  |  161 ++
 drivers/gpu/host1x/syncpt.h  |4 +
 include/linux/host1x.h   |1 +
 11 files changed, 883 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/host1x/hw/intr_hw.c
 create mode 100644 drivers/gpu/host1x/intr.c
 create mode 100644 drivers/gpu/host1x/intr.h

diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index a4adcc6..9d00b62 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -2,7 +2,8 @@ ccflags-y = -Idrivers/gpu/host1x
 
 host1x-objs = \
syncpt.o \
-   dev.o
+   dev.o \
+   intr.o
 
 obj-$(CONFIG_TEGRA_HOST1X) += hw/
 obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index b0d630d..9255a49 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include "dev.h"
+#include "intr.h"
 #include "hw/host1x01.h"
 
 #define CREATE_TRACE_POINTS
@@ -48,6 +49,19 @@ u32 host1x_syncpt_read_byid(u32 id)
 }
 EXPORT_SYMBOL(host1x_syncpt_read_byid);
 
+int host1x_syncpt_wait_byid(u32 id, u32 thresh, long timeout, u32 *value)
+{
+   struct host1x_syncpt *sp = host1x->syncpt + id;
+   return host1x_syncpt_wait(sp, thresh, timeout, value);
+}
+EXPORT_SYMBOL(host1x_syncpt_wait_byid);
+
+static void host1x_free_resources(struct host1x *host)
+{
+   kfree(host->intr.syncpt);
+   host->intr.syncpt = 0;
+}
+
 void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
 {
void __iomem *sync_regs = host1x->regs + host1x->info.sync_offset;
@@ -62,6 +76,21 @@ u32 host1x_sync_readl(struct host1x *host1x, u32 r)
return readl(sync_regs + r);
 }
 
+static int host1x_alloc_resources(struct host1x *host)
+{
+   host->intr.syncpt = devm_kzalloc(&host->dev->dev,
+   sizeof(struct host1x_intr_syncpt) *
+   host->info.nb_pts,
+   GFP_KERNEL);
+
+   if (!host->intr.syncpt) {
+   /* frees happen in the support removal phase */
+   return -ENOMEM;
+   }
+
+   return 0;
+}
+
 static struct host1x_device_info host1x_info = {
.nb_channels= 8,
.nb_pts = 32,
@@ -118,6 +147,12 @@ static int host1x_probe(struct platform_device *dev)
goto fail;
}
 
+   err = host1x_alloc_resources(host);
+   if (err) {
+   dev_err(&dev->dev, "failed to init chip support\n");
+   goto fail;
+   }
+
if (host->info.init) {
err = host->info.init(host);
if (err)
@@ -132,6 +167,10 @@ static int host1x_probe(struct platform_device *dev)
if (!host->nop_sp)
goto fail;
 
+   err = host1x_intr_init(&host->intr, syncpt_irq);
+   if (err)
+   goto fail;
+
host->clk = devm_clk_get(&dev->dev, NULL);
if (IS_ERR(host->clk)) {
dev_err(&dev->dev, "failed to get clock\n");
@@ -145,6 +184,8 @@ static int host1x_probe(struct platform_device *dev)
 
host1x_syncpt_reset(host);
 
+   host1x_intr_start(&host->intr, clk_get_rate(host->clk));
+
host1x = host;
 
dev_info(&dev->dev, "initialized\n");
@@ -153,6 +194,7 @@ static int host1x_probe(struct platform_device *dev)
 
 fail:
host1x_syncpt_free(host->nop_sp);
+   host1x_free_resources(host);
kfree(host);
return err;
 }
@@ -160,8 +202,10 @@ fail:
 static int __exit host1x_remove(struct platform_device *dev)
 {
struct host1x *host = platform_get_drvdata(dev);
+   host1x_intr_deinit(&host->intr);
host1x_syncpt_deinit(host);
clk_disable_unprepare(host->clk);
+   host1x_free_resources(host);
return 0;
 }
 
diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h
index 8245e24..a1622bb 100644
--- a/drivers/gpu/host1x/dev.h
+++ b/drivers/gpu/host1x/dev.h
@@ -20,6 +20,7 @@
 #include 
 
 #include "syncpt.h"
+#include "intr.h"
 
 struct host1x;
 struct host1x_syncpt;
@@ -36,6 +37,18 @@ struct host1x_syncpt_ops {
const char * (*name)(struct host1x_syncpt *);
 };
 
+struct host1x_intr_ops {
+   void (*init_host_sync)(struct host1x_intr *);
+   void (*set_host_clocks_per_usec)(
+   struct host1x_intr *, u32 clocks