PCA9555 확장기의 #interrupt-cell 구성에 대한 혼란

PCA9555 확장기의 #interrupt-cell 구성에 대한 혼란

내 사용자 정의 플랫폼에서 처음으로 장치 트리 소스 파일을 설정하려고 합니다. 보드에는 NXP PCA9555 gpio 확장기가 있습니다. 장치에 대한 노드를 설정하려고 하는데 약간 혼란스럽습니다.

내 노드가 dts 파일에 있는 위치는 다음과 같습니다.

ioexp0: gpio-exp@21 {
        compatible = "nxp,pca9555";
        reg = <21>;

        interrupt-parent = <&gpio>;
        interrupts = <8 0>;

        gpio-controller;
        #gpio-cells = <2>;

        /*I don't understand the following two lines*/
        interrupt-controller;
        #interrupt-cells = <2>;
};

나는 이것을 사용하여 이것을 달성했습니다.함대-388-gp.dts지침 출처.

어떤 코드가 이 속성을 처리하는지에 대한 혼란이 있습니다 #interrupt-cells. 이것바인딩 문서인터럽트 장치의 해석에 대해서는 아무 것도 알려주지 않기 때문에 이 칩에는 전혀 도움이 되지 않습니다.

pca953x_irq_setup기능 보기소스 코드#interrupt-cellspca9555 드라이버의 경우 - 이 속성을 처리하는 방법 이 표시되지 않습니다 . 이것이 Linux 인터럽트 처리 코드에서 처리됩니까? 두 개의 인터럽트 장치가 무엇을 의미하는지 아는 방법이 혼란스럽습니다.

pca953x_irq_setup귀하의 편의를 위해:

static int pca953x_irq_setup(struct pca953x_chip *chip,
                 int irq_base)
{
    struct i2c_client *client = chip->client;
    int ret, i;

    if (client->irq && irq_base != -1
            && (chip->driver_data & PCA_INT)) {
        ret = pca953x_read_regs(chip,
                    chip->regs->input, chip->irq_stat);
        if (ret)
            return ret;

        /*
         * There is no way to know which GPIO line generated the
         * interrupt.  We have to rely on the previous read for
         * this purpose.
         */
        for (i = 0; i < NBANK(chip); i++)
            chip->irq_stat[i] &= chip->reg_direction[i];
        mutex_init(&chip->irq_lock);

        ret = devm_request_threaded_irq(&client->dev,
                    client->irq,
                       NULL,
                       pca953x_irq_handler,
                       IRQF_TRIGGER_LOW | IRQF_ONESHOT |
                           IRQF_SHARED,
                       dev_name(&client->dev), chip);
        if (ret) {
            dev_err(&client->dev, "failed to request irq %d\n",
                client->irq);
            return ret;
        }

        ret =  gpiochip_irqchip_add_nested(&chip->gpio_chip,
                           &pca953x_irq_chip,
                           irq_base,
                           handle_simple_irq,
                           IRQ_TYPE_NONE);
        if (ret) {
            dev_err(&client->dev,
                "could not connect irqchip to gpiochip\n");
            return ret;
        }

        gpiochip_set_nested_irqchip(&chip->gpio_chip,
                        &pca953x_irq_chip,
                        client->irq);
    }

    return 0;
}

장치 트리를 처음 사용하는 것이므로 이것이 제가 놓친 부분이 분명 있기를 바랍니다.

고쳐 쓰다:

설명하자면 4.12-rc4현재 커널 버전을 사용하고 있습니다.

이제 장치 트리의 일부 속성을 잘못 이해했음을 이해합니다. 이전에는 드라이버가 모든 속성을 처리하는 방법을 지정해야 한다는 인상을 받았습니다. 이제 나는 리눅스가 실제로 gpios또는 interrupts(말이 되는) 같은 많은 공통 속성을 처리한다는 것을 알았습니다.

intspec에서 발생하도록 변환하는 방법에 대한 자세한 설명은 다음과 같습니다 IRQ_TYPE*.

