Несколько методов создания экземпляров устройств i2c в ядре Linux ----./Linux-4.9.88/Documentation/i2c/instantiating-devices перевод файлов

Оглавление

Как создать экземпляр устройства I2C

Способ 1a: объявить устройство I2C по номеру шины

Способ 1b: объявить устройство I2C через дерево устройств.

Способ 1c: объявить устройство I2C через ACPI

Способ 2. Явно создайте экземпляр устройства.

Способ 3. Проверьте шину I2C некоторых устройств.

Способ 4: создание экземпляра из пользовательского пространства


Следующее содержимое взято из ./Linux-4.9.88/Documentation/i2c/instantiating-devices и только что переведено на китайский язык.

Как создать экземпляр устройства I2C

В отличие от устройств PCI или USB, устройства I2C не нумеруются на аппаратном уровне. Вместо этого программное обеспечение должно знать, какие устройства подключены к каждому сегменту шины I2C, а также адреса, используемые этими устройствами. Следовательно, код ядра должен явно создавать экземпляр устройства I2C. Существует несколько способов добиться этого, в зависимости от контекста и требований.

Способ 1a: объявить устройство I2C по номеру шины

Этот подход подходит, когда шина I2C является системной шиной, как это имеет место во многих встроенных системах. В такой системе каждая шина I2C имеет заранее известный номер. Следовательно, устройства I2C на этой шине могут быть заранее объявлены. Это   делается путем вызова i2c_register_board_info() Register  массива структур.i2c_board_info

Пример (из 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));
	(...)
}

Приведенный выше код объявляет 3 устройства на шине I2C 1, включая их соответствующие адреса и пользовательские данные, необходимые драйверу. Устройства I2C будут автоматически создаваться экземплярами i2c-core при регистрации шины I2C.

Когда шина I2C, на которой они подключены, исчезает (если она когда-либо исчезает), устройства автоматически отвязываются и уничтожаются.

Способ 1b: объявить устройство I2C через дерево устройств.

Этот метод имеет то же значение, что и метод 1а. Объявление устройства I2C выполняется через дерево устройств как дочернего узла главного контроллера.

Пример:

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>;
	};
};

Здесь два устройства соединены с использованием шины со скоростью 100 кГц. Дополнительные свойства, которые, возможно, потребуется установить для устройства, см. в документации по дереву устройств по адресу Documentation/devicetree/bindings/.

Способ 1c: объявить устройство I2C через ACPI

ACPI также может описывать устройства I2C. Специальная документация по этому вопросу в настоящее время находится по адресу Documentation/acpi/enumeration.txt.

Способ 2. Явно создайте экземпляр устройства.

Этот метод подходит, когда более крупные устройства используют шину I2C для внутренней связи. Обычно это ТВ-адаптер. Они могут иметь тюнеры, видеодекодеры, аудиодекодеры и т. д. и обычно подключаются к основному чипу через шину I2C. Вы не будете знать номер шины I2C заранее, поэтому не сможете использовать метод 1, описанный выше. Вместо этого вы явно создаете экземпляр своего устройства I2C. Это   делается путем заполнения i2c_board_info структуры и вызова  .i2c_new_device()

Пример (из сетевого драйвера 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);

	(...)
}

Приведенный выше код создает экземпляр устройства I2C на шине I2C сетевого адаптера.

Когда вы не уверены, присутствует ли устройство I2C (например, для дополнительных функций, которых нет в более дешевой модели платы, но вы не можете их отличить) или оно может иметь другой адрес от одной платы к другой ( производитель меняет конструкцию без предварительного уведомления). В этом случае вы можете позвонить  i2c_new_probed_device() вместо этого  i2c_new_device().

Пример (из драйвера 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);
	(...)
}

Приведенный выше код создает экземпляр до 1 устройства I2C на шине I2C адаптера OHCI. Сначала он пробует адрес 0x2c, если там ничего не находит, затем пробует адрес 0x2d, и если все равно ничего не находит, то просто сдается.

Драйвер, создающий экземпляр устройства I2C, отвечает за его уничтожение во время очистки. Это делается путем вызова указателя, ранее   возвращенного  функцией i2c_new_device() или  .i2c_new_probed_device()i2c_unregister_device()

Способ 3. Проверьте шину I2C некоторых устройств.

Иногда вы недостаточно знаете об устройстве I2C, чтобы даже назвать его  i2c_new_probed_device(). Типичным случаем является микросхема аппаратного мониторинга на материнской плате ПК. Доступны десятки моделей, доступных по 25 различным адресам. Учитывая огромное количество материнских плат, практически невозможно составить исчерпывающий список используемых чипов аппаратного мониторинга. К счастью, большинство этих чипов имеют регистры производителя и идентификатора устройства, поэтому их можно идентифицировать путем зондирования.

