2021-05-24 04:58:34

by Maxim Kochetkov

[permalink] [raw]
Subject: [PATCH v2 1/1] regmap-irq: Introduce inverted status registers support

Some interrupt controllers have inverted status register:
cleared bits is active interrupts and set bits is inactive interrupts,
so add inverted status support to the framework.

Signed-off-by: Maxim Kochetkov <[email protected]>
---
drivers/base/regmap/regmap-irq.c | 7 +++++++
include/linux/regmap.h | 2 ++
2 files changed, 9 insertions(+)

diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 760296a4b606..0797f41153d9 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -531,6 +531,10 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
}
}

+ if (chip->status_invert)
+ for (i = 0; i < data->chip->num_regs; i++)
+ data->status_buf[i] = ~data->status_buf[i];
+
/*
* Ignore masked IRQs and ack if we need to; we ack early so
* there is no race between handling and acknowleding the
@@ -800,6 +804,9 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
goto err_alloc;
}

+ if (chip->status_invert)
+ data->status_buf[i] = ~data->status_buf[i];
+
if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) {
reg = sub_irq_reg(d, d->chip->ack_base, i);
if (chip->ack_invert)
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index bf5a834d1774..f5f08dd0a116 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -1449,6 +1449,7 @@ struct regmap_irq_sub_irq_map {
* @not_fixed_stride: Used when chip peripherals are not laid out with fixed
* stride. Must be used with sub_reg_offsets containing the
* offsets to each peripheral.
+ * @status_invert: Inverted status register: cleared bits are active interrupts.
* @runtime_pm: Hold a runtime PM lock on the device when accessing it.
*
* @num_regs: Number of registers in each control bank.
@@ -1501,6 +1502,7 @@ struct regmap_irq_chip {
bool type_in_mask:1;
bool clear_on_unmask:1;
bool not_fixed_stride:1;
+ bool status_invert:1;

int num_regs;

--
2.31.1


2021-05-24 11:36:39

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 1/1] regmap-irq: Introduce inverted status registers support

Hi Maxim,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on regmap/for-next]
[also build test ERROR on linux/master linus/master v5.13-rc3 next-20210524]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Maxim-Kochetkov/regmap-irq-Introduce-inverted-status-registers-support/20210524-125907
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git for-next
config: microblaze-randconfig-r016-20210524 (attached as .config)
compiler: microblaze-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/0592cd096312150d005b37a78a5a1fa1763561b5
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Maxim-Kochetkov/regmap-irq-Introduce-inverted-status-registers-support/20210524-125907
git checkout 0592cd096312150d005b37a78a5a1fa1763561b5
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=microblaze

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

drivers/base/regmap/regmap-irq.c: In function 'regmap_add_irq_chip_fwnode':
>> drivers/base/regmap/regmap-irq.c:808:8: error: '*data' is a pointer; did you mean to use '->'?
808 | data->status_buf[i] = ~data->status_buf[i];
| ^~
| ->
drivers/base/regmap/regmap-irq.c:808:31: error: '*data' is a pointer; did you mean to use '->'?
808 | data->status_buf[i] = ~data->status_buf[i];
| ^~
| ->


vim +808 drivers/base/regmap/regmap-irq.c

610
611 /**
612 * regmap_add_irq_chip_fwnode() - Use standard regmap IRQ controller handling
613 *
614 * @fwnode: The firmware node where the IRQ domain should be added to.
615 * @map: The regmap for the device.
616 * @irq: The IRQ the device uses to signal interrupts.
617 * @irq_flags: The IRQF_ flags to use for the primary interrupt.
618 * @irq_base: Allocate at specific IRQ number if irq_base > 0.
619 * @chip: Configuration for the interrupt controller.
620 * @data: Runtime data structure for the controller, allocated on success.
621 *
622 * Returns 0 on success or an errno on failure.
623 *
624 * In order for this to be efficient the chip really should use a
625 * register cache. The chip driver is responsible for restoring the
626 * register values used by the IRQ controller over suspend and resume.
627 */
628 int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
629 struct regmap *map, int irq,
630 int irq_flags, int irq_base,
631 const struct regmap_irq_chip *chip,
632 struct regmap_irq_chip_data **data)
633 {
634 struct regmap_irq_chip_data *d;
635 int i;
636 int ret = -ENOMEM;
637 int num_type_reg;
638 u32 reg;
639 u32 unmask_offset;
640
641 if (chip->num_regs <= 0)
642 return -EINVAL;
643
644 if (chip->clear_on_unmask && (chip->ack_base || chip->use_ack))
645 return -EINVAL;
646
647 for (i = 0; i < chip->num_irqs; i++) {
648 if (chip->irqs[i].reg_offset % map->reg_stride)
649 return -EINVAL;
650 if (chip->irqs[i].reg_offset / map->reg_stride >=
651 chip->num_regs)
652 return -EINVAL;
653 }
654
655 if (chip->not_fixed_stride) {
656 for (i = 0; i < chip->num_regs; i++)
657 if (chip->sub_reg_offsets[i].num_regs != 1)
658 return -EINVAL;
659 }
660
661 if (irq_base) {
662 irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0);
663 if (irq_base < 0) {
664 dev_warn(map->dev, "Failed to allocate IRQs: %d\n",
665 irq_base);
666 return irq_base;
667 }
668 }
669
670 d = kzalloc(sizeof(*d), GFP_KERNEL);
671 if (!d)
672 return -ENOMEM;
673
674 if (chip->num_main_regs) {
675 d->main_status_buf = kcalloc(chip->num_main_regs,
676 sizeof(unsigned int),
677 GFP_KERNEL);
678
679 if (!d->main_status_buf)
680 goto err_alloc;
681 }
682
683 d->status_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
684 GFP_KERNEL);
685 if (!d->status_buf)
686 goto err_alloc;
687
688 d->mask_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
689 GFP_KERNEL);
690 if (!d->mask_buf)
691 goto err_alloc;
692
693 d->mask_buf_def = kcalloc(chip->num_regs, sizeof(unsigned int),
694 GFP_KERNEL);
695 if (!d->mask_buf_def)
696 goto err_alloc;
697
698 if (chip->wake_base) {
699 d->wake_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
700 GFP_KERNEL);
701 if (!d->wake_buf)
702 goto err_alloc;
703 }
704
705 num_type_reg = chip->type_in_mask ? chip->num_regs : chip->num_type_reg;
706 if (num_type_reg) {
707 d->type_buf_def = kcalloc(num_type_reg,
708 sizeof(unsigned int), GFP_KERNEL);
709 if (!d->type_buf_def)
710 goto err_alloc;
711
712 d->type_buf = kcalloc(num_type_reg, sizeof(unsigned int),
713 GFP_KERNEL);
714 if (!d->type_buf)
715 goto err_alloc;
716 }
717
718 if (chip->num_virt_regs) {
719 /*
720 * Create virt_buf[chip->num_extra_config_regs][chip->num_regs]
721 */
722 d->virt_buf = kcalloc(chip->num_virt_regs, sizeof(*d->virt_buf),
723 GFP_KERNEL);
724 if (!d->virt_buf)
725 goto err_alloc;
726
727 for (i = 0; i < chip->num_virt_regs; i++) {
728 d->virt_buf[i] = kcalloc(chip->num_regs,
729 sizeof(unsigned int),
730 GFP_KERNEL);
731 if (!d->virt_buf[i])
732 goto err_alloc;
733 }
734 }
735
736 d->irq_chip = regmap_irq_chip;
737 d->irq_chip.name = chip->name;
738 d->irq = irq;
739 d->map = map;
740 d->chip = chip;
741 d->irq_base = irq_base;
742
743 if (chip->irq_reg_stride)
744 d->irq_reg_stride = chip->irq_reg_stride;
745 else
746 d->irq_reg_stride = 1;
747
748 if (chip->type_reg_stride)
749 d->type_reg_stride = chip->type_reg_stride;
750 else
751 d->type_reg_stride = 1;
752
753 if (!map->use_single_read && map->reg_stride == 1 &&
754 d->irq_reg_stride == 1) {
755 d->status_reg_buf = kmalloc_array(chip->num_regs,
756 map->format.val_bytes,
757 GFP_KERNEL);
758 if (!d->status_reg_buf)
759 goto err_alloc;
760 }
761
762 mutex_init(&d->lock);
763
764 for (i = 0; i < chip->num_irqs; i++)
765 d->mask_buf_def[chip->irqs[i].reg_offset / map->reg_stride]
766 |= chip->irqs[i].mask;
767
768 /* Mask all the interrupts by default */
769 for (i = 0; i < chip->num_regs; i++) {
770 d->mask_buf[i] = d->mask_buf_def[i];
771 if (!chip->mask_base)
772 continue;
773
774 reg = sub_irq_reg(d, d->chip->mask_base, i);
775
776 if (chip->mask_invert)
777 ret = regmap_irq_update_bits(d, reg,
778 d->mask_buf[i], ~d->mask_buf[i]);
779 else if (d->chip->unmask_base) {
780 unmask_offset = d->chip->unmask_base -
781 d->chip->mask_base;
782 ret = regmap_irq_update_bits(d,
783 reg + unmask_offset,
784 d->mask_buf[i],
785 d->mask_buf[i]);
786 } else
787 ret = regmap_irq_update_bits(d, reg,
788 d->mask_buf[i], d->mask_buf[i]);
789 if (ret != 0) {
790 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
791 reg, ret);
792 goto err_alloc;
793 }
794
795 if (!chip->init_ack_masked)
796 continue;
797
798 /* Ack masked but set interrupts */
799 reg = sub_irq_reg(d, d->chip->status_base, i);
800 ret = regmap_read(map, reg, &d->status_buf[i]);
801 if (ret != 0) {
802 dev_err(map->dev, "Failed to read IRQ status: %d\n",
803 ret);
804 goto err_alloc;
805 }
806
807 if (chip->status_invert)
> 808 data->status_buf[i] = ~data->status_buf[i];
809
810 if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) {
811 reg = sub_irq_reg(d, d->chip->ack_base, i);
812 if (chip->ack_invert)
813 ret = regmap_write(map, reg,
814 ~(d->status_buf[i] & d->mask_buf[i]));
815 else
816 ret = regmap_write(map, reg,
817 d->status_buf[i] & d->mask_buf[i]);
818 if (chip->clear_ack) {
819 if (chip->ack_invert && !ret)
820 ret = regmap_write(map, reg,
821 (d->status_buf[i] &
822 d->mask_buf[i]));
823 else if (!ret)
824 ret = regmap_write(map, reg,
825 ~(d->status_buf[i] &
826 d->mask_buf[i]));
827 }
828 if (ret != 0) {
829 dev_err(map->dev, "Failed to ack 0x%x: %d\n",
830 reg, ret);
831 goto err_alloc;
832 }
833 }
834 }
835
836 /* Wake is disabled by default */
837 if (d->wake_buf) {
838 for (i = 0; i < chip->num_regs; i++) {
839 d->wake_buf[i] = d->mask_buf_def[i];
840 reg = sub_irq_reg(d, d->chip->wake_base, i);
841
842 if (chip->wake_invert)
843 ret = regmap_irq_update_bits(d, reg,
844 d->mask_buf_def[i],
845 0);
846 else
847 ret = regmap_irq_update_bits(d, reg,
848 d->mask_buf_def[i],
849 d->wake_buf[i]);
850 if (ret != 0) {
851 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
852 reg, ret);
853 goto err_alloc;
854 }
855 }
856 }
857
858 if (chip->num_type_reg && !chip->type_in_mask) {
859 for (i = 0; i < chip->num_type_reg; ++i) {
860 reg = sub_irq_reg(d, d->chip->type_base, i);
861
862 ret = regmap_read(map, reg, &d->type_buf_def[i]);
863
864 if (d->chip->type_invert)
865 d->type_buf_def[i] = ~d->type_buf_def[i];
866
867 if (ret) {
868 dev_err(map->dev, "Failed to get type defaults at 0x%x: %d\n",
869 reg, ret);
870 goto err_alloc;
871 }
872 }
873 }
874
875 if (irq_base)
876 d->domain = irq_domain_create_legacy(fwnode, chip->num_irqs,
877 irq_base, 0,
878 &regmap_domain_ops, d);
879 else
880 d->domain = irq_domain_create_linear(fwnode, chip->num_irqs,
881 &regmap_domain_ops, d);
882 if (!d->domain) {
883 dev_err(map->dev, "Failed to create IRQ domain\n");
884 ret = -ENOMEM;
885 goto err_alloc;
886 }
887
888 ret = request_threaded_irq(irq, NULL, regmap_irq_thread,
889 irq_flags | IRQF_ONESHOT,
890 chip->name, d);
891 if (ret != 0) {
892 dev_err(map->dev, "Failed to request IRQ %d for %s: %d\n",
893 irq, chip->name, ret);
894 goto err_domain;
895 }
896
897 *data = d;
898
899 return 0;
900
901 err_domain:
902 /* Should really dispose of the domain but... */
903 err_alloc:
904 kfree(d->type_buf);
905 kfree(d->type_buf_def);
906 kfree(d->wake_buf);
907 kfree(d->mask_buf_def);
908 kfree(d->mask_buf);
909 kfree(d->status_buf);
910 kfree(d->status_reg_buf);
911 if (d->virt_buf) {
912 for (i = 0; i < chip->num_virt_regs; i++)
913 kfree(d->virt_buf[i]);
914 kfree(d->virt_buf);
915 }
916 kfree(d);
917 return ret;
918 }
919 EXPORT_SYMBOL_GPL(regmap_add_irq_chip_fwnode);
920

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (12.23 kB)
.config.gz (21.02 kB)
Download all attachments

