I.MX6 AD7606-4 device driver registe hacking

/**********************************************************************
 *          I.MX6 AD7606-4 device driver registe hacking
 * 说明:
 *     看一下AD7606的驱动注册上是否存在一些问题。
 *
 *                                2017-8-4 深圳 龙华樟坑村 曾剑锋
 *********************************************************************/

/*
 * initialize __mach_desc_MX6Q_SABRESD data structure.
 */
MACHINE_START(MX6Q_SABRESD, "Freescale i.MX 6Quad/DualLite/Solo Sabre-SD Board")
    /* Maintainer: Freescale Semiconductor, Inc. */
    .boot_params = MX6_PHYS_OFFSET + 0x100,
    .fixup = fixup_mxc_board,
    .map_io = mx6_map_io,
    .init_irq = mx6_init_irq,
    .init_machine = mx6_sabresd_board_init,    ------------+
    .timer = &mx6_sabresd_timer,                           |
    .reserve = mx6q_sabresd_reserve,                       |
MACHINE_END                                                |
                                                           |
static void __init mx6_sabresd_board_init(void)   <--------+
{
    ...                                                                                             

    /* SPI */
    imx6q_add_ecspi(1, &mx6q_sabresd_spi2_data);   ---------------------------+
    spi_device_init();                             ---------------------------*-+
                                                                              | |
    ...                                                                       | |
}                                                                             | |
                                                                              | |
static const struct spi_imx_master mx6q_sabresd_spi2_data __initconst = { <---+ |
    .chipselect     = mx6q_sabresd_spi2_cs,                                     |
    .num_chipselect = ARRAY_SIZE(mx6q_sabresd_spi2_cs),                         |
};                                                                              |
                                                                                |
static void spi_device_init(void)              <--------------------------------+
{
    spi_register_board_info(imx6_sabresd_spi_nor_device,    -----------------------+
                ARRAY_SIZE(imx6_sabresd_spi_nor_device));                          |
}                                                                                  |
                                                                                   |
