kobox :gpio drv ok --gpio drv v3

gpio drv ok --gpio drv v3

v3更新:

(1)梳理打印信息,有的信息需要打印,有的是debug信息

(2)做成可rmmod、并且可以重新insmod,主要是资源的释放


驱动代码:

#include "gpio.h"
// ref arch/arm/mach-s3c24xx/mach-mini2440.c how to set gpio 
MODULE_LICENSE("GPL");
/*
datasheet: page274
— Port A(GPA): 25-output port
— Port B(GPB): 11-input/out port
— Port C(GPC): 16-input/output por
— Port D(GPD): 16-input/output por
— Port E(GPE): 16-input/output por
— Port F(GPF): 8-input/output port
— Port G(GPG): 16-input/output po
— Port H(GPH): 9-input/output port
— Port J(GPJ): 13-input/output port
*/

#define S3C_ADDR_BASE	0xF6000000
#define S3C_ADDR(x)	(S3C_ADDR_BASE + (x))
#define S3C2410_PA_UART		(0x50000000)
#define S3C2410_PA_GPIO		(0x56000000)
#define S3C_VA_UART	S3C_ADDR(0x01000000)	/* UART */
#define S3C24XX_PA_UART		S3C2410_PA_UART
#define S3C24XX_VA_UART		S3C_VA_UART
#define S3C24XX_PA_GPIO		S3C2410_PA_GPIO
#define S3C24XX_VA_GPIO		((S3C24XX_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)

#define S3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)

#define S3C2410_GPBCON	   S3C2410_GPIOREG(0x10)
#define S3C2410_GPBDAT	   S3C2410_GPIOREG(0x14)
#define S3C2410_GPBUP	   S3C2410_GPIOREG(0x18)

#define kobox_debug(fmt, args...)// do{printk("[kobox]"fmt, ##args);}while(0)
#define kobox_info(fmt, args...)  do{printk("[kobox]"fmt, ##args);}while(0)

typedef struct
{
	unsigned port;
	unsigned pin;
	unsigned val;
}kobox_ioctl_st;

#define KOBOX_GPIO_IOCTL_MAIGC 'g'
#define KOBOX_GPIO_IOCTL_WRITE _IOWR(KOBOX_GPIO_IOCTL_MAIGC, 0, kobox_ioctl_st)
#define KOBOX_GPIO_IOCTL_READ _IOWR(KOBOX_GPIO_IOCTL_MAIGC, 1, kobox_ioctl_st)

static int kobox_gpio_open(struct inode *inode, struct file *file)
{
	return 0;
}

static int kobox_gpio_release(struct inode *inode, struct file *file)
{
	return 0;
}

static ssize_t kobox_gpio_read(struct file *file, __user char *buf, size_t count,
			     loff_t *offp)
{
	return 0;
}
static ssize_t kobox_gpio_write(struct file *file, const char __user *buf,
			      size_t count, loff_t *offp)
{
	return 0;
}

//set mux, set GPB_0 as gpio and output
/*
PORT CONFIGURATION REGISTER (GPACON-GPJCON)
In S3C2440A, most of the pins are multiplexed pins. So, It is determined which function is selected for each pins.
The PnCON(port control register) determines which function is used for each pin.
GPBCON 0x56000010 R/W Configures the pins of port B 0x0
GPB0 [1:0] 00 = Input  01 = Output	10 = TOUT0 11 = reserved
GPB1 [3:2] 00 = Input  01 = Output	10 = TOUT1 11 = reserved
GPB2 [5:4] 00 = Input  01 = Output	10 = TOUT2 11 = reserved
GPB3 [7:6] 00 = Input 01 = Output	10 = TOUT3 11 = reserved
GPB4 [9:8] 00 = Input  01 = Output	10 = TCLK [0] 11 = reserved
GPB5 [11:10] 00 = Input 01 = Output 10 = nXBACK 11 = reserved
GPB6 [13:12] 00 = Input  01 = Output 10 = nXBREQ 11 = reserved
GPB7 [15:14] 00 = Input  01 = Output 10 = nXDACK1 11 = Reserved
GPB8 [17:16] 00 = Input  01 = Output 10 = nXDREQ1 11 = Reserved
GPB9 [19:18] 00 = Input  01 = Output 10 = nXDACK0 11 = reserved
GPB10 [21:20] 00 = Input  01 = Output 10 = nXDREQ0 11 = reserved
*/
static int gpio_portb_set_init(unsigned pin)
{
	unsigned uiVal = 0;

	uiVal = readl(S3C2410_GPBCON);
	uiVal |= (0x01<<(2*pin)); 
	uiVal &= ~(0x01 <<((2*pin)+1)) ; 
	writel(uiVal, S3C2410_GPBCON);
	
	return 0;
}