2021-05-24 14:36:27

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 1/1] regmap-irq: Introduce inverted status registers support

Hi Maxim,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on regmap/for-next]
[also build test ERROR on linux/master linus/master v5.13-rc3 next-20210524]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Maxim-Kochetkov/regmap-irq-Introduce-inverted-status-registers-support/20210524-125907
base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git for-next
config: x86_64-randconfig-a013-20210524 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 93d1e5822ed64abd777eb94ea9899e96c4c39fbe)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install x86_64 cross compiling tool for clang build
# apt-get install binutils-x86-64-linux-gnu
# https://github.com/0day-ci/linux/commit/0592cd096312150d005b37a78a5a1fa1763561b5
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Maxim-Kochetkov/regmap-irq-Introduce-inverted-status-registers-support/20210524-125907
git checkout 0592cd096312150d005b37a78a5a1fa1763561b5
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

>> drivers/base/regmap/regmap-irq.c:808:8: error: member reference base type 'struct regmap_irq_chip_data *' is not a structure or union
data->status_buf[i] = ~data->status_buf[i];
~~~~^ ~~~~~~~~~~
drivers/base/regmap/regmap-irq.c:808:31: error: member reference base type 'struct regmap_irq_chip_data *' is not a structure or union
data->status_buf[i] = ~data->status_buf[i];
~~~~^ ~~~~~~~~~~
2 errors generated.