В этом случае устройство I2C не объявляется и не создается явным образом. Вместо этого, как только драйвер будет загружен, i2c-core обнаружит эти устройства, и если таковые будут обнаружены, экземпляр устройства I2C будет создан автоматически. Чтобы предотвратить любое ненадлежащее поведение этого механизма, применяются следующие ограничения:

  • Драйверы устройств I2C должны реализовывать  detect() методы, которые идентифицируют поддерживаемые устройства путем чтения из любого регистра.
  • Проверяться будут только автобусы, которые могут иметь вспомогательные устройства, согласные на проверку. Это позволяет избежать проверки микросхем аппаратного мониторинга, например, на ТВ-адаптерах.

Пример: см. lm90_driver и lm90_detect() в файле driver/hwmon/lm90.c.

Устройства I2C, созданные в результате успешного обнаружения, будут автоматически уничтожены, когда будет обнаружено, что их драйвер удален, или когда будет уничтожена сама базовая шина I2C, в зависимости от того, что произойдет раньше.

Те, кто знаком с подсистемой i2c в ядре 2.4 и более ранних ядрах 2.6, обнаружат, что этот подход 3 по сути аналогичен тому, что делалось в то время. Два существенных различия:

  • Сейчас зондирование — это просто способ создания экземпляра устройства I2C, но в то время это был единственный способ. По возможности следует отдавать предпочтение методам 1 и 2. Метод 3 следует использовать только в том случае, если другой метод недоступен, поскольку он может иметь нежелательные побочные эффекты.
  • Шины I2C теперь должны явно указывать, какие классы драйверов I2C могут их проверять (через поле бита класса), когда все шины I2C проверяются по умолчанию. По умолчанию используется пустая категория, что означает отсутствие проверки. Целью битового поля категории является ограничение нежелательных побочных эффектов, упомянутых выше.

Опять же, по возможности следует избегать метода 3. Явное создание экземпляра устройства (методы 1 и 2) предпочтительнее, поскольку это безопаснее и быстрее.

Способ 4: создание экземпляра из пользовательского пространства

В норме ядро ​​должно знать, какие устройства I2C подключены и где они расположены. Однако в некоторых случаях он не знает, поэтому был добавлен интерфейс sysfs, позволяющий пользователю предоставлять информацию. Интерфейс состоит из двух файлов свойств, которые создаются в каждом каталоге шины I2C: new_device и delete_device. Оба файла доступны только для записи, и вы должны записать в них правильные параметры, чтобы правильно создать экземпляр или удалить устройство I2C.

Файл new_device требует 2 параметра: имя устройства I2C (строка) и адрес устройства I2C (число, обычно представленное в шестнадцатеричном формате, начинающееся с 0x, но также может быть представлено в десятичном формате).

Файл delete_device требует один параметр: адрес устройства I2C. Поскольку никакие два устройства не могут находиться по одному и тому же адресу в данном сегменте I2C, адреса достаточно, чтобы однозначно идентифицировать устройство, подлежащее удалению.

Пример:

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

Хотя этот интерфейс используется только тогда, когда объявление устройства ядра не может быть завершено, он может быть полезен в нескольких ситуациях:

  • Драйвер I2C обычно обнаруживает устройство (метод 3 выше), но в сегменте шины, на котором находится ваше устройство, не установлен правильный бит класса, поэтому обнаружение не срабатывает.
  • Драйвер I2C обычно обнаруживает устройство, но ваше устройство находится по неожиданному адресу.
  • Драйверы I2C часто обнаруживают устройства, но ваше устройство не обнаруживается либо потому, что процедура обнаружения слишком строга, либо потому, что ваше устройство еще официально не поддерживается, но вы знаете, что оно совместимо.
  • Вы разрабатываете драйвер на тестовой плате, на которую сами припаяли устройство I2C.

Этот интерфейс является заменой параметров модуля Force_*, реализованных некоторыми драйверами I2C. Поскольку он реализован в ядре i2c, а не в каждом драйвере устройства индивидуально, он более эффективен и имеет то преимущество, что не нужно перезагружать драйвер при изменении настроек. Вы также можете создать экземпляр устройства до того, как драйвер будет загружен или даже доступен, и вам не нужно знать, какой драйвер требуется устройству.

Supongo que te gusta

Origin blog.csdn.net/u013171226/article/details/132016973
Recomendado
Clasificación