<form id="bpvnp"></form>

            <address id="bpvnp"><listing id="bpvnp"><meter id="bpvnp"></meter></listing></address>

                <address id="bpvnp"><nobr id="bpvnp"><menuitem id="bpvnp"></menuitem></nobr></address>

                    技术文摘

                    GSC3280的ADC子系统驱动模型(一)












                    一、芯片和驱动架构总体介绍

                    1.1、芯片介绍

                    本文使用的芯片为GSC3280,根据芯片手册的介绍,ADC 与触摸屏控制器通过SPI 接口挂在GSC3280的SPI0总线上,支持4线电阻式触摸屏或当ADC输入使用。GSC3280片上集成的ADC与触摸屏控制器主要有以下特性:

                    1、通过标准SPI接口传输命令和数据;

                    2、最大分辨率为12位;

                    3、输入最大的SPI 时钟是6MHz,对应最大采样率为120Ksps;

                    4、支持4线电阻式触摸屏;

                    5、可以当4路ADC输入;

                    6、支持触摸屏触笔中断;

                    7、支持低功耗模式;







                    1.2、驱动架构介绍

                    本文所设计的ADC子系统架构关系图如下:

                    驱动架构介绍.png


                    由于AD转换使用的是SPI0,所以此处在Linux内核源码目录的/driver/spi目录下建立一个adc目录,根据上图,建立了adc-core.c、adc-dev.c、adc-sysfs.c、adc-proc.c、adc.h和 gsc3280_adc.c等文件。现在先简单说下各个文件的功能:

                    gsc3280_adc.c:是最底层的直接和硬件打交道的驱动文件,将在(二)中讲述。

                    adc-core.c:gsc3280_adc.c的上面一层,提供了ADC子系统的一些公共函数,让各个ADC驱动注册集成到linux内核中,向驱动程序提供了注册/注销接口。将在第二篇文章中讲述。

                    adc-dev.c:adc-core.c再往上就到了adc-dev.c,adc-dev.c最终生成了/dev/adc设备节点,上层的应用程序就是通过操作此文件来进行相关的读取AD转换值等操作的。定义了基本的设备文件操作函数,用户程序与ADC驱动的接口函数,这里定义了每个ioctl命令需要调用的函数,还有open,read等。将在第二篇文章中讲述。

                    adc-proc.c:与proc文件系统有关,提供通过proc文件系统操作ADC。将在第二篇文章中讲述。

                    adc-sysfs.c:与sysfs有关,提供通过sys文件系统操作ADC。将在第二篇文章中讲述。

                    adc.h、adc-core.h:定义了与ADC有关的数据结构,变量和函数声明等。在使用时讲述。







                    二、驱动程序gsc3280_adc.c  

                    2.1、??槌跏蓟?/strong>

                    本部分讲述gsc3280_adc.c文件中的程序,此即为上图中的最下部分--驱动程序,首先从??槌跏蓟?,程序如下:

                    1.       static struct platform_driver gsc3280adc_driver = {

                    2.           .driver    = {

                    3.               .name    = "adc-core",

                    4.               .owner    = THIS_MODULE,

                    5.           },

                    6.           .probe    = gsc3280_adc_probe,

                    7.           .remove    = __devexit_p(gsc3280_adc_remove),

                    8.           .suspend    = gsc3280_adc_suspend,

                    9.           .resume    = gsc3280_adc_resume,

                    10.      };

                    11.       

                    12.      static int __init gsc3280_adc_init(void)

                    13.      {

                    14.          int ret = 0;

                    15.          

                    16.          ret = platform_driver_register(&gsc3280adc_driver);

                    17.          if (ret != 0)

                    18.              DBG("!!!!!!gsc adc core register error!!!!!!\n");

                    19.          return ret;

                    20.      }

                    21.      static void __exit gsc3280_adc_exit(void)

                    22.      {

                    23.          platform_driver_unregister(&gsc3280adc_driver);

                    24.      }

                    25.      module_init(gsc3280_adc_init);

                    26.      module_exit(gsc3280_adc_exit);

                    27.       

                    28.      MODULE_AUTHOR("Davied<apple_guet@126.com>");

                    29.      MODULE_DESCRIPTION("gsc3280 spi0 adc Driver");

                    30.      MODULE_LICENSE("GPL");

                    31.      MODULE_ALIAS("platform:gsc3280-spi0 adc");


                    在这里将设备定义为平台设备,驱动注册函数即为平台驱动的注册。







                    2.2、探测函数

                    接下来看下平台驱动的探测函数,程序如下:

                    1.       static int __devinit gsc3280_adc_probe(struct platform_device *pdev)

                    2.       {

                    3.           int ret = 0, size = 0;

                    4.           unsigned long rate = 0;

                    5.           struct gsc_adc_dev *adc;

                    6.           struct resource *mem, *ioarea;

                    7.        

                    8.           DBG("############\n");

                    9.           printk(KERN_INFO "GSC3280 spi0 adc probe start\n");

                    10.          adc = kzalloc(sizeof(struct gsc_adc_dev), GFP_KERNEL);

                    11.          if (adc == NULL) {

                    12.              DBG("failed to allocate adc_core_dev\n");

                    13.              return -ENOMEM;

                    14.          }

                    15.          mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 

                    16.          if (!mem) {

                    17.              DBG("no mem resource.\n"); 

                    18.              ret = -EINVAL;

                    19.              goto err_alloc;

                    20.          }

                    21.          size = resource_size(mem);

                    22.          ioarea = request_mem_region(mem->start, size, pdev->name); 

                    23.          if (!ioarea) {

                    24.              DBG("SPI region already claimed.\n"); 

                    25.              ret = -EBUSY;

                    26.              goto err_alloc; 

                    27.          } 

                    28.          adc->regs = ioremap_nocache(mem->start, resource_size(mem));

                    29.          if (!adc->regs) {

                    30.              DBG("SPI region already mapped.\n");

                    31.              ret = -ENOMEM;

                    32.              goto err_mem;

                    33.          }

                    34.          DBG("probe: mapped spi0 base=%p.\n", adc->regs);

                    35.       

                    36.          adc->clk = clk_get(NULL, "spi0");

                    37.          if (IS_ERR(adc->clk)) {

                    38.              DBG("failed to find watchdog clock source.\n");

                    39.              ret = PTR_ERR(adc->clk);

                    40.              goto err_map;

                    41.          }

                    42.          rate = clk_get_rate(adc->clk);

                    43.          DBG("rate is %ld.\n", rate);

                    44.          clk_enable(adc->clk);

                    45.          ret = adc_sysctl(adc);

                    46.          if (ret != 0)

                    47.              goto err_map;

                    48.          

                    49.          spin_lock_init(&adc->lock);

                    50.          INIT_LIST_HEAD(&adc->device_entry);

                    51.          strlcpy(adc->name, GSC3280_ADC_NAME, sizeof(adc->name));

                    52.       

                    53.          mutex_lock(&gsc3280_adc_list_lock);

                    54.          list_add(&adc->device_entry, &gsc3280_adc_list);

                    55.          mutex_unlock(&gsc3280_adc_list_lock);

                    56.       

                    57.          adc->adc_dev = adc_device_register(adc->name, &pdev->dev, &gsc3280_adc_ops, THIS_MODULE);

                    58.          if (IS_ERR(adc->adc_dev)) {

                    59.              ret = PTR_ERR(adc->adc_dev);

                    60.              DBG("unable to register the class device\n");

                    61.              goto err_clk;

                    62.          }

                    63.       

                    64.          platform_set_drvdata(pdev, adc);

                    65.          printk(KERN_INFO "GSC3280 adc probe SUCCESS.\n");

                    66.          DBG("############\n");

                    67.          return 0;

                    68.       

                    69.       err_clk:

                    70.          clk_disable(adc->clk);

                    71.          clk_put(adc->clk);

                    72.       err_map:

                    73.          iounmap(adc->regs);

                    74.       err_mem:

                    75.          release_mem_region(mem->start, size);

                    76.          mem = NULL;

                    77.       err_alloc:

                    78.          kfree(adc);

                    79.          printk(KERN_INFO "!!!!!!GSC3280 adc probe error!!!!!!\n");

                    80.          return ret;

                    81.      }


                    说明:

                    1、首先申请驱动结构体内存。

                    2、对资源的申请和映射,包括IO内存等。

                    3、使能spi0时钟。

                    4、配置系统控制寄存器--ret = adc_sysctl(adc)。

                    5、驱动结构体成员初始化。

                    6、adc子系统注册,此处尤为重要,将在(三)中讲述。

                    7、通过gsc3280_adc_list_lock和gsc3280_adc_list,使得在其他函数中也能找到1中定义的驱动结构体内存。

                    8、在红色部分程序中,注册了文件操作函数集gsc3280_adc_ops,在第二篇文章中会多次使用此函数,具体定义如下:

                    1.       static const struct adc_class_ops gsc3280_adc_ops = {

                    2.           .convert = gsc3280AdcCon,

                    3.       };

                    这里只定义一个转换函数gsc3280AdcCon,就是底层驱动程序提供的对spi0操作的函数,上层调用的AD转换动作,最终都是由此程序来完成的。具体程序如下:
                    1.       //return 0:date valid, other:date error
                    2.       static int gsc3280AdcCon(unsigned short cmd)
                    3.       {
                    4.           struct gsc_adc_dev *adc;

                    5.           int ret = 0, status = 0/*, cnt = 0*/;

                    6.        

                    7.           //DBG("gscAdcCon\n");

                    8.           mutex_lock(&gsc3280_adc_list_lock);

                    9.           list_for_each_entry(adc, &gsc3280_adc_list, device_entry) {

                    10.              if(strcmp(adc->name, GSC3280_ADC_NAME) == 0) {

                    11.                  status = 0;

                    12.                  break;

                    13.              }

                    14.          }

                    15.          mutex_unlock(&gsc3280_adc_list_lock);

                    16.          if (status != 0) {

                    17.              DBG("get gsc3280 adc struct error\n");

                    18.              return -5;

                    19.          }

                    20.       

                    21.          adc->cmd = cmd;

                    22.          ret = writeSpiDate(adc);    //send test cmd

                    23.          if (ret < 0) {

                    24.              //DBG("cmd = %x\n", adc->cmd);

                    25.              return ret;

                    26.          }

                    27.          ret = readSpiDate(adc);

                    28.          if (ret < 0) {

                    29.              //DBG("result = %x\n", adc->result);

                    30.              return ret;

                    31.          }

                    32.          if (adc->result != ((adc->cmd >> 12) | 0x8000)) {

                    33.              DBG("cmd error\n");

                    34.              return CMD_ERR;

                    35.          }

                    36.      again:

                    37.          adc->cmd = CMD_GSC_ADC_NOP;

                    38.          ret = writeSpiDate(adc);    //send nop cmd

                    39.          if (ret < 0) {

                    40.              DBG("send nop cmd error\n");

                    41.              return ret;

                    42.          }

                    43.          ret = readSpiDate(adc);

                    44.          if (ret < 0) {

                    45.              DBG("in read result = %x\n", adc->result);

                    46.              return ret;

                    47.          }

                    48.          if ((adc->result & 0xf000) == 0xf000)

                    49.              goto again;

                    50.          if ((adc->result & 0xf000) == 0) {

                    51.              adc->result &= 0x0fff;

                    52.              DBG("get result success, result = %d\n", adc->result);

                    53.              return adc->result;

                    54.          } else {

                    55.              DBG("get adc result error, result = %d\n", adc->result);

                    56.              return RESULT_ERR;

                    57.          }

                    58.      }


                    使用spi读写数据函数如下:

                    1.       //ret: 1:busy, 0:free

                    2.       static int getSpiState(struct gsc_adc_dev *adc)

                    3.       {

                    4.           unsigned int time_cnt = 0;

                    5.        

                    6.           while (readl(adc->regs + GSC_SPI_SR) & GSC_SPI_SR_BUSY) {

                    7.               if (time_cnt++ > MAX_WAIT_CNT) {

                    8.                   DBG("spi busy, stat = %x\n", readl(adc->regs + GSC_SPI_SR));

                    9.                   return SPI_BUSY;

                    10.              }

                    11.          }

                    12.          return 0;

                    13.      }

                    14.       

                    15.      static int writeSpiDate(struct gsc_adc_dev *adc)

                    16.      {

                    17.          int cnt = 0, stat = 0;

                    18.          

                    19.          stat = getSpiState(adc);

                    20.          if (stat != 0) {

                    21.              DBG("in write spi date,spi is busy\n");

                    22.              return stat;

                    23.          }

                    24.          //spi0 fifo can write, transmit fifo empty

                    25.          while (!(readl(adc->regs + GSC_SPI_SR) & GSC_SPI_SR_TX_NO_FULL)) {

                    26.              if (cnt++ > MAX_WAIT_CNT) {

                    27.                  DBG("write spi date error, stat = %x\n", readl(adc->regs + GSC_SPI_SR));

                    28.                  return WRITE_DATE_ERR;

                    29.              }

                    30.          }

                    31.          writel(adc->cmd, adc->regs + GSC_SPI_DA_S);

                    32.          return 0;

                    33.      }

                    34.       

                    35.      /* prepare to read data from adc */

                    36.      static int readSpiDate(struct gsc_adc_dev *adc)

                    37.      {

                    38.          int cnt= 0, stat = 0;

                    39.          

                    40.          stat = getSpiState(adc);

                    41.          if (stat < 0) {

                    42.              DBG("in read spi date,spi is busy\n");

                    43.              return stat;

                    44.          }

                    45.          //spi0 fifo receive not empty

                    46.          while (!(readl(adc->regs + GSC_SPI_SR) & GSC_SPI_SR_RX_N_EMPTY)) {

                    47.              if (cnt++ > MAX_WAIT_CNT) {

                    48.                  DBG("read spi date error, spi stat = %x\n", readl(adc->regs + GSC_SPI_SR));

                    49.                  return READ_DATE_ERR;

                    50.              }

                    51.          }

                    52.          adc->result = (unsigned short)readl(adc->regs + GSC_SPI_DA_S);

                    53.          return 0;

                    54.      }








                    2.3、移除函数--gsc3280_adc_remove

                    移除函数就是探测函数的相反过程,程序如下:

                    1.     static int __devexit gsc3280_adc_remove(struct platform_device *pdev)

                    2.     {

                    3.         struct gsc_adc_dev *adc = platform_get_drvdata(pdev);

                    4.      

                    5.         iounmap(adc->regs);

                    6.         clk_disable(adc->clk);

                    7.         clk_put(adc->clk);

                    8.         adc_device_unregister(adc->adc_dev);

                    9.         kfree(adc);

                    10.        return 0;

                    11.    }







                    三、ADC子系统核心(adc-core.c)

                    adc-core.c是gsc3280_adc.c的上面一层,提供了ADC子系统的一些公共函数,让各个ADC驱动注册集成到linux内核中,向驱动程序提供了注册/注销接口。首先还是先看下??槌跏蓟屯顺龊?。

                    3.1、??槌跏蓟屯顺龊?/strong>


                    1.     static int __init gsc_adc_init(void)

                    2.     {

                    3.         adc_class = class_create(THIS_MODULE, "adc");

                    4.         if (IS_ERR(adc_class)) {

                    5.             printk(KERN_ERR "%s: couldn't create class\n", __FILE__);

                    6.             return PTR_ERR(adc_class);

                    7.         }

                    8.         //adc_class->suspend = adcSuspend;

                    9.         //adc_class->resume = adcResume;

                    10.        adc_dev_init();

                    11.        adc_sysfs_init(adc_class);

                    12.        writel(0x01, (volatile unsigned int *)0xbc04a0ac);    //enable ts and adc

                    13.        return 0;

                    14.    }

                    15.    static void __exit gsc_adc_exit(void)

                    16.    {

                    17.        adc_dev_exit();

                    18.        class_destroy(adc_class);

                    19.        idr_destroy(&adc_idr);

                    20.    }

                    21.    subsys_initcall(gsc_adc_init);

                    22.    module_exit(gsc_adc_exit);


                    说明:

                    1、首先建立了一个设备类,在GSC3280的ADC子系统驱动模型(三)----class的使用中介绍。

                    2、对ADC子系统中的dev进行初始化,第二篇文章讲述。

                    3、对ADC子系统中的sysfs进行初始化,第二篇文章讲述。

                    4、注意:此处的初始化宏使用的是subsys_initcall,优先级高于module_init(),即subsys_initcall先于module_init()执行。

                    5、退出函数就是初始化函数的相反过程。







                    3.2、ADC子系统注册和注销函数

                    现在就来看下2.2中涉及到的ADC子系统注册函数。程序如下:

                    1.       struct class *adc_class;

                    2.       static DEFINE_IDR(adc_idr);

                    3.       static DEFINE_MUTEX(adc_idr_lock);

                    4.        

                    5.       static void adc_device_release(struct device *dev)

                    6.       {

                    7.           struct adc_core_dev *adc = to_adc_device(dev);

                    8.           

                    9.           mutex_lock(&adc_idr_lock);

                    10.          idr_remove(&adc_idr, adc->id);

                    11.          mutex_unlock(&adc_idr_lock);

                    12.          kfree(adc);

                    13.      }

                    14.       

                    15.      /**

                    16.       * adc_device_register - register w/ ADC class

                    17.       * @dev: the device to register

                    18.       *

                    19.       * adc_device_unregister() must be called when the class device is no

                    20.       * longer needed.

                    21.       *

                    22.       * Returns the pointer to the new struct class device.

                    23.       */

                    24.      struct adc_core_dev *adc_device_register(const char *name, struct device *dev,

                    25.                                              const struct adc_class_ops *ops,

                    26.                                              struct module *owner)

                    27.      {

                    28.          struct adc_core_dev *adc;

                    29.          int id, err;

                    30.       

                    31.          if (idr_pre_get(&adc_idr, GFP_KERNEL) == 0) {

                    32.              err = -ENOMEM;

                    33.              goto exit;

                    34.          }

                    35.          mutex_lock(&adc_idr_lock);

                    36.          err = idr_get_new(&adc_idr, NULL, &id);

                    37.          mutex_unlock(&adc_idr_lock);

                    38.          if (err < 0)

                    39.              goto exit;

                    40.          id = id & MAX_ID_MASK;

                    41.       

                    42.          adc= kzalloc(sizeof(struct adc_core_dev), GFP_KERNEL);

                    43.          if (adc == NULL) {

                    44.              err = -ENOMEM;

                    45.              goto exit_idr;

                    46.          }

                    47.       

                    48.          adc->id = id;

                    49.          adc->ops = ops;

                    50.          adc->owner = owner;

                    51.          adc->dev.parent = dev;

                    52.          adc->dev.class = adc_class;

                    53.          adc->dev.release = adc_device_release;

                    54.       

                    55.          mutex_init(&adc->ops_lock);

                    56.          strlcpy(adc->name, name, ADC_CORE_NAME_SIZE);

                    57.          dev_set_name(&adc->dev, "adc%d", id);

                    58.       

                    59.          adc_dev_prepare(adc);

                    60.       

                    61.          err = device_register(&adc->dev);

                    62.          if (err) {

                    63.              put_device(&adc->dev);

                    64.              goto exit_kfree;

                    65.          }

                    66.       

                    67.      #ifdef CONFIG_TOUCHSCREEN_GSC3280

                    68.          err = adc_ts_add_dev(adc);

                    69.          if (err < 0)

                    70.              DBG("adc ts add dev error\n");

                    71.      #endif

                    72.       

                    73.          adc_dev_add_device(adc);

                    74.          adc_sysfs_add_device(adc);

                    75.          adc_proc_add_device(adc);

                    76.       

                    77.          dev_info(dev, "adc core: registered %s as %s\n", adc->name, dev_name(&adc->dev));

                    78.          return adc;

                    79.       

                    80.      exit_kfree:

                    81.          kfree(adc);

                    82.      exit_idr:

                    83.          mutex_lock(&adc_idr_lock);

                    84.          idr_remove(&adc_idr, id);

                    85.          mutex_unlock(&adc_idr_lock);

                    86.      exit:

                    87.          dev_err(dev, "adc core: unable to register %s, err = %d\n", name, err);

                    88.          return ERR_PTR(err);

                    89.      }

                    90.      EXPORT_SYMBOL_GPL(adc_device_register);

                    91.       

                    92.      /**

                    93.       * adc_device_unregister - removes the previously registered ADC class device

                    94.       *

                    95.       * @adc: the ADC class device to destroy

                    96.       */

                    97.      void adc_device_unregister(struct adc_core_dev *adc)

                    98.      {

                    99.          if (get_device(&adc->dev) != NULL) {

                    100.            mutex_lock(&adc->ops_lock);

                    101.            adc_sysfs_del_device(adc);

                    102.            adc_dev_del_device(adc);

                    103.            adc_proc_del_device(adc);

                    104.            device_unregister(&adc->dev);

                    105.            adc->ops = NULL;

                    106.            mutex_unlock(&adc->ops_lock);

                    107.            put_device(&adc->dev);

                    108.        }

                    109.    }

                    110.    EXPORT_SYMBOL_GPL(adc_device_unregister);


                    说明:

                    1、首先使用idr机制获取id。

                    2、申请结构体内存,初始化成员变量。

                    3、注册device,在GSC3280的ADC子系统驱动模型(三)----class的使用中介绍。

                    4、增加dev、proc和sysfs设备,第二篇文章中讲述。

                    5、注销函数是注册函数的相反过程。

                    6、释放函数就是移除idr,释放结构体内存。







                    四、Kconfig和Makefile编写

                    首先我们在Linux内核源码目录下的/driver/spi/adc目录下创建Kconfig和Makefile文件。

                    4.1、Kconfig

                    Kconfig程序如下:

                    1.       #

                    2.       # Sensor device configuration

                    3.       # add by hdw,in order to use adc

                    4.       #

                    5.        

                    6.       menuconfig SPI0_ADC

                    7.           bool "Adc Hardware support"

                    8.           help

                    9.            GSC3280 Adc Hardware support.

                    10.       

                    11.       

                    12.      if SPI0_ADC

                    13.       

                    14.      config GSC_SPI0_ADC_CORE

                    15.          tristate "support adc core"

                    16.          default SPI0_ADC

                    17.          help

                    18.           If you say yes to this option, support will be included gsc3280

                    19.           adc core.

                    20.       

                    21.      config GSC_ADC_CORE_DEBUG

                    22.          bool "adc core debugging messages"

                    23.          depends on GSC_SPI0_ADC_CORE

                    24.          help

                    25.           Say Y here if you want the GSC3280 to produce a bunch of debug

                    26.           messages to the system log. Select this if you are having a

                    27.           problem with GSC3280 and want to see more of what is going on.

                    28.       

                    29.      comment "ADC interfaces"

                    30.       

                    31.      config ADC_INTF_SYSFS

                    32.          boolean "/sys/class/adc/adcN (sysfs)"

                    33.          depends on SYSFS

                    34.          default SPI0_ADC

                    35.          help

                    36.           Say yes here if you want to use your ADCs using sysfs interfaces,

                    37.           /sys/class/adc/adc0 through /sys/.../adcN.

                    38.       

                    39.           If unsure, say Y.

                    40.       

                    41.      config ADC_SYS_DEBUG

                    42.          bool "adc sys debugging messages"

                    43.          depends on ADC_INTF_SYSFS

                    44.          help

                    45.           Say Y here if you want the adc sysfs dev to produce a bunch of debug

                    46.           messages to the system log. Select this if you are having a

                    47.           problem with adc core and want to see more of what is going on.

                    48.       

                    49.      config ADC_INTF_PROC

                    50.          boolean "/proc/driver/adc (procfs for adc0)"

                    51.          depends on PROC_FS

                    52.          default SPI0_ADC

                    53.          help

                    54.           Say yes here if you want to use your first ADC through the proc

                    55.           interface, /proc/driver/adc. Other ADCs will not be available

                    56.           through that API.

                    57.       

                    58.           If unsure, say Y.

                    59.       

                    60.      config ADC_PROC_DEBUG

                    61.          bool "adc proc debugging messages"

                    62.          depends on ADC_INTF_PROC

                    63.          help

                    64.           Say Y here if you want the adc proc dev to produce a bunch of debug

                    65.           messages to the system log. Select this if you are having a

                    66.           problem with adc core and want to see more of what is going on.

                    67.       

                    68.      config ADC_INTF_DEV

                    69.          boolean "/dev/adcN (character devices)"

                    70.          default SPI0_ADC

                    71.          help

                    72.           Say yes here if you want to use your ADCs using the /dev

                    73.           interfaces, which "udev" sets up as /dev/adc0 through

                    74.           /dev/adcN.

                    75.       

                    76.           You may want to set up a symbolic link so one of these

                    77.           can be accessed as /dev/adc, which is a name

                    78.           expected by "hwclock" and some other programs. Recent

                    79.           versions of "udev" are known to set up the symlink for you.

                    80.       

                    81.           If unsure, say Y.

                    82.       

                    83.      config ADC_DEV_DEBUG

                    84.          bool "adc dev debugging messages"

                    85.          depends on ADC_INTF_DEV

                    86.          help

                    87.           Say Y here if you want the adc dev to produce a bunch of debug

                    88.           messages to the system log. Select this if you are having a

                    89.           problem with adc core and want to see more of what is going on.

                    90.       

                    91.       

                    92.      comment "ADC devices"

                    93.       

                    94.      config GSC3280_ADC

                    95.          tristate "support gsc3280 adc"

                    96.          depends on GSC_SPI0_ADC_CORE

                    97.          default SPI0_ADC

                    98.          help

                    99.           If you say yes to this option, support will be included gsc3280

                    100.         adc convert and touchscreen.

                    101.     

                    102.    config GSC3280_ADC_DEBUG

                    103.        bool "GSC3280 adc debugging messages"

                    104.        depends on GSC3280_ADC

                    105.        help

                    106.         Say Y here if you want the GSC3280 adc to produce a bunch of debug

                    107.         messages to the system log. Select this if you are having a

                    108.         problem with GSC3280 and want to see more of what is going on.

                    109.         

                    110.     

                    111.    endif


                    在上一层的Kconfig,也就是Linux内核源码目录下的/driver/spi下的Kconfig增加如下内容:
                    1.       # add by hdw
                    2.       comment "gsc3280 spi0 adc"
                    3.       source drivers/spi/adc/Kconfig

                    这样在配置选项中,就可以配置ADC子系统的内容了。







                    4.2、Makefile

                    类似Kconfig,在Linux内核源码目录/driver/spi/adc目录下创建Makefile文件,具体内容如下:

                    1.       #

                    2.       # Makefile for the i2c bus drivers.

                    3.       #

                    4.        

                    5.       obj-$(CONFIG_GSC_SPI0_ADC_CORE)        += adc-core.o

                    6.       obj-$(CONFIG_ADC_INTF_DEV)            += adc-dev.o

                    7.       obj-$(CONFIG_ADC_INTF_PROC)            += adc-proc.o

                    8.       obj-$(CONFIG_ADC_INTF_SYSFS)            += adc-sysfs.o

                    9.        

                    10.      obj-$(CONFIG_GSC3280_ADC)            += gsc3280_adc.o

                    11.       

                    12.      ccflags-$(CONFIG_GSC_ADC_DEV_DEBUG) += -DGSC3280_ADC_DEV_DEBUG


                    在上一层的Makefile,也就是Linux内核源码目录下的/driver/spi下的Makefile增加如下内容

                    1.       #add by hdw

                    2.       obj-y                += adc/




                    原文参见:http://blog.chinaunix.net/uid-25445243-id-4010249.html















                     
                    彩神ll【中国】股份有限公司