#include #include #include #include #include #include #include #include #include #include #include #include "ls7366r.h" /* interrupt stuff */ static int dt_interrupt_probe(struct platform_device *pdev); static void dt_interrupt_remove(struct platform_device *pdev); static struct of_device_id interrupt_driver_ids[] = { { .compatible = "hottis,intr", }, {}, }; MODULE_DEVICE_TABLE(of, interrupt_driver_ids); struct platform_driver interrupt_driver = { .probe = dt_interrupt_probe, .remove = dt_interrupt_remove, .driver = { .name = "interrupt_device_driver", .of_match_table = interrupt_driver_ids, }, }; static struct gpio_desc *counter_interrupt; static int irq_number; // workqueue struct counter_irq_data { struct work_struct work; u64 timestamp; struct spi_device *client; u64 last_timestamp; u32 last_value; }; static struct counter_irq_data counter_irq_wq_data; static void counter_worker(struct work_struct *work) { struct counter_irq_data *data = container_of(work, struct counter_irq_data, work); u64 ts = data->timestamp; u32 counter_value; int ret = read_otr(data->client, &counter_value); if (ret < 0) { printk("counter - Error! read32 failed in counter_worker\n"); return; } if (data->last_value) { u32 period = counter_value - data->last_value; u64 duration = ts - data->last_timestamp; printk("counter %llu %llu %u\n", ts, duration, period); } data->last_value = counter_value; data->last_timestamp = ts; } // ISR static irqreturn_t counter_isr(int irq, void *dev_id) { counter_irq_wq_data.timestamp = ktime_get(); schedule_work(&counter_irq_wq_data.work); return IRQ_HANDLED; } static int dt_interrupt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; printk("counter - interrupt probing\n"); INIT_WORK(&counter_irq_wq_data.work, counter_worker); counter_irq_wq_data.client = ls7366r_spi_client; counter_irq_wq_data.last_value = 0; counter_irq_wq_data.last_timestamp = 0; counter_interrupt = gpiod_get(dev, "intr", GPIOD_IN); if (IS_ERR(counter_interrupt)) { printk("counter - Error! Could not setup the GPIO intr\n"); return -1 * IS_ERR(counter_interrupt); } irq_number = gpiod_to_irq(counter_interrupt); if (irq_number < 0) { printk("counter - Error! Could not map GPIO to IRQ\n"); gpiod_put(counter_interrupt); return irq_number; } printk("counter - Info! IRQ %d assigned\n", irq_number); int ret = request_irq(irq_number, counter_isr, IRQF_TRIGGER_RISING, "gpio19_irq", dev); if (ret) { printk("counter - Error! Could not request IRQ\n"); gpiod_put(counter_interrupt); return ret; } printk("counter - Info! Interrupt assigned\n"); return 0; } static void dt_interrupt_remove(struct platform_device *pdev) { printk("counter - interrupt removing\n"); struct device *dev = &pdev->dev; free_irq(irq_number, dev); gpiod_put(counter_interrupt); }