이 함수는 of_irq_parse_one인터럽트 지정자 정수를struct of_phandle_args 여기. 그런 다음 이 매개변수는 irq_create_of_mapping소비자 함수를 통해 (예를 들어) 전달됩니다 of_irq_get. 그런 다음 함수는 이러한 매개변수를 struct irq_fwspecvia 에 매핑 of_phandle_args_to_fwspec하고 해당 fwspec 데이터를 에 전달합니다 irq_create_fwspec_mapping.irqdomain.c. 이 시점에서 irq는 내가 아는 한 에 속하거나 irq_domain사용하게 됩니다. 드라이버는 기본 도메인을 사용합니다. 이 필드는 일반적으로 플랫폼별 코드로 설정됩니다. 검색해서 찾았어요irq_default_domainpca853xirq_domain_ops 상호 참조. 그 중 다수는 intspec[1] & IRQ_TYPE_SENSE_MASKvia type에 있는 변수의 단순한 복사 본인 것 같습니다 . 이제부터 유형은 via of irq로 설정됩니다.irq_create_fwspec_mappingirq_domain_translateirq_datairqd_set_trigger_type

답변1

이 기사의 섹션 2를 읽어보십시오.지정된 장치에 대한 인터럽트 정보...

2) 인터럽트 컨트롤러 노드

장치는 "인터럽트 컨트롤러" 속성을 가진 인터럽트 컨트롤러로 표시됩니다. 이는 빈 부울 속성입니다. 추가 "#interrupt-cells" 속성은 단일 인터럽트를 지정하는 데 필요한 셀 수를 정의합니다.

인터럽트 컨트롤러의 바인딩은 인터럽트 지정자의 길이와 형식을 정의하는 역할을 합니다. 다음 두 가지 변형이 일반적으로 사용됩니다.

a) 셀


#interrupt-cells 속성을 1로 설정하면 단일 셀이 컨트롤러 내의 인터럽트 인덱스를 정의합니다.

예:

   vic: intc@10140000 {
           compatible = "arm,versatile-vic";
           interrupt-controller;
           #interrupt-cells = <1>;
           reg = <0x10140000 0x1000>;
   };

   sic: intc@10003000 {
           compatible = "arm,versatile-sic";
           interrupt-controller;
           #interrupt-cells = <1>;
           reg = <0x10003000 0x1000>;
           interrupt-parent = <&vic>;
           interrupts = <31>; /* Cascaded to vic */
   };

b) 두 개의 셀


#interrupt-cells 속성은 2로 설정되고 첫 번째 셀은 컨트롤러 내의 인터럽트 인덱스를 정의하며 두 번째 셀은 다음 플래그 중 하나를 지정하는 데 사용됩니다.

  • Bits[3:0] 트리거 유형 및 레벨 플래그

    1 = 낮은 에지에서 높은 에지까지 트리거됨
    2 = 높은 에지에서 낮은 에지까지 트리거됨
    4 = 활성 높음, 민감함
    8 = 활성 낮음, 민감함

예:

   i2c@7000c000 {
           gpioext: gpio-adnp@41 {
                   compatible = "ad,gpio-adnp";
                   reg = <0x41>;

                   interrupt-parent = <&gpio>;
                   interrupts = <160 1>;

                   gpio-controller;
                   #gpio-cells = <1>;

                   interrupt-controller;
                   #interrupt-cells = <2>;

                   nr-gpios = <64>;
           };

           sx8634@2b {
                   compatible = "smtc,sx8634";
                   reg = <0x2b>;

                   interrupt-parent = <&gpioext>;
                   interrupts = <3 0x8>;

                   #address-cells = <1>;
                   #size-cells = <0>;

                   threshold = <0x40>;
                   sensitivity = <7>;
           };
   };

따라서 2셀 변형의 경우 첫 번째 숫자는 인덱스이고 두 번째 숫자는 인터럽트 입력 유형을 정의하는 비트마스크입니다.

drivers/of/irq.c장치 트리의 이 부분은 (예를 들어) 의 코드에 의해 처리됩니다 of_irq_parse_one().

인용한 예에서 인용한 두 줄은 gpio-exp@21device()를 인터럽트 컨트롤러로 선언하고 이를 사용하려는 다른 장치는 각 인터럽트에 대해 두 개의 단위를 제공해야 합니다.

gpio이 줄 바로 위에는 두 가지 속성을 통해 다른 인터럽트 컨트롤러(이 컨트롤러가 아니라 별칭이 있는 장치)에서 인터럽트를 지정하는 장치의 예가 있습니다. interrupt-parent또는 각 인터럽트가 다른 인터럽트를 사용하도록 허용하는 interrupts새 속성을 사용할 수 있습니다. interrupts-extended부모를 속성의 첫 번째 셀로 지정하는 컨트롤러).

관련 정보