[PATCHv3 2/7] gpu: host1x: Add syncpoint wait and interrupts
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
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