From 3714d84481c151e004e621c7186488282cc7b9d7 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 13 Jun 2025 07:56:37 +0100 Subject: [PATCH 1/2] still works 2 --- driver/counter.c | 92 ++++++++++++++++++++++++++++++++++++---------- driver/counter.dts | 32 ++++++++++++++-- 2 files changed, 102 insertions(+), 22 deletions(-) diff --git a/driver/counter.c b/driver/counter.c index c03bc25..2cccc00 100644 --- a/driver/counter.c +++ b/driver/counter.c @@ -5,6 +5,7 @@ #include #include #include +#include /* Meta Information */ MODULE_LICENSE("GPL"); @@ -12,22 +13,22 @@ MODULE_AUTHOR("Wolfgang Hottgenroth"); MODULE_DESCRIPTION("A simple LKM to parse the device tree for a specific device and its properties"); /* Declate the probe and remove functions */ -static int dt_probe(struct platform_device *pdev); -static void dt_remove(struct platform_device *pdev); +static int dt_leds_probe(struct platform_device *pdev); +static void dt_leds_remove(struct platform_device *pdev); -static struct of_device_id my_driver_ids[] = { +static struct of_device_id leds_driver_ids[] = { { - .compatible = "hottis,counter", + .compatible = "hottis,leds", }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, my_driver_ids); +MODULE_DEVICE_TABLE(of, leds_driver_ids); -static struct platform_driver my_driver = { - .probe = dt_probe, - .remove = dt_remove, +static struct platform_driver leds_driver = { + .probe = dt_leds_probe, + .remove = dt_leds_remove, .driver = { - .name = "my_device_driver", - .of_match_table = my_driver_ids, + .name = "leds_device_driver", + .of_match_table = leds_driver_ids, }, }; @@ -36,13 +37,40 @@ static struct gpio_desc *red_led = NULL; static struct gpio_desc *blue_led = NULL; +/* spi stuff */ +static int dt_ls7366r_probe(struct spi_device *client); +static void dt_ls7366r_remove(struct spi_device *client); + +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, + }, +}; + /** * @brief This function is called on loading the driver */ -static int dt_probe(struct platform_device *pdev) { +static int dt_leds_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - printk("counter - probing\n"); + printk("counter - leds probing\n"); if(!device_property_present(dev, "red-led-gpio")) { printk("counter - Error! Device property 'red-led-gpio' not found!\n"); @@ -72,22 +100,46 @@ static int dt_probe(struct platform_device *pdev) { /** * @brief This function is called on unloading the driver */ -static void dt_remove(struct platform_device *pdev) { - printk("counter - removing\n"); +static void dt_leds_remove(struct platform_device *pdev) { + printk("counter - leds removing\n"); gpiod_put(red_led); gpiod_put(blue_led); } +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; + } + + return 0; +} + + +static void dt_ls7366r_remove(struct spi_device *client) { + printk("counter - ls7366r removing\n"); +} + + /** * @brief This function is called, when the module is loaded into the kernel */ static int __init my_init(void) { - printk("counter - Loading the driver...\n"); - if(platform_driver_register(&my_driver)) { + printk("counter - Loading the leds driver...\n"); + if(platform_driver_register(&leds_driver)) { printk("dt_gpio - Error! Could not load 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 - red led on\n"); gpiod_set_value(red_led, 1); @@ -98,12 +150,14 @@ static int __init my_init(void) { * @brief This function is called, when the module is removed from the kernel */ static void __exit my_exit(void) { - printk("counter - Unload driver"); - printk("counter - red led off\n"); gpiod_set_value(red_led, 0); - platform_driver_unregister(&my_driver); + printk("counter - Unloading the leds driver...\n"); + platform_driver_unregister(&leds_driver); + + printk("counter - Unloading the ls7366r driver...\n"); + spi_unregister_driver(&ls7366r_driver); } module_init(my_init); diff --git a/driver/counter.dts b/driver/counter.dts index 442f794..2c9ef42 100644 --- a/driver/counter.dts +++ b/driver/counter.dts @@ -3,14 +3,40 @@ / { compatible = "brcm,bcm2835"; fragment@0 { - target-path = "/"; + target-path = "/soc"; __overlay__ { status = "okay"; - counter { - compatible = "hottis,counter"; + + leds { + compatible = "hottis,leds"; red-led-gpio = <&gpio 26 0>; blue-led-gpio = <&gpio 21 0>; }; }; }; + + fragment@1 { + target = <&spidev0>; + __overlay__ { + status = "disabled"; + }; + }; + + fragment@2 { + target = <&spi0>; + __overlay__ { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + ls7366r: ls7366r0@0 { + compatible = "hottis,ls7366r"; + reg = <0x0>; + spi-max-frequency = <1000000>; + spi-bits-per-word = <8>; + status = "okay"; + }; + }; + }; + }; From 581de7dabd7b2cca23576bf35856037ed8d29962 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Fri, 13 Jun 2025 09:47:13 +0100 Subject: [PATCH 2/2] spi working, counter seems to --- driver/counter.c | 168 +++++++++++++++++++++++++++++++++------------ driver/counter.dts | 2 +- driver/ls7366r.h | 53 ++++++++++++++ 3 files changed, 177 insertions(+), 46 deletions(-) create mode 100644 driver/ls7366r.h diff --git a/driver/counter.c b/driver/counter.c index 2cccc00..ff2ea69 100644 --- a/driver/counter.c +++ b/driver/counter.c @@ -7,19 +7,22 @@ #include #include -/* Meta Information */ +#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"); -/* Declate the probe and remove functions */ +/* 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", - }, { /* sentinel */ } + }, + {}, }; MODULE_DEVICE_TABLE(of, leds_driver_ids); @@ -32,41 +35,9 @@ static struct platform_driver leds_driver = { }, }; -/* GPIO variable */ static struct gpio_desc *red_led = NULL; static struct gpio_desc *blue_led = NULL; - -/* spi stuff */ -static int dt_ls7366r_probe(struct spi_device *client); -static void dt_ls7366r_remove(struct spi_device *client); - -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, - }, -}; - -/** - * @brief This function is called on loading the driver - */ static int dt_leds_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -97,15 +68,95 @@ static int dt_leds_probe(struct platform_device *pdev) { return 0; } -/** - * @brief This function is called on unloading the driver - */ 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; + } + printk("counter - Info! rx_buf: %02x %02x %02x %02x %02x\n", rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3], rx_buf[4]); + *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; + } + printk("counter - Info! rx_buf: %02x %02x\n", rx_buf[0], rx_buf[1]); + *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 int dt_ls7366r_probe(struct spi_device *client) { printk("counter - ls7366r probing\n"); @@ -115,18 +166,48 @@ static int dt_ls7366r_probe(struct spi_device *client) { 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; + } + printk("counter - Info! x = %02x\n", x); + + u32 y; + ret = read32(client, CMD_RD | REG_OTR, &y); + if (ret < 0) { + printk("counter - Error! read32 failed in probe\n"); + return ret; + } + printk("counter - Info! y = %d\n", y); + + return 0; } - static void dt_ls7366r_remove(struct spi_device *client) { printk("counter - ls7366r removing\n"); } -/** - * @brief This function is called, when the module is loaded into the kernel - */ +/* module loading and unloading */ static int __init my_init(void) { printk("counter - Loading the leds driver...\n"); if(platform_driver_register(&leds_driver)) { @@ -146,9 +227,6 @@ static int __init my_init(void) { return 0; } -/** - * @brief This function is called, when the module is removed from the kernel - */ static void __exit my_exit(void) { printk("counter - red led off\n"); gpiod_set_value(red_led, 0); diff --git a/driver/counter.dts b/driver/counter.dts index 2c9ef42..136909f 100644 --- a/driver/counter.dts +++ b/driver/counter.dts @@ -29,7 +29,7 @@ #address-cells = <1>; #size-cells = <0>; - ls7366r: ls7366r0@0 { + ls7366r: ls7366r@0 { compatible = "hottis,ls7366r"; reg = <0x0>; spi-max-frequency = <1000000>; diff --git a/driver/ls7366r.h b/driver/ls7366r.h new file mode 100644 index 0000000..3388dba --- /dev/null +++ b/driver/ls7366r.h @@ -0,0 +1,53 @@ +#ifndef _LS7366R_H_ +#define _LS7366R_H_ + +#define REG_MDR0 0b00001000 +#define REG_MDR1 0b00010000 +#define REG_DTR 0b00011000 +#define REG_CNTR 0b00100000 +#define REG_OTR 0b00101000 +#define REG_STR 0b00110000 + +#define CMD_CLR 0b00000000 +#define CMD_RD 0b01000000 +#define CMD_WR 0b10000000 +#define CMD_LOAD 0b11000000 + +#define STR_CY 0b10000000 +#define STR_BW 0b01000000 +#define STR_CMP 0b00100000 +#define STR_IDX 0b00010000 +#define STR_CEN 0b00001000 +#define STR_PLS 0b00000100 +#define STR_UD 0b00000010 +#define STR_S 0b00000001 + +#define MDR0_NOQ 0b00000000 +#define MDR0_Q1 0b00000001 +#define MDR0_Q2 0b00000010 +#define MDR0_Q4 0b00000011 +#define MDR0_FRC 0b00000000 +#define MDR0_SCC 0b00000100 +#define MDR0_RLC 0b00001000 +#define MDR0_MNC 0b00001100 +#define MDR0_DI 0b00000000 +#define MDR0_ILC 0b00010000 +#define MDR0_IRC 0b00100000 +#define MDR0_ILO 0b00110000 +#define MDR0_AI 0b00000000 +#define MDR0_SI 0b01000000 +#define MDR0_FC1 0b00000000 +#define MDR0_FC2 0b10000000 + +#define MDR1_4CM 0b00000000 +#define MDR1_3CM 0b00000001 +#define MDR1_2CM 0b00000010 +#define MDR1_1CM 0b00000011 +#define MDR1_EC 0b00000000 +#define MDR1_DC 0b00000100 +#define MDR1_F_IDX 0b00010000 +#define MDR1_F_CMP 0b00100000 +#define MDR1_F_BW 0b01000000 +#define MDR1_F_CY 0b10000000 + +#endif /* _LS7366R_H_ */