diff options
author | lonkaars <loek@pipeframe.xyz> | 2024-05-12 15:21:19 +0200 |
---|---|---|
committer | lonkaars <loek@pipeframe.xyz> | 2024-05-12 15:21:19 +0200 |
commit | 891595b9307eb2695411d8e32e4addd9cd927ec8 (patch) | |
tree | b24c323ad3e09f05ca75386ac8fef38a6fff3e74 /driver/main.c | |
parent | 6926a88695ce2e9fca51e01a1bf6fded3e4cbcca (diff) |
rename folders
Diffstat (limited to 'driver/main.c')
-rw-r--r-- | driver/main.c | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/driver/main.c b/driver/main.c new file mode 100644 index 0000000..d8ea7fc --- /dev/null +++ b/driver/main.c @@ -0,0 +1,110 @@ +#include <linux/cdev.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/io.h> + +#include "fopdrv.h" +#include "config.h" + +int one = 0; +module_param(one, int, 0400); +MODULE_PARM_DESC(one, "first parameter, only printed on init"); + +int not_named_two = 0; +module_param_named(two, not_named_two, int, 0400); +MODULE_PARM_DESC(not_named_two, "second parameter, only printed on init"); + +struct cdev *cdev; +struct device *dev; +struct class *class; +dev_t node; +struct file_operations fops = { + .read = fop_read, + .write = fop_write, + .open = fop_open, + .release = fop_release, +}; + +static int mod_init(void) { + int err; + + err = alloc_chrdev_region(&node, 0, 1, DRV_NAME); + if (err < 0) { + printk(KERN_ERR "alloc_chrdev_region error %d\n", err); + goto return_err; + } + + class = class_create(DRV_NAME); + if (IS_ERR_OR_NULL(class)) { + err = PTR_ERR(class); + printk(KERN_ERR "class_create error %d\n", err); + goto free_class; + } + + cdev = cdev_alloc(); + if (!cdev) { + err = ENOMEM; + goto free_cdev; + } + + cdev->ops = &fops; + cdev_init(cdev, &fops); + err = cdev_add(cdev, node, 1); + if (err < 0) { + printk(KERN_ERR "cdev_add error %d\n", err); + goto free_cdev; + } + + dev = device_create(class, NULL, node, NULL, DRV_NAME); + if (IS_ERR_OR_NULL(dev)) { + err = PTR_ERR(dev); + printk(KERN_ERR "device_create error %d\n", err); + goto free_device; + } + + printk("%s() -> 0 (%d:%d)\n", __PRETTY_FUNCTION__, MAJOR(node), MINOR(node)); + printk("one = %d, two = %d\n", one, not_named_two); + + // configure gpio mux + uint32_t* conf_gpmc_a3 = ioremap(TI_AM335X_CM_GPMC_A3_ADDR, sizeof(ti_am335x_word_t)); + if (conf_gpmc_a3 == NULL) + return -EINVAL; + barrier(); + uint32_t val = ioread32(conf_gpmc_a3); rmb(); + val &= ~0x7; + val |= 0x7; + iowrite32(val, conf_gpmc_a3); wmb(); + iounmap(conf_gpmc_a3); + + // configure output pin + ti_am335x_word_t* gpio1 = ioremap(TI_AM335X_GPIO1_ADDR, GPIO_REG_SIZE); + barrier(); + ti_am335x_word_t oe_reg = ioread32(gpio1 + GPIO_OE); rmb(); + oe_reg &= ~(1<<PIN); // 0=output + iowrite32(oe_reg, gpio1 + GPIO_OE); wmb(); + iounmap(gpio1); + + return 0; + +free_device: + device_destroy(class, node); +free_cdev: + cdev_del(cdev); +free_class: + class_destroy(class); +return_err: + printk("%s() -> %d\n", __PRETTY_FUNCTION__, err); + return err; +} + +static void mod_exit(void) { + device_destroy(class, node); + cdev_del(cdev); + class_destroy(class); + printk("%s()\n", __PRETTY_FUNCTION__); +} + +module_init(mod_init); +module_exit(mod_exit); +MODULE_LICENSE("Dual MIT/GPL"); + |