Hi,

I attach a simple standalone driver for the for the dm365 ADC in the
hope that it might prove useful.

Shlomo

----
adc_driver.c

#include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/mc146818rtc.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 
 #include "adc.h"
 #define ADC_VERSION "1.0"
 
 void *dm365_adc_base;
 
 int adc_single(unsigned int channel)
 {
   if (channel >= ADC_MAX_CHANNELS)
     return -1;
 
   //select channel
   iowrite32(1 << channel,dm365_adc_base + DM365_ADC_CHSEL);
 
   //start coversion
   iowrite32(DM365_ADC_ADCTL_BIT_START,dm365_adc_base +
DM365_ADC_ADCTL);
 
   // Wait for conversion to start
   while (!(ioread32(dm365_adc_base + DM365_ADC_ADCTL) &
DM365_ADC_ADCTL_BIT_BUSY)){
     cpu_relax();
   }
 
   // Wait for conversion to be complete.
   while ((ioread32(dm365_adc_base + DM365_ADC_ADCTL) &
DM365_ADC_ADCTL_BIT_BUSY)){
     cpu_relax();
   }
 
   return ioread32(dm365_adc_base + DM365_ADC_AD0DAT + 4 * channel);
 }
 
 static spinlock_t adc_lock = SPIN_LOCK_UNLOCKED;
 
 static void adc_read_block(unsigned short *data, size_t length)
 {
   int i;
   spin_lock_irq(&adc_lock);
     for(i = 0; i < length; i++) {
       data [i] = adc_single(i);
     }
   spin_unlock_irq(&adc_lock);
 }
 
 #ifndef CONFIG_PROC_FS
 static int adc_add_proc_fs(void)
 {
   return 0;
 }
 
 #else
 static int adc_proc_read(struct seq_file *seq, void *offset)
 {
   int i;
   unsigned short data [ADC_MAX_CHANNELS];
 
   adc_read_block(data,ADC_MAX_CHANNELS);  
  
   for(i = 0; i < ADC_MAX_CHANNELS; i++) {
     seq_printf(seq, "0x%04X\n", data[i]);
   }
 
   return 0;
 }
 
 static int adc_proc_open(struct inode *inode, struct file *file)
 {
   return single_open(file, adc_proc_read, NULL);
 }
 
 static const struct file_operations adc_proc_fops = {
   .owner    = THIS_MODULE,
   .open   = adc_proc_open,
   .read   = seq_read,
   .release  = single_release,
 };
 
 static int adc_add_proc_fs(void)
 {
   if (!proc_create("driver/adc", 0, NULL, &adc_proc_fops))
     return -ENOMEM;
   return 0;
 }
 
 #endif /* CONFIG_PROC_FS */
 
 static ssize_t adc_read(struct file *file, char __user *buf,
             size_t count, loff_t *ppos)
 {
   unsigned short data [ADC_MAX_CHANNELS];
   
   if (count < sizeof(unsigned short))
     return -ETOOSMALL;
 
   adc_read_block(data,ADC_MAX_CHANNELS);
 
   if (copy_to_user(buf, data, count))
     return -EFAULT;
 
   return count;
 
 }
 static int adc_open(struct inode *inode, struct file *file)
 {
   return 0;
 }
 static int adc_release(struct inode *inode, struct file *file)
 {
   return 0;
 }
 static const struct file_operations adc_fops = {
   .owner    = THIS_MODULE,
   .read   = adc_read,
   .open   = adc_open,
   .release  = adc_release,
 };
 
 static struct miscdevice adc_dev = {
   NVRAM_MINOR,
   "adc",
   &adc_fops
 };
 
 
 static int adc_init_module(void)
 {
   int ret;
   ret = misc_register(&adc_dev);
   if (ret) {
     printk(KERN_ERR "adc: can't misc_register on minor=%d\n",
         NVRAM_MINOR);
     return ret;
   }
   ret = adc_add_proc_fs();
   if (ret) {
     misc_deregister(&adc_dev);
     printk(KERN_ERR "adc: can't create /proc/driver/adc\n");
     return ret;
   }
   if (!devm_request_mem_region(adc_dev.this_device,
DM365_ADC_BASE,64,"adc"))
      return -EBUSY;
 
   dm365_adc_base =
devm_ioremap_nocache(adc_dev.this_device,DM365_ADC_BASE, 64);// Physical
address,Number of bytes to be mapped.
   if (!dm365_adc_base)
     return -ENOMEM;
 
   printk(KERN_INFO "TI Davinci ADC v" ADC_VERSION "\n");
   return 0;
 }
 
 static void adc_exit_module(void)
 {
   remove_proc_entry("driver/adc", NULL);
   misc_deregister(&adc_dev);
        printk( KERN_DEBUG "Module adc exit\n" );
 }
 
 module_init(adc_init_module);
 module_exit(adc_exit_module);
 MODULE_DESCRIPTION("TI Davinci Dm365 ADC");
 MODULE_AUTHOR("Shlomo Kut,,, ([email protected])");
 MODULE_LICENSE("GPL");

