#include <linux/init.h>
#include <linux/module.h>
#include <linux/leds.h>
#include <linux/io.h>
#include <linux/semaphore.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <mach/gpio.h>
#include <plat/mux.h>
#include <linux/gpio.h>
#include <linux/slab.h>
/************************
gpmc_ad8.gpio0_22
gpmc_ad9.gpio0_23
gpmc_ad10.gpio0_26
gpmc_ad11.gpio0_27
gpmc_ad12.gpio1_12
gpmc_ad13.gpio1_13
gpmc_ad14.gpio1_14
gpmc_ad15.gpio1_15
AM335X_GPMC_AD12---821
AM335X_GPMC_AD14---120
AM335X_GPMC_AD15---mc8635
************************/
#define GPIO_IOC_MAGIC 'G'
#define IOCTL_GPIO_SETOUTPUT _IOW(GPIO_IOC_MAGIC, 0, int)
#define IOCTL_GPIO_SETINPUT _IOW(GPIO_IOC_MAGIC, 1, int)
#define IOCTL_GPIO_SETVALUE _IOW(GPIO_IOC_MAGIC, 2, int)
#define IOCTL_GPIO_GETVALUE _IOR(GPIO_IOC_MAGIC, 3, int)
#define GPIO_IOC_MAXNR 3
#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))
struct am335x_gpio_arg{
int pin;
int data;
};
struct am335x_gpio_node{
int pin;
struct am335x_gpio_node *next;
};
static int gpio_major = 0;
static int gpio_minor = 0;
static struct class *gpio_class;
static struct class_device *class_dev;
static struct cdev gpio_cdev;
static struct am335x_gpio_node *head;
static int is_required(int pinnum)
{
struct am335x_gpio_node *pnode = head->next;
struct am335x_gpio_node *rnode = head;
while(pnode != NULL)
{
if(pnode->pin == pinnum)
return 0;
else
{
rnode = pnode;
pnode = pnode->next;
}
}
printk("New GPIO Register at pin num %d\n",pinnum);
pnode = (struct am335x_gpio_node *)kmalloc(sizeof(struct am335x_gpio_node), GFP_KERNEL);
if(pnode != NULL)
{
rnode->next = pnode;
pnode->pin = pinnum;
pnode->next = NULL;
}
else
printk("Can't Kmalloc... register fail\n");
return 1;
}
static int gpio_open(struct inode *inode,struct file *filp)
{
//is_required(GPIO_TO_PIN(0,22));
//is_required(GPIO_TO_PIN(0,23));
//is_required(GPIO_TO_PIN(0,26));
//is_required(GPIO_TO_PIN(0,27));
//is_required(GPIO_TO_PIN(1,12));
//is_required(GPIO_TO_PIN(1,13));
//is_required(GPIO_TO_PIN(1,14));
//is_required(GPIO_TO_PIN(1,15));
return 0;
}
static int gpio_release(struct inode *inode,struct file *filp)
{
//struct am335x_gpio_node *pnode = head->next;
//struct am335x_gpio_node *rnode = NULL;
//while(pnode != NULL )
// {
// rnode = pnode->next;
// kfree(pnode);
// pnode = rnode;
// }
//kfree(head); //freed by exit function
return 0;
}
static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int err = 0;
struct am335x_gpio_arg *parg = (struct am335x_gpio_arg *)arg;
if(is_required(parg->pin))
{
err = gpio_request(parg->pin, "am335x_gpio");
if(err != 0)
{
printk("Can't request this gpio!\n");
gpio_free(parg->pin);
}
}
switch (cmd) {
case IOCTL_GPIO_SETOUTPUT:
gpio_direction_output(parg->pin, parg->data);
break;
case IOCTL_GPIO_SETINPUT:
gpio_direction_input(parg->pin);
break;
case IOCTL_GPIO_SETVALUE:
gpio_set_value(parg->pin, parg->data);
break;
case IOCTL_GPIO_GETVALUE:
parg->data = gpio_get_value(parg->pin) ? 1 : 0;
break;
default :
printk(KERN_WARNING "Unsuported Ioctl Cmd\n");
}
return 0;
}
struct file_operations gpio_fops = {
.owner = THIS_MODULE,
.open = gpio_open,
.unlocked_ioctl = gpio_ioctl,
.release = gpio_release,
};
static int __init am335x_gpio_init(void)
{
int result;
dev_t dev = 0;
result = alloc_chrdev_region(&dev, gpio_minor, 1,"am335x_gpio_group");
gpio_major = MAJOR(dev);
if (result < 0) {
printk(KERN_WARNING "Can't get major %d\n", gpio_major);
return result;
}
printk("AM335X GPIO GROUP Driver Registered.\n");
cdev_init(&gpio_cdev, &gpio_fops);
gpio_cdev.owner = THIS_MODULE;
gpio_cdev.ops = &gpio_fops;
result = cdev_add (&gpio_cdev, dev, 1);
gpio_class = class_create(THIS_MODULE, "am335x_gpio_group");
if (IS_ERR(gpio_class)) {
printk(KERN_WARNING "Class_create faild\n");
cdev_del(&gpio_cdev);
unregister_chrdev_region(dev, 0);
return result;
}
class_dev = device_create(gpio_class,NULL,dev,0,"am335x_gpio_group");
head = (struct am335x_gpio_node *)kmalloc(sizeof(struct am335x_gpio_node), GFP_KERNEL);
if(head == NULL)
{
return -1;
}
else
{
head->pin = 0;
head->next = NULL;
}
return 0;
}
static void __exit am335x_gpio_exit(void)
{
dev_t dev = 0;
struct am335x_gpio_node *pnode = head->next;
struct am335x_gpio_node *rnode = NULL;
while(pnode != NULL )
{
rnode = pnode->next;
kfree(pnode);
pnode = rnode;
}
kfree(head);
dev = MKDEV(gpio_major, gpio_minor);
class_unregister(class_dev);
class_destroy(gpio_class);
unregister_chrdev_region(dev, 0);
cdev_del(&gpio_cdev);
}
module_init(am335x_gpio_init);
module_exit(am335x_gpio_exit);
MODULE_DESCRIPTION("Driver for AM335X GPIO");
MODULE_AUTHOR("[email protected]");
MODULE_LICENSE("GPL");
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <linux/ioctl.h>
/************************
gpmc_ad8.gpio0_22
gpmc_ad9.gpio0_23
gpmc_ad10.gpio0_26
gpmc_ad11.gpio0_27
gpmc_ad12.gpio1_12
gpmc_ad13.gpio1_13
gpmc_ad14.gpio1_14
gpmc_ad15.gpio1_15
AM335X_GPMC_AD12---821
AM335X_GPMC_AD14---120
AM335X_GPMC_AD15---mc8635
************************/
#define DEV_GPIO "/dev/am335x_gpio_group"
#define GPIO_IOC_MAGIC 'G'
#define IOCTL_GPIO_SETOUTPUT _IOW(GPIO_IOC_MAGIC, 0, int)
//#define IOCTL_GPIO_SETINPUT _IOW(GPIO_IOC_MAGIC, 1, int)
//#define IOCTL_GPIO_SETVALUE _IOW(GPIO_IOC_MAGIC, 2, int)
//#define IOCTL_GPIO_GETVALUE _IOR(GPIO_IOC_MAGIC, 3, int)
#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))
typedef struct {
int pin;
int data;
}am335x_gpio_arg;
int main(int argc, void *argv[])
{
am335x_gpio_arg arg;
int fd = -1;
int i = 0, group = 0, num = 0;
fd = open(DEV_GPIO, O_RDWR);
if (fd < 0) {
printf("Error device open fail! %d\n", fd);
return -1;
}
arg.data = 1;// 1- set gpio to high level 0- low level
arg.pin = GPIO_TO_PIN(1, 12);//gpmc_ad8.gpio0_22 , at top region of this file , gpio list show.
ioctl(fd, IOCTL_GPIO_SETOUTPUT, &arg);
arg.pin = GPIO_TO_PIN(1, 14);
ioctl(fd, IOCTL_GPIO_SETOUTPUT, &arg);
arg.pin = GPIO_TO_PIN(1, 15);
ioctl(fd, IOCTL_GPIO_SETOUTPUT, &arg);
printf("set all 1\n");
sleep(5);
printf("sleep.\n");
sleep(5);
printf("sleep.\n");
sleep(5);
printf("sleep.\n");
arg.data = 0;// 1- set gpio to high level 0- low level
arg.pin = GPIO_TO_PIN(1, 12);//gpmc_ad8.gpio0_22 , at top region of this file , gpio list show.
ioctl(fd, IOCTL_GPIO_SETOUTPUT, &arg);
arg.pin = GPIO_TO_PIN(1, 14);
ioctl(fd, IOCTL_GPIO_SETOUTPUT, &arg);
arg.pin = GPIO_TO_PIN(1, 15);
ioctl(fd, IOCTL_GPIO_SETOUTPUT, &arg);
printf("set all 0\n");
close(fd);
printf("close file\n");
return 0;
}