#include #include #include #include #include "fopdrv.h" #include "config.h" 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; } // 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< 0 (%d:%d)\n", __PRETTY_FUNCTION__, MAJOR(node), MINOR(node)); 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");