Explorar o código

[documentation][device_driver_model] Add comprehensive PIC documentation (EN) - critical module 1/6

Co-authored-by: BernardXiong <1241087+BernardXiong@users.noreply.github.com>
copilot-swe-agent[bot] hai 1 semana
pai
achega
b10da2d554

+ 966 - 0
documentation/6.components/device-driver/device_driver_model/pic/README.md

@@ -0,0 +1,966 @@
+# Platform Interrupt Controller (PIC) Framework
+
+## Introduction
+
+The Platform Interrupt Controller (PIC) framework provides a unified abstraction layer for managing hardware interrupts in RT-Thread's Device Driver Model. It supports various interrupt controllers including ARM GIC (Generic Interrupt Controller) v1/v2/v3, and provides comprehensive interrupt management capabilities including cascading, MSI support, and inter-processor interrupts (IPI).
+
+### Key Features
+
+- **Unified Interrupt Management**: Abstract interface for all interrupt controllers
+- **Interrupt Cascading**: Support for hierarchical interrupt routing
+- **CPU Affinity**: Configure which CPUs can handle specific interrupts
+- **Priority Control**: Set interrupt priorities for different IRQ sources
+- **Trigger Modes**: Support edge/level triggered interrupts
+- **IPI Support**: Inter-processor interrupt mechanisms for multi-core systems
+- **MSI/MSI-X**: Message Signaled Interrupts for PCIe devices
+- **Statistics**: Optional ISR execution time tracking
+
+### Architecture
+
+The PIC framework consists of:
+
+1. **PIC Core** (`pic.c`): Central interrupt management and routing
+2. **PIC IRQ** (`struct rt_pic_irq`): Individual interrupt descriptor
+3. **PIC Operations** (`struct rt_pic_ops`): Hardware-specific callbacks
+4. **ISR Management**: Interrupt Service Routine registration and execution
+
+```
+┌──────────────────────────────────────────┐
+│         Application/Drivers              │
+│  (Call rt_pic_attach_irq, enable, etc.) │
+└──────────────────┬───────────────────────┘
+                   │
+┌──────────────────▼───────────────────────┐
+│       PIC Framework (pic.c)              │
+│  - IRQ allocation & management           │
+│  - ISR dispatch                          │
+│  - Cascading support                     │
+│  - Affinity & priority management        │
+└──────────────────┬───────────────────────┘
+                   │
+┌──────────────────▼───────────────────────┐
+│     PIC Operations (rt_pic_ops)          │
+│  - irq_enable/disable                    │
+│  - irq_mask/unmask                       │
+│  - irq_set_priority                      │
+│  - irq_set_affinity                      │
+│  - irq_send_ipi (for multi-core)         │
+└──────────────────┬───────────────────────┘
+                   │
+┌──────────────────▼───────────────────────┐
+│   Hardware Interrupt Controller          │
+│   (GICv2, GICv3, etc.)                   │
+└──────────────────────────────────────────┘
+```
+
+## Kconfig Configuration
+
+### Location in menuconfig
+
+```
+RT-Thread Components
+    └── Device Drivers
+        └── Using Device Driver Model with DeviceTree (RT_USING_DM)
+            └── Using Programmable Interrupt Controller (PIC) (RT_USING_PIC)
+```
+
+### Configuration Options
+
+#### RT_USING_PIC
+- **Type**: bool
+- **Default**: n
+- **Description**: Enable the Platform Interrupt Controller framework
+- **Dependencies**: RT_USING_DM, RT_USING_ADT, RT_USING_ADT_BITMAP
+- **Purpose**: Main switch for PIC support
+
+#### RT_USING_PIC_STATISTICS
+- **Type**: bool
+- **Default**: n
+- **Description**: Enable ISR execution time statistics
+- **Dependencies**: RT_USING_PIC, RT_USING_KTIME, RT_USING_INTERRUPT_INFO
+- **Purpose**: Track min/max/average IRQ handling times for profiling
+
+#### MAX_HANDLERS
+- **Type**: int
+- **Range**: 1-4294967294
+- **Default**: 256
+- **Description**: Maximum number of interrupt handlers the system can register
+- **Purpose**: Defines the size of the global IRQ hash table
+
+#### RT_PIC_ARM_GIC
+- **Type**: bool
+- **Default**: n
+- **Description**: Enable ARM Generic Interrupt Controller v1/v2 support
+- **Dependencies**: RT_USING_PIC, RT_USING_OFW
+- **Purpose**: Support for ARM GICv1/v2 hardware
+
+#### RT_PIC_ARM_GIC_V2M
+- **Type**: bool
+- **Default**: n
+- **Description**: Enable ARM GIC V2M (MSI support for GICv2)
+- **Dependencies**: RT_PIC_ARM_GIC, RT_PCI_MSI, RT_USING_OFW
+- **Purpose**: Message Signaled Interrupts on GICv2
+
+#### RT_PIC_ARM_GIC_V3
+- **Type**: bool
+- **Default**: n
+- **Description**: Enable ARM Generic Interrupt Controller v3 support
+- **Dependencies**: RT_USING_PIC, RT_USING_OFW
+- **Purpose**: Support for ARM GICv3 hardware
+
+#### RT_PIC_ARM_GIC_V3_ITS
+- **Type**: bool
+- **Default**: n
+- **Description**: Enable ARM GICv3 ITS (Interrupt Translation Service)
+- **Dependencies**: RT_PIC_ARM_GIC_V3, RT_PCI_MSI, RT_USING_OFW, RT_USING_ADT_REF
+- **Purpose**: MSI/MSI-X support for GICv3 via ITS
+
+#### RT_PIC_ARM_GIC_V3_ITS_IRQ_MAX
+- **Type**: int
+- **Default**: 127 (64-bit), 63 (32-bit)
+- **Description**: Maximum IRQ number for GICv3 ITS
+- **Dependencies**: RT_PIC_ARM_GIC_V3_ITS
+- **Purpose**: Limit ITS-managed interrupt range
+
+## Device Tree Bindings
+
+### GICv2 Example
+
+```dts
+gic: interrupt-controller@08000000 {
+    compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+    #interrupt-cells = <3>;
+    #address-cells = <1>;
+    interrupt-controller;
+    reg = <0x08000000 0x1000>,  /* Distributor */
+          <0x08010000 0x1000>;  /* CPU interface */
+};
+
+/* Consumer example: UART using GIC */
+uart0: serial@09000000 {
+    compatible = "arm,pl011", "arm,primecell";
+    reg = <0x09000000 0x1000>;
+    interrupts = <0 5 4>;  /* SPI, IRQ 5, IRQ_TYPE_LEVEL_HIGH */
+    interrupt-parent = <&gic>;
+};
+```
+
+### GICv3 Example
+
+```dts
+gic: interrupt-controller@08000000 {
+    compatible = "arm,gic-v3";
+    #interrupt-cells = <3>;
+    #address-cells = <2>;
+    #size-cells = <2>;
+    interrupt-controller;
+    reg = <0x0 0x08000000 0 0x10000>,  /* Distributor */
+          <0x0 0x080A0000 0 0xF60000>; /* Redistributor */
+    
+    gic_its: msi-controller@08020000 {
+        compatible = "arm,gic-v3-its";
+        msi-controller;
+        #msi-cells = <1>;
+        reg = <0x0 0x08020000 0 0x20000>;
+    };
+};
+
+/* Consumer with interrupts */
+timer {
+    compatible = "arm,armv8-timer";
+    interrupts = <1 13 0xff08>,  /* Physical Secure PPI */
+                 <1 14 0xff08>,  /* Physical Non-Secure PPI */
+                 <1 11 0xff08>,  /* Virtual PPI */
+                 <1 10 0xff08>;  /* Hypervisor PPI */
+    interrupt-parent = <&gic>;
+};
+```
+
+### Interrupt Cells Explanation
+
+For ARM GIC, `interrupts` property has 3 cells:
+1. **Type**: 0 = SPI (Shared Peripheral Interrupt), 1 = PPI (Private Peripheral Interrupt)
+2. **Number**: IRQ number within the type (SPI: 0-987, PPI: 0-15)
+3. **Flags**: Trigger type and priority
+   - `IRQ_TYPE_EDGE_RISING` = 1
+   - `IRQ_TYPE_EDGE_FALLING` = 2
+   - `IRQ_TYPE_LEVEL_HIGH` = 4
+   - `IRQ_TYPE_LEVEL_LOW` = 8
+
+## Application API
+
+### IRQ Attachment
+
+#### rt_pic_attach_irq
+
+```c
+rt_err_t rt_pic_attach_irq(int irq, rt_isr_handler_t handler, void *uid, 
+                            const char *name, int flags);
+```
+
+Attach an interrupt service routine to an IRQ.
+
+**Parameters:**
+- `irq`: IRQ number to attach to
+- `handler`: ISR function pointer `void (*handler)(int irq, void *param)`
+- `uid`: User-defined parameter passed to the handler
+- `name`: Descriptive name for the interrupt (for debugging)
+- `flags`: Interrupt flags (currently unused, pass 0)
+
+**Returns:**
+- `RT_EOK`: Success
+- `-RT_EINVAL`: Invalid IRQ number
+- `-RT_ENOMEM`: Out of memory
+
+**Example:**
+```c
+void uart_isr(int irq, void *param)
+{
+    struct uart_device *uart = (struct uart_device *)param;
+    /* Handle interrupt */
+    rt_kprintf("UART interrupt occurred\n");
+}
+
+/* In driver probe function */
+static rt_err_t uart_probe(struct rt_platform_device *pdev)
+{
+    struct uart_device *uart;
+    int irq;
+    
+    /* Get IRQ from device tree */
+    irq = rt_platform_get_irq(pdev, 0);
+    if (irq < 0)
+        return irq;
+    
+    /* Attach ISR */
+    rt_err_t ret = rt_pic_attach_irq(irq, uart_isr, uart, "uart0", 0);
+    if (ret != RT_EOK)
+        return ret;
+    
+    /* Enable the interrupt */
+    rt_pic_irq_enable(irq);
+    
+    return RT_EOK;
+}
+```
+
+#### rt_pic_detach_irq
+
+```c
+rt_err_t rt_pic_detach_irq(int irq, void *uid);
+```
+
+Detach an interrupt service routine from an IRQ.
+
+**Parameters:**
+- `irq`: IRQ number
+- `uid`: Must match the `uid` passed to `rt_pic_attach_irq`
+
+**Returns:**
+- `RT_EOK`: Success
+- `-RT_EINVAL`: Invalid IRQ or UID mismatch
+
+### IRQ Control
+
+#### rt_pic_irq_enable / rt_pic_irq_disable
+
+```c
+void rt_pic_irq_enable(int irq);
+void rt_pic_irq_disable(int irq);
+```
+
+Enable or disable an interrupt at the PIC level.
+
+**Parameters:**
+- `irq`: IRQ number
+
+**Example:**
+```c
+/* Enable interrupt before starting operation */
+rt_pic_irq_enable(uart_irq);
+
+/* Disable during critical sections */
+rt_pic_irq_disable(uart_irq);
+/* ... critical code ... */
+rt_pic_irq_enable(uart_irq);
+```
+
+#### rt_pic_irq_mask / rt_pic_irq_unmask
+
+```c
+void rt_pic_irq_mask(int irq);
+void rt_pic_irq_unmask(int irq);
+```
+
+Mask or unmask an interrupt (similar to enable/disable but may have different semantics on some hardware).
+
+**Parameters:**
+- `irq`: IRQ number
+
+#### rt_pic_irq_ack
+
+```c
+void rt_pic_irq_ack(int irq);
+```
+
+Acknowledge an interrupt (required for some edge-triggered interrupts).
+
+**Parameters:**
+- `irq`: IRQ number
+
+#### rt_pic_irq_eoi
+
+```c
+void rt_pic_irq_eoi(int irq);
+```
+
+Signal End-Of-Interrupt to the PIC.
+
+**Parameters:**
+- `irq`: IRQ number
+
+### Priority Management
+
+#### rt_pic_irq_set_priority
+
+```c
+rt_err_t rt_pic_irq_set_priority(int irq, rt_uint32_t priority);
+```
+
+Set the priority of an interrupt.
+
+**Parameters:**
+- `irq`: IRQ number
+- `priority`: Priority value (lower = higher priority typically)
+
+**Returns:**
+- `RT_EOK`: Success
+- `-RT_ENOSYS`: Not supported by hardware
+
+**Example:**
+```c
+/* Set high priority for critical timer interrupt */
+rt_pic_irq_set_priority(timer_irq, 0);
+
+/* Set lower priority for UART */
+rt_pic_irq_set_priority(uart_irq, 128);
+```
+
+#### rt_pic_irq_get_priority
+
+```c
+rt_uint32_t rt_pic_irq_get_priority(int irq);
+```
+
+Get the current priority of an interrupt.
+
+**Parameters:**
+- `irq`: IRQ number
+
+**Returns:** Current priority value
+
+### CPU Affinity (Multi-core)
+
+#### rt_pic_irq_set_affinity
+
+```c
+rt_err_t rt_pic_irq_set_affinity(int irq, rt_bitmap_t *affinity);
+```
+
+Set which CPUs can handle a specific interrupt.
+
+**Parameters:**
+- `irq`: IRQ number
+- `affinity`: Bitmap of allowed CPUs
+
+**Returns:**
+- `RT_EOK`: Success
+- `-RT_ENOSYS`: Not supported
+
+**Example:**
+```c
+RT_IRQ_AFFINITY_DECLARE(cpumask);
+
+/* Route interrupt to CPU 0 and CPU 2 */
+rt_bitmap_clear(cpumask, RT_BITMAP_LEN(RT_CPUS_NR));
+RT_IRQ_AFFINITY_SET(cpumask, 0);
+RT_IRQ_AFFINITY_SET(cpumask, 2);
+rt_pic_irq_set_affinity(eth_irq, cpumask);
+```
+
+#### rt_pic_irq_get_affinity
+
+```c
+rt_err_t rt_pic_irq_get_affinity(int irq, rt_bitmap_t *out_affinity);
+```
+
+Get the current CPU affinity for an interrupt.
+
+**Parameters:**
+- `irq`: IRQ number
+- `out_affinity`: Output bitmap
+
+**Returns:**
+- `RT_EOK`: Success
+- `-RT_EINVAL`: Invalid IRQ
+
+### Trigger Mode
+
+#### rt_pic_irq_set_triger_mode
+
+```c
+rt_err_t rt_pic_irq_set_triger_mode(int irq, rt_uint32_t mode);
+```
+
+Set the trigger mode for an interrupt.
+
+**Parameters:**
+- `irq`: IRQ number
+- `mode`: Trigger mode
+  - `RT_IRQ_MODE_EDGE_RISING`: Rising edge
+  - `RT_IRQ_MODE_EDGE_FALLING`: Falling edge
+  - `RT_IRQ_MODE_EDGE_BOTH`: Both edges
+  - `RT_IRQ_MODE_LEVEL_HIGH`: High level
+  - `RT_IRQ_MODE_LEVEL_LOW`: Low level
+
+**Returns:**
+- `RT_EOK`: Success
+- `-RT_ENOSYS`: Not supported
+
+#### rt_pic_irq_get_triger_mode
+
+```c
+rt_uint32_t rt_pic_irq_get_triger_mode(int irq);
+```
+
+Get the current trigger mode.
+
+**Parameters:**
+- `irq`: IRQ number
+
+**Returns:** Current trigger mode
+
+### Inter-Processor Interrupts (IPI)
+
+#### rt_pic_irq_send_ipi
+
+```c
+void rt_pic_irq_send_ipi(int irq, rt_bitmap_t *cpumask);
+```
+
+Send an inter-processor interrupt to specified CPUs.
+
+**Parameters:**
+- `irq`: IPI number (typically in range 0-15)
+- `cpumask`: Bitmap of target CPUs
+
+**Example:**
+```c
+RT_IRQ_AFFINITY_DECLARE(targets);
+
+/* Send IPI to CPU 1 */
+rt_bitmap_clear(targets, RT_BITMAP_LEN(RT_CPUS_NR));
+RT_IRQ_AFFINITY_SET(targets, 1);
+rt_pic_irq_send_ipi(0, targets);  /* IPI 0 */
+```
+
+### State Management
+
+#### rt_pic_irq_set_state / rt_pic_irq_get_state
+
+```c
+rt_err_t rt_pic_irq_set_state(int irq, int type, rt_bool_t state);
+rt_err_t rt_pic_irq_get_state(int irq, int type, rt_bool_t *out_state);
+```
+
+Set or get interrupt state (pending, active, masked).
+
+**Parameters:**
+- `irq`: IRQ number
+- `type`: State type
+  - `RT_IRQ_STATE_PENDING`: Interrupt is pending
+  - `RT_IRQ_STATE_ACTIVE`: Interrupt is being serviced
+  - `RT_IRQ_STATE_MASKED`: Interrupt is masked
+- `state` / `out_state`: State value
+
+**Returns:**
+- `RT_EOK`: Success
+- `-RT_ENOSYS`: Not supported
+
+## Complete Driver Example: GPIO Interrupt Handler
+
+```c
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <drivers/pic.h>
+#include <drivers/platform.h>
+
+struct gpio_int_device
+{
+    struct rt_device parent;
+    void *base;
+    int irq;
+    rt_uint32_t pin_mask;
+};
+
+/* GPIO interrupt service routine */
+static void gpio_isr(int irq, void *param)
+{
+    struct gpio_int_device *gpio = (struct gpio_int_device *)param;
+    rt_uint32_t status;
+    
+    /* Read interrupt status register */
+    status = readl(gpio->base + GPIO_INT_STATUS);
+    
+    /* Clear interrupt */
+    writel(status, gpio->base + GPIO_INT_CLEAR);
+    
+    /* Handle each pin */
+    for (int i = 0; i < 32; i++)
+    {
+        if (status & (1 << i))
+        {
+            rt_kprintf("GPIO pin %d triggered\n", i);
+            /* Notify application or trigger event */
+        }
+    }
+    
+    /* Send EOI to PIC */
+    rt_pic_irq_eoi(irq);
+}
+
+static rt_err_t gpio_int_probe(struct rt_platform_device *pdev)
+{
+    struct gpio_int_device *gpio;
+    struct rt_device *dev = &pdev->parent;
+    int irq;
+    rt_err_t ret;
+    
+    gpio = rt_calloc(1, sizeof(*gpio));
+    if (!gpio)
+        return -RT_ENOMEM;
+    
+    /* Map registers */
+    gpio->base = rt_dm_dev_iomap(dev, 0);
+    if (!gpio->base)
+    {
+        ret = -RT_ERROR;
+        goto err_free;
+    }
+    
+    /* Get IRQ from device tree */
+    irq = rt_platform_get_irq(pdev, 0);
+    if (irq < 0)
+    {
+        ret = irq;
+        goto err_iounmap;
+    }
+    gpio->irq = irq;
+    
+    /* Set interrupt trigger mode - rising edge */
+    ret = rt_pic_irq_set_triger_mode(irq, RT_IRQ_MODE_EDGE_RISING);
+    if (ret != RT_EOK && ret != -RT_ENOSYS)
+    {
+        rt_kprintf("Failed to set trigger mode: %d\n", ret);
+        goto err_iounmap;
+    }
+    
+    /* Set interrupt priority (high priority) */
+    ret = rt_pic_irq_set_priority(irq, 32);
+    if (ret != RT_EOK && ret != -RT_ENOSYS)
+    {
+        rt_kprintf("Failed to set priority: %d\n", ret);
+    }
+    
+    /* Attach interrupt handler */
+    ret = rt_pic_attach_irq(irq, gpio_isr, gpio, "gpio-int", 0);
+    if (ret != RT_EOK)
+    {
+        rt_kprintf("Failed to attach IRQ: %d\n", ret);
+        goto err_iounmap;
+    }
+    
+    /* Configure GPIO pins for interrupt */
+    writel(0xFFFFFFFF, gpio->base + GPIO_INT_ENABLE);  /* Enable all pins */
+    writel(0x00000000, gpio->base + GPIO_INT_MASK);    /* Unmask all */
+    
+    /* Enable interrupt at PIC level */
+    rt_pic_irq_enable(irq);
+    
+    /* Store device data */
+    rt_platform_set_drvdata(pdev, gpio);
+    
+    rt_kprintf("GPIO interrupt controller probed successfully (IRQ %d)\n", irq);
+    return RT_EOK;
+    
+err_iounmap:
+    rt_dm_dev_iounmap(dev, gpio->base);
+err_free:
+    rt_free(gpio);
+    return ret;
+}
+
+static rt_err_t gpio_int_remove(struct rt_platform_device *pdev)
+{
+    struct gpio_int_device *gpio = rt_platform_get_drvdata(pdev);
+    
+    /* Disable interrupt */
+    rt_pic_irq_disable(gpio->irq);
+    
+    /* Detach handler */
+    rt_pic_detach_irq(gpio->irq, gpio);
+    
+    /* Disable GPIO interrupts */
+    writel(0x00000000, gpio->base + GPIO_INT_ENABLE);
+    
+    /* Cleanup */
+    rt_dm_dev_iounmap(&pdev->parent, gpio->base);
+    rt_free(gpio);
+    
+    return RT_EOK;
+}
+
+static const struct rt_ofw_node_id gpio_int_ofw_ids[] =
+{
+    { .compatible = "myvendor,gpio-interrupt-controller" },
+    { /* sentinel */ }
+};
+
+static struct rt_platform_driver gpio_int_driver =
+{
+    .name = "gpio-int",
+    .ids = gpio_int_ofw_ids,
+    .probe = gpio_int_probe,
+    .remove = gpio_int_remove,
+};
+
+static int gpio_int_drv_register(void)
+{
+    rt_platform_driver_register(&gpio_int_driver);
+    return 0;
+}
+INIT_DEVICE_EXPORT(gpio_int_drv_register);
+```
+
+## PIC Provider Implementation
+
+For implementing a custom interrupt controller driver:
+
+```c
+#include <rtthread.h>
+#include <drivers/pic.h>
+
+struct my_pic_data
+{
+    void *base;
+    struct rt_pic pic;
+};
+
+static void my_pic_irq_enable(struct rt_pic_irq *pirq)
+{
+    struct rt_pic *pic = pirq->pic;
+    struct my_pic_data *priv = pic->priv_data;
+    
+    /* Enable interrupt in hardware */
+    writel(1 << pirq->hwirq, priv->base + MY_PIC_ENABLE_REG);
+}
+
+static void my_pic_irq_disable(struct rt_pic_irq *pirq)
+{
+    struct rt_pic *pic = pirq->pic;
+    struct my_pic_data *priv = pic->priv_data;
+    
+    /* Disable interrupt in hardware */
+    writel(1 << pirq->hwirq, priv->base + MY_PIC_DISABLE_REG);
+}
+
+static void my_pic_irq_ack(struct rt_pic_irq *pirq)
+{
+    struct rt_pic *pic = pirq->pic;
+    struct my_pic_data *priv = pic->priv_data;
+    
+    /* Acknowledge interrupt */
+    writel(1 << pirq->hwirq, priv->base + MY_PIC_ACK_REG);
+}
+
+static void my_pic_irq_eoi(struct rt_pic_irq *pirq)
+{
+    struct rt_pic *pic = pirq->pic;
+    struct my_pic_data *priv = pic->priv_data;
+    
+    /* Send EOI signal */
+    writel(1 << pirq->hwirq, priv->base + MY_PIC_EOI_REG);
+}
+
+static rt_err_t my_pic_irq_set_priority(struct rt_pic_irq *pirq, rt_uint32_t priority)
+{
+    struct rt_pic *pic = pirq->pic;
+    struct my_pic_data *priv = pic->priv_data;
+    
+    /* Set priority in hardware register */
+    writel(priority, priv->base + MY_PIC_PRIORITY_REG(pirq->hwirq));
+    
+    return RT_EOK;
+}
+
+static int my_pic_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
+{
+    int irq;
+    
+    /* Allocate software IRQ number */
+    irq = pic->irq_start + hwirq;
+    
+    /* Configure trigger mode in hardware */
+    /* ... */
+    
+    return irq;
+}
+
+static rt_err_t my_pic_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *args,
+                                  struct rt_pic_irq *out_pirq)
+{
+    if (args->args_count != 2)
+        return -RT_EINVAL;
+    
+    /* Parse: <hwirq trigger_type> */
+    out_pirq->hwirq = args->args[0];
+    out_pirq->mode = args->args[1];
+    
+    return RT_EOK;
+}
+
+static const struct rt_pic_ops my_pic_ops =
+{
+    .name = "my-pic",
+    .irq_enable = my_pic_irq_enable,
+    .irq_disable = my_pic_irq_disable,
+    .irq_ack = my_pic_irq_ack,
+    .irq_eoi = my_pic_irq_eoi,
+    .irq_set_priority = my_pic_irq_set_priority,
+    .irq_map = my_pic_irq_map,
+    .irq_parse = my_pic_irq_parse,
+};
+
+static rt_err_t my_pic_probe(struct rt_platform_device *pdev)
+{
+    struct my_pic_data *priv;
+    rt_err_t ret;
+    
+    priv = rt_calloc(1, sizeof(*priv));
+    if (!priv)
+        return -RT_ENOMEM;
+    
+    /* Map registers */
+    priv->base = rt_dm_dev_iomap(&pdev->parent, 0);
+    if (!priv->base)
+    {
+        ret = -RT_ERROR;
+        goto err_free;
+    }
+    
+    /* Initialize PIC structure */
+    priv->pic.ops = &my_pic_ops;
+    priv->pic.priv_data = priv;
+    
+    /* Allocate IRQ range (32 interrupts) */
+    ret = rt_pic_linear_irq(&priv->pic, 32);
+    if (ret != RT_EOK)
+    {
+        rt_kprintf("Failed to allocate IRQs\n");
+        goto err_iounmap;
+    }
+    
+    /* Configure each IRQ */
+    for (int i = 0; i < 32; i++)
+    {
+        rt_pic_config_irq(&priv->pic, i, i);  /* Map 1:1 */
+    }
+    
+    /* Call user extensions if needed */
+    rt_pic_user_extends(&priv->pic);
+    
+    /* Initialize hardware */
+    writel(0xFFFFFFFF, priv->base + MY_PIC_DISABLE_REG);  /* Disable all */
+    writel(0xFFFFFFFF, priv->base + MY_PIC_CLEAR_REG);    /* Clear pending */
+    
+    rt_platform_set_drvdata(pdev, priv);
+    rt_kprintf("My PIC initialized with %d IRQs\n", 32);
+    
+    return RT_EOK;
+    
+err_iounmap:
+    rt_dm_dev_iounmap(&pdev->parent, priv->base);
+err_free:
+    rt_free(priv);
+    return ret;
+}
+
+static const struct rt_ofw_node_id my_pic_ofw_ids[] =
+{
+    { .compatible = "myvendor,my-pic" },
+    { /* sentinel */ }
+};
+
+static struct rt_platform_driver my_pic_driver =
+{
+    .name = "my-pic",
+    .ids = my_pic_ofw_ids,
+    .probe = my_pic_probe,
+};
+
+RT_PIC_OFW_DECLARE(my_pic, my_pic_ofw_ids, my_pic_probe);
+```
+
+## Best Practices
+
+### For Interrupt Consumers
+
+1. **Always disable interrupts during cleanup**:
+   ```c
+   rt_pic_irq_disable(irq);
+   rt_pic_detach_irq(irq, uid);
+   ```
+
+2. **Handle spurious interrupts**:
+   ```c
+   static void my_isr(int irq, void *param)
+   {
+       if (!check_interrupt_source())
+           return;  /* Spurious interrupt */
+       
+       /* Handle interrupt */
+   }
+   ```
+
+3. **Use EOI for level-triggered interrupts**:
+   ```c
+   static void my_isr(int irq, void *param)
+   {
+       handle_interrupt();
+       clear_interrupt_source();  /* Clear in device first */
+       rt_pic_irq_eoi(irq);       /* Then send EOI to PIC */
+   }
+   ```
+
+4. **Set appropriate priorities**:
+   - Critical real-time interrupts: 0-31 (highest)
+   - Normal device interrupts: 32-127
+   - Low-priority interrupts: 128-255
+
+5. **Consider CPU affinity on multi-core systems**:
+   ```c
+   /* Pin network interrupt to CPU 0 for better cache locality */
+   RT_IRQ_AFFINITY_DECLARE(mask);
+   rt_bitmap_clear(mask, RT_BITMAP_LEN(RT_CPUS_NR));
+   RT_IRQ_AFFINITY_SET(mask, 0);
+   rt_pic_irq_set_affinity(net_irq, mask);
+   ```
+
+### For PIC Providers
+
+1. **Implement minimum required operations**:
+   - `irq_enable`, `irq_disable`
+   - `irq_ack` or `irq_eoi`
+   - `irq_map`, `irq_parse`
+
+2. **Use `rt_pic_linear_irq` for simple IRQ allocation**:
+   ```c
+   ret = rt_pic_linear_irq(pic, num_irqs);
+   ```
+
+3. **Support cascading for hierarchical interrupt controllers**:
+   ```c
+   struct rt_pic_irq *parent_pirq = rt_pic_find_pirq(parent_pic, parent_irq);
+   rt_pic_cascade(child_pirq, parent_irq);
+   ```
+
+4. **Implement statistics support** (optional):
+   ```c
+   #ifdef RT_USING_PIC_STATISTICS
+   /* Framework tracks this automatically */
+   #endif
+   ```
+
+## Troubleshooting
+
+### Interrupt Not Firing
+
+1. **Check interrupt is enabled**:
+   ```c
+   rt_pic_irq_enable(irq);
+   ```
+
+2. **Verify device interrupt is not masked**:
+   - Check device-specific interrupt enable registers
+   - Ensure interrupt source is configured correctly
+
+3. **Confirm device tree configuration**:
+   - Verify `interrupts` property
+   - Check `interrupt-parent` is correct
+
+4. **Check trigger mode**:
+   - Edge vs. level triggered
+   - Active high vs. active low
+
+### Interrupt Storms
+
+1. **Always acknowledge/clear interrupts**:
+   ```c
+   /* Clear source BEFORE EOI */
+   clear_device_interrupt();
+   rt_pic_irq_eoi(irq);
+   ```
+
+2. **For level-triggered, clear condition**:
+   - Level-triggered interrupts re-assert if condition persists
+   - Must clear the underlying condition in the device
+
+### ISR Not Called
+
+1. **Verify IRQ number**:
+   ```c
+   rt_kprintf("Attached to IRQ %d\n", irq);
+   ```
+
+2. **Check MAX_HANDLERS**:
+   - Ensure IRQ < MAX_HANDLERS
+
+3. **Confirm attachment succeeded**:
+   ```c
+   ret = rt_pic_attach_irq(irq, isr, param, "name", 0);
+   if (ret != RT_EOK)
+       rt_kprintf("Attach failed: %d\n", ret);
+   ```
+
+### Priority/Affinity Not Working
+
+- Some PICs don't support priority or affinity
+- Check return value for `-RT_ENOSYS`
+- Verify hardware capabilities
+
+## Performance Considerations
+
+1. **Keep ISRs short**: Defer heavy processing to threads
+2. **Minimize register access**: Cache PIC state when possible
+3. **Use shared interrupts carefully**: Check device status first
+4. **Consider IRQ coalescing**: For high-rate interrupt sources
+5. **Profile with statistics**:
+   ```c
+   /* Enable RT_USING_PIC_STATISTICS */
+   /* Check /proc or debug output for timing data */
+   ```
+
+## Related Modules
+
+- **OFW (Device Tree)**: IRQ parsing and `interrupt-parent` resolution
+- **Platform Device**: `rt_platform_get_irq` for IRQ retrieval
+- **PCI**: MSI/MSI-X interrupt support via PIC
+- **Pinctrl**: GPIO interrupt configuration
+
+## References
+
+- ARM GIC Architecture Specification
+- Device Tree Interrupt Mapping Specification
+- RT-Thread Interrupt Management Documentation
+- `components/drivers/pic/pic.c` - Core implementation
+- `components/drivers/include/drivers/pic.h` - API header