From e8f5493e5daa4a508e2a60ceb0156019f2e02d63 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 13 Jun 2025 12:13:28 +0100 Subject: [PATCH] still works after split --- driver/Makefile | 3 +- driver/counter.c | 359 ----------------------------------------------- driver/init.c | 53 +++++++ driver/leds.c | 74 ++++++++++ driver/leds.h | 0 driver/ls7366r.c | 140 ++++++++++++++++++ driver/ls7366r.h | 3 + driver/trigger.c | 125 +++++++++++++++++ 8 files changed, 397 insertions(+), 360 deletions(-) delete mode 100644 driver/counter.c create mode 100644 driver/init.c create mode 100644 driver/leds.c create mode 100644 driver/leds.h create mode 100644 driver/ls7366r.c create mode 100644 driver/trigger.c diff --git a/driver/Makefile b/driver/Makefile index f1a25d5..765bb8b 100644 --- a/driver/Makefile +++ b/driver/Makefile @@ -1,10 +1,11 @@ NAME = counter obj-m += $(NAME).o +$(NAME)-objs := init.o leds.o ls7366r.o trigger.o all: $(NAME).ko $(NAME).dtbo echo Builded Device Tree Overlay and kernel module -$(NAME).ko: $(NAME).c +$(NAME).ko: init.c leds.c ls7366r.c trigger.c make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules $(NAME).dtbo: $(NAME).dts diff --git a/driver/counter.c b/driver/counter.c deleted file mode 100644 index e192cbd..0000000 --- a/driver/counter.c +++ /dev/null @@ -1,359 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ls7366r.h" - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Wolfgang Hottgenroth"); -MODULE_DESCRIPTION("A simple LKM to parse the device tree for a specific device and its properties"); - -/* leds stuff */ -static int dt_leds_probe(struct platform_device *pdev); -static void dt_leds_remove(struct platform_device *pdev); - -static struct of_device_id leds_driver_ids[] = { - { - .compatible = "hottis,leds", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, leds_driver_ids); - -static struct platform_driver leds_driver = { - .probe = dt_leds_probe, - .remove = dt_leds_remove, - .driver = { - .name = "leds_device_driver", - .of_match_table = leds_driver_ids, - }, -}; - -static struct gpio_desc *red_led = NULL; -static struct gpio_desc *blue_led = NULL; - -static int dt_leds_probe(struct platform_device *pdev) { - struct device *dev = &pdev->dev; - - printk("counter - leds probing\n"); - - if(!device_property_present(dev, "red-led-gpio")) { - printk("counter - Error! Device property 'red-led-gpio' not found!\n"); - return -1; - } - if(!device_property_present(dev, "blue-led-gpio")) { - printk("counter - Error! Device property 'blue-led-gpio' not found!\n"); - return -1; - } - - - /* Init GPIO */ - red_led = gpiod_get(dev, "red-led", GPIOD_OUT_LOW); - if(IS_ERR(red_led)) { - printk("counter - Error! Could not setup the GPIO red-led\n"); - return -1 * IS_ERR(red_led); - } - blue_led = gpiod_get(dev, "blue-led", GPIOD_OUT_LOW); - if(IS_ERR(blue_led)) { - printk("counter - Error! Could not setup the GPIO blue-led\n"); - return -1 * IS_ERR(blue_led); - } - - return 0; -} - -static void dt_leds_remove(struct platform_device *pdev) { - printk("counter - leds removing\n"); - gpiod_put(red_led); - gpiod_put(blue_led); -} - - -/* spi stuff */ -static int dt_ls7366r_probe(struct spi_device *client); -static void dt_ls7366r_remove(struct spi_device *client); - -/* LS7366R functions */ -static int writeCmd(struct spi_device *client, u8 c) { - u8 buf[1]; - buf[0] = c; - return spi_write(client, buf, 1); -} - -static int writeCmdData(struct spi_device *client, u8 c, u8 d) { - u8 buf[2]; - buf[0] = c; - buf[1] = d; - return spi_write(client, buf, 2); -} - -static int read32(struct spi_device *client, u8 c, u32 *r) { - u8 tx_buf[5]; - tx_buf[0] = c; - u8 rx_buf[5]; - struct spi_transfer t = { - .tx_buf = tx_buf, - .rx_buf = rx_buf, - .len = 5, - }; - int ret = spi_sync_transfer(client, &t, 1); - if (ret < 0) { - printk("counter - Error! spi_sync_transfer failed in read32\n"); - return ret; - } - *r = ((u32)rx_buf[1] << 24) | ((u32)rx_buf[2] << 16) | ((u32)rx_buf[3] << 8) | ((u32)rx_buf[4]); - return 0; -} - -static int read8(struct spi_device *client, u8 c, u8 *r) { - u8 tx_buf[2]; - tx_buf[0] = c; - u8 rx_buf[2]; - struct spi_transfer t = { - .tx_buf = tx_buf, - .rx_buf = rx_buf, - .len = 2, - }; - int ret = spi_sync_transfer(client, &t, 1); - if (ret < 0) { - printk("counter - Error! spi_sync_transfer failed in read8\n"); - return ret; - } - *r = rx_buf[1]; - return 0; -} - - -static struct of_device_id ls7366r_driver_ids[] = { - { - .compatible = "hottis,ls7366r", - }, {} -}; -MODULE_DEVICE_TABLE(of, ls7366r_driver_ids); - -static struct spi_device_id ls7366r[] = { - { "ls7366r", 0 }, - {}, -}; -MODULE_DEVICE_TABLE(spi, ls7366r); - -static struct spi_driver ls7366r_driver = { - .probe = dt_ls7366r_probe, - .remove = dt_ls7366r_remove, - .id_table = ls7366r, - .driver = { - .name = "ls7366r_device_driver", - .of_match_table = ls7366r_driver_ids, - }, -}; - -static struct spi_device *spi_client; - -static int dt_ls7366r_probe(struct spi_device *client) { - printk("counter - ls7366r probing\n"); - - int ret = spi_setup(client); - if (ret < 0) { - printk("counter - Error! Failed to set up the SPI bus\n"); - return ret; - } - - ret = writeCmd(client, CMD_CLR | REG_STR); - if (ret < 0) { - printk("counter - Error! writeCmd 1 failed in probe\n"); - return ret; - } - ret = writeCmd(client, CMD_CLR | REG_CNTR); - if (ret < 0) { - printk("counter - Error! writeCmd 2 failed in probe\n"); - return ret; - } - ret = writeCmdData(client, CMD_WR | REG_MDR0, MDR0_ILO); - if (ret < 0) { - printk("counter - Error! writeCmdData failed in probe\n"); - return ret; - } - - u8 x; - ret = read8(client, CMD_RD | REG_MDR0, &x); - if (ret < 0) { - printk("counter - Error! read8 failed in probe\n"); - return ret; - } - if (x != MDR0_ILO) { - printk("counter - Error! failed to initialize counter\n"); - return -1; - } - - spi_client = client; - - return 0; -} - -static void dt_ls7366r_remove(struct spi_device *client) { - printk("counter - ls7366r removing\n"); -} - - -/* 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); - -static 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 = read32(data->client, CMD_RD | REG_OTR, &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 - Info! ts = %llu, duration = %llu, period = %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 = 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); -} - - - -/* module loading and unloading */ -static int __init my_init(void) { - printk("counter - Loading the leds driver...\n"); - if(platform_driver_register(&leds_driver)) { - printk("dt_gpio - Error! Could not load leds driver\n"); - return -1; - } - - printk("counter - Loading the ls7366r driver...\n"); - if (spi_register_driver(&ls7366r_driver)) { - printk("counter - Error! Could not load spi driver\n"); - return -1; - } - - printk("counter - Loading the interrupt driver...\n"); - if(platform_driver_register(&interrupt_driver)) { - printk("dt_gpio - Error! Could not load interrupt driver\n"); - return -1; - } - - - printk("counter - red led on\n"); - gpiod_set_value(red_led, 1); - - return 0; -} - -static void __exit my_exit(void) { - printk("counter - red led off\n"); - gpiod_set_value(red_led, 0); - - printk("counter - Unloading the leds driver...\n"); - platform_driver_unregister(&leds_driver); - - printk("counter - Unloading the ls7366r driver...\n"); - spi_unregister_driver(&ls7366r_driver); - - printk("counter - Unloading the interrupt driver...\n"); - platform_driver_unregister(&interrupt_driver); -} - -module_init(my_init); -module_exit(my_exit); - - diff --git a/driver/init.c b/driver/init.c new file mode 100644 index 0000000..5b0104d --- /dev/null +++ b/driver/init.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Wolfgang Hottgenroth"); +MODULE_DESCRIPTION("A simple LKM to parse the device tree for a specific device and its properties"); + + +extern struct platform_driver leds_driver; +extern struct spi_driver ls7366r_driver; +extern struct platform_driver interrupt_driver; + +/* module loading and unloading */ +static int __init my_init(void) { + printk("counter - Loading the leds driver...\n"); + if(platform_driver_register(&leds_driver)) { + printk("dt_gpio - Error! Could not load leds driver\n"); + return -1; + } + + printk("counter - Loading the ls7366r driver...\n"); + if (spi_register_driver(&ls7366r_driver)) { + printk("counter - Error! Could not load spi driver\n"); + return -1; + } + + printk("counter - Loading the interrupt driver...\n"); + if(platform_driver_register(&interrupt_driver)) { + printk("dt_gpio - Error! Could not load interrupt driver\n"); + return -1; + } + + return 0; +} + +static void __exit my_exit(void) { + printk("counter - Unloading the leds driver...\n"); + platform_driver_unregister(&leds_driver); + + printk("counter - Unloading the ls7366r driver...\n"); + spi_unregister_driver(&ls7366r_driver); + + printk("counter - Unloading the interrupt driver...\n"); + platform_driver_unregister(&interrupt_driver); +} + +module_init(my_init); +module_exit(my_exit); + + diff --git a/driver/leds.c b/driver/leds.c new file mode 100644 index 0000000..17bfe43 --- /dev/null +++ b/driver/leds.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include + + +/* leds stuff */ +static int dt_leds_probe(struct platform_device *pdev); +static void dt_leds_remove(struct platform_device *pdev); + +static struct of_device_id leds_driver_ids[] = { + { + .compatible = "hottis,leds", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, leds_driver_ids); + +struct platform_driver leds_driver = { + .probe = dt_leds_probe, + .remove = dt_leds_remove, + .driver = { + .name = "leds_device_driver", + .of_match_table = leds_driver_ids, + }, +}; + +static struct gpio_desc *red_led = NULL; +static struct gpio_desc *blue_led = NULL; + +static int dt_leds_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + + printk("counter - leds probing\n"); + + if(!device_property_present(dev, "red-led-gpio")) { + printk("counter - Error! Device property 'red-led-gpio' not found!\n"); + return -1; + } + if(!device_property_present(dev, "blue-led-gpio")) { + printk("counter - Error! Device property 'blue-led-gpio' not found!\n"); + return -1; + } + + + /* Init GPIO */ + red_led = gpiod_get(dev, "red-led", GPIOD_OUT_LOW); + if(IS_ERR(red_led)) { + printk("counter - Error! Could not setup the GPIO red-led\n"); + return -1 * IS_ERR(red_led); + } + blue_led = gpiod_get(dev, "blue-led", GPIOD_OUT_LOW); + if(IS_ERR(blue_led)) { + printk("counter - Error! Could not setup the GPIO blue-led\n"); + return -1 * IS_ERR(blue_led); + } + + printk("counter - red led on\n"); + gpiod_set_value(red_led, 1); + + return 0; +} + +static void dt_leds_remove(struct platform_device *pdev) { + printk("counter - red led off\n"); + gpiod_set_value(red_led, 0); + + printk("counter - leds removing\n"); + gpiod_put(red_led); + gpiod_put(blue_led); +} diff --git a/driver/leds.h b/driver/leds.h new file mode 100644 index 0000000..e69de29 diff --git a/driver/ls7366r.c b/driver/ls7366r.c new file mode 100644 index 0000000..8155f7d --- /dev/null +++ b/driver/ls7366r.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ls7366r.h" + + +/* spi stuff */ +static int dt_ls7366r_probe(struct spi_device *client); +static void dt_ls7366r_remove(struct spi_device *client); + +/* LS7366R functions */ +static int writeCmd(struct spi_device *client, u8 c) { + u8 buf[1]; + buf[0] = c; + return spi_write(client, buf, 1); +} + +static int writeCmdData(struct spi_device *client, u8 c, u8 d) { + u8 buf[2]; + buf[0] = c; + buf[1] = d; + return spi_write(client, buf, 2); +} + +int read32(struct spi_device *client, u8 c, u32 *r) { + u8 tx_buf[5]; + tx_buf[0] = c; + u8 rx_buf[5]; + struct spi_transfer t = { + .tx_buf = tx_buf, + .rx_buf = rx_buf, + .len = 5, + }; + int ret = spi_sync_transfer(client, &t, 1); + if (ret < 0) { + printk("counter - Error! spi_sync_transfer failed in read32\n"); + return ret; + } + *r = ((u32)rx_buf[1] << 24) | ((u32)rx_buf[2] << 16) | ((u32)rx_buf[3] << 8) | ((u32)rx_buf[4]); + return 0; +} + +static int read8(struct spi_device *client, u8 c, u8 *r) { + u8 tx_buf[2]; + tx_buf[0] = c; + u8 rx_buf[2]; + struct spi_transfer t = { + .tx_buf = tx_buf, + .rx_buf = rx_buf, + .len = 2, + }; + int ret = spi_sync_transfer(client, &t, 1); + if (ret < 0) { + printk("counter - Error! spi_sync_transfer failed in read8\n"); + return ret; + } + *r = rx_buf[1]; + return 0; +} + + +static struct of_device_id ls7366r_driver_ids[] = { + { + .compatible = "hottis,ls7366r", + }, {} +}; +MODULE_DEVICE_TABLE(of, ls7366r_driver_ids); + +static struct spi_device_id ls7366r[] = { + { "ls7366r", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(spi, ls7366r); + +struct spi_driver ls7366r_driver = { + .probe = dt_ls7366r_probe, + .remove = dt_ls7366r_remove, + .id_table = ls7366r, + .driver = { + .name = "ls7366r_device_driver", + .of_match_table = ls7366r_driver_ids, + }, +}; + +struct spi_device *ls7366r_spi_client; + +static int dt_ls7366r_probe(struct spi_device *client) { + printk("counter - ls7366r probing\n"); + + int ret = spi_setup(client); + if (ret < 0) { + printk("counter - Error! Failed to set up the SPI bus\n"); + return ret; + } + + ret = writeCmd(client, CMD_CLR | REG_STR); + if (ret < 0) { + printk("counter - Error! writeCmd 1 failed in probe\n"); + return ret; + } + ret = writeCmd(client, CMD_CLR | REG_CNTR); + if (ret < 0) { + printk("counter - Error! writeCmd 2 failed in probe\n"); + return ret; + } + ret = writeCmdData(client, CMD_WR | REG_MDR0, MDR0_ILO); + if (ret < 0) { + printk("counter - Error! writeCmdData failed in probe\n"); + return ret; + } + + u8 x; + ret = read8(client, CMD_RD | REG_MDR0, &x); + if (ret < 0) { + printk("counter - Error! read8 failed in probe\n"); + return ret; + } + if (x != MDR0_ILO) { + printk("counter - Error! failed to initialize counter\n"); + return -1; + } + + ls7366r_spi_client = client; + + return 0; +} + +static void dt_ls7366r_remove(struct spi_device *client) { + printk("counter - ls7366r removing\n"); +} + diff --git a/driver/ls7366r.h b/driver/ls7366r.h index 3388dba..3c13b71 100644 --- a/driver/ls7366r.h +++ b/driver/ls7366r.h @@ -50,4 +50,7 @@ #define MDR1_F_BW 0b01000000 #define MDR1_F_CY 0b10000000 + +int read32(struct spi_device *client, u8 c, u32 *r); + #endif /* _LS7366R_H_ */ diff --git a/driver/trigger.c b/driver/trigger.c new file mode 100644 index 0000000..feb6e51 --- /dev/null +++ b/driver/trigger.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ls7366r.h" + + + +extern struct spi_device *ls7366r_spi_client; + + +/* 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 = read32(data->client, CMD_RD | REG_OTR, &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 - Info! ts = %llu, duration = %llu, period = %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); +} +