motor

//#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <asm/irq.h>
#include <mach/gpio.h>
#include <plat/regs-gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/hardware.h>
#include <linux/io.h>
#include <mach/map.h>
#include <plat/devs.h>
#include <plat/regs-timer.h>
#include <plat/gpio-bank-m.h>
#include <plat/gpio-bank-p.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#define DEVICE_NAME	"motor"
#define MOTOR_MAJOR 232
//mpu6050 register define
#define SELF_TEST_X 0x0D
#define SELF_TEST_Y 0x0E
#define SELF_TEST_Z 0x0F
#define SELF_TEST_A 0x10

#define SMPLRT_DIV  0x19 
#define CONFIG   0x1A 
#define GYRO_CONFIG  0x1B 
#define ACCEL_CONFIG 0x1C 

#define MOT_THR 0x1F

#define FIFO_EN 0x23

#define I2C_MST_CTRL 0x24

#define I2C_SLV0_ADDR 0x25
#define I2C_SLV0_REG 0x26
#define I2C_SLV0_CTRL 0x27
#define I2C_SLV0_DO 0x63

#define I2C_SLV1_ADDR 0x28
#define I2C_SLV1_REG 0x29
#define I2C_SLV1_CTRL 0x2A
#define I2C_SLV1_DO 0x64

#define I2C_SLV2_ADDR 0x2B
#define I2C_SLV2_REG 0x2C
#define I2C_SLV2_CTRL 0x2D
#define I2C_SLV2_DO 0x65

#define I2C_SLV3_ADDR 0x2E
#define I2C_SLV3_REG 0x2F
#define I2C_SLV3_CTRL 0x30
#define I2C_SLV3_DO 0x66

#define I2C_SLV4_ADDR 0x31
#define I2C_SLV4_REG 0x32
#define I2C_SLV4_DO  0x33
#define I2C_SLV4_CTRL 0x34
#define I2C_SLV4_DI 0x35

#define I2C_MST_STATUS 0x36
#define INT_PIN_CFG 0x37
#define INT_ENABLE 0x38
#define INT_STATUS 0x3A

#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H  0x41
#define TEMP_OUT_L  0x42
#define GYRO_XOUT_H  0x43
#define GYRO_XOUT_L  0x44
#define GYRO_YOUT_H  0x45
#define GYRO_YOUT_L  0x46
#define GYRO_ZOUT_H  0x47
#define GYRO_ZOUT_L  0x48

#define EXT_SENS_DATA_00 0x49
//........
#define EXT_SENS_DATA_23 0x60

#define I2C_MST_DELAY_CTRL 0x67
#define SIGNAL_PATH_RESET 0x68
#define MOT_DETECT_CTRL 0x69
#define USER_CTRL 0x6A
#define PWR_MGMT_1  0x6B
#define PWR_MGMT_2 0x6C
#define FIFO_COUNTH 0x72
#define FIFO_COUNTL 0x73
#define FIFO_R_W 0x74 
#define WHO_AM_I  0x75 
#define SlaveAddress 0xD0

#define SCL 1
#define SDA 8

static unsigned long motor_m_table[] = { S3C64XX_GPM(0), S3C64XX_GPM(1),
		S3C64XX_GPM(2), S3C64XX_GPM(3), };

static unsigned long motor_p_table[] = { S3C64XX_GPP(1), S3C64XX_GPP(8),
		S3C64XX_GPP(9), S3C64XX_GPP(12), S3C64XX_GPP(13),};

static unsigned int motor_cfg_table[] = { S3C64XX_GPM_OUTPUT(0),
		S3C64XX_GPM_OUTPUT(1), S3C64XX_GPM_OUTPUT(2), S3C64XX_GPM_OUTPUT(3), };

struct motor_ok6410_dev{
	
    struct cdev cdev_motor;
	struct class *motor_class;
	dev_t devno;
	atomic_t counter[5];
	//GPP Timer
	struct timer_list gpp_timer[5];
};

struct motor_ok6410_dev *p_motor_dev=NULL;
static void gpp_timer_ini_handler(unsigned long arg);
static void I2C_SendACK(int ack);
static char I2C_RecvByte(void);
static void Single_WriteI2C(char REG_Address, char REG_data);
static void InitMPU6050(void);
static unsigned long setGppGPIO(int which_pin,unsigned long arg_high_low);

