#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.