static struct spi_board_info imx6_sabresd_spi_nor_device[] __initdata = {  <-------+
{
    {
        /* the modalias must be the same as spi device driver name */
        .modalias = "ad7606-4", /* Name of spi_driver for this device */
        .max_speed_hz = 500000,     /* max spi clock (SCK) speed in HZ */
        //.max_speed_hz = 10000000,     /* max spi clock (SCK) speed in HZ */
        //.max_speed_hz = 14500000,     /* max spi clock (SCK) speed in HZ */
        .bus_num = 1, /* Framework bus number */
        .chip_select = 0, /* Framework chip select */
        .platform_data = &ad7606_pdata,                            -----------+
        // .controller_data = &ad7606_chip_info, /* Blackfin only */          |
        .irq = gpio_to_irq(AD7606_GPIO_BUSY),                                 |
        .mode = SPI_MODE_0,                                                   |
    },                                                                        |
};                                                                            |
                                                                              |
static struct ad7606_platform_data ad7606_pdata = {          <----------------+
    .default_os = 0,
    .default_range = 5000,
    .gpio_convst = AD7606_GPIO_CONVST,
    .gpio_reset = AD7606_GPIO_RESET,
    .gpio_range = -1,
    .gpio_os0 = AD7606_GPIO_OS0,
    .gpio_os1 = AD7606_GPIO_OS1,
    .gpio_os2 = AD7606_GPIO_OS2,
    .gpio_frstdata = -1,
    //.gpio_frstdata = AD7606_GPIO_FRSTDATA,
    .gpio_stby = AD7606_GPIO_STBY,
};                                                                                                  

"drivers/staging/iio/adc/ad7606_spi.c"
static const struct spi_device_id ad7606_id[] = {   <---------+
    {"ad7606-8", ID_AD7606_8},                                |
    {"ad7606-6", ID_AD7606_6},                                |
    {"ad7606-4", ID_AD7606_4},                                |
    {}                                                        |
};                                                            |
                                                              |
static struct spi_driver ad7606_driver = {     <------------+ |
    .driver = {                                             | |
        .name = "ad7606",                                   | |
        .bus = &spi_bus_type,                               | |
        .owner = THIS_MODULE,                               | |
        .pm    = AD7606_SPI_PM_OPS,                         | |
    },                                                      | |
    .probe = ad7606_spi_probe,                        ------*-*-------+
    .remove = __devexit_p(ad7606_spi_remove),               | |       |
    .id_table = ad7606_id,                     -------------*-+       |
};                                                          |         |
                                                            |         |
static int __init ad7606_spi_init(void)                     |         |
{                                                           |         |
    return spi_register_driver(&ad7606_driver);       ------+         |
}                                                                     |
module_init(ad7606_spi_init);                                         |
                                                                      |
static void __exit ad7606_spi_exit(void)                              |
{                                                                     |
    spi_unregister_driver(&ad7606_driver);                            |
}                                                                     |
module_exit(ad7606_spi_exit);                                         |
                                                                      |
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");  |
MODULE_DESCRIPTION("Analog Devices AD7606 ADC");                      |
MODULE_LICENSE("GPL v2");                                             |
MODULE_ALIAS("spi:ad7606_spi");                                       |
                                                                      |
static int __devinit ad7606_spi_probe(struct spi_device *spi)  <------+
{
    struct iio_dev *indio_dev;                                                                      

    indio_dev = ad7606_probe(&spi->dev, spi->irq, NULL,      ---------+
               spi_get_device_id(spi)->driver_data,                   |
               &ad7606_spi_bops);                                     |
                                                                      |
    if (IS_ERR(indio_dev))                                            |
        return PTR_ERR(indio_dev);                                    |
                                                                      |
    spi_set_drvdata(spi, indio_dev);                                  |
                                                                      |
    return 0;                                                         |
}                                                                     |
                                                                      |
struct iio_dev *ad7606_probe(struct device *dev, int irq,     <-------+
                  void __iomem *base_address,
                  unsigned id,
                  const struct ad7606_bus_ops *bops)
{
    struct ad7606_platform_data *pdata = dev->platform_data;
    struct ad7606_state *st;
    int ret, regdone = 0;
    struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st));                                   

    if (indio_dev == NULL) {
        ret = -ENOMEM;
        goto error_ret;
    }                                                                                               

    st = iio_priv(indio_dev);                                                                       

    st->dev = dev;
    st->id = id;
    st->irq = irq;
    st->bops = bops;
    st->base_address = base_address;
    st->range = pdata->default_range == 10000 ? 10000 : 5000;                                       

    ret = ad7606_oversampling_get_index(pdata->default_os);
    if (ret < 0) {
        dev_warn(dev, "oversampling %d is not supported\n",
             pdata->default_os);
        st->oversampling = 0;
    } else {
        st->oversampling = pdata->default_os;
    }                                                                                               

    st->reg = regulator_get(dev, "vcc");
    if (!IS_ERR(st->reg)) {
        ret = regulator_enable(st->reg);
        if (ret)
            goto error_put_reg;
    }                                                                                               

    st->pdata = pdata;
    st->chip_info = &ad7606_chip_info_tbl[id];                                                      

    indio_dev->dev.parent = dev;
    indio_dev->info = &ad7606_info;
    indio_dev->modes = INDIO_DIRECT_MODE;
    indio_dev->name = st->chip_info->name;
    indio_dev->channels = st->chip_info->channels;
    indio_dev->num_channels = st->chip_info->num_channels;                                          

    init_waitqueue_head(&st->wq_data_avail);                                                        

    ret = ad7606_request_gpios(st);
    if (ret)
        goto error_disable_reg;                                                                     

    ret = ad7606_reset(st);
    if (ret)
        dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n");                            

    ret = request_irq(st->irq, ad7606_interrupt,
        IRQF_TRIGGER_FALLING, st->chip_info->name, indio_dev);
    if (ret)
        goto error_free_gpios;                                                                      

    ret = ad7606_register_ring_funcs_and_init(indio_dev);
    if (ret)
        goto error_free_irq;                                                                        

    ret = iio_device_register(indio_dev);
    if (ret)
        goto error_free_irq;
    regdone = 1;                                                                                    

    ret = iio_ring_buffer_register_ex(indio_dev->ring, 0,
                      indio_dev->channels,
                      indio_dev->num_channels);
    if (ret)
        goto error_cleanup_ring;                                                                    

    return indio_dev;                                                                               

