aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/imx-drm/TODO1
-rw-r--r--drivers/staging/imx-drm/ipu-v3/ipu-common.c66
-rw-r--r--drivers/staging/imx-drm/ipu-v3/ipu-prv.h2
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
11Missing features (not necessarily for moving out of staging): 10Missing 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:
799static void ipu_irq_handle(struct ipu_soc *ipu, const int *regs, int num_regs) 800static 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)
841static void ipu_ack_irq(struct irq_data *d) 844static 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)
849static void ipu_unmask_irq(struct irq_data *d) 852static 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)
865static void ipu_mask_irq(struct irq_data *d) 868static 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 = {
888int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel, 891int 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}
893EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq); 901EXPORT_SYMBOL_GPL(ipu_idmac_channel_irq);
894 902
@@ -975,18 +983,30 @@ err_register:
975 return ret; 983 return ret;
976} 984}
977 985
978static int ipu_irq_init(struct ipu_soc *ipu) 986static 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); 998const 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++) { 1003static 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
1000static void ipu_irq_exit(struct ipu_soc *ipu) 1020static 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
1018static int ipu_probe(struct platform_device *pdev) 1038static 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;