Kernel

關於 PCA9555 擴展器上的#interrupt-cells 配置的困惑

  • June 14, 2017

我第一次嘗試在我的自定義平台上設置設備樹源文件。板上是 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>;
};

通過使用armada-388-gp.dts源作為指南,我達到了這一點。

我的困惑在於哪些程式碼處理了該#interrupt-cells屬性。綁定文件對這個晶片沒有太大幫助,因為它沒有說明任何關於中斷單元解釋的內容。

查看pca9555 驅動程序原始碼pca953x_irq_setup中的函式- 我看不到任何處理該屬性的地方。這是在linux中斷處理程式碼中處理的嗎?我只是對我應該如何知道兩個中斷單元的含義感到困惑。#interrupt-cells

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目前正在使用核心版本。

我現在明白我誤解了設備樹的某些屬性。我以前的印像是驅動程序必須指定如何處理所有屬性。我現在看到 linux 實際上會處理許多通用屬性,例如gpiosor interrupts(這很有意義)。

以下是關於從 intspec 轉換為如何IRQ_TYPE*發生的詳細說明:

該函式of_irq_parse_one將中斷說明符整數複製到struct of_phandle_args 此處irq_create_of_mapping然後通過消費者函式(例如of_irq_get)將此 arg 傳遞給。然後,此函式將這些 args 映射到struct irq_fwspecviaof_phandle_args_to_fwspec並將其 fwspec 數據傳遞給irq_create_fwspec_mapping. 這些函式都可以在irqdomain.c中找到。此時 irq 將屬於一個irq_domain或使用irq_default_domain. 據我所知 -pca853x驅動程序使用預設域。該域通常由特定於平台的程式碼設置。我通過搜尋irq_domain_ops 交叉引用找到了我的。其中很多似乎只是簡單地複製intspec[1] & IRQ_TYPE_SENSE_MASK到via中的type變數。從這裡將類型設置為 irq 的viairq_create_fwspec_mapping``irq_domain_translate``irq_data``irqd_set_trigger_type.

閱讀第 2 節:為設備指定中斷資訊

  1. 中斷控制器節點

設備被標記為具有“中斷控制器”屬性的中斷控制器。這是一個空的布爾屬性。附加的“#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,第一個單元定義控制器內中斷的索引,而第二個單元用於指定以下任何標誌:

> > * 位 > > $$ 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>;
           };
   };

因此,對於雙單元變體,第一個數字是索引,第二個是定義中斷輸入類型的位遮罩。

設備樹的這一部分由drivers/of/irq.c(例如of_irq_parse_one())中的程式碼處理。

您在引用的範例中引用的兩行將設備 ( gpio-exp@21) 聲明為中斷控制器,並且任何其他想要使用它的設備必須為每個中斷提供兩個單元。

就在這些行之上是一個設備在另一個中斷控制器中指定中斷的範例(不是這個,而是具有 alias 的設備gpio),通過兩個屬性interrupt-parentinterrupts(或者您可以使用 newinterrupts-extended允許每個中斷使用不同的中斷控制器將父級指定為屬性的第一個單元格)。

引用自:https://unix.stackexchange.com/questions/370910