error_cleanup_ring:
    ad7606_ring_cleanup(indio_dev);                                                                 

error_free_irq:
    free_irq(st->irq, indio_dev);                                                                   

error_free_gpios:
    ad7606_free_gpios(st);                                                                          

error_disable_reg:
    if (!IS_ERR(st->reg))
        regulator_disable(st->reg);
error_put_reg:
    if (!IS_ERR(st->reg))
        regulator_put(st->reg);
    if (regdone)
        iio_device_unregister(indio_dev);
    else
        iio_free_device(indio_dev);
error_ret:
    return ERR_PTR(ret);
}                                                                                                   

 

时间: 2024-11-04 00:38:29

I.MX6 AD7606-4 device driver registe hacking的相关文章

I.MX6 Linux I2C device&amp; driver hacking

/******************************************************************************************* * I.MX6 Linux I2C device& driver hacking * 声明: * 1. 本文主要是对Linux I2C驱动进行代码跟踪,主要是为了能够对I2C驱动框架有个全面的了解: * 2. 本文源代码来自myzr_android4_2_2_1_1_0.tar.bz2: * 3. 如果你有兴趣,

I.MX6 ar1020 SPI device driver hacking

/************************************************************************************ * I.MX6 ar1020 SPI device driver hacking * 声明: * 1. 本文主要是解读I.MX6中ar1020 SPI设备注册,以及驱动调用流程: * 2. 本文主要使用了vim+ctags进行代码跟踪,所以几乎都是函数原型之间的调用: * * 2015-9-5 晴 深圳 南山平山村 曾剑锋 *

OK335xS UART device registe hacking

/************************************************************************* * OK335xS UART device registe hacking * 声明: * 1. 本文是对OK335xS Linux内核中UART设备注册代码进行跟踪: * 2. 本人在文中采用函数调用线路图进行标记,方便阅读: * 3. 代码跟踪的用的是vim+ctags: * * 2015-6-30 晴 深圳 南山平山村 曾剑锋 *******

I.MX6 Goodix GT9xx touchscreen driver porting

/************************************************************************ * I.MX6 Goodix GT9xx touchscreen driver porting * 声明: * 本文主要是记录GT9xx电容Touch移植过程中遇到的一些问题. * * 2016-1-27 深圳 南山平山村 曾剑锋 ************************************************************

Device Driver Development for Beginners - Reloaded

Hi, This is just a little starter for people interested in starting Kernel-Mode Development By following an good thread on UIC forum, opened by a beginner that wanted to know how to start with Device Driver Development, I remembered that long time ag

Samsung_tiny4412(驱动笔记10)----mdev,bus,device,driver,platform

/*********************************************************************************** * * mdev,bus,device,driver,platform * * 声明: * 1. 本系列文档是在vim下编辑,请尽量是用vim来阅读,在其它编辑器下可能会 * 不对齐,从而影响阅读. * 2. 由于本人水平有限,很难阐述清楚bus device driver platform的关系 * 所以强烈要求您详细参考本次

I.MX6 天嵌 E9 U-boot menu hacking

/************************************************************************************ * I.MX6 天嵌 E9 U-boot menu hacking * 说明: * 天嵌在U-boot中添加了自己的选择menu,想看一下怎么实现的. * * 2016-8-5 深圳 南山平山村 曽剑锋 **************************************************************

I.MX6 recovery mode hacking

/******************************************************************************** * I.MX6 recovery mode hacking * 说明: * 看一下i.MX6 Recovery模式是怎么工作的. * * 2017-6-12 深圳 龙华樟坑村 曾剑锋 ****************************************************************************

汇编源码系列之driver

这个都是过去DOS时代的汇编源码,虽然已经过去了,但是对于学习汇编还是有帮助的,汇编语言只是程序员一门基础语言,大多人掌握即可,不一定要深入研究....... name driver page 55,132 title 'DRIVER --- installable driver template';; This is a "template" for a MS-DOS installable device driver.; The actual driver subroutines