[PATCHv6 2/9] 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: Arto Merilainen Signed-off-by: Terje Bergstrom --- drivers/gpu/host1x/Makefile |1 + drivers/gpu/host1x/dev.c | 12 ++ drivers/gpu/host1x/dev.h | 51 + drivers/gpu/host1x/hw/host1x01.c |2 + drivers/gpu/host1x/hw/hw_host1x01_sync.h | 42 drivers/gpu/host1x/hw/intr_hw.c | 143 + drivers/gpu/host1x/intr.c| 328 ++ drivers/gpu/host1x/intr.h| 96 + drivers/gpu/host1x/syncpt.c | 159 +++ drivers/gpu/host1x/syncpt.h | 14 +- 10 files changed, 847 insertions(+), 1 deletion(-) 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 363e6ab..5ef47ff 100644 --- a/drivers/gpu/host1x/Makefile +++ b/drivers/gpu/host1x/Makefile @@ -3,6 +3,7 @@ ccflags-y = -Idrivers/gpu/host1x host1x-y = \ syncpt.o \ dev.o \ + intr.o \ hw/host1x01.o obj-$(CONFIG_TEGRA_HOST1X) += host1x.o diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index d95a9b2..4421e28 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -28,6 +28,7 @@ #include #include "dev.h" +#include "intr.h" #include "hw/host1x01.h" void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r) @@ -127,12 +128,23 @@ static int host1x_probe(struct platform_device *pdev) return err; } + err = host1x_intr_init(host, syncpt_irq); + if (err) { + dev_err(dev, "failed to init irq"); + goto fail_deinit_syncpt; + } + return 0; + +fail_deinit_syncpt: + host1x_syncpt_deinit(host); + return err; } static int __exit host1x_remove(struct platform_device *pdev) { struct host1x *host = platform_get_drvdata(pdev); + host1x_intr_deinit(host); host1x_syncpt_deinit(host); clk_disable_unprepare(host->clk); return 0; diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index 750daa3..fb5f842 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -21,6 +21,7 @@ #include #include "syncpt.h" +#include "intr.h" struct host1x_syncpt; @@ -33,6 +34,17 @@ struct host1x_syncpt_ops { int (*patch_wait)(struct host1x_syncpt *syncpt, void *patch_addr); }; +struct host1x_intr_ops { + int (*init_host_sync)(struct host1x *host, u32 cpm, + void (*syncpt_thresh_work)(struct work_struct *work)); + void (*set_syncpt_threshold)( + struct host1x *host, u32 id, u32 thresh); + void (*enable_syncpt_intr)(struct host1x *host, u32 id); + void (*disable_syncpt_intr)(struct host1x *host, u32 id); + void (*disable_all_syncpt_intrs)(struct host1x *host); + int (*free_syncpt_irq)(struct host1x *host); +}; + struct host1x_info { int nb_channels;/* host1x: num channels supported */ int nb_pts; /* host1x: num syncpoints supported */ @@ -50,7 +62,13 @@ struct host1x { struct device *dev; struct clk *clk; + struct mutex intr_mutex; + struct workqueue_struct *intr_wq; + int intr_syncpt_irq; + const struct host1x_syncpt_ops *syncpt_op; + const struct host1x_intr_ops *intr_op; + }; static inline struct host1x *host1x_get_host(struct device *dev) @@ -101,4 +119,37 @@ static inline int host1x_hw_syncpt_patch_wait(struct host1x *host, return host->syncpt_op->patch_wait(sp, patch_addr); } +static inline int host1x_hw_intr_init_host_sync(struct host1x *host, u32 cpm, + void (*syncpt_thresh_work)(struct work_struct *)) +{ + return host->intr_op->init_host_sync(host, cpm, syncpt_thresh_work); +} + +static inline void host1x_hw_intr_set_syncpt_threshold(struct host1x *host, + u32 id, u32 thresh) +{ + host->intr_op->set_syncpt_threshold(host, id, thresh); +} + +static inline void host1x_hw_intr_enable_syncpt_intr(struct host1x *host, +u32 id) +{ + host->intr_op->enable_syncpt_intr(host, id); +} + +static inline void host1x_hw_intr_disable_syncpt_intr(struct host1x *host, + u32 id) +{ + host->intr_op->disable_syncpt_intr(host, id); +} + +static inline void host1x_hw_intr_disable_all_syncpt_intrs(struct host1x *host) +{ + host->intr_op->disable_all_syncpt_intrs(host); +} + +static inline int host1x_hw_intr_free_syncpt_irq(struct host1x *host) +{ + return host->intr_op->free_syncpt_irq(host); +} #endif diff --git a/
[PATCHv6 2/9] 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: Arto Merilainen Signed-off-by: Terje Bergstrom --- drivers/gpu/host1x/Makefile |1 + drivers/gpu/host1x/dev.c | 12 ++ drivers/gpu/host1x/dev.h | 51 + drivers/gpu/host1x/hw/host1x01.c |2 + drivers/gpu/host1x/hw/hw_host1x01_sync.h | 42 drivers/gpu/host1x/hw/intr_hw.c | 143 + drivers/gpu/host1x/intr.c| 328 ++ drivers/gpu/host1x/intr.h| 96 + drivers/gpu/host1x/syncpt.c | 159 +++ drivers/gpu/host1x/syncpt.h | 14 +- 10 files changed, 847 insertions(+), 1 deletion(-) 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 363e6ab..5ef47ff 100644 --- a/drivers/gpu/host1x/Makefile +++ b/drivers/gpu/host1x/Makefile @@ -3,6 +3,7 @@ ccflags-y = -Idrivers/gpu/host1x host1x-y = \ syncpt.o \ dev.o \ + intr.o \ hw/host1x01.o obj-$(CONFIG_TEGRA_HOST1X) += host1x.o diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index d95a9b2..4421e28 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -28,6 +28,7 @@ #include #include "dev.h" +#include "intr.h" #include "hw/host1x01.h" void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r) @@ -127,12 +128,23 @@ static int host1x_probe(struct platform_device *pdev) return err; } + err = host1x_intr_init(host, syncpt_irq); + if (err) { + dev_err(dev, "failed to init irq"); + goto fail_deinit_syncpt; + } + return 0; + +fail_deinit_syncpt: + host1x_syncpt_deinit(host); + return err; } static int __exit host1x_remove(struct platform_device *pdev) { struct host1x *host = platform_get_drvdata(pdev); + host1x_intr_deinit(host); host1x_syncpt_deinit(host); clk_disable_unprepare(host->clk); return 0; diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index 750daa3..fb5f842 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -21,6 +21,7 @@ #include #include "syncpt.h" +#include "intr.h" struct host1x_syncpt; @@ -33,6 +34,17 @@ struct host1x_syncpt_ops { int (*patch_wait)(struct host1x_syncpt *syncpt, void *patch_addr); }; +struct host1x_intr_ops { + int (*init_host_sync)(struct host1x *host, u32 cpm, + void (*syncpt_thresh_work)(struct work_struct *work)); + void (*set_syncpt_threshold)( + struct host1x *host, u32 id, u32 thresh); + void (*enable_syncpt_intr)(struct host1x *host, u32 id); + void (*disable_syncpt_intr)(struct host1x *host, u32 id); + void (*disable_all_syncpt_intrs)(struct host1x *host); + int (*free_syncpt_irq)(struct host1x *host); +}; + struct host1x_info { int nb_channels;/* host1x: num channels supported */ int nb_pts; /* host1x: num syncpoints supported */ @@ -50,7 +62,13 @@ struct host1x { struct device *dev; struct clk *clk; + struct mutex intr_mutex; + struct workqueue_struct *intr_wq; + int intr_syncpt_irq; + const struct host1x_syncpt_ops *syncpt_op; + const struct host1x_intr_ops *intr_op; + }; static inline struct host1x *host1x_get_host(struct device *dev) @@ -101,4 +119,37 @@ static inline int host1x_hw_syncpt_patch_wait(struct host1x *host, return host->syncpt_op->patch_wait(sp, patch_addr); } +static inline int host1x_hw_intr_init_host_sync(struct host1x *host, u32 cpm, + void (*syncpt_thresh_work)(struct work_struct *)) +{ + return host->intr_op->init_host_sync(host, cpm, syncpt_thresh_work); +} + +static inline void host1x_hw_intr_set_syncpt_threshold(struct host1x *host, + u32 id, u32 thresh) +{ + host->intr_op->set_syncpt_threshold(host, id, thresh); +} + +static inline void host1x_hw_intr_enable_syncpt_intr(struct host1x *host, +u32 id) +{ + host->intr_op->enable_syncpt_intr(host, id); +} + +static inline void host1x_hw_intr_disable_syncpt_intr(struct host1x *host, + u32 id) +{ + host->intr_op->disable_syncpt_intr(host, id); +} + +static inline void host1x_hw_intr_disable_all_syncpt_intrs(struct host1x *host) +{ + host->intr_op->disable_all_syncpt_intrs(host); +} + +static inline int host1x_hw_intr_free_syncpt_irq(struct host1x *host) +{ + return host->intr_op->free_syncpt_irq(host); +} #endif d