Plusieurs méthodes d'instanciation des périphériques i2c dans le noyau Linux ----./Linux-4.9.88/Documentation/i2c/instantiating-devices traduction de fichiers

Table des matières

Comment instancier un appareil I2C

Méthode 1a : déclarer le périphérique I2C par numéro de bus

Méthode 1b : déclarer le périphérique I2C via l'arborescence des périphériques

Méthode 1c : déclarer le périphérique I2C via ACPI

Méthode 2 : instancier explicitement le périphérique

Méthode 3 : Sonder le bus I2C de certains appareils

Méthode 4 : Instancier depuis l’espace utilisateur


Le contenu suivant provient de ./Linux-4.9.88/Documentation/i2c/instantiating-devices, vient d'être traduit en chinois.

Comment instancier un appareil I2C

Contrairement aux périphériques PCI ou USB, les périphériques I2C ne sont pas répertoriés au niveau matériel. Au lieu de cela, le logiciel doit savoir quels appareils sont connectés à chaque segment de bus I2C et les adresses utilisées par ces appareils. Par conséquent, le code du noyau doit instancier explicitement le périphérique I2C. Il existe plusieurs manières d’y parvenir, selon le contexte et les exigences.

Méthode 1a : déclarer le périphérique I2C par numéro de bus

Cette approche est appropriée lorsque le bus I2C est un bus système, comme c'est le cas de nombreux systèmes embarqués. Sur un tel système, chaque bus I2C possède un numéro pré-connu. Par conséquent, les appareils I2C sur ce bus peuvent être pré-déclarés. Cela se   fait en appelant i2c_register_board_info() Register un  tableau de structures.i2c_board_info

Exemple (de omap2 h4) :

static struct i2c_board_info h4_i2c_board_info[] __initdata = {
	{
		I2C_BOARD_INFO("isp1301_omap", 0x2d),
		.irq		= OMAP_GPIO_IRQ(125),
	},
	{	/* EEPROM on mainboard */
		I2C_BOARD_INFO("24c01", 0x52),
		.platform_data	= &m24c01,
	},
	{	/* EEPROM on cpu card */
		I2C_BOARD_INFO("24c01", 0x57),
		.platform_data	= &m24c01,
	},
};

static void __init omap_h4_init(void)
{
	(...)
	i2c_register_board_info(1, h4_i2c_board_info,
			ARRAY_SIZE(h4_i2c_board_info));
	(...)
}

Le code ci-dessus déclare 3 appareils sur le bus I2C 1, y compris leurs adresses respectives et les données personnalisées requises par le pilote. Les appareils I2C seront automatiquement instanciés par i2c-core lors de l'enregistrement du bus I2C.

Lorsque le bus I2C sur lequel ils se trouvent disparaît (si jamais il disparaît), les appareils sont automatiquement déliés et détruits.

Méthode 1b : déclarer le périphérique I2C via l'arborescence des périphériques

Cette méthode a la même signification que la méthode 1a. La déclaration d'un périphérique I2C s'effectue via l'arborescence des périphériques en tant que nœud enfant du contrôleur maître.

Exemple:

i2c1: i2c@400a0000 {
	/* ... 跳过主属性 ... */
	clock-frequency = <100000>;

	flash@50 {
		compatible = "atmel,24c256";
		reg = <0x50>;
	};

	pca9532: gpio@60 {
		compatible = "nxp,pca9532";
		gpio-controller;
		#gpio-cells = <2>;
		reg = <0x60>;
	};
};

Ici, les deux appareils sont connectés via une vitesse de bus de 100 kHz. Pour connaître les propriétés supplémentaires qui peuvent devoir être définies pour un périphérique, consultez la documentation de son arborescence de périphériques à l'adresse Documentation/devicetree/bindings/.

Méthode 1c : déclarer le périphérique I2C via ACPI

ACPI peut également décrire les appareils I2C. Une documentation spéciale à ce sujet se trouve actuellement dans Documentation/acpi/enumeration.txt.

Méthode 2 : instancier explicitement le périphérique