vim +808 drivers/base/regmap/regmap-irq.c

610
611 /**
612 * regmap_add_irq_chip_fwnode() - Use standard regmap IRQ controller handling
613 *
614 * @fwnode: The firmware node where the IRQ domain should be added to.
615 * @map: The regmap for the device.
616 * @irq: The IRQ the device uses to signal interrupts.
617 * @irq_flags: The IRQF_ flags to use for the primary interrupt.
618 * @irq_base: Allocate at specific IRQ number if irq_base > 0.
619 * @chip: Configuration for the interrupt controller.
620 * @data: Runtime data structure for the controller, allocated on success.
621 *
622 * Returns 0 on success or an errno on failure.
623 *
624 * In order for this to be efficient the chip really should use a
625 * register cache. The chip driver is responsible for restoring the
626 * register values used by the IRQ controller over suspend and resume.
627 */
628 int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
629 struct regmap *map, int irq,
630 int irq_flags, int irq_base,
631 const struct regmap_irq_chip *chip,
632 struct regmap_irq_chip_data **data)
633 {
634 struct regmap_irq_chip_data *d;
635 int i;
636 int ret = -ENOMEM;
637 int num_type_reg;
638 u32 reg;
639 u32 unmask_offset;
640
641 if (chip->num_regs <= 0)
642 return -EINVAL;
643
644 if (chip->clear_on_unmask && (chip->ack_base || chip->use_ack))
645 return -EINVAL;
646
647 for (i = 0; i < chip->num_irqs; i++) {
648 if (chip->irqs[i].reg_offset % map->reg_stride)
649 return -EINVAL;
650 if (chip->irqs[i].reg_offset / map->reg_stride >=
651 chip->num_regs)
652 return -EINVAL;
653 }
654
655 if (chip->not_fixed_stride) {
656 for (i = 0; i < chip->num_regs; i++)
657 if (chip->sub_reg_offsets[i].num_regs != 1)
658 return -EINVAL;
659 }
660
661 if (irq_base) {
662 irq_base = irq_alloc_descs(irq_base, 0, chip->num_irqs, 0);
663 if (irq_base < 0) {
664 dev_warn(map->dev, "Failed to allocate IRQs: %d\n",
665 irq_base);
666 return irq_base;
667 }
668 }
669
670 d = kzalloc(sizeof(*d), GFP_KERNEL);
671 if (!d)
672 return -ENOMEM;
673
674 if (chip->num_main_regs) {
675 d->main_status_buf = kcalloc(chip->num_main_regs,
676 sizeof(unsigned int),
677 GFP_KERNEL);
678
679 if (!d->main_status_buf)
680 goto err_alloc;
681 }
682
683 d->status_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
684 GFP_KERNEL);
685 if (!d->status_buf)
686 goto err_alloc;
687
688 d->mask_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
689 GFP_KERNEL);
690 if (!d->mask_buf)
691 goto err_alloc;
692
693 d->mask_buf_def = kcalloc(chip->num_regs, sizeof(unsigned int),
694 GFP_KERNEL);
695 if (!d->mask_buf_def)
696 goto err_alloc;
697
698 if (chip->wake_base) {
699 d->wake_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
700 GFP_KERNEL);
701 if (!d->wake_buf)
702 goto err_alloc;
703 }
704
705 num_type_reg = chip->type_in_mask ? chip->num_regs : chip->num_type_reg;
706 if (num_type_reg) {
707 d->type_buf_def = kcalloc(num_type_reg,
708 sizeof(unsigned int), GFP_KERNEL);
709 if (!d->type_buf_def)
710 goto err_alloc;
711
712 d->type_buf = kcalloc(num_type_reg, sizeof(unsigned int),
713 GFP_KERNEL);
714 if (!d->type_buf)
715 goto err_alloc;
716 }
717
718 if (chip->num_virt_regs) {
719 /*
720 * Create virt_buf[chip->num_extra_config_regs][chip->num_regs]
721 */
722 d->virt_buf = kcalloc(chip->num_virt_regs, sizeof(*d->virt_buf),
723 GFP_KERNEL);
724 if (!d->virt_buf)
725 goto err_alloc;
726
727 for (i = 0; i < chip->num_virt_regs; i++) {
728 d->virt_buf[i] = kcalloc(chip->num_regs,
729 sizeof(unsigned int),
730 GFP_KERNEL);
731 if (!d->virt_buf[i])
732 goto err_alloc;
733 }
734 }
735
736 d->irq_chip = regmap_irq_chip;
737 d->irq_chip.name = chip->name;
738 d->irq = irq;
739 d->map = map;
740 d->chip = chip;
741 d->irq_base = irq_base;
742
743 if (chip->irq_reg_stride)
744 d->irq_reg_stride = chip->irq_reg_stride;
745 else
746 d->irq_reg_stride = 1;
747
748 if (chip->type_reg_stride)
749 d->type_reg_stride = chip->type_reg_stride;
750 else
751 d->type_reg_stride = 1;
752
753 if (!map->use_single_read && map->reg_stride == 1 &&
754 d->irq_reg_stride == 1) {
755 d->status_reg_buf = kmalloc_array(chip->num_regs,
756 map->format.val_bytes,
757 GFP_KERNEL);
758 if (!d->status_reg_buf)
759 goto err_alloc;
760 }
761
762 mutex_init(&d->lock);
763
764 for (i = 0; i < chip->num_irqs; i++)
765 d->mask_buf_def[chip->irqs[i].reg_offset / map->reg_stride]
766 |= chip->irqs[i].mask;
767
768 /* Mask all the interrupts by default */
769 for (i = 0; i < chip->num_regs; i++) {
770 d->mask_buf[i] = d->mask_buf_def[i];
771 if (!chip->mask_base)
772 continue;
773
774 reg = sub_irq_reg(d, d->chip->mask_base, i);
775
776 if (chip->mask_invert)
777 ret = regmap_irq_update_bits(d, reg,
778 d->mask_buf[i], ~d->mask_buf[i]);
779 else if (d->chip->unmask_base) {
780 unmask_offset = d->chip->unmask_base -
781 d->chip->mask_base;
782 ret = regmap_irq_update_bits(d,
783 reg + unmask_offset,
784 d->mask_buf[i],
785 d->mask_buf[i]);
786 } else
787 ret = regmap_irq_update_bits(d, reg,
788 d->mask_buf[i], d->mask_buf[i]);
789 if (ret != 0) {
790 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
791 reg, ret);
792 goto err_alloc;
793 }
794
795 if (!chip->init_ack_masked)
796 continue;
797
798 /* Ack masked but set interrupts */
799 reg = sub_irq_reg(d, d->chip->status_base, i);
800 ret = regmap_read(map, reg, &d->status_buf[i]);
801 if (ret != 0) {
802 dev_err(map->dev, "Failed to read IRQ status: %d\n",
803 ret);
804 goto err_alloc;
805 }
806
807 if (chip->status_invert)
> 808 data->status_buf[i] = ~data->status_buf[i];
809
810 if (d->status_buf[i] && (chip->ack_base || chip->use_ack)) {
811 reg = sub_irq_reg(d, d->chip->ack_base, i);
812 if (chip->ack_invert)
813 ret = regmap_write(map, reg,
814 ~(d->status_buf[i] & d->mask_buf[i]));
815 else
816 ret = regmap_write(map, reg,
817 d->status_buf[i] & d->mask_buf[i]);
818 if (chip->clear_ack) {
819 if (chip->ack_invert && !ret)
820 ret = regmap_write(map, reg,
821 (d->status_buf[i] &
822 d->mask_buf[i]));
823 else if (!ret)
824 ret = regmap_write(map, reg,
825 ~(d->status_buf[i] &
826 d->mask_buf[i]));
827 }
828 if (ret != 0) {
829 dev_err(map->dev, "Failed to ack 0x%x: %d\n",
830 reg, ret);
831 goto err_alloc;
832 }
833 }
834 }
835
836 /* Wake is disabled by default */
837 if (d->wake_buf) {
838 for (i = 0; i < chip->num_regs; i++) {
839 d->wake_buf[i] = d->mask_buf_def[i];
840 reg = sub_irq_reg(d, d->chip->wake_base, i);
841
842 if (chip->wake_invert)
843 ret = regmap_irq_update_bits(d, reg,
844 d->mask_buf_def[i],
845 0);
846 else
847 ret = regmap_irq_update_bits(d, reg,
848 d->mask_buf_def[i],
849 d->wake_buf[i]);
850 if (ret != 0) {
851 dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
852 reg, ret);
853 goto err_alloc;
854 }
855 }
856 }
857
858 if (chip->num_type_reg && !chip->type_in_mask) {
859 for (i = 0; i < chip->num_type_reg; ++i) {
860 reg = sub_irq_reg(d, d->chip->type_base, i);
861
862 ret = regmap_read(map, reg, &d->type_buf_def[i]);
863
864 if (d->chip->type_invert)
865 d->type_buf_def[i] = ~d->type_buf_def[i];
866
867 if (ret) {
868 dev_err(map->dev, "Failed to get type defaults at 0x%x: %d\n",
869 reg, ret);
870 goto err_alloc;
871 }
872 }
873 }
874
875 if (irq_base)
876 d->domain = irq_domain_create_legacy(fwnode, chip->num_irqs,
877 irq_base, 0,
878 &regmap_domain_ops, d);
879 else
880 d->domain = irq_domain_create_linear(fwnode, chip->num_irqs,
881 &regmap_domain_ops, d);
882 if (!d->domain) {
883 dev_err(map->dev, "Failed to create IRQ domain\n");
884 ret = -ENOMEM;
885 goto err_alloc;
886 }
887
888 ret = request_threaded_irq(irq, NULL, regmap_irq_thread,
889 irq_flags | IRQF_ONESHOT,
890 chip->name, d);
891 if (ret != 0) {
892 dev_err(map->dev, "Failed to request IRQ %d for %s: %d\n",
893 irq, chip->name, ret);
894 goto err_domain;
895 }
896
897 *data = d;
898
899 return 0;
900
901 err_domain:
902 /* Should really dispose of the domain but... */
903 err_alloc:
904 kfree(d->type_buf);
905 kfree(d->type_buf_def);
906 kfree(d->wake_buf);
907 kfree(d->mask_buf_def);
908 kfree(d->mask_buf);
909 kfree(d->status_buf);
910 kfree(d->status_reg_buf);
911 if (d->virt_buf) {
912 for (i = 0; i < chip->num_virt_regs; i++)
913 kfree(d->virt_buf[i]);
914 kfree(d->virt_buf);
915 }
916 kfree(d);
917 return ret;
918 }
919 EXPORT_SYMBOL_GPL(regmap_add_irq_chip_fwnode);
920

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (12.42 kB)
.config.gz (37.54 kB)
Download all attachments