diff options
-rw-r--r-- | drivers/staging/imx-drm/TODO | 1 | ||||
-rw-r--r-- | drivers/staging/imx-drm/ipu-v3/ipu-common.c | 66 | ||||
-rw-r--r-- | drivers/staging/imx-drm/ipu-v3/ipu-prv.h | 2 |
3 files changed, 44 insertions, 25 deletions
diff --git a/drivers/staging/imx-drm/TODO b/drivers/staging/imx-drm/TODO index 123acbe9b379..f80641528f75 100644 --- a/drivers/staging/imx-drm/TODO +++ b/drivers/staging/imx-drm/TODO | |||
@@ -6,7 +6,6 @@ TODO: | |||
6 | - Factor out more code to common helper functions | 6 | - Factor out more code to common helper functions |
7 | - decide where to put the base driver. It is not specific to a subsystem | 7 | - decide where to put the base driver. It is not specific to a subsystem |
8 | and would be used by DRM/KMS and media/V4L2 | 8 | and would be used by DRM/KMS and media/V4L2 |
9 | - convert irq driver to irq_domain_add_linear | ||
10 | 9 | ||
11 | Missing features (not necessarily for moving out of staging): | 10 | Missing features (not necessarily for moving out of staging): |
12 | 11 | ||
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c index 0127601c26c7..1a7b59e31278 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/list.h> | 27 | #include <linux/list.h> |
28 | #include <linux/irq.h> | 28 | #include <linux/irq.h> |
29 | #include <linux/irqchip/chained_irq.h> | 29 | #include <linux/irqchip/chained_irq.h> |
30 | #include <linux/irqdomain.h> | ||
30 | #include <linux/of_device.h> | 31 | #include <linux/of_device.h> |
31 | 32 | ||
32 | #include "imx-ipu-v3.h" | 33 | #include "imx-ipu-v3.h" |
@@ -799,16 +800,18 @@ err_di_0: | |||
799 | static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs) | 800 | static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs) |
800 | { | 801 | { |
801 | unsigned long status; | 802 | unsigned long status; |
802 | int i, bit, irq_base; | 803 | int i, bit, irq; |
803 | 804 | ||
804 | for (i = 0; i < num_regs; i++) { | 805 | for (i = 0; i < num_regs; i++) { |
805 | 806 | ||
806 | status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i])); | 807 | status = ipu_cm_read(ipu, IPU_INT_STAT(regs[i])); |
807 | status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i])); | 808 | status &= ipu_cm_read(ipu, IPU_INT_CTRL(regs[i])); |
808 | 809 | ||
809 | irq_base = ipu->irq_start + regs[i] * 32; | 810 | for_each_set_bit(bit, &status, 32) { |
810 | for_each_set_bit(bit, &status, 32) | 811 | irq = irq_linear_revmap(ipu->domain, regs[i] * 32 + bit); |
811 | generic_handle_irq(irq_base + bit); | 812 | if (irq) |
813 | generic_handle_irq(irq); | ||
814 | } | ||
812 | } | 815 | } |
813 | } | 816 | } |
814 | 817 | ||
@@ -841,7 +844,7 @@ static void ipu_err_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
841 | static void ipu_ack_irq(struct irq_data *d) | 844 | static void ipu_ack_irq(struct irq_data *d) |
842 | { | 845 | { |
843 | struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); | 846 | struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); |
844 | unsigned int irq = d->irq - ipu->irq_start; | 847 | irq_hw_number_t irq = d->hwirq; |
845 | 848 | ||
846 | ipu_cm_write(ipu, 1 << (irq % 32), IPU_INT_STAT(irq / 32)); | 849 | ipu_cm_write(ipu, 1 << (irq % 32), IPU_INT_STAT(irq / 32)); |
847 | } | 850 | } |
@@ -849,7 +852,7 @@ static void ipu_ack_irq(struct irq_data *d) | |||
849 | static void ipu_unmask_irq(struct irq_data *d) | 852 | static void ipu_unmask_irq(struct irq_data *d) |
850 | { | 853 | { |
851 | struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); | 854 | struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); |
852 | unsigned int irq = d->irq - ipu->irq_start; | 855 | irq_hw_number_t irq = d->hwirq; |
853 | unsigned long flags; | 856 | unsigned long flags; |
854 | u32 reg; | 857 | u32 reg; |
855 | 858 | ||
@@ -865,7 +868,7 @@ static void ipu_unmask_irq(struct irq_data *d) | |||
865 | static void ipu_mask_irq(struct irq_data *d) | 868 | static void ipu_mask_irq(struct irq_data *d) |
866 | { | 869 | { |
867 | struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); | 870 | struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); |
868 | unsigned int irq = d->irq - ipu->irq_start; | 871 | irq_hw_number_t irq = d->hwirq; |
869 | unsigned long flags; | 872 | unsigned long flags; |
870 | u32 reg; | 873 | u32 reg; |
871 | 874 | ||
@@ -888,7 +891,12 @@ static struct irq_chip ipu_irq_chip = { | |||
888 | int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel, | 891 | int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel, |
889 | enum ipu_channel_irq irq_type) | 892 | enum ipu_channel_irq irq_type) |
890 | { | 893 | { |
891 | return ipu->irq_start + irq_type + channel->num; | 894 | int irq = irq_linear_revmap(ipu->domain, irq_type + channel->num); |
895 | |||
896 | if (!irq) | ||
897 | irq = irq_create_mapping(ipu->domain, irq_type + channel->num); | ||
898 | |||
899 | return irq; | ||
892 | } | 900 | } |
893 | EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq); | 901 | EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq); |
894 | 902 | ||
@@ -975,18 +983,30 @@ err_register: | |||
975 | return ret; | 983 | return ret; |
976 | } | 984 | } |
977 | 985 | ||
978 | static int ipu_irq_init(struct ipu_soc *ipu) | 986 | static int ipu_irq_map(struct irq_domain *h, unsigned int irq, |
987 | irq_hw_number_t hw) | ||
979 | { | 988 | { |
980 | int i; | 989 | struct ipu_soc *ipu = h->host_data; |
990 | |||
991 | irq_set_chip_and_handler(irq, &ipu_irq_chip, handle_level_irq); | ||
992 | set_irq_flags(irq, IRQF_VALID); | ||
993 | irq_set_chip_data(irq, ipu); | ||
994 | |||
995 | return 0; | ||
996 | } | ||
981 | 997 | ||
982 | ipu->irq_start = irq_alloc_descs(-1, 0, IPU_NUM_IRQS, 0); | 998 | const struct irq_domain_ops ipu_irq_domain_ops = { |
983 | if (ipu->irq_start < 0) | 999 | .map = ipu_irq_map, |
984 | return ipu->irq_start; | 1000 | .xlate = irq_domain_xlate_onecell, |
1001 | }; | ||
985 | 1002 | ||
986 | for (i = ipu->irq_start; i < ipu->irq_start + IPU_NUM_IRQS; i++) { | 1003 | static int ipu_irq_init(struct ipu_soc *ipu) |
987 | irq_set_chip_and_handler(i, &ipu_irq_chip, handle_level_irq); | 1004 | { |
988 | set_irq_flags(i, IRQF_VALID); | 1005 | ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS, |
989 | irq_set_chip_data(i, ipu); | 1006 | &ipu_irq_domain_ops, ipu); |
1007 | if (!ipu->domain) { | ||
1008 | dev_err(ipu->dev, "failed to add irq domain\n"); | ||
1009 | return -ENODEV; | ||
990 | } | 1010 | } |
991 | 1011 | ||
992 | irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler); | 1012 | irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler); |
@@ -999,20 +1019,20 @@ static int ipu_irq_init(struct ipu_soc *ipu) | |||
999 | 1019 | ||
1000 | static void ipu_irq_exit(struct ipu_soc *ipu) | 1020 | static void ipu_irq_exit(struct ipu_soc *ipu) |
1001 | { | 1021 | { |
1002 | int i; | 1022 | int i, irq; |
1003 | 1023 | ||
1004 | irq_set_chained_handler(ipu->irq_err, NULL); | 1024 | irq_set_chained_handler(ipu->irq_err, NULL); |
1005 | irq_set_handler_data(ipu->irq_err, NULL); | 1025 | irq_set_handler_data(ipu->irq_err, NULL); |
1006 | irq_set_chained_handler(ipu->irq_sync, NULL); | 1026 | irq_set_chained_handler(ipu->irq_sync, NULL); |
1007 | irq_set_handler_data(ipu->irq_sync, NULL); | 1027 | irq_set_handler_data(ipu->irq_sync, NULL); |
1008 | 1028 | ||
1009 | for (i = ipu->irq_start; i < ipu->irq_start + IPU_NUM_IRQS; i++) { | 1029 | for (i = 0; i < IPU_NUM_IRQS; i++) { |
1010 | set_irq_flags(i, 0); | 1030 | irq = irq_linear_revmap(ipu->domain, i); |
1011 | irq_set_chip(i, NULL); | 1031 | if (irq) |
1012 | irq_set_chip_data(i, NULL); | 1032 | irq_dispose_mapping(irq); |
1013 | } | 1033 | } |
1014 | 1034 | ||
1015 | irq_free_descs(ipu->irq_start, IPU_NUM_IRQS); | 1035 | irq_domain_remove(ipu->domain); |
1016 | } | 1036 | } |
1017 | 1037 | ||
1018 | static int ipu_probe(struct platform_device *pdev) | 1038 | static int ipu_probe(struct platform_device *pdev) |
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-prv.h b/drivers/staging/imx-drm/ipu-v3/ipu-prv.h index 12d7eafa65fe..4df00501adc2 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-prv.h +++ b/drivers/staging/imx-drm/ipu-v3/ipu-prv.h | |||
@@ -170,9 +170,9 @@ struct ipu_soc { | |||
170 | 170 | ||
171 | struct ipuv3_channel channel[64]; | 171 | struct ipuv3_channel channel[64]; |
172 | 172 | ||
173 | int irq_start; | ||
174 | int irq_sync; | 173 | int irq_sync; |
175 | int irq_err; | 174 | int irq_err; |
175 | struct irq_domain *domain; | ||
176 | 176 | ||
177 | struct ipu_dc_priv *dc_priv; | 177 | struct ipu_dc_priv *dc_priv; |
178 | struct ipu_dp_priv *dp_priv; | 178 | struct ipu_dp_priv *dp_priv; |