Cette méthode est appropriée lorsque des appareils plus grands utilisent le bus I2C pour la communication interne. Un cas typique est un adaptateur TV. Ils peuvent avoir des tuners, des décodeurs vidéo, des décodeurs audio, etc. et sont généralement connectés à la puce principale via un bus I2C. Vous ne connaîtrez pas le numéro de bus I2C à l'avance, vous ne pouvez donc pas utiliser la méthode 1 ci-dessus. Au lieu de cela, vous instanciez explicitement votre appareil I2C. Cela se   fait en remplissant i2c_board_info la structure et en appelant  .i2c_new_device()

Exemple (à partir du pilote réseau sfe4001) :

static struct i2c_board_info sfe4001_hwmon_info = {
	I2C_BOARD_INFO("max6647", 0x4e),
};

int sfe4001_init(struct efx_nic *efx)
{
	(...)
	efx->board_info.hwmon_client =
		i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info);

	(...)
}

Le code ci-dessus instancie un périphérique I2C sur le bus I2C de la carte réseau en question.

Lorsque vous n'êtes pas sûr si le périphérique I2C est présent (par exemple pour des fonctionnalités optionnelles qui ne sont pas présentes sur le modèle de carte le moins cher mais que vous ne pouvez pas les distinguer) ou s'il peut avoir une adresse différente d'une carte à l'autre ( le fabricant modifie sa conception sans préavis). Dans ce cas, vous pouvez appeler  i2c_new_probed_device() à la place  i2c_new_device().

Exemple (à partir du pilote nxp OHCI) :

static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };

static int usb_hcd_nxp_probe(struct platform_device *pdev)
{
	(...)
	struct i2c_adapter *i2c_adap;
	struct i2c_board_info i2c_info;

	(...)
	i2c_adap = i2c_get_adapter(2);
	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
	strlcpy(i2c_info.type, "isp1301_nxp", I2C_NAME_SIZE);
	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
						   normal_i2c, NULL);
	i2c_put_adapter(i2c_adap);
	(...)
}

Le code ci-dessus instancie jusqu'à 1 périphérique I2C sur le bus I2C de l'adaptateur OHCI. Il essaie d'abord l'adresse 0x2c, s'il n'y trouve rien, puis il essaie l'adresse 0x2d, et s'il ne trouve toujours rien, il abandonne simplement.

Le pilote qui instancie le périphérique I2C est chargé de le détruire lors du nettoyage. Cela se fait en appelant le pointeur précédemment   renvoyé  par i2c_new_device() ou  .i2c_new_probed_device()i2c_unregister_device()

Méthode 3 : Sonder le bus I2C de certains appareils

Parfois, vous n'en savez pas assez sur le périphérique I2C pour même l'appeler  i2c_new_probed_device(). Le cas typique est la puce de surveillance matérielle de la carte mère du PC. Il existe des dizaines de modèles disponibles, disponibles à 25 adresses différentes. Compte tenu du grand nombre de cartes mères disponibles, il est presque impossible de dresser une liste exhaustive des puces de surveillance matérielle utilisées. Heureusement, la plupart de ces puces disposent de registres d’identification du fabricant et de l’appareil afin qu’elles puissent être identifiées par sondage.

Dans ce cas, le périphérique I2C n'est ni déclaré ni explicitement instancié. Au lieu de cela, une fois le pilote chargé, i2c-core détectera ces périphériques et s'il en trouve, le périphérique I2C sera automatiquement instancié. Pour éviter tout comportement inapproprié de ce mécanisme, les restrictions suivantes s'appliquent :

  • Les pilotes de périphériques I2C doivent implémenter  detect() des méthodes qui identifient les périphériques pris en charge en lisant à partir de registres arbitraires.
  • Seuls les bus pouvant être dotés de dispositifs de support acceptant d'être sondés seront sondés. Cela évite de sonder les puces de surveillance matérielle des adaptateurs TV, par exemple.

Exemple : voir lm90_driver et lm90_detect() dans drivers/hwmon/lm90.c

