diff options
-rw-r--r-- | drivers/staging/imx-drm/ipu-v3/ipu-common.c | 90 |
1 files changed, 26 insertions, 64 deletions
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c index 1a7b59e31278..7135b2d1790d 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c | |||
@@ -841,53 +841,6 @@ static void ipu_err_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
841 | chained_irq_exit(chip, desc); | 841 | chained_irq_exit(chip, desc); |
842 | } | 842 | } |
843 | 843 | ||
844 | static void ipu_ack_irq(struct irq_data *d) | ||
845 | { | ||
846 | struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); | ||
847 | irq_hw_number_t irq = d->hwirq; | ||
848 | |||
849 | ipu_cm_write(ipu, 1 << (irq % 32), IPU_INT_STAT(irq / 32)); | ||
850 | } | ||
851 | |||
852 | static void ipu_unmask_irq(struct irq_data *d) | ||
853 | { | ||
854 | struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); | ||
855 | irq_hw_number_t irq = d->hwirq; | ||
856 | unsigned long flags; | ||
857 | u32 reg; | ||
858 | |||
859 | spin_lock_irqsave(&ipu->lock, flags); | ||
860 | |||
861 | reg = ipu_cm_read(ipu, IPU_INT_CTRL(irq / 32)); | ||
862 | reg |= 1 << (irq % 32); | ||
863 | ipu_cm_write(ipu, reg, IPU_INT_CTRL(irq / 32)); | ||
864 | |||
865 | spin_unlock_irqrestore(&ipu->lock, flags); | ||
866 | } | ||
867 | |||
868 | static void ipu_mask_irq(struct irq_data *d) | ||
869 | { | ||
870 | struct ipu_soc *ipu = irq_data_get_irq_chip_data(d); | ||
871 | irq_hw_number_t irq = d->hwirq; | ||
872 | unsigned long flags; | ||
873 | u32 reg; | ||
874 | |||
875 | spin_lock_irqsave(&ipu->lock, flags); | ||
876 | |||
877 | reg = ipu_cm_read(ipu, IPU_INT_CTRL(irq / 32)); | ||
878 | reg &= ~(1 << (irq % 32)); | ||
879 | ipu_cm_write(ipu, reg, IPU_INT_CTRL(irq / 32)); | ||
880 | |||
881 | spin_unlock_irqrestore(&ipu->lock, flags); | ||
882 | } | ||
883 | |||
884 | static struct irq_chip ipu_irq_chip = { | ||
885 | .name = "IPU", | ||
886 | .irq_ack = ipu_ack_irq, | ||
887 | .irq_mask = ipu_mask_irq, | ||
888 | .irq_unmask = ipu_unmask_irq, | ||
889 | }; | ||
890 | |||
891 | int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel, | 844 | int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel, |
892 | enum ipu_channel_irq irq_type) | 845 | enum ipu_channel_irq irq_type) |
893 | { | 846 | { |
@@ -983,32 +936,39 @@ err_register: | |||
983 | return ret; | 936 | return ret; |
984 | } | 937 | } |
985 | 938 | ||
986 | static int ipu_irq_map(struct irq_domain *h, unsigned int irq, | ||
987 | irq_hw_number_t hw) | ||
988 | { | ||
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 | } | ||
997 | |||
998 | const struct irq_domain_ops ipu_irq_domain_ops = { | ||
999 | .map = ipu_irq_map, | ||
1000 | .xlate = irq_domain_xlate_onecell, | ||
1001 | }; | ||
1002 | 939 | ||
1003 | static int ipu_irq_init(struct ipu_soc *ipu) | 940 | static int ipu_irq_init(struct ipu_soc *ipu) |
1004 | { | 941 | { |
942 | struct irq_chip_generic *gc; | ||
943 | struct irq_chip_type *ct; | ||
944 | int ret, i; | ||
945 | |||
1005 | ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS, | 946 | ipu->domain = irq_domain_add_linear(ipu->dev->of_node, IPU_NUM_IRQS, |
1006 | &ipu_irq_domain_ops, ipu); | 947 | &irq_generic_chip_ops, ipu); |
1007 | if (!ipu->domain) { | 948 | if (!ipu->domain) { |
1008 | dev_err(ipu->dev, "failed to add irq domain\n"); | 949 | dev_err(ipu->dev, "failed to add irq domain\n"); |
1009 | return -ENODEV; | 950 | return -ENODEV; |
1010 | } | 951 | } |
1011 | 952 | ||
953 | ret = irq_alloc_domain_generic_chips(ipu->domain, 32, 1, "IPU", | ||
954 | handle_level_irq, 0, IRQF_VALID, 0); | ||
955 | if (ret < 0) { | ||
956 | dev_err(ipu->dev, "failed to alloc generic irq chips\n"); | ||
957 | irq_domain_remove(ipu->domain); | ||
958 | return ret; | ||
959 | } | ||
960 | |||
961 | for (i = 0; i < IPU_NUM_IRQS; i += 32) { | ||
962 | gc = irq_get_domain_generic_chip(ipu->domain, i); | ||
963 | gc->reg_base = ipu->cm_reg; | ||
964 | ct = gc->chip_types; | ||
965 | ct->chip.irq_ack = irq_gc_ack_set_bit; | ||
966 | ct->chip.irq_mask = irq_gc_mask_clr_bit; | ||
967 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | ||
968 | ct->regs.ack = IPU_INT_STAT(i / 32); | ||
969 | ct->regs.mask = IPU_INT_CTRL(i / 32); | ||
970 | } | ||
971 | |||
1012 | irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler); | 972 | irq_set_chained_handler(ipu->irq_sync, ipu_irq_handler); |
1013 | irq_set_handler_data(ipu->irq_sync, ipu); | 973 | irq_set_handler_data(ipu->irq_sync, ipu); |
1014 | irq_set_chained_handler(ipu->irq_err, ipu_err_irq_handler); | 974 | irq_set_chained_handler(ipu->irq_err, ipu_err_irq_handler); |
@@ -1026,6 +986,8 @@ static void ipu_irq_exit(struct ipu_soc *ipu) | |||
1026 | irq_set_chained_handler(ipu->irq_sync, NULL); | 986 | irq_set_chained_handler(ipu->irq_sync, NULL); |
1027 | irq_set_handler_data(ipu->irq_sync, NULL); | 987 | irq_set_handler_data(ipu->irq_sync, NULL); |
1028 | 988 | ||
989 | /* TODO: remove irq_domain_generic_chips */ | ||
990 | |||
1029 | for (i = 0; i < IPU_NUM_IRQS; i++) { | 991 | for (i = 0; i < IPU_NUM_IRQS; i++) { |
1030 | irq = irq_linear_revmap(ipu->domain, i); | 992 | irq = irq_linear_revmap(ipu->domain, i); |
1031 | if (irq) | 993 | if (irq) |