linux kernel subsystem MFD

Analysis of kernel version 5.1.3

1.MFD full name

  Multi-function Device, multifunction device

 

2. Why will MFD subsystem

  Since the emergence of a class of the peripheral device having multiple functions within or integrated hardware module cpu

 

3. What multifunction devices have it?

  3.1 PMIC, the power management chip

    da9063: regulator, led controller, watchdog controller real-time clock, a temperature sensor, a vibration motor driving, long press shutdown (ON key)

    max77843: regulator, charger, fuel gauge, tactile feedback, led controllers, micro USB interface controller

    wm831x: regulator, a clock, real time clock control, watchdog, the touch controller, a temperature sensor, a backlight controller, a state led controller, GPIO, long press shutdown (ON key), ADC

    Other: even with the codec function

  3.2 atmel-hlcdc: the backlight and the display controller pwm

  3.3 Diolan DLN2: USB transfer I2C, SPI, and GPIO controller

  3.4 Realtek PCI-E Card Reader: SD / MMC and Memory Stick reader

 

The main problem 4. MFD subsystem solutions of

  These drivers are registered in different kernel subsystems. In particular external peripheral device is only rendered by a structure struct device (or designated i2c_client or spi_device)

 

5. MFD subsystem advantage of what?

  5.1 is allowed to register the same device in the plurality of subsystems

  5.2 MFD drive can be multiplexed bus (mainly processed on the lock) and interrupt request

  5.3 processing clock

  5.4 you need to configure IP

  5.5 allows the drive to reuse, a plurality of multi-function device driver can be reused in other subsystems

 

6. MFD provides API

  

int mfd_add_devices(struct device *parent,int id,
                    const struct mfd_cell *cells, int n_devs,
struct resource *mem_base, int irq_base, struct irq_domain *irq_domain);
extern void mfd_remove_devices(struct device *parent);

These interfaces are defined in the include / linux / mfd / core.h of, be implemented within drivers / mfd / mtd-core.c in

 

7. The structure of the MFD provided

struct mfd_cell {
    const char      *name;
    int         id;

    /* refcounting for multiple drivers to use a single cell */
    atomic_t        *usage_count;
    int         (*enable)(struct platform_device *dev);
    int         (*disable)(struct platform_device *dev);

    int         (*suspend)(struct platform_device *dev);
    int         (*resume)(struct platform_device *dev);

    /* platform data passed to the sub devices drivers */
    void            *platform_data;
    size_t          pdata_size;

    /* device properties passed to the sub devices drivers */
    struct property_entry *properties;

    /*  
     * Device Tree compatible string
     * See: Documentation/devicetree/usage-model.txt Chapter 2.2 for details
     */
    const char      *of_compatible;

    /* Matches ACPI */
    const struct mfd_cell_acpi_match    *acpi_match;

    /*  
     * These resources can be specified relative to the parent device.
     * For accessing hardware you should use resources from the platform dev
     */
    int         num_resources;
    const struct resource   *resources;

    /* don't check for resource conflicts */
    bool            ignore_resource_conflicts;

    /*  
     * Disable runtime PM callbacks for this subdevice - see
     * pm_runtime_no_callbacks().
     */
    bool            pm_runtime_no_callbacks;

    /* A list of regulator supplies that should be mapped to the MFD
     * device rather than the child device when requested
     */
    const char * const  *parent_supplies;
    int         num_parent_supplies;
};

 

Example 8. Analysis

 8.1 Analysis of multi-function drive tps6507x

  8.1.1 documents involved

    drivers/mfd/tps6507x.c

    include/linux/mfd/tps6507x.h

    drivers/regulator/tps6507x-regulator.c

    drivers/input/touchscreen/tps6507x-ts.c

  8.1.2 according to the structure

static const struct mfd_cell tps6507x_devs[] = { 
    {   
        .name = "tps6507x-pmic",
    },  
    {   
        .name = "tps6507x-ts",
    },  
};

    Can be derived from the above structure, tps6507x series chip serves two functions: power management features (regulator) + touch screen function (Touchscreen)

    

    

static struct i2c_driver tps6507x_i2c_driver = {
    .driver = {
           .name = "tps6507x",
           .of_match_table = of_match_ptr(tps6507x_of_match),
    },
    .probe = tps6507x_i2c_probe,
    .id_table = tps6507x_i2c_id,
};

    This structure provides a probe function is tps6507x tps6507x_i2c_probe

 

    

struct tps6507x_dev {
    struct device *dev;
    struct i2c_client *i2c_client;
    int (*read_dev)(struct tps6507x_dev *tps6507x, char reg, int size,
            void *dest);
    int (*write_dev)(struct tps6507x_dev *tps6507x, char reg, int size,
             void *src);

    /* Client devices */
    struct tps6507x_pmic *pmic;
};

 

    tps6507x of read-write interface is placed in this structure, which is the so-called common

 

 

  

  8.1.3 tps6507x initialize

    subsys_initcall(tps6507x_i2c_init);

    Call path as follows:

        tps6507x_i2c_init->i2c_add_driver

  8.1.4 Probe functions tps6507x_i2c_probe done?

    Register read and write functions of tps6507x: tps6507x_i2c_read_device tps6507x_i2c_write_device and to the structure struct tps6507x_dev

    

  Two functions 8.1.5 tps6507x implementation where is it?

    drivers / regulator / tps6507x-regulator.c, which are to achieve power management functions (drive voltage regulator)

    drivers / input / touchscreen / tps6507x-ts.c, which are to achieve the touch screen function

  8.1.6 tps6507x driving voltage regulator

    8.1.6.1 call path

    subsys_initcall(tps6507x_pmic_init);

      tps6507x_pmic_init->platform_driver_register

    8.1.6.2 probe function tps6507x_pmic_probe what did?

      Obtaining a common structure struct tps6507x_dev

      Re-register the associated structure in order to provide a user interface pmic follows:       

              static  struct regulator_ops tps6507x_pmic_ops = { 
                  .is_enabled = pmic function tps6507x_pmic_is_enabled, check whether the tps6507x enabled 
                  .enable = tps6507x_pmic_enable, so that the function can tps6507x pmic of 
                  .disable = tps6507x_pmic_disable, tsp6507x disable the function pmic 
                  .get_voltage_sel = tps6507x_pmic_get_voltage_sel, acquires the voltage value 
                  .set_voltage_sel = tps6507x_pmic_set_voltage_sel, set voltage value 
                  .list_voltage = regulator_list_voltage_table, listed voltmeter 
                  .map_voltage = regulator_map_voltage_ascend,
              };

 

  

 

  8.1.7 tps6507x touch screen driver

    8.1.7.1 drive Where?

      drivers/input/touchscreen/tps6507x-ts.c

    8.1.7.2 Analysis probe functions are done?

      Obtaining common structure struct tps6507x_dev

      Filling structure struct tps6507x_ts, the key is registered as a function tps6507x_ts_poll

      

      

            

 

      

    

    

 

 

    

  

    

  

 

  

References:

  MFD subsystem

Guess you like

Origin www.cnblogs.com/dakewei/p/10991941.html