Les périphériques I2C instanciés à la suite d'une détection réussie seront automatiquement détruits lorsque leur pilote est détecté comme étant supprimé ou lorsque le bus I2C sous-jacent lui-même est détruit, selon la première éventualité.

Ceux qui connaissent le sous-système i2c dans le noyau 2.4 et les noyaux 2.6 antérieurs constateront que cette approche 3 est essentiellement similaire à ce qui était fait à l'époque. Deux différences notables sont :

  • Le sondage n'est désormais qu'un moyen d'instancier un périphérique I2C, mais à l'époque, c'était le seul moyen. Dans la mesure du possible, les méthodes 1 et 2 doivent être privilégiées. La méthode 3 ne doit être utilisée que si aucune autre méthode n’est disponible, car elle peut avoir des effets secondaires indésirables.
  • Les bus I2C doivent désormais spécifier explicitement quelles classes de pilotes I2C peuvent les sonder (via le champ de bits de classe), alors que tous les bus I2C sont sondés par défaut. La valeur par défaut est une catégorie vide, ce qui signifie qu'aucune vérification n'a lieu. Le but du champ de bits de catégorie est de limiter les effets secondaires indésirables mentionnés ci-dessus.

Encore une fois, la méthode 3 doit être évitée autant que possible. L'instanciation explicite du périphérique (méthodes 1 et 2) est préférable car elle est plus sûre et plus rapide.

Méthode 4 : Instancier depuis l’espace utilisateur

Normalement, le noyau doit savoir quels périphériques I2C sont connectés et les adresses auxquelles ils se trouvent. Cependant, dans certains cas, il ne le sait pas, c'est pourquoi une interface sysfs a été ajoutée pour permettre à l'utilisateur de fournir les informations. L'interface se compose de deux fichiers de propriétés, tous deux créés dans chaque répertoire de bus I2C : new_device et delete_device. Les deux fichiers sont en écriture seule et vous devez y écrire les paramètres corrects pour instancier ou supprimer correctement le périphérique I2C.

Le fichier new_device nécessite 2 paramètres : le nom du périphérique I2C (une chaîne) et l'adresse du périphérique I2C (un nombre, généralement représenté en hexadécimal commençant par 0x, mais peut également être représenté en décimal).

Le fichier delete_device nécessite un paramètre : l'adresse du périphérique I2C. Étant donné que deux appareils ne peuvent pas avoir la même adresse sur un segment I2C donné, l'adresse est suffisante pour identifier de manière unique l'appareil à supprimer.

Exemple:

echo eeprom 0x50 > /sys/bus/i2c/devices/i2c-3/new_device

Bien que cette interface ne soit utilisée que lorsque la déclaration des périphériques du noyau ne peut pas être complétée, elle peut être utile dans plusieurs situations :

  • Le pilote I2C détecte normalement le périphérique (méthode 3 ci-dessus), mais le segment de bus sur lequel se trouve votre périphérique n'a pas le bon bit de classe défini, donc la détection ne se déclenche pas.
  • Le pilote I2C détecte normalement le périphérique, mais votre appareil se trouve à une adresse inattendue.
  • Les pilotes I2C détectent souvent les appareils, mais votre appareil n'est pas détecté, soit parce que la routine de détection est trop stricte, soit parce que votre appareil n'est pas encore officiellement pris en charge, mais vous savez qu'il est compatible.
  • Vous développez le pilote sur une carte de test sur laquelle vous avez soudé vous-même le périphérique I2C.

Cette interface remplace les paramètres du module force_* implémentés par certains pilotes I2C. Puisqu'il est implémenté dans i2c-core plutôt que dans chaque pilote de périphérique individuellement, il est plus efficace et présente l'avantage de ne pas avoir à recharger le pilote lors de la modification des paramètres. Vous pouvez également instancier le périphérique avant que le pilote ne soit chargé ou même disponible, et vous n'avez pas besoin de savoir de quel pilote le périphérique a besoin.

Je suppose que tu aimes

Origine blog.csdn.net/u013171226/article/details/132016973
conseillé
Classement