static char I2C_RecvByte(void) {
	char i;
	char dat = 0;
	unsigned long tmp;
	//SDA = 1; //ʹÄÜÄÚ²¿ÉÏÀ­,×¼±¸¶ÁÈ¡Êý¾Ý,
	//for (i = 0; i < 8; i++) //8λ¼ÆÊýÆ÷
	//{
		//dat <<= 1;
		//SCL = 1; //À­¸ßʱÖÓÏß
		//Delay5us(); //ÑÓʱ
		//dat |= SDA; //¶ÁÊý¾Ý
		//SCL = 0; //À­µÍʱÖÓÏß
		//Delay5us(); //ÑÓʱ
	//}
	tmp &=(~(0xffff));
	setGppGPIO(SDA,1);
	for (i = 0; i < 8; i++)
	{
		dat <<=1;
		setGppGPIO(SCL,1);
		udelay(5);
			if(gpio_get_value(S3C64XX_GPP(8))==1)
				dat |=1;
			else
				dat |=0;
		setGppGPIO(SCL,0);		
		udelay(5);
	}
	return dat;
}
static void I2C_SendACK(int ack) {
	
	//SDA = ack; //дӦ´ðÐźÅ
	//SCL = 1; //À­¸ßʱÖÓÏß
	//Delay5us(); //ÑÓʱ
	//SCL = 0; //À­µÍʱÖÓÏß
	//Delay5us(); //ÑÓʱ
	s3c_gpio_cfgpin(S3C64XX_GPP(8), S3C_GPIO_SFN(1));
	s3c_gpio_cfgpin(S3C64XX_GPP(1), S3C_GPIO_SFN(1));
	
	gpio_set_value(S3C64XX_GPP(8), ack);
	gpio_set_value(S3C64XX_GPP(1), 1);
	udelay(5);
	gpio_set_value(S3C64XX_GPP(1), 0);	
	udelay(5);	
	s3c_gpio_cfgpin(S3C64XX_GPP(8), S3C_GPIO_SFN(0));
	s3c_gpio_cfgpin(S3C64XX_GPP(1), S3C_GPIO_SFN(0));
	
}
static void I2C_Start_Stop(int key) {
	if(key==1){
		//SDA = 1;
		//SCL = 1;
		//Delay5us();
		//SDA = 0;
		//Delay5us();
		//SCL = 0;
		scl :gpp1 sda :gpp8
		setGppGPIO(SCL,1);
		setGppGPIO(SDA,1);
		udelay(5);
		setGppGPIO(SDA,0);
		udelay(5);
		setGppGPIO(SCL,0);
		udelay(10);
	}
	else
	{
		//SDA = 0; //À­µÍÊý¾ÝÏß
		//SCL = 1; //À­¸ßʱÖÓÏß
		//Delay5us(); //ÑÓʱ
		//SDA = 1; //²úÉúÉÏÉýÑØ
		//Delay5us(); //ÑÓʱ
		setGppGPIO(SCL,1);
		setGppGPIO(SDA,0);
		udelay(5);
		setGppGPIO(SDA,1);
		udelay(5);
		setGppGPIO(SCL,1);
		udelay(10);
	}	
}

static void I2C_SendByte(char dat) {
	char i;
	for (i = 0; i < 8; i++) //8λ¼ÆÊýÆ÷
	{
		//dat <<= 1; //ÒƳöÊý¾ÝµÄ×î¸ßλ
		//SDA = CY; //ËÍÊý¾Ý¿Ú
		//SCL = 1; //À­¸ßʱÖÓÏß
		//Delay5us(); //ÑÓʱ
		//SCL = 0; //À­µÍʱÖÓÏß
		//Delay5us(); //ÑÓʱ
				
		if(dat&0x80)
			gpio_set_value(S3C64XX_GPP(8), 1);
		else
			gpio_set_value(S3C64XX_GPP(8), 0);	
		gpio_set_value(S3C64XX_GPP(1), 1);
		udelay(5);
		gpio_set_value(S3C64XX_GPP(1), 0);
		udelay(5);
		dat <<= 1;
	}
	//I2C_RecvACK();
}

static void Single_WriteI2C(char REG_Address, char REG_data) {
	I2C_Start_Stop(1); 
	I2C_SendByte(SlaveAddress); 
	I2C_SendByte(REG_Address); 
	I2C_SendByte(REG_data); 
	I2C_Start_Stop(0);
}


