2017-06-06 2 views
0

J'ai besoin de créer un pilote de noyau Linux pour interfacer avec un groupe de MCU sur I2C, via une carte d'interface. Parce qu'ils seraient nombreux, c'est-à-dire vers 1-18, nous utilisons un multiplexeur NXP/TI I2C.Pilote de noyau Linux I2C

J'ai importé le pilote de noyau NXP/TI I2C Multiplexer et l'ai incorporé dans le fichier DTS. J'ai réussi à répertorier tous les multiplexeurs I2C en tant que différents nœuds i2c-x.

Les MCU utilisent tous la même adresse 0x08. Et je crée un pilote de noyau qui crée une interface hwmon + sysfs pour cela. Toutefois, le pilote sur insmod déclenche uniquement la fonction __init. Et ne dérange pas avec probe().

À se référant à de nombreuses documentations j'ai pu déclencher seule fonction de sonde lorsque je suis l'insertion

static struct i2c_board_info xxxx_i2c_devices[] = { 
    { 
    I2C_BOARD_INFO("xxxx", 0x08), 
    }, 
}; 

Et son correspondant

i2c_register_board_info(0, xxxx_i2c_devices, ARRAY_SIZE(xxxx_i2c_devices)); 

Cependant, cela crée une seule instance dans HWMON et non plus de plusieurs Je l'ai imaginé être. J'ai parlé https://www.kernel.org/doc/Documentation/i2c/instantiating-devices

Sans les changements à bord init, j'ai essayé d'utiliser la méthode 3, mais le noyau ne remet même pas le probe() et détecter function(), seule la fonction __init du conducteur.

Am suivant le conducteur - https://github.com/1119553797/sprd-kernel-common/blob/sprdb2g_gonk4.0/drivers/hwmon/w83l785ts.c

posterais l'ensemble pilote du noyau si nécessaire, pour référence emploie le noyau 3.0.8, un conseil personnalisé à l'aide des modifications au niveau du conseil au même noyau mentionné.

+0

change _init du conseil DTS &. Essayez moins noyau ancien en premier. – 0andriy

Répondre

0

Ok, après un googling étendu et des correctifs, différentes méthodes proposent une solution de contournement. Tout d'abord, dans le DTS, nous pouvons assigner directement l'adresse I2C dans l'adressage Mux. Pour, par exemple.

[email protected] { 
    #address-cells = <1>; 
    #size-cells = <0>; 
    reg = <0>; 

    adc0: [email protected] { 
     compatible = "nuvoton,nau7802"; 
     reg = <0x2a>; 
     nuvoton,vldo = <3000>; 
    }; 
}; 

[email protected] { 
    #address-cells = <1>; 
    #size-cells = <0>; 
    reg = <1>; 

    adc1: [email protected] { 
     compatible = "nuvoton,nau7802"; 
     reg = <0x2a>; 
     nuvoton,vldo = <3000>; 
    }; 
}; 

[email protected] { 
    #address-cells = <1>; 
    #size-cells = <0>; 
    reg = <2>; 

    adc2: [email protected] { 
     compatible = "nuvoton,nau7802"; 
     reg = <0x2a>; 
     nuvoton,vldo = <3000>; 
    }; 
}; 

Ensuite, dans le pilote, afin d'identifier la VendorID, la structure ProductID comme dans l'exemple ci-dessus "Nuvoton, nau7802", nous devons apporter les modifications suivantes: -

static const struct i2c_device_id nau7802_i2c_id[] = { 
    { "nau7802", 0 }, 
    { } 
}; 
MODULE_DEVICE_TABLE(i2c, nau7802_i2c_id); 

static const struct of_device_id nau7802_dt_ids[] = { 
    { .compatible = "nuvoton,nau7802" }, 
    {}, 
}; 
MODULE_DEVICE_TABLE(of, nau7802_dt_ids); 

static struct i2c_driver nau7802_driver = { 
    .probe = nau7802_probe, 
    .remove = nau7802_remove, 
    .id_table = nau7802_i2c_id, 
    .driver = { 
     .name = "nau7802", 
     .of_match_table = nau7802_dt_ids, 
    }, 
}; 

Le la partie "adc1" etc. peut être simplement ignorée. « MODULE_DEVICE_TABLE (de, » est censé être l'information device_tree, de ce que je pouvais recueillir.

S'il vous plaît ne laissez-moi savoir si vous trouvez une meilleure méthode qui ne nécessite pas un