金牌会员
 
- 积分
- 1827
- 金钱
- 1827
- 注册时间
- 2019-7-23
- 在线时间
- 282 小时
|
设备树节点如下: 其中 CS片选引脚配置为GPIO功能。 且ICM26080工作在spi mode3模式。
- &ecspi3 {
- fsl,spi-num-chipselects = <1>;
- cs-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ecspi3>;
- status = "okay";
- icm20608@0 {
- compatible = "InvenSense,icm26080";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_icmInt>;
-
- interrupt-parent = <&gpio1>;
- interrupts = <1 0>;
- spi-max-frequency = <8000000>;
icm20608.zip
(5.69 KB, 下载次数: 0)
若spi3设备节点下大于4个节点的话,即fsl,spi-num-chipselects大于4,设备spi驱动程序可能会出问题。其原因如下
驱动如下- #include <linux/module.h>
- #include <linux/ratelimit.h>
- #include <linux/interrupt.h>
- #include <linux/uaccess.h>
- #include <linux/delay.h>
- #include <linux/debugfs.h>
- #include <linux/slab.h>
- #include <linux/gpio.h>
- #include <linux/of_gpio.h>
- #include <linux/spi/spi.h>
- #include <linux/types.h>
- #include <linux/of.h>
- #include <linux/of_device.h>
- #include <linux/device.h>
- #include <linux/miscdevice.h>
- #include <linux/wait.h>
- #include <linux/sched.h>
- #include <linux/poll.h>
- #include <linux/fcntl.h>
- #define WHO_AM_I 0x75
- #define PWR1 0x6B
- #define SMPLRT_DIV 0x19
- #define CONFIG 0x1A
- #define GYRO_CONFIG 0x1B
- #define ACCEL_CONFIG 0x1C
- #define ACCEL_CONFIG_2 0x1D
- #define LP_MODE_CFG 0x1E
- #define FIFO_EN 0x23
- #define INT_PIN_CFG 0x37
- #define INT_ENABLLE 0x38
- #define INT_STATUS 0x3A
- #define ACCEL_XOUT_H 0x3B // 3B -- 48
- struct sensor_data {
- float accel_scal;
- float gyro_scal;
- short accel_xad;
- short accel_yad;
- short accel_zad;
- short tempad;
- short gyro_Xad;
- short gyro_yad;
- short gyro_zad;
- };
- struct icm26080_data {
- struct spi_device *spi;
- u8 whoami;
- struct sensor_data sd;
- struct miscdevice misc;
- atomic_t lock;
- wait_queue_head_t r_wait;
- struct fasync_struct *async_queue;
- };
- struct ICM_names {
- int index;
- const char * const name;
- };
- struct ICM_InfoNames {
- u8 count;
- struct ICM_names icm_name[2];
- };
- struct ICM_InfoNames ICM_InfoName = {
- .count = 2,
- .icm_name = {
- {.index = 0XAF, .name = "ICM-20608G",},
- {.index = 0XAE, .name = "ICM-20608D",},
- },
- };
- static const struct of_device_id icm26080_dt_ids[] = {
- { .compatible = "InvenSense,icm26080",.data = &ICM_InfoName},
- {},
- };
- static int icm26080_write_reg(struct icm26080_data *icmdata,u8 addr, u8 *buf, u32 size)
- {
- int ret = 0;
- u8 *localbuf = kzalloc(size + 1, GFP_KERNEL);
- struct spi_transfer t = {
- .tx_buf = localbuf,
- .len = size + 1,
-
- };
- struct spi_message m;
- localbuf[0] = addr;
- memcpy(&localbuf[1],buf,size);
- spi_message_init(&m);
- spi_message_add_tail(&t, &m);
-
- ret = spi_sync(icmdata->spi, &m);
- kfree(localbuf);
-
- return ret;
- }
- static int icm26080_read_reg(struct icm26080_data *icmdata,u8 addr, u8 *buf, u32 size)
- {
- int ret = 0;
- u8 localaddr = addr | 0x80;
- struct spi_transfer t[2] = {
- {
- .tx_buf = &localaddr,
- .len = 1,
- },
-
- {
- .rx_buf = buf,
- .len = size,
- },
-
- };
- struct spi_message m;
- spi_message_init(&m);
- spi_message_add_tail(&t[0], &m);
- spi_message_add_tail(&t[1], &m);
-
- ret = spi_sync(icmdata->spi, &m);
- return ret;
- }
- //#define INT_STATUS 0x3A
- static int icm26080_setup(struct icm26080_data *icmdata)
- {
- u8 reg = 0;
- icm26080_write_reg(icmdata,SMPLRT_DIV,"\x09",1); // 100hz samp
- icm26080_write_reg(icmdata,GYRO_CONFIG,"\x18",1); // +- 2000dps
- icm26080_write_reg(icmdata,ACCEL_CONFIG,"\x18",1); // +- 16G
- icm26080_write_reg(icmdata,CONFIG,"\x04",1); // BW 20HZ
- icm26080_write_reg(icmdata,ACCEL_CONFIG_2,"\x04",1);
-
- icm26080_write_reg(icmdata,INT_PIN_CFG,"\xa0",1);
- icm26080_write_reg(icmdata,INT_ENABLLE,"\x01",1);
- icm26080_read_reg(icmdata, GYRO_CONFIG, ®, 1);
- switch((reg >> 3)&0x03)
- {
- case 0:
- icmdata->sd.gyro_scal = 131.0f;
- break;
- case 1:
- icmdata->sd.gyro_scal = 62.5f;
- break;
- case 2:
- icmdata->sd.gyro_scal = 32.8f;
- break;
- case 3:
- icmdata->sd.gyro_scal = 16.4f;
- break;
- }
-
- icm26080_read_reg(icmdata, ACCEL_CONFIG, ®, 1);
- switch((reg >> 3)&0x03)
- {
- case 0:
- icmdata->sd.accel_scal = 16384;
- break;
- case 1:
- icmdata->sd.accel_scal = 8192;
- break;
- case 2:
- icmdata->sd.accel_scal = 4096;
- break;
- case 3:
- icmdata->sd.accel_scal = 2048;
- break;
- }
-
- return 0;
- }
- static int icm26080_open(struct inode *inode, struct file *filp)
- {
- struct icm26080_data *icmdata = container_of(filp->private_data,struct icm26080_data,misc);
- filp->private_data = icmdata;
- return 0;
- }
- static ssize_t icm26080_read(struct file *filp, char __user *buf, size_t count, loff_t *offt)
- {
- struct icm26080_data *icmdata = filp->private_data;
- if(filp->f_flags & O_NONBLOCK)
- {
- if(!atomic_dec_and_test(&icmdata->lock))
- {
- atomic_inc(&icmdata->lock);
- return -EAGAIN;
- }
- }else {
- wait_event_interruptible(icmdata->r_wait, atomic_read(&icmdata->lock));
- }
- if(count != sizeof(struct sensor_data))
- return -EINVAL;
- if(copy_to_user(buf, &icmdata->sd, count))
- return -EINVAL;
-
-
- return count;
- }
- static unsigned int icm26080_poll(struct file *file, poll_table * wait)
- {
- struct icm26080_data *icmdata = file->private_data;
- unsigned int mask = 0;
- poll_wait(file, &icmdata->r_wait, wait);
- if(atomic_read(&icmdata->lock))
- mask = POLLIN | POLLRDNORM;
-
- return mask;
- }
- static int
- icm26080_fasync(int fd, struct file *file, int on)
- {
- struct icm26080_data *icmdata = file->private_data;
- return fasync_helper(fd, file, on, &icmdata->async_queue);
- }
- static int icm26080_release(struct inode *inode, struct file *file)
- {
- struct icm26080_data *icmdata = file->private_data;
- return fasync_helper(-1, file, 0,&icmdata->async_queue);
- }
- static struct file_operations icm_fops = {
- .owner = THIS_MODULE,
- .open = icm26080_open,
- .read = icm26080_read,
- .poll = icm26080_poll,
- .fasync = icm26080_fasync,
- .release = icm26080_release,
- };
- static irqreturn_t icm26080_isr(int irq, void *dev_id)
- {
- u8 int_status = 0;
- u8 buf[14];
- struct icm26080_data *icmdata = (struct icm26080_data *)dev_id;
-
- icm26080_read_reg(icmdata,INT_STATUS, &int_status, 1);
-
- if(int_status & 0x01)
- {
- icm26080_read_reg(icmdata,ACCEL_XOUT_H, buf, 14);
-
- icmdata->sd.accel_xad = (signed short)(buf[0] << 8 | buf[1]);
- icmdata->sd.accel_yad = (signed short)(buf[2] << 8 | buf[3]);
- icmdata->sd.accel_zad = (signed short)(buf[4] << 8 | buf[5]);
- icmdata->sd.tempad = (signed short)(buf[6] << 8 | buf[7]);
- icmdata->sd.gyro_Xad = (signed short)(buf[8] << 8 | buf[9]) ;
- icmdata->sd.gyro_yad = (signed short)(buf[10] << 8 | buf[11]) ;
- icmdata->sd.gyro_zad = (signed short)(buf[12] << 8 | buf[13]);
- atomic_set(&icmdata->lock, 1);
- wake_up_interruptible(&icmdata->r_wait);
- kill_fasync(&icmdata->async_queue, SIGIO, POLL_IN);
- }
- icm26080_write_reg(icmdata,INT_STATUS,"\x00",1);
-
- return IRQ_HANDLED;
- }
- static int icm26080_probe(struct spi_device *spi)
- {
- int ret = 0;
- int i = 0;
- struct icm26080_data *icmdata;
- const struct of_device_id *of_id =
- of_match_device(icm26080_dt_ids, &spi->dev);
- const struct ICM_InfoNames *name = (struct ICM_InfoNames *)of_id ->data;
-
- icmdata = devm_kzalloc(&spi->dev, sizeof(*icmdata), GFP_KERNEL);
- if (!icmdata) {
- dev_err(&spi->dev, "failed to allocate driver data.\n");
- return -ENOMEM;
- }
- icmdata->spi = spi;
- spi_set_drvdata(spi, icmdata);
- icm26080_write_reg(icmdata,PWR1,"\x80",1);
- msleep(50);
- icm26080_write_reg(icmdata,PWR1,"\x01",1);
- msleep(50);
-
- ret = icm26080_read_reg(icmdata,WHO_AM_I,&(icmdata->whoami),1);
- if(!ret)
- {
- for(i=0; i<name->count; i++)
- {
- if(icmdata->whoami == name->icm_name[i].index)
- {
- dev_info(&spi->dev,"%s probed\n",name->icm_name[i].name);
- break;
- }
- }
- if(i >= name->count)
- {
- dev_info(&spi->dev,"No device probed!\n");
- goto failed;
- }
- }else {
- goto failed;
- }
-
- icm26080_setup(icmdata);
- atomic_set(&icmdata->lock, 0);
- init_waitqueue_head(&icmdata->r_wait);
-
- ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
- icm26080_isr,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- spi->modalias, icmdata);
- icmdata->misc.minor = MISC_DYNAMIC_MINOR;
- icmdata->misc.name = spi->modalias;
- icmdata->misc.parent = &spi->dev;
- icmdata->misc.fops = &icm_fops;
- ret = misc_register(&icmdata->misc);
- failed:
- return ret;
- }
- static int icm26080_remove(struct spi_device *spi)
- {
- struct icm26080_data *icmdata = spi_get_drvdata(spi);
- misc_deregister(&icmdata->misc);
- dev_info(&spi->dev,"removed\n");
- return 0;
- }
- static struct spi_driver spidev_spi_driver = {
- .driver = {
- .name = "icm26080",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(icm26080_dt_ids),
- },
- .probe = icm26080_probe,
- .remove = icm26080_remove,
- };
- module_spi_driver(spidev_spi_driver);
- MODULE_LICENSE("GPL");
复制代码
|
|