#include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/spi/spi.h> #include <linux/fs.h> #include <linux/miscdevice.h> #include <asm/uaccess.h> #include <linux/clk.h> #include <linux/errno.h> #include <linux/irq.h> #include <linux/list.h> //#include <mach/hardware.h> #include <asm/delay.h> #include <asm/pmu.h> #include <asm/gpio.h> //#include <mach/gpio.h> #include <linux/gpio.h> #include <asm/io.h> #include "ads1191.h" #include "Am335x_gpio.h" #define DEBUG_ENABLE 1 #define CS GPIO_TO_PIN(3, 26) #define Set(X,V) gpio_set_value(X,V) static unsigned char TransBuf[8]; static unsigned char RecvBuf[18]; long AdsResult; struct ads1191_bus { struct spi_message Pmsg; struct spi_transfer Pxfer[2]; }; struct spi_device *ads1191spi; int ads1191init(void); void ads1191ConvertRaw(void); unsigned char ads1191ReadReg(unsigned char ); unsigned char ads1191ReadRegID(unsigned char ); void ads1191WriteReg(unsigned char ,unsigned char ); unsigned char Msb2Lsb(unsigned char Data); static int ads1191_user_read(struct file *file, unsigned int *buf, size_t count, loff_t *ppos) { int p=0; Set(CS,0); // CHIP_SELECT LOW while(p <= count) { ads1191ConvertRaw(); if(AdsResult>0) buf[p++] = AdsResult; } Set(CS,1); // CHIP_SELECT HIGH return 0; } static long ads1191_user_ioctl(struct file *file, int arg) { int p; long adcval=0; char chnum; chnum = arg; Set(CS,0); // CHIP_SELECT LOW chnum=0; for(p=0; p<10; p++) { ads1191ConvertRaw(); if(AdsResult>0) adcval = adcval+AdsResult; else chnum++; } adcval = adcval/(10 - chnum); printk("adcval value in ioctl=%d\n",adcval); Set(CS,1); // CHIP_SELECT HIGH return adcval; } int ads1191init(void) { unsigned char ID=0,LOFF=0; Set(CS,0); // CHIP_SELECT LOW TransBuf[0] = RESET; spi_write_then_read(ads1191spi,TransBuf, 1,NULL,0); mdelay(50); TransBuf[0] = SDATAC; spi_write_then_read(ads1191spi,TransBuf, 1,NULL,0); mdelay(5); ID=0; // 0 previous ID=ads1191ReadRegID(ADS1191_ID_REG); #ifdef DEBUG_ENABLE printk("\n.......Ads1191 ID in INIT= %d",ID); #endif if(ID != ADS1191_ID) { printk("\n.......Ads1191 ID = %d",ID); mdelay(10); ID=0; ID=ads1191ReadRegID(ADS1191_ID_REG); if(ID != ADS1191_ID) { printk("\n.......Ads1191 ID = %d",ID); #ifdef DEBUG_ENABLE printk("\nAds1191 ID Not Matched/Device not Detected"); #endif //return -1; } } ads1191WriteReg(ADS1191_CONFIG1, 0x02); //Single-Short with 125 SPS=0x80 old, continous=0x00 ads1191WriteReg(ADS1191_CONFIG2, 0xB0); //0x80 //old 0xB0 ads1191WriteReg(ADS1191_CH1SET, 0x10); //0x00 //old 0x10 ads1191WriteReg(ADS1191_CH2SET, 0x80); //0x00 //old 0x80 ads1191WriteReg(ADS1191_MISC1, 0x02); ads1191WriteReg(ADS1191_GPIO, 0x0C); ads1191WriteReg(ADS1191_LOFF_STAT, 0x00); // fclk=512 fmod=fclk/4 TransBuf[0] = SDATAC; spi_write_then_read(ads1191spi,TransBuf, 1,NULL,0); mdelay(5); LOFF=ads1191ReadReg(ADS1191_LOFF); #ifdef DEBUG_ENABLE printk("\nAds1191 LOFF = %d\n",LOFF); #endif printk("\n- Reg Read... "); for(ID=0;ID<12;ID++) { memset(RecvBuf, 0x00, sizeof(RecvBuf)); TransBuf[0] = ADS1191_REG_READ | ID; TransBuf[1] = 0x00; spi_write_then_read(ads1191spi,TransBuf, 2,RecvBuf,1); //printk("[%02x %02x %02x %02x]",RecvBuf[0],RecvBuf[1],RecvBuf[2],RecvBuf[3]); printk("[%02x] ",RecvBuf[0]); } ads1191ConvertRaw(); Set(CS,1); // CHIP_SELECT HIGH return 1; } void ads1191ConvertRaw(void) { unsigned char p,val=0x00; AdsResult = 0x00; TransBuf[0] = START; spi_write_then_read(ads1191spi,TransBuf, 1,NULL,0); mdelay(4); /*5*/ for(p=0;p<2;p++) /*10*/ { memset(RecvBuf, 0x00, sizeof(RecvBuf)); TransBuf[0] = ADS1191_REG_READ | ADS1191_GPIO; TransBuf[1] = 0x00; spi_write_then_read(ads1191spi,TransBuf, 2,RecvBuf,1); //printk("\n-GPIO Read... %02x \n",RecvBuf[0]); val=RecvBuf[0]; if(!(val&0x02)) { //printk("\n DREADY LOW...\n"); memset(RecvBuf, 0x00, sizeof(RecvBuf)); TransBuf[0] = RDATA; spi_write_then_read(ads1191spi,TransBuf, 1,RecvBuf,6); //printk("ADC Value [0x%02x 0x%02x]",RecvBuf[2],RecvBuf[3]); break; } } AdsResult = RecvBuf[2]; AdsResult <<= 8;//bits a2d11 to a2d4 AdsResult |= RecvBuf[3]; //bits a2d3 to a2d0 + 4 dummy bits #ifdef DEBUG_ENABLE // printk("\nAdsResult = 0x%x %ld\n",AdsResult,AdsResult); //printk("\nAdsResult = 0x%x %f\n",AdsResult,(AdsResult*12.099)/(2*32768)); #endif } unsigned char Msb2Lsb(unsigned char Data) { unsigned char k,tmp1,tmp=0x00; tmp1 = Data; for(k=0;k<8;k++) { tmp = tmp << 1; tmp |= tmp1&0x01; tmp1 = tmp1 >> 1; } return tmp; } unsigned char ads1191ReadRegID(unsigned char reg) { unsigned char data = 0x00; TransBuf[0] = ADS1191_REG_READ | reg; TransBuf[1] = 0x01; //0x00 old //printk("\n Reg to be Read... %02x ",TransBuf[0]); spi_write_then_read(ads1191spi,TransBuf, 2,RecvBuf,1); data = RecvBuf[0]; //data = 0X50; printk("\n Value Read... %02x %02x %02x %02x",RecvBuf[0],RecvBuf[1],RecvBuf[2],RecvBuf[3]); printk("\n Msb2Lsb ... %02x %02x %02x %02x",Msb2Lsb(RecvBuf[0]),Msb2Lsb(RecvBuf[1]),Msb2Lsb(RecvBuf[2]),Msb2Lsb(RecvBuf[3])); return data; } unsigned char ads1191ReadReg(unsigned char reg) { unsigned char data = 0xff; TransBuf[0] = ADS1191_REG_READ | reg; TransBuf[1] = 0x00; //printk("\n Reg to be Read... %02x ",TransBuf[0]); spi_write_then_read(ads1191spi,TransBuf, 1,RecvBuf,1); data = RecvBuf[0]; //printk("\n Value Read... %02x ",RecvBuf[0]); return data; } void ads1191WriteReg(unsigned char reg,unsigned char value) { TransBuf[0] = ADS1191_REG_WRITE | reg; TransBuf[1] = 0x00; TransBuf[2] = value; spi_write_then_read(ads1191spi,TransBuf, 3,NULL,0); } static int ads1191_probe(struct spi_device *spi) { int err; spi->bits_per_word = 8; spi->mode = SPI_MODE_1;//RAISE/FALL is COnnected to GND so MODE_2 err = spi_setup(spi); if (err < 0) return err; Gpio_set_value(CS,"adc_cs",1,1); ads1191spi = spi; if(ads1191init() < 0) { #ifdef DEBUG_ENABLE printk("\n>>>>>> Failed to detect ads1191"); #endif return -1; } #ifdef DEBUG_ENABLE printk("\n>>>>>>ads1191 detect success<<<<<<<"); #endif return 0; } static const struct of_device_id ads_match_table[] = { {.compatible = "ads1191_ADC",}, { }, }; static struct spi_driver ads1191Driver = { .driver = { .name = "ads1191", .bus = &spi_bus_type, .owner = THIS_MODULE, .of_match_table = of_match_ptr(ads_match_table), }, .probe = ads1191_probe, }; static struct file_operations ads1191_user_file_ops = { .owner = THIS_MODULE, .read = ads1191_user_read, .unlocked_ioctl = ads1191_user_ioctl, }; static struct miscdevice ads1191_device = { 55, "ads1191dev", &ads1191_user_file_ops, }; static int ads1191_init(void) { int ret; ret = spi_register_driver(&ads1191Driver); if(ret < 0) { mdelay(10); ret = spi_register_driver(&ads1191Driver); } ret = misc_register(&ads1191_device); return ret; } module_init(ads1191_init); static void ads1191_exit(void) { spi_unregister_driver(&ads1191Driver); misc_deregister(&ads1191_device); } module_exit(ads1191_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("RAVINDRANATH"); MODULE_DESCRIPTION("ADS 1191 INTERFACE");
In our custom board(IMX6ULL) we used ads1191-16bit ADC SPI interface , The Driver for the same is being probed but when we read ADC value the output is zero even though giving (2V to 3.3V for AIN(4th pin)) when reading from the userspace using IOCTL call .
Kernel Version:4.1.1
dts declaration is,
&ecspi1 {
status = "okay";
pinctrl-names = "default";
fsl,spi-num-chipselects = <1>;
pinctrl-0 = <&ecspi1_pins>;
ads1191dev@0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&printer2t_pins_default>;
compatible = "ads1191_ADC";
reg = <0>;
spi-max-frequency = <512000>; /* 16M */
};
};
ecspi1_pins:ecspi1_pins_default {
fsl,pins = <
MX6UL_PAD_CSI_DATA07__ECSPI1_MISO 0x70a1
MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI 0x79
MX6UL_PAD_CSI_DATA04__ECSPI1_SCLK 0x70a1
>;
};
printer2t_pins_default: printer2t_pins {
fsl,pins = <
MX6UL_PAD_CSI_DATA05__GPIO4_IO26 0x79
>;
};
Getting below dmesg while inserting the driver.....
Value Read... ff 00 00 00
Msb2Lsb ... ff 00 00 00
.......Ads1191 ID in INIT= 255
.......Ads1191 ID = 255
Value Read... ff 00 00 00
Msb2Lsb ... ff 00 00 00
.......Ads1191 ID = 255
Ads1191 ID Not Matched/Device not Detected
Ads1191 LOFF = 255
- Reg Read...
>>>>>>ads1191 detect success<<<<<<<
Getting below dmesg when calling ioctl function....
Division by zero in kernel.
CPU: 0 PID: 815 Comm: test33V2 Not tainted 4.1.15-2.0.1+gb63f3f5 #75
Hardware name: Freescale i.MX6 Ultralite (Device Tree)
[<80015d78>] (unwind_backtrace) from [<8001271c>] (show_stack+0x10/0x14)
[<8001271c>] (show_stack) from [<8082d360>] (dump_stack+0x84/0xc4)
[<8082d360>] (dump_stack) from [<802b1418>] (Ldiv0+0x8/0x10)
[<802b1418>] (Ldiv0) from [<8063c12c>] (ads1191_user_ioctl+0x54/0x80)
[<8063c12c>] (ads1191_user_ioctl) from [<800fb204>] (do_vfs_ioctl+0x3e8/0x608)
[<800fb204>] (do_vfs_ioctl) from [<800fb458>] (SyS_ioctl+0x34/0x5c)
[<800fb458>] (SyS_ioctl) from [<8000f480>] (ret_fast_syscall+0x0/0x3c)
adcval value in ioctl=0
I am attaching driver ads1191.c , please go through them and the error log ,suggest me if any software and Hardware changes are required.