//#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");
motor
最新推荐文章于 2023-04-10 17:08:57 发布