From f0f671c6fb3a5bd556c98b895203a7eee68f8a07 Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Fri, 1 Nov 2019 12:50:05 +0100 Subject: [PATCH] ioc: kernel-driver: Create framework for serdev driver --- ioc/kernel-driver/.gitignore | 2 + ioc/kernel-driver/Makefile | 14 +-- ioc/kernel-driver/device-tree-opi-pc.dtb | 28 ----- ioc/kernel-driver/device-tree-opi-pc.patch | 18 ++++ ioc/kernel-driver/lw35-ioc.c | 78 -------------- ioc/kernel-driver/lw35ioc.c | 102 ++++++++++++++++++ .../{lw35-ioc.pro => lw35ioc.pro} | 2 +- 7 files changed, 130 insertions(+), 114 deletions(-) delete mode 100644 ioc/kernel-driver/device-tree-opi-pc.dtb create mode 100644 ioc/kernel-driver/device-tree-opi-pc.patch delete mode 100644 ioc/kernel-driver/lw35-ioc.c create mode 100644 ioc/kernel-driver/lw35ioc.c rename ioc/kernel-driver/{lw35-ioc.pro => lw35ioc.pro} (88%) diff --git a/ioc/kernel-driver/.gitignore b/ioc/kernel-driver/.gitignore index f7f5fc8..19db6bf 100644 --- a/ioc/kernel-driver/.gitignore +++ b/ioc/kernel-driver/.gitignore @@ -4,3 +4,5 @@ modules.order Module.symvers *.pro.user +.* +*.a diff --git a/ioc/kernel-driver/Makefile b/ioc/kernel-driver/Makefile index a68eff4..c8ea8a3 100644 --- a/ioc/kernel-driver/Makefile +++ b/ioc/kernel-driver/Makefile @@ -1,12 +1,12 @@ -obj-m := lw35-ioc.o -KDIR := ~/projects/arm-linux/current +obj-m := lw35ioc.o +KDIR := ~/projects/linux/opi-current PWD := $(shell pwd) -default: lw35-ioc.ko -lw35-ioc.ko: lw35-ioc.c - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules +default: lw35ioc.ko +lw35ioc.ko: lw35ioc.c + $(MAKE) -C $(KDIR) M=$(PWD) -deploy: lw35-ioc.ko - scp $< markus@opi:/home/markus/lw35-ioc/deploy +deploy: lw35ioc.ko + scp $< markus@opi:/home/markus/projects/lw35/deploy/ clean: rm -f ./*.o ./*.ko ./*.mod.c modules.order Module.symvers diff --git a/ioc/kernel-driver/device-tree-opi-pc.dtb b/ioc/kernel-driver/device-tree-opi-pc.dtb deleted file mode 100644 index 24d23dd..0000000 --- a/ioc/kernel-driver/device-tree-opi-pc.dtb +++ /dev/null @@ -1,28 +0,0 @@ -/* - Reading: https://www.kernel.org/doc/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt -*/ - -&spi1 { - status = "okay"; - lw35ioc@0 { - compatible = "brother,lw35ioc"; - reg = <0x0>; - spi-max-frequency = <2000000>; - - pinctrl-names = "default"; - pinctrl-0 = <&lw35ioc>; - data-gpios = <&pio 0 7 GPIO_ACTIVE_HIGH>; /* TODO: get real IO num */ - - interrupt-parent = <&pio>; - interrupts = <52 2>; - }; -}; - -&pio { - lmg6202ulyt_opc: lmg6202ulyt_pins { - pins = "PA7"; - function = "gpio_out"; - interrupt-controller; - #interrupt-cells = <1>; - }; -}; diff --git a/ioc/kernel-driver/device-tree-opi-pc.patch b/ioc/kernel-driver/device-tree-opi-pc.patch new file mode 100644 index 0000000..43c7d73 --- /dev/null +++ b/ioc/kernel-driver/device-tree-opi-pc.patch @@ -0,0 +1,18 @@ +diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts +index 5aff8ecc66cb..c8201e79dff3 100644 +--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts ++++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts +@@ -211,9 +211,12 @@ + }; + + &uart1 { ++ status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; +- status = "disabled"; ++ lw35ioc@0 { ++ compatible = "brother,lw35"; ++ }; + }; + + &uart2 { diff --git a/ioc/kernel-driver/lw35-ioc.c b/ioc/kernel-driver/lw35-ioc.c deleted file mode 100644 index 68338c7..0000000 --- a/ioc/kernel-driver/lw35-ioc.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * irq in general: https://notes.shichao.io/lkd/ch7/ - * raspi irqs: http://morethanuser.blogspot.com/2013/04/raspberry-pi-gpio-interrupts-in-kernel.html - * kdoc devtree irq: https://www.kernel.org/doc/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt - * GPIOD doc (including irq): https://www.kernel.org/doc/Documentation/gpio/consumer.txt - */ - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Markus Koch"); -MODULE_DESCRIPTION("LW35 I/O Controller Driver"); -MODULE_VERSION("0.1"); - -static char *testparam = "param"; -module_param(testparam, charp, S_IRUGO); -MODULE_PARM_DESC(testparam, "A test parameter"); - -static struct of_device_id lw35ioc_dt_ids[] = { -{ .compatible = "brother,lw35", }, -{ /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, lw35ioc_dt_ids); - -struct lw35ioc_priv { - struct spi_device *spi; - - // USER VARS HERE -}; - -static int lw35ioc_probe(struct spi_device *spi) -{ - struct lw35ioc_priv *priv = NULL; - - printk(KERN_INFO "lw35ioc: probe\n"); - - priv = devm_kzalloc(&spi->dev, - sizeof(struct lw35ioc_priv), - GFP_KERNEL); - if (!priv) - return -ENOMEM; - spi_set_drvdata(spi, priv); - - priv->spi = spi; - - printk(KERN_INFO "lw35ioc: Loaded driver\n"); - - return 0; - - // Error handlers go here -} - -static int lw35ioc_remove(struct spi_device *spi) -{ - struct lw35ioc_priv *priv = spi_get_drvdata(spi); - - return 0; -} - -static struct spi_driver lw35ioc_driver = { - .probe = lw35ioc_probe, - .remove = lw35ioc_remove, - .driver = { - .name = "lw35ioc", - .owner = THIS_MODULE, - .of_match_table = lw35ioc_dt_ids, - }, -}; -module_spi_driver(lw35ioc_driver); - diff --git a/ioc/kernel-driver/lw35ioc.c b/ioc/kernel-driver/lw35ioc.c new file mode 100644 index 0000000..b313966 --- /dev/null +++ b/ioc/kernel-driver/lw35ioc.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Markus Koch"); +MODULE_DESCRIPTION("LW-35 I/O Controller Driver"); +MODULE_VERSION("0.1"); + +static int debug_level = 0; +module_param(debug_level, int, 0); +MODULE_PARM_DESC(debug_level, "Debug level"); + +static struct of_device_id lw35ioc_dt_ids[] = { +{ .compatible = "brother,lw35", }, +{ /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, lw35ioc_dt_ids); + +struct lw35ioc_priv { + struct serdev_device *serdev; + + // USER VARS HERE +}; + +static int lw35ioc_receive_buf(struct serdev_device *serdev, + const unsigned char *data, + size_t count) +{ + dev_info(&serdev->dev, "RX: %c\n", data[0]); + return 1; // TODO: return proper value +} + +static void lw35ioc_write_wakeup(struct serdev_device *serdev) +{ + dev_info(&serdev->dev, "Write wakeup\n"); + // schedule work here +} + +static struct serdev_device_ops lw35ioc_serdev_ops = { + .receive_buf = lw35ioc_receive_buf, + .write_wakeup = lw35ioc_write_wakeup, +}; + +static int lw35ioc_probe(struct serdev_device *serdev) +{ + struct lw35ioc_priv *priv = NULL; + int ret; + u32 speed = 9600; + + printk(KERN_INFO "lw35ioc: probe\n"); + + priv = devm_kzalloc(&serdev->dev, + sizeof(struct lw35ioc_priv), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + priv->serdev = serdev; + serdev_device_set_drvdata(serdev, priv); + serdev_device_set_client_ops(serdev, &lw35ioc_serdev_ops); + + ret = serdev_device_open(serdev); + if (ret) { + dev_err(&serdev->dev, "Unable to open device.\n"); + goto fail0; + } + + speed = serdev_device_set_baudrate(serdev, speed); + dev_info(&serdev->dev, "Using baudrate: %u\n", speed); + + dev_info(&serdev->dev, "Loaded driver\n"); + + return 0; + +fail0: + return ret; +} + +static void lw35ioc_remove(struct serdev_device *serdev) +{ + struct lw35ioc_priv *priv = serdev_device_get_drvdata(serdev); + dev_info(&serdev->dev, "remove\n"); + return; +} + +static struct serdev_device_driver lw35ioc_driver = { + .probe = lw35ioc_probe, + .remove = lw35ioc_remove, + .driver = { + .name = "lw35ioc", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(lw35ioc_dt_ids), + }, +}; + +module_serdev_device_driver(lw35ioc_driver); + diff --git a/ioc/kernel-driver/lw35-ioc.pro b/ioc/kernel-driver/lw35ioc.pro similarity index 88% rename from ioc/kernel-driver/lw35-ioc.pro rename to ioc/kernel-driver/lw35ioc.pro index e80adec..445dc6f 100644 --- a/ioc/kernel-driver/lw35-ioc.pro +++ b/ioc/kernel-driver/lw35ioc.pro @@ -6,4 +6,4 @@ CONFIG -= qt INCLUDEPATH += /home/markus/projects/arm-linux/current/include SOURCES += \ - lw35-ioc.c + lw35ioc.c