static char Single_ReadI2C(char REG_Address) {
	char REG_data;
	I2C_Start_Stop(1); //ÆðʼÐźÅ
	I2C_SendByte(SlaveAddress); //·¢ËÍÉ豸µØÖ·+дÐźÅ
	I2C_SendByte(REG_Address); //·¢ËÍ´æ´¢µ¥ÔªµØÖ·£¬´Ó0¿ªÊ¼
	I2C_Start_Stop(1); //ÆðʼÐźÅ
	I2C_SendByte(SlaveAddress + 1); //·¢ËÍÉ豸µØÖ·+¶ÁÐźÅ
	REG_data = I2C_RecvByte(); //¶Á³ö¼Ä´æÆ÷Êý¾Ý
	I2C_SendACK(1); //½ÓÊÕÓ¦´ðÐźÅ
	I2C_Start_Stop(0); //Í£Ö¹ÐźÅ
	return REG_data;
}


static void InitMPU6050(void) {
	Single_WriteI2C(PWR_MGMT_1, 0x00); 
	Single_WriteI2C(SMPLRT_DIV, 0x07);
	Single_WriteI2C(CONFIG, 0x06);
	Single_WriteI2C(GYRO_CONFIG, 0x18);
	Single_WriteI2C(ACCEL_CONFIG, 0x01);
}	

static int GetMpu6050Data(char REG_Address) {
	char H, L;
	H = Single_ReadI2C(REG_Address);
	L = Single_ReadI2C(REG_Address + 1);
	return (H << 8) + L; //ºÏ³ÉÊý¾Ý
}

//ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
static ssize_t  s3c6410_motor_read(struct file *filp, char __user *buf, size_t len,loff_t *lft)
{
	
	int mpu_data[6] = {0,0,0,0,0,0};
	InitMPU6050();
	
		mpu_data[0]=GetMpu6050Data(ACCEL_XOUT_H);
		mpu_data[1]=GetMpu6050Data(ACCEL_YOUT_H);
		mpu_data[2]=GetMpu6050Data(ACCEL_ZOUT_H);
		mpu_data[3]=GetMpu6050Data(GYRO_XOUT_H);
		mpu_data[4]=GetMpu6050Data(GYRO_YOUT_H);
		mpu_data[5]=GetMpu6050Data(GYRO_ZOUT_H);
	printk(KERN_NOTICE"\nAcc:-%d-%d-%d-Gyro:-%d-%d-%d-\n",mpu_data[0],mpu_data[1],
		//									mpu_data[2],mpu_data[3],
		//									mpu_data[4],mpu_data[5]);	
	if(copy_to_user(buf,mpu_data,sizeof(mpu_data)))
	{
		;
	}
	
	return (ssize_t)sizeof(mpu_data);
}

static DEFINE_TIMER(gpp_timer1, gpp_timer_ini_handler, 20, 0);
static DEFINE_TIMER(gpp_timer8, gpp_timer_ini_handler, 20, 0);
static DEFINE_TIMER(gpp_timer9, gpp_timer_ini_handler, 20, 0);
static DEFINE_TIMER(gpp_timer12, gpp_timer_ini_handler, 20, 0);
static DEFINE_TIMER(gpp_timer13, gpp_timer_ini_handler, 20, 0);

/*定时器处理函数*/
static void gpp_timer_ini_handler(unsigned long arg)
{
	mod_timer(&p_motor_dev->gpp_timer[arg],jiffies + HZ);
	atomic_inc(&p_motor_dev->counter[arg]);
	//printk(KERN_EMERG "timer:%d,current counter is %ld,current jiffies is %ld\n",
		//	arg,p_motor_dev->counter[arg],jiffies);
}

/*设备打开函数*/
static int s3c6410_motor_open(
		struct inode *inode,
		struct file *file)
{
	/*初始化定时器*/
	int i=0;
	for(i=0;i<5;i++){
		init_timer(&p_motor_dev->gpp_timer[i]);
		p_motor_dev->gpp_timer[i].function = &gpp_timer_ini_handler;
		p_motor_dev->gpp_timer[i].expires = jiffies + HZ;
		p_motor_dev->gpp_timer[i].data=(unsigned long)i;
		add_timer(&p_motor_dev->gpp_timer[i]);
		atomic_set(&p_motor_dev->counter[i],0);//计数0
	}
	//printk(KERN_EMERG "\ns3c6410_motor_open open successfully\n");
	return 0;
}

/*设备释放函数*/
static int s3c6410_motor_release(
		struct inode *inode,
		struct file *file)
{
	int i=0;
	for(i=0;i<5;i++){
		del_timer(&p_motor_dev->gpp_timer[i]);
	}
	//printk(KERN_EMERG"\ns3c6410_motor_release successfully\n");
	return 0;
}

static unsigned long setGppGPIO(int which_pin,unsigned long arg_high_low)
{
		unsigned int ppm_tmp=0,led_tmp=0,ret=0;
		int _led_pin=0;
		//s3c_gpio_cfgpin(S3C64XX_GPP(which_pin), S3C_GPIO_SFN(1));	
		//gpio_set_value(S3C64XX_GPP(which_pin), arg_high_low);			
		//s3c_gpio_cfgpin(S3C64XX_GPP(which_pin), S3C_GPIO_SFN(0));
		if(which_pin==1) _led_pin=0;
		else if(which_pin==9) _led_pin=1;
		else if(which_pin==12) _led_pin=2;
		else if(which_pin==13) _led_pin=3;
		else{return -1;}
		ppm_tmp = __raw_readl(S3C64XX_GPPDAT);
		led_tmp = __raw_readl(S3C64XX_GPMDAT);
		//printk(KERN_EMERG"\nbegin:S3C64XX_GPMDAT:%x,S3C64XX_GPPDAT:%x\n",__raw_readl(S3C64XX_GPMDAT),__raw_readl(S3C64XX_GPPDAT));
		if (arg_high_low){
			ppm_tmp |= (1 << which_pin);
			led_tmp &= (~(1 << _led_pin));
		}
		else{
			ppm_tmp &= (~(1 << which_pin));
			led_tmp |= (1 << _led_pin);
		}
		//printk(KERN_EMERG"ppm_tmp:%x,led_tmp:%x\n",ppm_tmp,led_tmp);
		__raw_writel(ppm_tmp, S3C64XX_GPPDAT);
		__raw_writel(led_tmp, S3C64XX_GPMDAT);
		//ret = __raw_readl(S3C64XX_GPPDAT);
		//printk(KERN_EMERG"end:S3C64XX_GPMDAT:%x,S3C64XX_GPPDAT:%x\n",__raw_readl(S3C64XX_GPMDAT),__raw_readl(S3C64XX_GPPDAT));
		return ret;
}
/**
 * arg:0~2000
 * */
static int s3c6410_motor_ioctl(
		struct inode *inode,
		struct file *file,
		unsigned int cmd,
		unsigned long arg) {
	//printk(KERN_EMERG" enter s3c6410_motor_ioctl successfully:\n");
	switch (cmd) {
		
	case -1:		
	case 0:	
		return 0;	
	case 1:			//GPP1 up 
	case 2:
	case 3:
	case 4:
	case 5:
	case 6:
	case 7:
	case 8:			//GPP8
	case 9:			//GPP9 left
	case 10:
	case 11:
	case 12:		//GPP12 right
	case 13:		//GPP13 down
	case 14:
	case 15:
	case 16:
	case 17:
	case 18:
	case 19:
	case 20:
	case 21:
	case 22:
	case 23:
	case 24:
	case 25:
	case 26:
	case 27:
	case 28:
	case 29:
	case 30:
	case 31:
	case 32:
	/*
			setGppGPIO(cmd,1);
				mdelay(arg/100);
				udelay(10*(arg%100));
			setGppGPIO(cmd,0);
				mdelay((2000-arg)/100);
				udelay(10*((2000-arg)%100));
	*/
	
	s3c_gpio_cfgpin(S3C64XX_GPP(cmd), S3C_GPIO_SFN(1));//out
		gpio_set_value(S3C64XX_GPP(cmd), 1);
		mdelay(arg/100);
				udelay(10*(arg%100));
		gpio_set_value(S3C64XX_GPP(cmd), 0);
		mdelay((2000-arg)/100);
				udelay(10*((2000-arg)%100));
					
		//printk(KERN_EMERG" exit s3c6410_motor_ioctl successfully\n");
		return 0;
	default:
		return -EINVAL;
	}
}

static struct file_operations s3c6410_motor_fops = {
		.owner = THIS_MODULE,	
		.open =  s3c6410_motor_open,
		.release = s3c6410_motor_release,
		.ioctl = s3c6410_motor_ioctl,
		.read = s3c6410_motor_read,
};

/*设备初始化*/
static int __init s3c6410_motor_init(void)
{
	unsigned long tmp;
	int ret=0;
	printk(KERN_NOTICE "enter s3c6410_motor_init\n");
	//动态申请设备结构体的内存
	p_motor_dev = (struct motor_ok6410_dev *)kmalloc(sizeof(struct motor_ok6410_dev),GFP_KERNEL);
	if(!p_motor_dev)
	{
		//printk(KERN_NOTICE "s3c6410_motor_init ----1\n");
		ret=- ENOMEM;
		goto fail_malloc;
	}	
	//memset(p_motor_dev,0,sizeof(struct motor_ok6410_dev));	
	//printk(KERN_NOTICE "s3c6410_motor_init ----2\n");
	//printk(KERN_NOTICE "s3c6410_motor_init ----3\n");
	//获取设备号
	if(alloc_chrdev_region(&p_motor_dev->devno, 0,1, DEVICE_NAME)<0)
	{
		//printk(KERN_NOTICE "can not register motor device");
		return ret;
	}
		
	//初始化字符设备,绑定fops
	//printk(KERN_NOTICE "s3c6410_motor_init ----5\n");
	cdev_init(&p_motor_dev->cdev_motor,&s3c6410_motor_fops);
	p_motor_dev->cdev_motor.owner = THIS_MODULE;
	//添加字符设备
	//printk(KERN_NOTICE "s3c6410_motor_init ----6\n");
	ret =cdev_add(&p_motor_dev->cdev_motor,p_motor_dev->devno,1);
	if(ret)
	{
		//printk(KERN_NOTICE "can not add motor device");
		return ret;
	}
	//指定class
	//printk(KERN_NOTICE "s3c6410_motor_init ----7\n");
	p_motor_dev->motor_class = class_create(THIS_MODULE,DEVICE_NAME);
	if(IS_ERR(p_motor_dev->motor_class))
	{
		//printk("Err: Fail motor in creating class\n");
		return -1;
	}
	//创建字符设备
	//printk(KERN_NOTICE "s3c6410_motor_init ----8\n");
	device_create(p_motor_dev->motor_class,NULL,MKDEV(MAJOR(p_motor_dev->devno),0),NULL,DEVICE_NAME);
	//printk(KERN_NOTICE "s3c6410_motor_init ----9\n");
	//gpm0-3 pull up
	tmp = __raw_readl(S3C64XX_GPMPUD);
	tmp &= (~0xFF);
	tmp |= 0xaa;            // 10101010
	__raw_writel(tmp,S3C64XX_GPMPUD);

	//gpm0-3 output mode
	tmp = __raw_readl(S3C64XX_GPMCON);
	tmp &= (~0xFFFF);
	tmp |= 0x1111;
	__raw_writel(tmp,S3C64XX_GPMCON);

	//gpm0-3 output 0
	tmp = __raw_readl(S3C64XX_GPMDAT);
	tmp |= 0x10;
	__raw_writel(tmp,S3C64XX_GPMDAT);
	
	//*****************************************************//
	gpp-1-8-9-12-13 pull up
	tmp = __raw_readl(S3C64XX_GPPPUD);
	tmp &= (~0xFFFF);
	tmp |= 0xaaaaaaaa;              //0000 1010 0000 1010 , 0000 0000 0000 1000  pull down
	__raw_writel(tmp,S3C64XX_GPPPUD);

	//gpp-1-8-9-12-13 output mode
	tmp = __raw_readl(S3C64XX_GPPCON);
	tmp &= (~0xFFFF);
	tmp |= 0x05050004;             // 0000 0101 0000 0101 , 0000 0000 0000 0100  output mode
	__raw_writel(tmp,S3C64XX_GPPCON);

	//gpp-1-8-9-12-13 output 0
	tmp = __raw_readl(S3C64XX_GPPDAT);
	tmp &= (~0xFFFF);
	__raw_writel(tmp,S3C64XX_GPPDAT);
	//*****************************************************//
	return 0;
	fail_malloc: unregister_chrdev_region(p_motor_dev->devno,1);
	return -1;
}

static void __exit s3c6410_motor_exit(void)
{
	unregister_chrdev_region(MKDEV(MOTOR_MAJOR,0),1);
	//printk(KERN_NOTICE "s3c2440_motor_exit 1\n");
	device_destroy(p_motor_dev->motor_class,MKDEV(MAJOR(p_motor_dev->devno),0));
	//printk(KERN_NOTICE "s3c2440_motor_exit 2\n");
	cdev_del(&p_motor_dev->cdev_motor);	
	//printk(KERN_NOTICE "s3c2440_motor_exit 3\n");	
	class_destroy(p_motor_dev->motor_class);	
	//printk(KERN_NOTICE "s3c2440_motor_exit 4\n");
	kfree(p_motor_dev);	
	//printk(KERN_NOTICE "s3c2440_motor_exit 5\n");
	return;
}

module_init( s3c6410_motor_init);
module_exit( s3c6410_motor_exit);

//module_param(MOTOR_MAJOR,int,S_IRUGO);

MODULE_AUTHOR("clare liu 2013/11/15");
MODULE_LICENSE("GPL");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值