/*
	GPB[10:0] [10:0] When the port is configured as input port, the corresponding bit is the pin
state. When the port is configured as output port, the pin state is the same
as the corresponding bit. When the port is configured as functional pin, the
undefined value will be read.
*/
static int gpio_portb_set_val(unsigned pin, unsigned val)
{
	unsigned uiVal = 0;

	kobox_debug("####[pin:%d][val:%d]\n", pin, val);

	if(0 == val)
	{
		uiVal = readl(S3C2410_GPBDAT);
		uiVal &= ~(0x01 << pin) ; 
		writel(uiVal, S3C2410_GPBDAT);
	}
	else if(1 == val)
	{
		uiVal = readl(S3C2410_GPBDAT);
		uiVal |= (0x01 << pin); 
		writel(uiVal, S3C2410_GPBDAT);
	}

	kobox_debug("####[func:%s][line:%d]\n",__FUNCTION__,__LINE__);

	return 0;
}

static int set_gpio_portb_val(unsigned pin, unsigned val)
{
	kobox_debug("####[pin:%d][val:%d]\n", pin, val);

	gpio_portb_set_init(pin);
	gpio_portb_set_val(pin, val);

	kobox_debug("####[func:%s][line:%d]\n",__FUNCTION__,__LINE__);

	return 0;
}

/*
	GPA: port = 0
	GPB: port = 1
	GPC: port = 2
	...
*/
static int set_gpio_val(unsigned port, unsigned pin, unsigned val)
{
	int ret;

	kobox_debug("####[func:%s][line:%d]\n",__FUNCTION__,__LINE__);
	
	if(port == 1)
	{
		ret = set_gpio_portb_val(pin, val);
		if(ret < 0)
		{
			kobox_debug("set_gpio_portb_val failed!\n");			
		}
	}
	else
	{
		kobox_debug("not support other gpio ports now!\n");
		return -1;
	}

	kobox_debug("####[func:%s][line:%d]\n",__FUNCTION__,__LINE__);	

	return ret;
}

static long kobox_gpio_ioctl(struct file *file, unsigned int cmd,
			   unsigned long arg)
{
	kobox_ioctl_st stGpioArg;
	unsigned port;
	unsigned pin;
	unsigned val;

	switch(cmd)
	{
		case KOBOX_GPIO_IOCTL_WRITE:
			kobox_debug("case KOBOX_GPIO_IOCTL_WRITE\n");
			copy_from_user((void*)&stGpioArg, (const void*)arg, sizeof(kobox_ioctl_st));
			port = stGpioArg.port;
			pin  = stGpioArg.pin;
			val  = stGpioArg.val;
			set_gpio_val(port, pin, val);
			break;

		case KOBOX_GPIO_IOCTL_READ:
			kobox_debug("case KOBOX_GPIO_IOCTL_READ\n");
			break;
		default:
			kobox_debug("Invalid cmd:%x\n", cmd);
			return -1;
	}
	
	return 0;
}

struct file_operations kobox_gpio_operations = {
	.owner          = THIS_MODULE,
	.open           = kobox_gpio_open,
	.release        = kobox_gpio_release,
	.read           = kobox_gpio_read,
	.write          = kobox_gpio_write,
	.unlocked_ioctl = kobox_gpio_ioctl,
};

//GPB0
int major;
int minor;
struct cdev cdev;
struct class *kobox_gpio_class;
struct device *pstdev = NULL;

int __init gpio_drv_init(void)
{
	int error;
	dev_t dev;

	kobox_info("#####enter gpio_drv_init!\n");	

	major = register_chrdev(0, "kobox_gpio", &kobox_gpio_operations);
	if (major < 0)
	{
		kobox_debug(" can't register major number\n");
		return major;
	}

	/* create class */
	kobox_gpio_class = class_create(THIS_MODULE, "kobox_gpio");
	if(IS_ERR(kobox_gpio_class))
	{
		kobox_debug("class_create failed!\n");
		goto fail;
	}

	/* create /dev/kobox_gpio */
	pstdev = device_create(kobox_gpio_class, NULL, MKDEV(major, 0), NULL, "kobox_gpio");
	if(!pstdev)
	{
		kobox_debug("device_create failed!\n");
		goto fail1;
	}

	kobox_info("#####gpio_drv_init ok!\n");
	
	return 0;
fail1:
	class_destroy(kobox_gpio_class);
fail:
	unregister_chrdev(major, "kobox_gpio");
	return -1;
}

void __exit gpio_drv_exit(void)
{
	kobox_info("exit gpio drv!\n");	

	device_destroy(kobox_gpio_class, MKDEV(major, 0));
	class_destroy(kobox_gpio_class);
	unregister_chrdev(major, "kobox_gpio");

	return;
}

module_init(gpio_drv_init);
module_exit(gpio_drv_exit);




你可能感兴趣的:(学习计划,驱动包,kobox)