[PATCHv9 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 | 12 ++ 10 files changed, 846 insertions(+) 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 0d6002c..b967f6e 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) @@ -123,13 +124,24 @@ static int host1x_probe(struct platform_device *pdev) return err; } + err = host1x_intr_init(host, syncpt_irq); + if (err) { + dev_err(&pdev->dev, "failed to initialize interrupts\n"); + 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); diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index eaf6026..caf9cc6 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; + }; void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v); @@ -93,4 +111,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/drivers/gpu/h
[PATCHv9 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 | 12 ++ 10 files changed, 846 insertions(+) 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 0d6002c..b967f6e 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) @@ -123,13 +124,24 @@ static int host1x_probe(struct platform_device *pdev) return err; } + err = host1x_intr_init(host, syncpt_irq); + if (err) { + dev_err(&pdev->dev, "failed to initialize interrupts\n"); + 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); diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index eaf6026..caf9cc6 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; + }; void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v); @@ -93,4 +111,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