• 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
    ",                                         
                 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
    ");                            
                                                                                                        
        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);                                                                            
    }                                                                                                   
  • 相关阅读:
    云计算OpenStack核心组件---keystone身份认证服务(5)
    云计算OpenStack环境搭建(4)
    云计算OpenStack共享组件---Memcache缓存系统(3)
    云计算OpenStack共享组件---信息队列rabbitmq(2)
    【面试题41】和为s的两个数字VS和为s的连续整数序列
    反转单链表
    【面试题40】数组中只出现一次的数字
    【面试题39】二叉树的深度
    【面试题38】数字在排序数组中出现的次数
    最少钱币问题
  • 原文地址:https://www.cnblogs.com/zengjfgit/p/7286769.html
Copyright © 2020-2023  润新知