--

--
adc.h

/***************************************************************************
 *   Copyright (C) 2009 by Shlomo Kut,,,   *
 *   shl...@shlomo-desktop   *
 *
*
 *   This program is free software; you can redistribute it and/or
modify  *
 *   it under the terms of the GNU General Public License as published
by  *
 *   the Free Software Foundation; either version 2 of the License, or
*
 *   (at your option) any later version.
*
 *
*
 *   This program is distributed in the hope that it will be useful,
*
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
*
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*
 *   GNU General Public License for more details.
*
 *
*
 *   You should have received a copy of the GNU General Public License
*
 *   along with this program; if not, write to the
*
 *   Free Software Foundation, Inc.,
*
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*

***************************************************************************/
#ifndef _ADC_h
#define _ADC_H

#define ADC_MAX_CHANNELS 6

int adc_single(unsigned int channel);

#define DM365_ADC_BASE      (0x01C23C00)

#define DM365_ADC_ADCTL     0x0
  #define DM365_ADC_ADCTL_BIT_BUSY    (1 << 7)
  #define DM365_ADC_ADCTL_BIT_CMPFLG  (1 << 6)
  #define DM365_ADC_ADCTL_BIT_CMPIEN  (1 << 5)
  #define DM365_ADC_ADCTL_BIT_CMPMD   (1 << 4)
  #define DM365_ADC_ADCTL_BIT_SCNFLG  (1 << 3)
  #define DM365_ADC_ADCTL_BIT_SCNIEN  (1 << 2)
  #define DM365_ADC_ADCTL_BIT_SCNMD   (1 << 1)
  #define DM365_ADC_ADCTL_BIT_START   (1 << 0)

#define DM365_ADC_CMPTGT    0x4

#define DM365_ADC_CMPLDAT   0x8

#define DM365_ADC_CMPHDAT   0xC

#define DM365_ADC_SETDIV    0x10

#define DM365_ADC_CHSEL     0x14

#define DM365_ADC_AD0DAT    0x18

#define DM365_ADC_AD1DAT    0x1C

#define DM365_ADC_AD2DAT    0x20
#define DM365_ADC_AD3DAT    0x24
#define DM365_ADC_AD4DAT    0x28
#define DM365_ADC_AD5DAT    0x2C
#define DM365_ADC_EMUCTRL   0x30



#endif //_ADC_H

----
test.c

//
//test program for adc driver
//
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>


#include "../driver/adc.h"


int main (int argc, char **argv)
{
  int res,i,fd;
  unsigned short data [ADC_MAX_CHANNELS];

  printf("testing adc driver..\n");
  
  fd = open("/dev/adc",O_RDONLY);
  if (fd < 0) {
    perror("open /dev/fdc");
    return 1;
  }

  res = read(fd,data,sizeof(data));
  if (res != sizeof(data)) {
    perror("read failed");
    close(fd);
    return 1;
  }
  printf("raw data:");
  for( i = 0; i < ADC_MAX_CHANNELS; i++){
    printf("0x%08X ",data [i]);
  }
  printf("\n");

  printf("converted data:");
  for( i = 0; i < ADC_MAX_CHANNELS; i++){
    double vref = 1.8;
    double max_raw = 1 << 10;
    double volts = (double) data [i] * vref / max_raw;
    printf("%1.3fV ",volts);
  }
  printf("\n");

  close(fd);
  
  
  return 0;  
}



_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to