#include #include #include #include #include #include #include #include #include #include #include //#include #include "gpio.h" #include "./../../stm32f429xx.h" #include "asm/uaccess.h" static int major = 100; static int minor = 0; static dev_t devno; static struct cdev *gpio_cdev = NULL; static int count = 3; #define DEVNAME "gpio" static int gpio_open(struct inode *inode, struct file *filep); static int gpio_close(struct inode *inode, struct file *filep); static ssize_t gpio_read(struct file *filep, char __user *buf, size_t size, loff_t *offset); static ssize_t gpio_write(struct file *filep, const char __user *buf, size_t size, loff_t *offset); static int gpio_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); static struct file_operations gpio_ops = { .owner = THIS_MODULE, .open = gpio_open, .release = gpio_close, .ioctl = gpio_ioctl, .read = gpio_read, .write = gpio_write, }; static int gpio_open(struct inode *inode, struct file *filep) { return 0; } static int gpio_close(struct inode *inode, struct file *filep) { return 0; } static int enable_gpio_clock(gpio_data_t *gpin_data) { RCC_TypeDef *rcc_dev = RCC; switch((int)gpin_data->port) { //AHB1 case (int)GPIOA: rcc_dev->AHB1ENR |= 0x001; break; case (int)GPIOB: rcc_dev->AHB1ENR |= 0x002; break; case (int)GPIOC: rcc_dev->AHB1ENR |= 0x004; break; case (int)GPIOD: rcc_dev->AHB1ENR |= 0x008; break; case (int)GPIOE: rcc_dev->AHB1ENR |= 0x010; break; case (int)GPIOF: rcc_dev->AHB1ENR |= 0x020; break; case (int)GPIOG: rcc_dev->AHB1ENR |= 0x040; break; case (int)GPIOH: rcc_dev->AHB1ENR |= 0x080; break; case (int)GPIOI: rcc_dev->AHB1ENR |= 0x100; break; case (int)GPIOJ: rcc_dev->AHB1ENR |= 0x200; break; case (int)GPIOK: rcc_dev->AHB1ENR |= 0x400; break; default: printk("---> invalid gpio port!\n");break; } return 0; } static int gpio_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg) { uint8_t position; gpio_data_t gpin_data; GPIO_TypeDef *gpio_dev; if ( copy_from_user(&gpin_data, (void*)arg, sizeof(gpio_data_t)) ) return -EFAULT; gpio_dev = (GPIO_TypeDef*)gpin_data.port; //get gpio pin position for(position=0;position<16;position++) { if(gpin_data.pin == 0x01<MODER &= ~((0x03) << (position<<1)); break; case SET_GPIO_PUSH_PULL_OUTPUT: enable_gpio_clock(&gpin_data); gpio_dev->MODER &= ~((0x03) << (position<<1)); gpio_dev->MODER |= ((0x01) << (position<<1)); gpio_dev->OTYPER &= (~gpin_data.pin); break; case SET_GPIO_OPEN_DRAIN_OUTPUT: enable_gpio_clock(&gpin_data); gpio_dev->MODER &= ~((0x03) << (position<<1)); gpio_dev->MODER |= ((0x01) << (position<<1)); gpio_dev->OTYPER |= gpin_data.pin; break; case SET_GPIO_PULL_UP: gpio_dev->PUPDR &= ~((0x03) << (position<<1)); gpio_dev->PUPDR |= ((0x01) << (position<<1)); break; case SET_GPIO_PULL_DOWN: gpio_dev->PUPDR &= ~((0x03) << (position<<1)); gpio_dev->PUPDR |= ((0x02) << (position<<1)); break; case SET_GPIO_NO_PULL: gpio_dev->PUPDR &= ~((0x03) << (position<<1)); break; case SET_GPIO_SPEED: switch(gpin_data.data) { case GPIO_LOW_SPEED: gpio_dev->OSPEEDR &= ~((0x03) << (position<<1)); break; case GPIO_MEDIUM_SPEED: gpio_dev->OSPEEDR &= ~((0x03) << (position<<1)); gpio_dev->OSPEEDR |= ((0x01) << (position<<1)); break; case GPIO_FAST_SPEED: gpio_dev->OSPEEDR &= ~((0x03) << (position<<1)); gpio_dev->OSPEEDR |= ((0x02) << (position<<1)); break; case GPIO_HIGH_SPEED: gpio_dev->OSPEEDR |= ((0x03) << (position<<1)); break; default:break; } break; case SET_GPIO_VALUE: if(gpin_data.data) gpio_dev->ODR |= gpin_data.pin; else gpio_dev->ODR &= ~gpin_data.pin; break; case GET_GPIO_VALUE: if(gpio_dev->IDR & gpin_data.pin) gpin_data.data = 0x01; else gpin_data.data = 0x00; break; default: printk("---> Invalid action\n"); return -EINVAL; break; } return 0; } static ssize_t gpio_read(struct file *filep, char __user *buf, size_t size, loff_t *offset) { return 0; } static ssize_t gpio_write(struct file *filep, const char __user *buf, size_t size, loff_t *offset) { return 0; } static int __init gpio_init(void) { int ret; gpio_cdev = cdev_alloc(); if(gpio_cdev == NULL){ return -ENOMEM; } cdev_init(gpio_cdev,&gpio_ops); devno = MKDEV(major,minor); ret = register_chrdev_region(devno, count, DEVNAME); if(ret){ goto ERR_STEP; } ret = cdev_add(gpio_cdev, devno, count); if(ret){ goto ERR_STEP1; } return 0; ERR_STEP1: unregister_chrdev_region(devno,count); ERR_STEP: cdev_del(gpio_cdev); return ret; } static void __exit gpio_exit(void) { unregister_chrdev_region(MKDEV(major,minor),count); cdev_del(gpio_cdev); } module_init(gpio_init); module_exit(gpio_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jimbo"); MODULE_DESCRIPTION("this is gpio module");