code:
==========================
Kernel driver i2c-mux-gpio
==========================

Author: Peter Korsgaard <peter.korsgaard@barco.com>

Description
-----------

i2c-mux-gpio is an i2c mux driver providing access to I2C bus segments
from a master I2C bus and a hardware MUX controlled through GPIO pins.

E.G.::

  ----------              ----------  Bus segment 1   - - - - -
 |          | SCL/SDA    |          |-------------- |           |
 |          |------------|          |
 |          |            |          | Bus segment 2 |           |
 |  Linux   | GPIO 1..N  |   MUX    |---------------   Devices
 |          |------------|          |               |           |
 |          |            |          | Bus segment M
 |          |            |          |---------------|           |
  ----------              ----------                  - - - - -

SCL/SDA of the master I2C bus is multiplexed to bus segment 1..M
according to the settings of the GPIO pins 1..N.

Usage
-----

i2c-mux-gpio uses the platform bus, so you need to provide a struct
platform_device with the platform_data pointing to a struct
i2c_mux_gpio_platform_data with the I2C adapter number of the master
bus, the number of bus segments to create and the GPIO pins used
to control it. See include/linux/platform_data/i2c-mux-gpio.h for details.

E.G. something like this for a MUX providing 4 bus segments
controlled through 3 GPIO pins::

  #include <linux/platform_data/i2c-mux-gpio.h>
  #include <linux/platform_device.h>

  static const unsigned myboard_gpiomux_gpios[] = {
	AT91_PIN_PC26, AT91_PIN_PC25, AT91_PIN_PC24
  };

  static const unsigned myboard_gpiomux_values[] = {
	0, 1, 2, 3
  };

  static struct i2c_mux_gpio_platform_data myboard_i2cmux_data = {
	.parent		= 1,
	.base_nr	= 2, /* optional */
	.values		= myboard_gpiomux_values,
	.n_values	= ARRAY_SIZE(myboard_gpiomux_values),
	.gpios		= myboard_gpiomux_gpios,
	.n_gpios	= ARRAY_SIZE(myboard_gpiomux_gpios),
	.idle		= 4, /* optional */
  };

  static struct platform_device myboard_i2cmux = {
	.name		= "i2c-mux-gpio",
	.id		= 0,
	.dev		= {
		.platform_data	= &myboard_i2cmux_data,
	},
  };

If you don't know the absolute GPIO pin numbers at registration time,
you can instead provide a chip name (.chip_name) and relative GPIO pin
numbers, and the i2c-mux-gpio driver will do the work for you,
including deferred probing if the GPIO chip isn't immediately
available.

Device Registration
-------------------

When registering your i2c-mux-gpio device, you should pass the number
of any GPIO pin it uses as the device ID. This guarantees that every
instance has a different ID.

Alternatively, if you don't need a stable device name, you can simply
pass PLATFORM_DEVID_AUTO as the device ID, and the platform core will
assign a dynamic ID to your device. If you do not know the absolute
GPIO pin numbers at registration time, this is even the only option.


code:
================================================================
I2C device driver binding control from user-space in old kernels
================================================================

.. NOTE::
   Note: this section is only relevant if you are handling some old code
   found in kernel 2.6. If you work with more recent kernels, you can
   safely skip this section.

Up to kernel 2.6.32, many I2C drivers used helper macros provided by
<linux/i2c.h> which created standard module parameters to let the user
control how the driver would probe I2C buses and attach to devices. These
parameters were known as ``probe`` (to let the driver probe for an extra
address), ``force`` (to forcibly attach the driver to a given device) and
``ignore`` (to prevent a driver from probing a given address).

With the conversion of the I2C subsystem to the standard device driver
binding model, it became clear that these per-module parameters were no
longer needed, and that a centralized implementation was possible. The new,
sysfs-based interface is described in
Documentation/i2c/instantiating-devices.rst, section
"Method 4: Instantiate from user-space".

Below is a mapping from the old module parameters to the new interface.

Attaching a driver to an I2C device
-----------------------------------

Old method (module parameters)::

  # modprobe <driver> probe=1,0x2d
  # modprobe <driver> force=1,0x2d
  # modprobe <driver> force_<device>=1,0x2d

New method (sysfs interface)::

  # echo <device> 0x2d > /sys/bus/i2c/devices/i2c-1/new_device

Preventing a driver from attaching to an I2C device
---------------------------------------------------

Old method (module parameters)::

  # modprobe <driver> ignore=1,0x2f

New method (sysfs interface)::

  # echo dummy 0x2f > /sys/bus/i2c/devices/i2c-1/new_device
  # modprobe <driver>

Of course, it is important to instantiate the ``dummy`` device before loading
the driver. The dummy device will be handled by i2c-core itself, preventing
other drivers from binding to it later on. If there is a real device at the
problematic address, and you want another driver to bind to it, then simply
pass the name of the device in question instead of ``dummy``.

repo_name: angery/linux


code:
==============================
Linux I2C slave EEPROM backend
==============================

by Wolfram Sang <wsa@sang-engineering.com> in 2014-20

This backend simulates an EEPROM on the connected I2C bus. Its memory contents
can be accessed from userspace via this file located in sysfs::

	/sys/bus/i2c/devices/<device-directory>/slave-eeprom

The following types are available: 24c02, 24c32, 24c64, and 24c512. Read-only
variants are also supported. The name needed for instantiating has the form
'slave-<type>[ro]'. Examples follow:

24c02, read/write, address 0x64:
  # echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-1/new_device

24c512, read-only, address 0x42:
  # echo slave-24c512ro 0x1042 > /sys/bus/i2c/devices/i2c-1/new_device

You can also preload data during boot if a device-property named
'firmware-name' contains a valid filename (DT or ACPI only).

As of 2015, Linux doesn't support poll on binary sysfs files, so there is no
notification when another master changed the content.


code:
=====================================
Linux I2C slave interface description
=====================================

by Wolfram Sang <wsa@sang-engineering.com> in 2014-15

Linux can also be an I2C slave if the I2C controller in use has slave
functionality. For that to work, one needs slave support in the bus driver plus
a hardware independent software backend providing the actual functionality. An
example for the latter is the slave-eeprom driver, which acts as a dual memory
driver. While another I2C master on the bus can access it like a regular
EEPROM, the Linux I2C slave can access the content via sysfs and handle data as
needed. The backend driver and the I2C bus driver communicate via events. Here
is a small graph visualizing the data flow and the means by which data is
transported. The dotted line marks only one example. The backend could also
use a character device, be in-kernel only, or something completely different::

              e.g. sysfs        I2C slave events        I/O registers
  +-----------+   v    +---------+     v     +--------+  v  +------------+
  | Userspace +........+ Backend +-----------+ Driver +-----+ Controller |
  +-----------+        +---------+           +--------+     +------------+
                                                                | |
  ----------------------------------------------------------------+--  I2C
  --------------------------------------------------------------+----  Bus

Note: Technically, there is also the I2C core between the backend and the
driver. However, at this time of writing, the layer is transparent.

User manual
===========

I2C slave backends behave like standard I2C clients. So, you can instantiate
them as described in the document instantiating-devices.rst. The only
difference is that i2c slave backends have their own address space. So, you
have to add 0x1000 to the address you would originally request. An example for
instantiating the slave-eeprom driver from userspace at the 7 bit address 0x64
on bus 1::

  # echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-1/new_device

Each backend should come with separate documentation to describe its specific
behaviour and setup.

Developer manual
================

First, the events which are used by the bus driver and the backend will be
described in detail. After that, some implementation hints for extending bus
drivers and writing backends will be given.

I2C slave events
----------------

The bus driver sends an event to the backend using the following function::

	ret = i2c_slave_event(client, event, &val)

'client' describes the I2C slave device. 'event' is one of the special event
types described hereafter. 'val' holds an u8 value for the data byte to be
read/written and is thus bidirectional. The pointer to val must always be
provided even if val is not used for an event, i.e. don't use NULL here. 'ret'
is the return value from the backend. Mandatory events must be provided by the
bus drivers and must be checked for by backend drivers.

Event types:

* I2C_SLAVE_WRITE_REQUESTED (mandatory)

  'val': unused

  'ret': 0 if the backend is ready, otherwise some errno

Another I2C master wants to write data to us. This event should be sent once
our own address and the write bit was detected. The data did not arrive yet, so
there is nothing to process or return. After returning, the bus driver must
always ack the address phase. If 'ret' is zero, backend initialization or
wakeup is done and further data may be received. If 'ret' is an errno, the bus
driver should nack all incoming bytes until the next stop condition to enforce
a retry of the transmission.

* I2C_SLAVE_READ_REQUESTED (mandatory)

  'val': backend returns first byte to be sent

  'ret': always 0

Another I2C master wants to read data from us. This event should be sent once
our own address and the read bit was detected. After returning, the bus driver
should transmit the first byte.

* I2C_SLAVE_WRITE_RECEIVED (mandatory)

  'val': bus driver delivers received byte

  'ret': 0 if the byte should be acked, some errno if the byte should be nacked

Another I2C master has sent a byte to us which needs to be set in 'val'. If 'ret'
is zero, the bus driver should ack this byte. If 'ret' is an errno, then the byte
should be nacked.

* I2C_SLAVE_READ_PROCESSED (mandatory)

  'val': backend returns next byte to be sent

  'ret': always 0

The bus driver requests the next byte to be sent to another I2C master in
'val'. Important: This does not mean that the previous byte has been acked, it
only means that the previous byte is shifted out to the bus! To ensure seamless
transmission, most hardware requests the next byte when the previous one is
still shifted out. If the master sends NACK and stops reading after the byte
currently shifted out, this byte requested here is never used. It very likely
needs to be sent again on the next I2C_SLAVE_READ_REQUEST, depending a bit on
your backend, though.

* I2C_SLAVE_STOP (mandatory)

  'val': unused

  'ret': always 0

A stop condition was received. This can happen anytime and the backend should
reset its state machine for I2C transfers to be able to receive new requests.

Software backends
-----------------

If you want to write a software backend:

* use a standard i2c_driver and its matching mechanisms
* write the slave_callback which handles the above slave events
  (best using a state machine)
* register this callback via i2c_slave_register()

Check the i2c-slave-eeprom driver as an example.

Bus driver support
------------------

If you want to add slave support to the bus driver:

* implement calls to register/unregister the slave and add those to the
  struct i2c_algorithm. When registering, you probably need to set the I2C
  slave address and enable slave specific interrupts. If you use runtime pm, you
  should use pm_runtime_get_sync() because your device usually needs to be
  powered on always to be able to detect its slave address. When unregistering,
  do the inverse of the above.

* Catch the slave interrupts and send appropriate i2c_slave_events to the backend.

Note that most hardware supports being master _and_ slave on the same bus. So,
if you extend a bus driver, please make sure that the driver supports that as
well. In almost all cases, slave support does not need to disable the master
functionality.

Check the i2c-rcar driver as an example.

About ACK/NACK
--------------

It is good behaviour to always ACK the address phase, so the master knows if a
device is basically present or if it mysteriously disappeared. Using NACK to
state being busy is troublesome. SMBus demands to always ACK the address phase,
while the I2C specification is more loose on that. Most I2C controllers also
automatically ACK when detecting their slave addresses, so there is no option
to NACK them. For those reasons, this API does not support NACK in the address
phase.

Currently, there is no slave event to report if the master did ACK or NACK a
byte when it reads from us. We could make this an optional event if the need
arises. However, cases should be extremely rare because the master is expected
to send STOP after that and we have an event for that. Also, keep in mind not
all I2C controllers have the possibility to report that event.

About buffers
-------------

During development of this API, the question of using buffers instead of just
bytes came up. Such an extension might be possible, usefulness is unclear at
this time of writing. Some points to keep in mind when using buffers:

* Buffers should be opt-in and backend drivers will always have to support
  byte-based transactions as the ultimate fallback anyhow because this is how
  the majority of HW works.

* For backends simulating hardware registers, buffers are largely not helpful
  because after each byte written an action should be immediately triggered.
  For reads, the data kept in the buffer might get stale if the backend just
  updated a register because of internal processing.

* A master can send STOP at any time. For partially transferred buffers, this
  means additional code to handle this exception. Such code tends to be
  error-prone.


code:
.. SPDX-License-Identifier: GPL-2.0

================================
Linux I2C slave testunit backend
================================

by Wolfram Sang <wsa@sang-engineering.com> in 2020

This backend can be used to trigger test cases for I2C bus masters which
require a remote device with certain capabilities (and which are usually not so
easy to obtain). Examples include multi-master testing, and SMBus Host Notify
testing. For some tests, the I2C slave controller must be able to switch
between master and slave mode because it needs to send data, too.

Note that this is a device for testing and debugging. It should not be enabled
in a production build. And while there is some versioning and we try hard to
keep backward compatibility, there is no stable ABI guaranteed!

Instantiating the device is regular. Example for bus 0, address 0x30:

# echo "slave-testunit 0x1030" > /sys/bus/i2c/devices/i2c-0/new_device

After that, you will have a write-only device listening. Reads will just return
an 8-bit version number of the testunit. When writing, the device consists of 4
8-bit registers and, except for some "partial" commands, all registers must be
written to start a testcase, i.e. you usually write 4 bytes to the device. The
registers are:

0x00 CMD   - which test to trigger
0x01 DATAL - configuration byte 1 for the test
0x02 DATAH - configuration byte 2 for the test
0x03 DELAY - delay in n * 10ms until test is started

Using 'i2cset' from the i2c-tools package, the generic command looks like:

# i2cset -y <bus_num> <testunit_address> <CMD> <DATAL> <DATAH> <DELAY> i

DELAY is a generic parameter which will delay the execution of the test in CMD.
While a command is running (including the delay), new commands will not be
acknowledged. You need to wait until the old one is completed.

The commands are described in the following section. An invalid command will
result in the transfer not being acknowledged.

Commands
--------

0x00 NOOP (reserved for future use)

0x01 READ_BYTES (also needs master mode)
   DATAL - address to read data from (lower 7 bits, highest bit currently unused)
   DATAH - number of bytes to read

This is useful to test if your bus master driver is handling multi-master
correctly. You can trigger the testunit to read bytes from another device on
the bus. If the bus master under test also wants to access the bus at the same
time, the bus will be busy. Example to read 128 bytes from device 0x50 after
50ms of delay:

# i2cset -y 0 0x30 0x01 0x50 0x80 0x05 i

0x02 SMBUS_HOST_NOTIFY (also needs master mode)
   DATAL - low byte of the status word to send
   DATAH - high byte of the status word to send

This test will send an SMBUS_HOST_NOTIFY message to the host. Note that the
status word is currently ignored in the Linux Kernel. Example to send a
notification after 10ms:

# i2cset -y 0 0x30 0x02 0x42 0x64 0x01 i

0x03 SMBUS_BLOCK_PROC_CALL (partial command)
   DATAL - must be '1', i.e. one further byte will be written
   DATAH - number of bytes to be sent back
   DELAY - not applicable, partial command!

This test will respond to a block process call as defined by the SMBus
specification. The one data byte written specifies how many bytes will be sent
back in the following read transfer. Note that in this read transfer, the
testunit will prefix the length of the bytes to follow. So, if your host bus
driver emulates SMBus calls like the majority does, it needs to support the
I2C_M_RECV_LEN flag of an i2c_msg. This is a good testcase for it. The returned
data consists of the length first, and then of an array of bytes from length-1
to 0. Here is an example which emulates i2c_smbus_block_process_call() using
i2ctransfer (you need i2c-tools v4.2 or later):

# i2ctransfer -y 0 w3@0x30 0x03 0x01 0x10 r?
0x10 0x0f 0x0e 0x0d 0x0c 0x0b 0x0a 0x09 0x08 0x07 0x06 0x05 0x04 0x03 0x02 0x01 0x00


code:
==================
The SMBus Protocol
==================

The following is a summary of the SMBus protocol. It applies to
all revisions of the protocol (1.0, 1.1, and 2.0).
Certain protocol features which are not supported by
this package are briefly described at the end of this document.

Some adapters understand only the SMBus (System Management Bus) protocol,
which is a subset from the I2C protocol. Fortunately, many devices use
only the same subset, which makes it possible to put them on an SMBus.

If you write a driver for some I2C device, please try to use the SMBus
commands if at all possible (if the device uses only that subset of the
I2C protocol). This makes it possible to use the device driver on both
SMBus adapters and I2C adapters (the SMBus command set is automatically
translated to I2C on I2C adapters, but plain I2C commands can not be
handled at all on most pure SMBus adapters).

Below is a list of SMBus protocol operations, and the functions executing
them.  Note that the names used in the SMBus protocol specifications usually
don't match these function names.  For some of the operations which pass a
single data byte, the functions using SMBus protocol operation names execute
a different protocol operation entirely.

Each transaction type corresponds to a functionality flag. Before calling a
transaction function, a device driver should always check (just once) for
the corresponding functionality flag to ensure that the underlying I2C
adapter supports the transaction in question. See
Documentation/i2c/functionality.rst for the details.

Key to symbols
==============

=============== =============================================================
S               Start condition
Sr              Repeated start condition, used to switch from write to
                read mode.
P               Stop condition
Rd/Wr (1 bit)   Read/Write bit. Rd equals 1, Wr equals 0.
A, NA (1 bit)   Acknowledge (ACK) and Not Acknowledge (NACK) bit
Addr  (7 bits)  I2C 7 bit address. Note that this can be expanded to
                get a 10 bit I2C address.
Comm  (8 bits)  Command byte, a data byte which often selects a register on
                the device.
Data  (8 bits)  A plain data byte. DataLow and DataHigh represent the low and
                high byte of a 16 bit word.
Count (8 bits)  A data byte containing the length of a block operation.

[..]            Data sent by I2C device, as opposed to data sent by the host
                adapter.
=============== =============================================================

SMBus Quick Command
===================

This sends a single bit to the device, at the place of the Rd/Wr bit::

  S Addr Rd/Wr [A] P

Functionality flag: I2C_FUNC_SMBUS_QUICK

SMBus Receive Byte
==================

Implemented by i2c_smbus_read_byte()

This reads a single byte from a device, without specifying a device
register. Some devices are so simple that this interface is enough; for
others, it is a shorthand if you want to read the same register as in
the previous SMBus command::

  S Addr Rd [A] [Data] NA P

Functionality flag: I2C_FUNC_SMBUS_READ_BYTE

SMBus Send Byte
===============

Implemented by i2c_smbus_write_byte()

This operation is the reverse of Receive Byte: it sends a single byte
to a device.  See Receive Byte for more information.

::

  S Addr Wr [A] Data [A] P

Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE

SMBus Read Byte
===============

Implemented by i2c_smbus_read_byte_data()

This reads a single byte from a device, from a designated register.
The register is specified through the Comm byte::

  S Addr Wr [A] Comm [A] Sr Addr Rd [A] [Data] NA P

Functionality flag: I2C_FUNC_SMBUS_READ_BYTE_DATA

SMBus Read Word
===============

Implemented by i2c_smbus_read_word_data()

This operation is very like Read Byte; again, data is read from a
device, from a designated register that is specified through the Comm
byte. But this time, the data is a complete word (16 bits)::

  S Addr Wr [A] Comm [A] Sr Addr Rd [A] [DataLow] A [DataHigh] NA P

Functionality flag: I2C_FUNC_SMBUS_READ_WORD_DATA

Note the convenience function i2c_smbus_read_word_swapped() is
available for reads where the two data bytes are the other way
around (not SMBus compliant, but very popular.)

SMBus Write Byte
================

Implemented by i2c_smbus_write_byte_data()

This writes a single byte to a device, to a designated register. The
register is specified through the Comm byte. This is the opposite of
the Read Byte operation.

::

  S Addr Wr [A] Comm [A] Data [A] P

Functionality flag: I2C_FUNC_SMBUS_WRITE_BYTE_DATA

SMBus Write Word
================

Implemented by i2c_smbus_write_word_data()

This is the opposite of the Read Word operation. 16 bits
of data are written to a device, to the designated register that is
specified through the Comm byte::

  S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P

Functionality flag: I2C_FUNC_SMBUS_WRITE_WORD_DATA

Note the convenience function i2c_smbus_write_word_swapped() is
available for writes where the two data bytes are the other way
around (not SMBus compliant, but very popular.)

SMBus Process Call
==================

This command selects a device register (through the Comm byte), sends
16 bits of data to it, and reads 16 bits of data in return::

  S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
                              Sr Addr Rd [A] [DataLow] A [DataHigh] NA P

Functionality flag: I2C_FUNC_SMBUS_PROC_CALL

SMBus Block Read
================

Implemented by i2c_smbus_read_block_data()

This command reads a block of up to 32 bytes from a device, from a
designated register that is specified through the Comm byte. The amount
of data is specified by the device in the Count byte.

::

  S Addr Wr [A] Comm [A]
            Sr Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P

Functionality flag: I2C_FUNC_SMBUS_READ_BLOCK_DATA

SMBus Block Write
=================

Implemented by i2c_smbus_write_block_data()

The opposite of the Block Read command, this writes up to 32 bytes to
a device, to a designated register that is specified through the
Comm byte. The amount of data is specified in the Count byte.

::

  S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P

Functionality flag: I2C_FUNC_SMBUS_WRITE_BLOCK_DATA

SMBus Block Write - Block Read Process Call
===========================================

SMBus Block Write - Block Read Process Call was introduced in
Revision 2.0 of the specification.

This command selects a device register (through the Comm byte), sends
1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return::

  S Addr Wr [A] Comm [A] Count [A] Data [A] ...
                              Sr Addr Rd [A] [Count] A [Data] ... A P

Functionality flag: I2C_FUNC_SMBUS_BLOCK_PROC_CALL

SMBus Host Notify
=================

This command is sent from a SMBus device acting as a master to the
SMBus host acting as a slave.
It is the same form as Write Word, with the command code replaced by the
alerting device's address.

::

  [S] [HostAddr] [Wr] A [DevAddr] A [DataLow] A [DataHigh] A [P]

This is implemented in the following way in the Linux kernel:

* I2C bus drivers which support SMBus Host Notify should report
  I2C_FUNC_SMBUS_HOST_NOTIFY.
* I2C bus drivers trigger SMBus Host Notify by a call to
  i2c_handle_smbus_host_notify().
* I2C drivers for devices which can trigger SMBus Host Notify will have
  client->irq assigned to a Host Notify IRQ if noone else specified an other.

There is currently no way to retrieve the data parameter from the client.

Packet Error Checking (PEC)
===========================

Packet Error Checking was introduced in Revision 1.1 of the specification.

PEC adds a CRC-8 error-checking byte to transfers using it, immediately
before the terminating STOP.

Address Resolution Protocol (ARP)
=================================

The Address Resolution Protocol was introduced in Revision 2.0 of
the specification. It is a higher-layer protocol which uses the
messages above.

ARP adds device enumeration and dynamic address assignment to
the protocol. All ARP communications use slave address 0x61 and
require PEC checksums.

SMBus Alert
===========

SMBus Alert was introduced in Revision 1.0 of the specification.

The SMBus alert protocol allows several SMBus slave devices to share a
single interrupt pin on the SMBus master, while still allowing the master
to know which slave triggered the interrupt.

This is implemented the following way in the Linux kernel:

* I2C bus drivers which support SMBus alert should call
  i2c_new_smbus_alert_device() to install SMBus alert support.
* I2C drivers for devices which can trigger SMBus alerts should implement
  the optional alert() callback.

I2C Block Transactions
======================

The following I2C block transactions are similar to the SMBus Block Read
and Write operations, except these do not have a Count byte. They are
supported by the SMBus layer and are described here for completeness, but
they are *NOT* defined by the SMBus specification.

I2C block transactions do not limit the number of bytes transferred
but the SMBus layer places a limit of 32 bytes.

I2C Block Read
==============

Implemented by i2c_smbus_read_i2c_block_data()

This command reads a block of bytes from a device, from a
designated register that is specified through the Comm byte::

  S Addr Wr [A] Comm [A]
            Sr Addr Rd [A] [Data] A [Data] A ... A [Data] NA P

Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK

I2C Block Write
===============

Implemented by i2c_smbus_write_i2c_block_data()

The opposite of the Block Read command, this writes bytes to
a device, to a designated register that is specified through the
Comm byte. Note that command lengths of 0, 2, or more bytes are
supported as they are indistinguishable from data.

::

  S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P

Functionality flag: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK


code:
=============================
Introduction to I2C and SMBus
=============================

I²C (pronounce: I squared C and written I2C in the kernel documentation) is
a protocol developed by Philips. It is a slow two-wire protocol (variable
speed, up to 400 kHz), with a high speed extension (3.4 MHz).  It provides
an inexpensive bus for connecting many types of devices with infrequent or
low bandwidth communications needs.  I2C is widely used with embedded
systems.  Some systems use variants that don't meet branding requirements,
and so are not advertised as being I2C but come under different names,
e.g. TWI (Two Wire Interface), IIC.

The latest official I2C specification is the `"I2C-bus specification and user
manual" (UM10204) <https://www.nxp.com/webapp/Download?colCode=UM10204>`_
published by NXP Semiconductors. However, you need to log-in to the site to
access the PDF. An older version of the specification (revision 6) is archived
`here <https://web.archive.org/web/20210813122132/https://www.nxp.com/docs/en/user-guide/UM10204.pdf>`_.

SMBus (System Management Bus) is based on the I2C protocol, and is mostly
a subset of I2C protocols and signaling.  Many I2C devices will work on an
SMBus, but some SMBus protocols add semantics beyond what is required to
achieve I2C branding.  Modern PC mainboards rely on SMBus.  The most common
devices connected through SMBus are RAM modules configured using I2C EEPROMs,
and hardware monitoring chips.

Because the SMBus is mostly a subset of the generalized I2C bus, we can
use its protocols on many I2C systems.  However, there are systems that don't
meet both SMBus and I2C electrical constraints; and others which can't
implement all the common SMBus protocol semantics or messages.

Terminology
===========

Using the terminology from the official documentation, the I2C bus connects
one or more *master* chips and one or more *slave* chips.

.. kernel-figure::  i2c_bus.svg
   :alt:    Simple I2C bus with one master and 3 slaves

   Simple I2C bus

A **master** chip is a node that starts communications with slaves. In the
Linux kernel implementation it is called an **adapter** or bus. Adapter
drivers are in the ``drivers/i2c/busses/`` subdirectory.

An **algorithm** contains general code that can be used to implement a
whole class of I2C adapters. Each specific adapter driver either depends on
an algorithm driver in the ``drivers/i2c/algos/`` subdirectory, or includes
its own implementation.

A **slave** chip is a node that responds to communications when addressed
by the master. In Linux it is called a **client**. Client drivers are kept
in a directory specific to the feature they provide, for example
``drivers/media/gpio/`` for GPIO expanders and ``drivers/media/i2c/`` for
video-related chips.

For the example configuration in figure, you will need a driver for your
I2C adapter, and drivers for your I2C devices (usually one driver for each
device).


code:
=====================
I2C Ten-bit Addresses
=====================

The I2C protocol knows about two kinds of device addresses: normal 7 bit
addresses, and an extended set of 10 bit addresses. The sets of addresses
do not intersect: the 7 bit address 0x10 is not the same as the 10 bit
address 0x10 (though a single device could respond to both of them).
To avoid ambiguity, the user sees 10 bit addresses mapped to a different
address space, namely 0xa000-0xa3ff. The leading 0xa (= 10) represents the
10 bit mode. This is used for creating device names in sysfs. It is also
needed when instantiating 10 bit devices via the new_device file in sysfs.

I2C messages to and from 10-bit address devices have a different format.
See the I2C specification for the details.

The current 10 bit address support is minimal. It should work, however
you can expect some problems along the way:

* Not all bus drivers support 10-bit addresses. Some don't because the
  hardware doesn't support them (SMBus doesn't require 10-bit address
  support for example), some don't because nobody bothered adding the
  code (or it's there but not working properly.) Software implementation
  (i2c-algo-bit) is known to work.
* Some optional features do not support 10-bit addresses. This is the
  case of automatic detection and instantiation of devices by their,
  drivers, for example.
* Many user-space packages (for example i2c-tools) lack support for
  10-bit addresses.

Note that 10-bit address devices are still pretty rare, so the limitations
listed above could stay for a long time, maybe even forever if nobody
needs them to be fixed.


code:
===============================
Implementing I2C device drivers
===============================

This is a small guide for those who want to write kernel drivers for I2C
or SMBus devices, using Linux as the protocol host/master (not slave).

To set up a driver, you need to do several things. Some are optional, and
some things can be done slightly or completely different. Use this as a
guide, not as a rule book!

General remarks
===============

Try to keep the kernel namespace as clean as possible. The best way to
do this is to use a unique prefix for all global symbols. This is
especially important for exported symbols, but it is a good idea to do
it for non-exported symbols too. We will use the prefix ``foo_`` in this
tutorial.

The driver structure
====================

Usually, you will implement a single driver structure, and instantiate
all clients from it. Remember, a driver structure contains general access
routines, and should be zero-initialized except for fields with data you
provide.  A client structure holds device-specific information like the
driver model device node, and its I2C address.

::

  static struct i2c_device_id foo_idtable[] = {
	{ "foo", my_id_for_foo },
	{ "bar", my_id_for_bar },
	{ }
  };

  MODULE_DEVICE_TABLE(i2c, foo_idtable);

  static struct i2c_driver foo_driver = {
	.driver = {
		.name	= "foo",
		.pm	= &foo_pm_ops,	/* optional */
	},

	.id_table	= foo_idtable,
	.probe_new	= foo_probe,
	.remove		= foo_remove,
	/* if device autodetection is needed: */
	.class		= I2C_CLASS_SOMETHING,
	.detect		= foo_detect,
	.address_list	= normal_i2c,

	.shutdown	= foo_shutdown,	/* optional */
	.command	= foo_command,	/* optional, deprecated */
  }

The name field is the driver name, and must not contain spaces.  It
should match the module name (if the driver can be compiled as a module),
although you can use MODULE_ALIAS (passing "foo" in this example) to add
another name for the module.  If the driver name doesn't match the module
name, the module won't be automatically loaded (hotplug/coldplug).

All other fields are for call-back functions which will be explained
below.

Extra client data
=================

Each client structure has a special ``data`` field that can point to any
structure at all.  You should use this to keep device-specific data.

::

	/* store the value */
	void i2c_set_clientdata(struct i2c_client *client, void *data);

	/* retrieve the value */
	void *i2c_get_clientdata(const struct i2c_client *client);

Note that starting with kernel 2.6.34, you don't have to set the ``data`` field
to NULL in remove() or if probe() failed anymore. The i2c-core does this
automatically on these occasions. Those are also the only times the core will
touch this field.

Accessing the client
====================

Let's say we have a valid client structure. At some time, we will need
to gather information from the client, or write new information to the
client.

I have found it useful to define foo_read and foo_write functions for this.
For some cases, it will be easier to call the I2C functions directly,
but many chips have some kind of register-value idea that can easily
be encapsulated.

The below functions are simple examples, and should not be copied
literally::

  int foo_read_value(struct i2c_client *client, u8 reg)
  {
	if (reg < 0x10)	/* byte-sized register */
		return i2c_smbus_read_byte_data(client, reg);
	else		/* word-sized register */
		return i2c_smbus_read_word_data(client, reg);
  }

  int foo_write_value(struct i2c_client *client, u8 reg, u16 value)
  {
	if (reg == 0x10)	/* Impossible to write - driver error! */
		return -EINVAL;
	else if (reg < 0x10)	/* byte-sized register */
		return i2c_smbus_write_byte_data(client, reg, value);
	else			/* word-sized register */
		return i2c_smbus_write_word_data(client, reg, value);
  }

Probing and attaching
=====================

The Linux I2C stack was originally written to support access to hardware
monitoring chips on PC motherboards, and thus used to embed some assumptions
that were more appropriate to SMBus (and PCs) than to I2C.  One of these
assumptions was that most adapters and devices drivers support the SMBUS_QUICK
protocol to probe device presence.  Another was that devices and their drivers
can be sufficiently configured using only such probe primitives.

As Linux and its I2C stack became more widely used in embedded systems
and complex components such as DVB adapters, those assumptions became more
problematic.  Drivers for I2C devices that issue interrupts need more (and
different) configuration information, as do drivers handling chip variants
that can't be distinguished by protocol probing, or which need some board
specific information to operate correctly.

Device/Driver Binding
---------------------

System infrastructure, typically board-specific initialization code or
boot firmware, reports what I2C devices exist.  For example, there may be
a table, in the kernel or from the boot loader, identifying I2C devices
and linking them to board-specific configuration information about IRQs
and other wiring artifacts, chip type, and so on.  That could be used to
create i2c_client objects for each I2C device.

I2C device drivers using this binding model work just like any other
kind of driver in Linux:  they provide a probe() method to bind to
those devices, and a remove() method to unbind.

::

	static int foo_probe(struct i2c_client *client);
	static void foo_remove(struct i2c_client *client);

Remember that the i2c_driver does not create those client handles.  The
handle may be used during foo_probe().  If foo_probe() reports success
(zero not a negative status code) it may save the handle and use it until
foo_remove() returns.  That binding model is used by most Linux drivers.

The probe function is called when an entry in the id_table name field
matches the device's name. If the probe function needs that entry, it
can retrieve it using

::

	const struct i2c_device_id *id = i2c_match_id(foo_idtable, client);

Device Creation
---------------

If you know for a fact that an I2C device is connected to a given I2C bus,
you can instantiate that device by simply filling an i2c_board_info
structure with the device address and driver name, and calling
i2c_new_client_device().  This will create the device, then the driver core
will take care of finding the right driver and will call its probe() method.
If a driver supports different device types, you can specify the type you
want using the type field.  You can also specify an IRQ and platform data
if needed.

Sometimes you know that a device is connected to a given I2C bus, but you
don't know the exact address it uses.  This happens on TV adapters for
example, where the same driver supports dozens of slightly different
models, and I2C device addresses change from one model to the next.  In
that case, you can use the i2c_new_scanned_device() variant, which is
similar to i2c_new_client_device(), except that it takes an additional list
of possible I2C addresses to probe.  A device is created for the first
responsive address in the list.  If you expect more than one device to be
present in the address range, simply call i2c_new_scanned_device() that
many times.

The call to i2c_new_client_device() or i2c_new_scanned_device() typically
happens in the I2C bus driver. You may want to save the returned i2c_client
reference for later use.

Device Detection
----------------

Sometimes you do not know in advance which I2C devices are connected to
a given I2C bus.  This is for example the case of hardware monitoring
devices on a PC's SMBus.  In that case, you may want to let your driver
detect supported devices automatically.  This is how the legacy model
was working, and is now available as an extension to the standard
driver model.

You simply have to define a detect callback which will attempt to
identify supported devices (returning 0 for supported ones and -ENODEV
for unsupported ones), a list of addresses to probe, and a device type
(or class) so that only I2C buses which may have that type of device
connected (and not otherwise enumerated) will be probed.  For example,
a driver for a hardware monitoring chip for which auto-detection is
needed would set its class to I2C_CLASS_HWMON, and only I2C adapters
with a class including I2C_CLASS_HWMON would be probed by this driver.
Note that the absence of matching classes does not prevent the use of
a device of that type on the given I2C adapter.  All it prevents is
auto-detection; explicit instantiation of devices is still possible.

Note that this mechanism is purely optional and not suitable for all
devices.  You need some reliable way to identify the supported devices
(typically using device-specific, dedicated identification registers),
otherwise misdetections are likely to occur and things can get wrong
quickly.  Keep in mind that the I2C protocol doesn't include any
standard way to detect the presence of a chip at a given address, let
alone a standard way to identify devices.  Even worse is the lack of
semantics associated to bus transfers, which means that the same
transfer can be seen as a read operation by a chip and as a write
operation by another chip.  For these reasons, explicit device
instantiation should always be preferred to auto-detection where
possible.

Device Deletion
---------------

Each I2C device which has been created using i2c_new_client_device()
or i2c_new_scanned_device() can be unregistered by calling
i2c_unregister_device().  If you don't call it explicitly, it will be
called automatically before the underlying I2C bus itself is removed,
as a device can't survive its parent in the device driver model.

Initializing the driver
=======================

When the kernel is booted, or when your foo driver module is inserted,
you have to do some initializing. Fortunately, just registering the
driver module is usually enough.

::

  static int __init foo_init(void)
  {
	return i2c_add_driver(&foo_driver);
  }
  module_init(foo_init);

  static void __exit foo_cleanup(void)
  {
	i2c_del_driver(&foo_driver);
  }
  module_exit(foo_cleanup);

  The module_i2c_driver() macro can be used to reduce above code.

  module_i2c_driver(foo_driver);

Note that some functions are marked by ``__init``.  These functions can
be removed after kernel booting (or module loading) is completed.
Likewise, functions marked by ``__exit`` are dropped by the compiler when
the code is built into the kernel, as they would never be called.

Driver Information
==================

::

  /* Substitute your own name and email address */
  MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
  MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");

  /* a few non-GPL license types are also allowed */
  MODULE_LICENSE("GPL");

Power Management
================

If your I2C device needs special handling when entering a system low
power state -- like putting a transceiver into a low power mode, or
activating a system wakeup mechanism -- do that by implementing the
appropriate callbacks for the dev_pm_ops of the driver (like suspend
and resume).

These are standard driver model calls, and they work just like they
would for any other driver stack.  The calls can sleep, and can use
I2C messaging to the device being suspended or resumed (since their
parent I2C adapter is active when these calls are issued, and IRQs
are still enabled).

System Shutdown
===============

If your I2C device needs special handling when the system shuts down
or reboots (including kexec) -- like turning something off -- use a
shutdown() method.

Again, this is a standard driver model call, working just like it
would for any other driver stack:  the calls can sleep, and can use
I2C messaging.

Command function
================

A generic ioctl-like function call back is supported. You will seldom
need this, and its use is deprecated anyway, so newer design should not
use it.

Sending and receiving
=====================

If you want to communicate with your device, there are several functions
to do this. You can find all of them in <linux/i2c.h>.

If you can choose between plain I2C communication and SMBus level
communication, please use the latter. All adapters understand SMBus level
commands, but only some of them understand plain I2C!

Plain I2C communication
-----------------------

::

	int i2c_master_send(struct i2c_client *client, const char *buf,
			    int count);
	int i2c_master_recv(struct i2c_client *client, char *buf, int count);

These routines read and write some bytes from/to a client. The client
contains the I2C address, so you do not have to include it. The second
parameter contains the bytes to read/write, the third the number of bytes
to read/write (must be less than the length of the buffer, also should be
less than 64k since msg.len is u16.) Returned is the actual number of bytes
read/written.

::

	int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg,
			 int num);

This sends a series of messages. Each message can be a read or write,
and they can be mixed in any way. The transactions are combined: no
stop condition is issued between transaction. The i2c_msg structure
contains for each message the client address, the number of bytes of the
message and the message data itself.

You can read the file i2c-protocol.rst for more information about the
actual I2C protocol.

SMBus communication
-------------------

::

	s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
			   unsigned short flags, char read_write, u8 command,
			   int size, union i2c_smbus_data *data);

This is the generic SMBus function. All functions below are implemented
in terms of it. Never use this function directly!

::

	s32 i2c_smbus_read_byte(struct i2c_client *client);
	s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value);
	s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command);
	s32 i2c_smbus_write_byte_data(struct i2c_client *client,
				      u8 command, u8 value);
	s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command);
	s32 i2c_smbus_write_word_data(struct i2c_client *client,
				      u8 command, u16 value);
	s32 i2c_smbus_read_block_data(struct i2c_client *client,
				      u8 command, u8 *values);
	s32 i2c_smbus_write_block_data(struct i2c_client *client,
				       u8 command, u8 length, const u8 *values);
	s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client,
					  u8 command, u8 length, u8 *values);
	s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client,
					   u8 command, u8 length,
					   const u8 *values);

These ones were removed from i2c-core because they had no users, but could
be added back later if needed::

	s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value);
	s32 i2c_smbus_process_call(struct i2c_client *client,
				   u8 command, u16 value);
	s32 i2c_smbus_block_process_call(struct i2c_client *client,
					 u8 command, u8 length, u8 *values);

All these transactions return a negative errno value on failure. The 'write'
transactions return 0 on success; the 'read' transactions return the read
value, except for block transactions, which return the number of values
read. The block buffers need not be longer than 32 bytes.

You can read the file smbus-protocol.rst for more information about the
actual SMBus protocol.

General purpose routines
========================

Below all general purpose routines are listed, that were not mentioned
before::

	/* Return the adapter number for a specific adapter */
	int i2c_adapter_id(struct i2c_adapter *adap);


code:
==================================
Memory Attribute Aliasing on IA-64
==================================

Bjorn Helgaas <bjorn.helgaas@hp.com>

May 4, 2006

Memory Attributes
=================

    Itanium supports several attributes for virtual memory references.
    The attribute is part of the virtual translation, i.e., it is
    contained in the TLB entry.  The ones of most interest to the Linux
    kernel are:

	==		======================
        WB		Write-back (cacheable)
	UC		Uncacheable
	WC		Write-coalescing
	==		======================

    System memory typically uses the WB attribute.  The UC attribute is
    used for memory-mapped I/O devices.  The WC attribute is uncacheable
    like UC is, but writes may be delayed and combined to increase
    performance for things like frame buffers.

    The Itanium architecture requires that we avoid accessing the same
    page with both a cacheable mapping and an uncacheable mapping[1].

    The design of the chipset determines which attributes are supported
    on which regions of the address space.  For example, some chipsets
    support either WB or UC access to main memory, while others support
    only WB access.

Memory Map
==========

    Platform firmware describes the physical memory map and the
    supported attributes for each region.  At boot-time, the kernel uses
    the EFI GetMemoryMap() interface.  ACPI can also describe memory
    devices and the attributes they support, but Linux/ia64 currently
    doesn't use this information.

    The kernel uses the efi_memmap table returned from GetMemoryMap() to
    learn the attributes supported by each region of physical address
    space.  Unfortunately, this table does not completely describe the
    address space because some machines omit some or all of the MMIO
    regions from the map.

    The kernel maintains another table, kern_memmap, which describes the
    memory Linux is actually using and the attribute for each region.
    This contains only system memory; it does not contain MMIO space.

    The kern_memmap table typically contains only a subset of the system
    memory described by the efi_memmap.  Linux/ia64 can't use all memory
    in the system because of constraints imposed by the identity mapping
    scheme.

    The efi_memmap table is preserved unmodified because the original
    boot-time information is required for kexec.

Kernel Identity Mappings
========================

    Linux/ia64 identity mappings are done with large pages, currently
    either 16MB or 64MB, referred to as "granules."  Cacheable mappings
    are speculative[2], so the processor can read any location in the
    page at any time, independent of the programmer's intentions.  This
    means that to avoid attribute aliasing, Linux can create a cacheable
    identity mapping only when the entire granule supports cacheable
    access.

    Therefore, kern_memmap contains only full granule-sized regions that
    can referenced safely by an identity mapping.

    Uncacheable mappings are not speculative, so the processor will
    generate UC accesses only to locations explicitly referenced by
    software.  This allows UC identity mappings to cover granules that
    are only partially populated, or populated with a combination of UC
    and WB regions.

User Mappings
=============

    User mappings are typically done with 16K or 64K pages.  The smaller
    page size allows more flexibility because only 16K or 64K has to be
    homogeneous with respect to memory attributes.

Potential Attribute Aliasing Cases
==================================

    There are several ways the kernel creates new mappings:

mmap of /dev/mem
----------------

	This uses remap_pfn_range(), which creates user mappings.  These
	mappings may be either WB or UC.  If the region being mapped
	happens to be in kern_memmap, meaning that it may also be mapped
	by a kernel identity mapping, the user mapping must use the same
	attribute as the kernel mapping.

	If the region is not in kern_memmap, the user mapping should use
	an attribute reported as being supported in the EFI memory map.

	Since the EFI memory map does not describe MMIO on some
	machines, this should use an uncacheable mapping as a fallback.

mmap of /sys/class/pci_bus/.../legacy_mem
-----------------------------------------

	This is very similar to mmap of /dev/mem, except that legacy_mem
	only allows mmap of the one megabyte "legacy MMIO" area for a
	specific PCI bus.  Typically this is the first megabyte of
	physical address space, but it may be different on machines with
	several VGA devices.

	"X" uses this to access VGA frame buffers.  Using legacy_mem
	rather than /dev/mem allows multiple instances of X to talk to
	different VGA cards.

	The /dev/mem mmap constraints apply.

mmap of /proc/bus/pci/.../??.?
------------------------------

	This is an MMIO mmap of PCI functions, which additionally may or
	may not be requested as using the WC attribute.

	If WC is requested, and the region in kern_memmap is either WC
	or UC, and the EFI memory map designates the region as WC, then
	the WC mapping is allowed.

	Otherwise, the user mapping must use the same attribute as the
	kernel mapping.

read/write of /dev/mem
----------------------

	This uses copy_from_user(), which implicitly uses a kernel
	identity mapping.  This is obviously safe for things in
	kern_memmap.

	There may be corner cases of things that are not in kern_memmap,
	but could be accessed this way.  For example, registers in MMIO
	space are not in kern_memmap, but could be accessed with a UC
	mapping.  This would not cause attribute aliasing.  But
	registers typically can be accessed only with four-byte or
	eight-byte accesses, and the copy_from_user() path doesn't allow
	any control over the access size, so this would be dangerous.

ioremap()
---------

	This returns a mapping for use inside the kernel.

	If the region is in kern_memmap, we should use the attribute
	specified there.

	If the EFI memory map reports that the entire granule supports
	WB, we should use that (granules that are partially reserved
	or occupied by firmware do not appear in kern_memmap).

	If the granule contains non-WB memory, but we can cover the
	region safely with kernel page table mappings, we can use
	ioremap_page_range() as most other architectures do.

	Failing all of the above, we have to fall back to a UC mapping.

Past Problem Cases
==================

mmap of various MMIO regions from /dev/mem by "X" on Intel platforms
--------------------------------------------------------------------

      The EFI memory map may not report these MMIO regions.

      These must be allowed so that X will work.  This means that
      when the EFI memory map is incomplete, every /dev/mem mmap must
      succeed.  It may create either WB or UC user mappings, depending
      on whether the region is in kern_memmap or the EFI memory map.

mmap of 0x0-0x9FFFF /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
----------------------------------------------------------------------

      The EFI memory map reports the following attributes:

        =============== ======= ==================
        0x00000-0x9FFFF WB only
        0xA0000-0xBFFFF UC only (VGA frame buffer)
        0xC0000-0xFFFFF WB only
        =============== ======= ==================

      This mmap is done with user pages, not kernel identity mappings,
      so it is safe to use WB mappings.

      The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000,
      which uses a granule-sized UC mapping.  This granule will cover some
      WB-only memory, but since UC is non-speculative, the processor will
      never generate an uncacheable reference to the WB-only areas unless
      the driver explicitly touches them.

mmap of 0x0-0xFFFFF legacy_mem by "X"
-------------------------------------

      If the EFI memory map reports that the entire range supports the
      same attributes, we can allow the mmap (and we will prefer WB if
      supported, as is the case with HP sx[12]000 machines with VGA
      disabled).

      If EFI reports the range as partly WB and partly UC (as on sx[12]000
      machines with VGA enabled), we must fail the mmap because there's no
      safe attribute to use.

      If EFI reports some of the range but not all (as on Intel firmware
      that doesn't report the VGA frame buffer at all), we should fail the
      mmap and force the user to map just the specific region of interest.

mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled
------------------------------------------------------------------------

      The EFI memory map reports the following attributes::

        0x00000-0xFFFFF WB only (no VGA MMIO hole)

      This is a special case of the previous case, and the mmap should
      fail for the same reason as above.

read of /sys/devices/.../rom
----------------------------

      For VGA devices, this may cause an ioremap() of 0xC0000.  This
      used to be done with a UC mapping, because the VGA frame buffer
      at 0xA0000 prevents use of a WB granule.  The UC mapping causes
      an MCA on HP sx[12]000 chipsets.

      We should use WB page table mappings to avoid covering the VGA
      frame buffer.

Notes
=====

    [1] SDM rev 2.2, vol 2, sec 4.4.1.
    [2] SDM rev 2.2, vol 2, sec 4.4.6.


code:
==========================
EFI Real Time Clock driver
==========================

S. Eranian <eranian@hpl.hp.com>

March 2000

1. Introduction
===============

This document describes the efirtc.c driver has provided for
the IA-64 platform.

The purpose of this driver is to supply an API for kernel and user applications
to get access to the Time Service offered by EFI version 0.92.

EFI provides 4 calls one can make once the OS is booted: GetTime(),
SetTime(), GetWakeupTime(), SetWakeupTime() which are all supported by this
driver. We describe those calls as well the design of the driver in the
following sections.

2. Design Decisions
===================

The original ideas was to provide a very simple driver to get access to,
at first, the time of day service. This is required in order to access, in a
portable way, the CMOS clock. A program like /sbin/hwclock uses such a clock
to initialize the system view of the time during boot.

Because we wanted to minimize the impact on existing user-level apps using
the CMOS clock, we decided to expose an API that was very similar to the one
used today with the legacy RTC driver (driver/char/rtc.c). However, because
EFI provides a simpler services, not all ioctl() are available. Also
new ioctl()s have been introduced for things that EFI provides but not the
legacy.

EFI uses a slightly different way of representing the time, noticeably
the reference date is different. Year is the using the full 4-digit format.
The Epoch is January 1st 1998. For backward compatibility reasons we don't
expose this new way of representing time. Instead we use something very
similar to the struct tm, i.e. struct rtc_time, as used by hwclock.
One of the reasons for doing it this way is to allow for EFI to still evolve
without necessarily impacting any of the user applications. The decoupling
enables flexibility and permits writing wrapper code is ncase things change.

The driver exposes two interfaces, one via the device file and a set of
ioctl()s. The other is read-only via the /proc filesystem.

As of today we don't offer a /proc/sys interface.

To allow for a uniform interface between the legacy RTC and EFI time service,
we have created the include/linux/rtc.h header file to contain only the
"public" API of the two drivers.  The specifics of the legacy RTC are still
in include/linux/mc146818rtc.h.

3. Time of day service
======================

The part of the driver gives access to the time of day service of EFI.
Two ioctl()s, compatible with the legacy RTC calls:

	Read the CMOS clock::

		ioctl(d, RTC_RD_TIME, &rtc);

	Write the CMOS clock::

		ioctl(d, RTC_SET_TIME, &rtc);

The rtc is a pointer to a data structure defined in rtc.h which is close
to a struct tm::

  struct rtc_time {
          int tm_sec;
          int tm_min;
          int tm_hour;
          int tm_mday;
          int tm_mon;
          int tm_year;
          int tm_wday;
          int tm_yday;
          int tm_isdst;
  };

The driver takes care of converting back an forth between the EFI time and
this format.

Those two ioctl()s can be exercised with the hwclock command:

For reading::

	# /sbin/hwclock --show
	Mon Mar  6 15:32:32 2000  -0.910248 seconds

For setting::

	# /sbin/hwclock --systohc

Root privileges are required to be able to set the time of day.

4. Wakeup Alarm service
=======================

EFI provides an API by which one can program when a machine should wakeup,
i.e. reboot. This is very different from the alarm provided by the legacy
RTC which is some kind of interval timer alarm. For this reason we don't use
the same ioctl()s to get access to the service. Instead we have
introduced 2 news ioctl()s to the interface of an RTC.

We have added 2 new ioctl()s that are specific to the EFI driver:

	Read the current state of the alarm::

		ioctl(d, RTC_WKALM_RD, &wkt)

	Set the alarm or change its status::

		ioctl(d, RTC_WKALM_SET, &wkt)

The wkt structure encapsulates a struct rtc_time + 2 extra fields to get
status information::

  struct rtc_wkalrm {

          unsigned char enabled; /* =1 if alarm is enabled */
          unsigned char pending; /* =1 if alarm is pending  */

          struct rtc_time time;
  }

As of today, none of the existing user-level apps supports this feature.
However writing such a program should be hard by simply using those two
ioctl().

Root privileges are required to be able to set the alarm.

5. References
=============

Checkout the following Web site for more information on EFI:

http://developer.intel.com/technology/efi/


code:
========================================
IPF Machine Check (MC) error inject tool
========================================

IPF Machine Check (MC) error inject tool is used to inject MC
errors from Linux. The tool is a test bed for IPF MC work flow including
hardware correctable error handling, OS recoverable error handling, MC
event logging, etc.

The tool includes two parts: a kernel driver and a user application
sample. The driver provides interface to PAL to inject error
and query error injection capabilities. The driver code is in
arch/ia64/kernel/err_inject.c. The application sample (shown below)
provides a combination of various errors and calls the driver's interface
(sysfs interface) to inject errors or query error injection capabilities.

The tool can be used to test Intel IPF machine MC handling capabilities.
It's especially useful for people who can not access hardware MC injection
tool to inject error. It's also very useful to integrate with other
software test suits to do stressful testing on IPF.

Below is a sample application as part of the whole tool. The sample
can be used as a working test tool. Or it can be expanded to include
more features. It also can be a integrated into a library or other user
application to have more thorough test.

The sample application takes err.conf as error configuration input. GCC
compiles the code. After you install err_inject driver, you can run
this sample application to inject errors.

Errata: Itanium 2 Processors Specification Update lists some errata against
the pal_mc_error_inject PAL procedure. The following err.conf has been tested
on latest Montecito PAL.

err.conf::

  #This is configuration file for err_inject_tool.
  #The format of the each line is:
  #cpu, loop, interval, err_type_info, err_struct_info, err_data_buffer
  #where
  #	cpu: logical cpu number the error will be inject in.
  #	loop: times the error will be injected.
  #	interval: In second. every so often one error is injected.
  #	err_type_info, err_struct_info: PAL parameters.
  #
  #Note: All values are hex w/o or w/ 0x prefix.

  #On cpu2, inject only total 0x10 errors, interval 5 seconds
  #corrected, data cache, hier-2, physical addr(assigned by tool code).
  #working on Montecito latest PAL.
  2, 10, 5, 4101, 95

  #On cpu4, inject and consume total 0x10 errors, interval 5 seconds
  #corrected, data cache, hier-2, physical addr(assigned by tool code).
  #working on Montecito latest PAL.
  4, 10, 5, 4109, 95

  #On cpu15, inject and consume total 0x10 errors, interval 5 seconds
  #recoverable, DTR0, hier-2.
  #working on Montecito latest PAL.
  0xf, 0x10, 5, 4249, 15

The sample application source code:

err_injection_tool.c::

  /*
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
   * NON INFRINGEMENT.  See the GNU General Public License for more
   * details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   *
   * Copyright (C) 2006 Intel Co
   *	Fenghua Yu <fenghua.yu@intel.com>
   *
   */
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
  #include <stdio.h>
  #include <sched.h>
  #include <unistd.h>
  #include <stdlib.h>
  #include <stdarg.h>
  #include <string.h>
  #include <errno.h>
  #include <time.h>
  #include <sys/ipc.h>
  #include <sys/sem.h>
  #include <sys/wait.h>
  #include <sys/mman.h>
  #include <sys/shm.h>

  #define MAX_FN_SIZE 		256
  #define MAX_BUF_SIZE 		256
  #define DATA_BUF_SIZE 		256
  #define NR_CPUS 		512
  #define MAX_TASK_NUM		2048
  #define MIN_INTERVAL		5	// seconds
  #define	ERR_DATA_BUFFER_SIZE 	3	// Three 8-byte.
  #define PARA_FIELD_NUM		5
  #define MASK_SIZE		(NR_CPUS/64)
  #define PATH_FORMAT "/sys/devices/system/cpu/cpu%d/err_inject/"

  int sched_setaffinity(pid_t pid, unsigned int len, unsigned long *mask);

  int verbose;
  #define vbprintf if (verbose) printf

  int log_info(int cpu, const char *fmt, ...)
  {
	FILE *log;
	char fn[MAX_FN_SIZE];
	char buf[MAX_BUF_SIZE];
	va_list args;

	sprintf(fn, "%d.log", cpu);
	log=fopen(fn, "a+");
	if (log==NULL) {
		perror("Error open:");
		return -1;
	}

	va_start(args, fmt);
	vprintf(fmt, args);
	memset(buf, 0, MAX_BUF_SIZE);
	vsprintf(buf, fmt, args);
	va_end(args);

	fwrite(buf, sizeof(buf), 1, log);
	fclose(log);

	return 0;
  }

  typedef unsigned long u64;
  typedef unsigned int  u32;

  typedef union err_type_info_u {
	struct {
		u64	mode		: 3,	/* 0-2 */
			err_inj		: 3,	/* 3-5 */
			err_sev		: 2,	/* 6-7 */
			err_struct	: 5,	/* 8-12 */
			struct_hier	: 3,	/* 13-15 */
			reserved	: 48;	/* 16-63 */
	} err_type_info_u;
	u64	err_type_info;
  } err_type_info_t;

  typedef union err_struct_info_u {
	struct {
		u64	siv		: 1,	/* 0	 */
			c_t		: 2,	/* 1-2	 */
			cl_p		: 3,	/* 3-5	 */
			cl_id		: 3,	/* 6-8	 */
			cl_dp		: 1,	/* 9	 */
			reserved1	: 22,	/* 10-31 */
			tiv		: 1,	/* 32	 */
			trigger		: 4,	/* 33-36 */
			trigger_pl 	: 3,	/* 37-39 */
			reserved2 	: 24;	/* 40-63 */
	} err_struct_info_cache;
	struct {
		u64	siv		: 1,	/* 0	 */
			tt		: 2,	/* 1-2	 */
			tc_tr		: 2,	/* 3-4	 */
			tr_slot		: 8,	/* 5-12	 */
			reserved1	: 19,	/* 13-31 */
			tiv		: 1,	/* 32	 */
			trigger		: 4,	/* 33-36 */
			trigger_pl 	: 3,	/* 37-39 */
			reserved2 	: 24;	/* 40-63 */
	} err_struct_info_tlb;
	struct {
		u64	siv		: 1,	/* 0	 */
			regfile_id	: 4,	/* 1-4	 */
			reg_num		: 7,	/* 5-11	 */
			reserved1	: 20,	/* 12-31 */
			tiv		: 1,	/* 32	 */
			trigger		: 4,	/* 33-36 */
			trigger_pl 	: 3,	/* 37-39 */
			reserved2 	: 24;	/* 40-63 */
	} err_struct_info_register;
	struct {
		u64	reserved;
	} err_struct_info_bus_processor_interconnect;
	u64	err_struct_info;
  } err_struct_info_t;

  typedef union err_data_buffer_u {
	struct {
		u64	trigger_addr;		/* 0-63		*/
		u64	inj_addr;		/* 64-127 	*/
		u64	way		: 5,	/* 128-132	*/
			index		: 20,	/* 133-152	*/
					: 39;	/* 153-191	*/
	} err_data_buffer_cache;
	struct {
		u64	trigger_addr;		/* 0-63		*/
		u64	inj_addr;		/* 64-127 	*/
		u64	way		: 5,	/* 128-132	*/
			index		: 20,	/* 133-152	*/
			reserved	: 39;	/* 153-191	*/
	} err_data_buffer_tlb;
	struct {
		u64	trigger_addr;		/* 0-63		*/
	} err_data_buffer_register;
	struct {
		u64	reserved;		/* 0-63		*/
	} err_data_buffer_bus_processor_interconnect;
	u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
  } err_data_buffer_t;

  typedef union capabilities_u {
	struct {
		u64	i		: 1,
			d		: 1,
			rv		: 1,
			tag		: 1,
			data		: 1,
			mesi		: 1,
			dp		: 1,
			reserved1	: 3,
			pa		: 1,
			va		: 1,
			wi		: 1,
			reserved2	: 20,
			trigger		: 1,
			trigger_pl	: 1,
			reserved3	: 30;
	} capabilities_cache;
	struct {
		u64	d		: 1,
			i		: 1,
			rv		: 1,
			tc		: 1,
			tr		: 1,
			reserved1	: 27,
			trigger		: 1,
			trigger_pl	: 1,
			reserved2	: 30;
	} capabilities_tlb;
	struct {
		u64	gr_b0		: 1,
			gr_b1		: 1,
			fr		: 1,
			br		: 1,
			pr		: 1,
			ar		: 1,
			cr		: 1,
			rr		: 1,
			pkr		: 1,
			dbr		: 1,
			ibr		: 1,
			pmc		: 1,
			pmd		: 1,
			reserved1	: 3,
			regnum		: 1,
			reserved2	: 15,
			trigger		: 1,
			trigger_pl	: 1,
			reserved3	: 30;
	} capabilities_register;
	struct {
		u64	reserved;
	} capabilities_bus_processor_interconnect;
  } capabilities_t;

  typedef struct resources_s {
	u64	ibr0		: 1,
		ibr2		: 1,
		ibr4		: 1,
		ibr6		: 1,
		dbr0		: 1,
		dbr2		: 1,
		dbr4		: 1,
		dbr6		: 1,
		reserved	: 48;
  } resources_t;

  long get_page_size(void)
  {
	long page_size=sysconf(_SC_PAGESIZE);
	return page_size;
  }

  #define PAGE_SIZE (get_page_size()==-1?0x4000:get_page_size())
  #define SHM_SIZE (2*PAGE_SIZE*NR_CPUS)
  #define SHM_VA 0x2000000100000000

  int shmid;
  void *shmaddr;

  int create_shm(void)
  {
	key_t key;
	char fn[MAX_FN_SIZE];

	/* cpu0 is always existing */
	sprintf(fn, PATH_FORMAT, 0);
	if ((key = ftok(fn, 's')) == -1) {
		perror("ftok");
		return -1;
	}

	shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT);
	if (shmid == -1) {
		if (errno==EEXIST) {
			shmid = shmget(key, SHM_SIZE, 0);
			if (shmid == -1) {
				perror("shmget");
				return -1;
			}
		}
		else {
			perror("shmget");
			return -1;
		}
	}
	vbprintf("shmid=%d", shmid);

	/* connect to the segment: */
	shmaddr = shmat(shmid, (void *)SHM_VA, 0);
	if (shmaddr == (void*)-1) {
		perror("shmat");
		return -1;
	}

	memset(shmaddr, 0, SHM_SIZE);
	mlock(shmaddr, SHM_SIZE);

	return 0;
  }

  int free_shm()
  {
	munlock(shmaddr, SHM_SIZE);
          shmdt(shmaddr);
	semctl(shmid, 0, IPC_RMID);

	return 0;
  }

  #ifdef _SEM_SEMUN_UNDEFINED
  union semun
  {
	int val;
	struct semid_ds *buf;
	unsigned short int *array;
	struct seminfo *__buf;
  };
  #endif

  u32 mode=1; /* 1: physical mode; 2: virtual mode. */
  int one_lock=1;
  key_t key[NR_CPUS];
  int semid[NR_CPUS];

  int create_sem(int cpu)
  {
	union semun arg;
	char fn[MAX_FN_SIZE];
	int sid;

	sprintf(fn, PATH_FORMAT, cpu);
	sprintf(fn, "%s/%s", fn, "err_type_info");
	if ((key[cpu] = ftok(fn, 'e')) == -1) {
		perror("ftok");
		return -1;
	}

	if (semid[cpu]!=0)
		return 0;

	/* clear old semaphore */
	if ((sid = semget(key[cpu], 1, 0)) != -1)
		semctl(sid, 0, IPC_RMID);

	/* get one semaphore */
	if ((semid[cpu] = semget(key[cpu], 1, IPC_CREAT | IPC_EXCL)) == -1) {
		perror("semget");
		printf("Please remove semaphore with key=0x%lx, then run the tool.\n",
			(u64)key[cpu]);
		return -1;
	}

	vbprintf("semid[%d]=0x%lx, key[%d]=%lx\n",cpu,(u64)semid[cpu],cpu,
		(u64)key[cpu]);
	/* initialize the semaphore to 1: */
	arg.val = 1;
	if (semctl(semid[cpu], 0, SETVAL, arg) == -1) {
		perror("semctl");
		return -1;
	}

	return 0;
  }

  static int lock(int cpu)
  {
	struct sembuf lock;

	lock.sem_num = cpu;
	lock.sem_op = 1;
	semop(semid[cpu], &lock, 1);

          return 0;
  }

  static int unlock(int cpu)
  {
	struct sembuf unlock;

	unlock.sem_num = cpu;
	unlock.sem_op = -1;
	semop(semid[cpu], &unlock, 1);

          return 0;
  }

  void free_sem(int cpu)
  {
	semctl(semid[cpu], 0, IPC_RMID);
  }

  int wr_multi(char *fn, unsigned long *data, int size)
  {
	int fd;
	char buf[MAX_BUF_SIZE];
	int ret;

	if (size==1)
		sprintf(buf, "%lx", *data);
	else if (size==3)
		sprintf(buf, "%lx,%lx,%lx", data[0], data[1], data[2]);
	else {
		fprintf(stderr,"write to file with wrong size!\n");
		return -1;
	}

	fd=open(fn, O_RDWR);
	if (!fd) {
		perror("Error:");
		return -1;
	}
	ret=write(fd, buf, sizeof(buf));
	close(fd);
	return ret;
  }

  int wr(char *fn, unsigned long data)
  {
	return wr_multi(fn, &data, 1);
  }

  int rd(char *fn, unsigned long *data)
  {
	int fd;
	char buf[MAX_BUF_SIZE];

	fd=open(fn, O_RDONLY);
	if (fd<0) {
		perror("Error:");
		return -1;
	}
	read(fd, buf, MAX_BUF_SIZE);
	*data=strtoul(buf, NULL, 16);
	close(fd);
	return 0;
  }

  int rd_status(char *path, int *status)
  {
	char fn[MAX_FN_SIZE];
	sprintf(fn, "%s/status", path);
	if (rd(fn, (u64*)status)<0) {
		perror("status reading error.\n");
		return -1;
	}

	return 0;
  }

  int rd_capabilities(char *path, u64 *capabilities)
  {
	char fn[MAX_FN_SIZE];
	sprintf(fn, "%s/capabilities", path);
	if (rd(fn, capabilities)<0) {
		perror("capabilities reading error.\n");
		return -1;
	}

	return 0;
  }

  int rd_all(char *path)
  {
	unsigned long err_type_info, err_struct_info, err_data_buffer;
	int status;
	unsigned long capabilities, resources;
	char fn[MAX_FN_SIZE];

	sprintf(fn, "%s/err_type_info", path);
	if (rd(fn, &err_type_info)<0) {
		perror("err_type_info reading error.\n");
		return -1;
	}
	printf("err_type_info=%lx\n", err_type_info);

	sprintf(fn, "%s/err_struct_info", path);
	if (rd(fn, &err_struct_info)<0) {
		perror("err_struct_info reading error.\n");
		return -1;
	}
	printf("err_struct_info=%lx\n", err_struct_info);

	sprintf(fn, "%s/err_data_buffer", path);
	if (rd(fn, &err_data_buffer)<0) {
		perror("err_data_buffer reading error.\n");
		return -1;
	}
	printf("err_data_buffer=%lx\n", err_data_buffer);

	sprintf(fn, "%s/status", path);
	if (rd("status", (u64*)&status)<0) {
		perror("status reading error.\n");
		return -1;
	}
	printf("status=%d\n", status);

	sprintf(fn, "%s/capabilities", path);
	if (rd(fn,&capabilities)<0) {
		perror("capabilities reading error.\n");
		return -1;
	}
	printf("capabilities=%lx\n", capabilities);

	sprintf(fn, "%s/resources", path);
	if (rd(fn, &resources)<0) {
		perror("resources reading error.\n");
		return -1;
	}
	printf("resources=%lx\n", resources);

	return 0;
  }

  int query_capabilities(char *path, err_type_info_t err_type_info,
			u64 *capabilities)
  {
	char fn[MAX_FN_SIZE];
	err_struct_info_t err_struct_info;
	err_data_buffer_t err_data_buffer;

	err_struct_info.err_struct_info=0;
	memset(err_data_buffer.err_data_buffer, -1, ERR_DATA_BUFFER_SIZE*8);

	sprintf(fn, "%s/err_type_info", path);
	wr(fn, err_type_info.err_type_info);
	sprintf(fn, "%s/err_struct_info", path);
	wr(fn, 0x0);
	sprintf(fn, "%s/err_data_buffer", path);
	wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);

	// Fire pal_mc_error_inject procedure.
	sprintf(fn, "%s/call_start", path);
	wr(fn, mode);

	if (rd_capabilities(path, capabilities)<0)
		return -1;

	return 0;
  }

  int query_all_capabilities()
  {
	int status;
	err_type_info_t err_type_info;
	int err_sev, err_struct, struct_hier;
	int cap=0;
	u64 capabilities;
	char path[MAX_FN_SIZE];

	err_type_info.err_type_info=0;			// Initial
	err_type_info.err_type_info_u.mode=0;		// Query mode;
	err_type_info.err_type_info_u.err_inj=0;

	printf("All capabilities implemented in pal_mc_error_inject:\n");
	sprintf(path, PATH_FORMAT ,0);
	for (err_sev=0;err_sev<3;err_sev++)
		for (err_struct=0;err_struct<5;err_struct++)
			for (struct_hier=0;struct_hier<5;struct_hier++)
	{
		status=-1;
		capabilities=0;
		err_type_info.err_type_info_u.err_sev=err_sev;
		err_type_info.err_type_info_u.err_struct=err_struct;
		err_type_info.err_type_info_u.struct_hier=struct_hier;

		if (query_capabilities(path, err_type_info, &capabilities)<0)
			continue;

		if (rd_status(path, &status)<0)
			continue;

		if (status==0) {
			cap=1;
			printf("For err_sev=%d, err_struct=%d, struct_hier=%d: ",
				err_sev, err_struct, struct_hier);
			printf("capabilities 0x%lx\n", capabilities);
		}
	}
	if (!cap) {
		printf("No capabilities supported.\n");
		return 0;
	}

	return 0;
  }

  int err_inject(int cpu, char *path, err_type_info_t err_type_info,
		err_struct_info_t err_struct_info,
		err_data_buffer_t err_data_buffer)
  {
	int status;
	char fn[MAX_FN_SIZE];

	log_info(cpu, "err_type_info=%lx, err_struct_info=%lx, ",
		err_type_info.err_type_info,
		err_struct_info.err_struct_info);
	log_info(cpu,"err_data_buffer=[%lx,%lx,%lx]\n",
		err_data_buffer.err_data_buffer[0],
		err_data_buffer.err_data_buffer[1],
		err_data_buffer.err_data_buffer[2]);
	sprintf(fn, "%s/err_type_info", path);
	wr(fn, err_type_info.err_type_info);
	sprintf(fn, "%s/err_struct_info", path);
	wr(fn, err_struct_info.err_struct_info);
	sprintf(fn, "%s/err_data_buffer", path);
	wr_multi(fn, err_data_buffer.err_data_buffer, ERR_DATA_BUFFER_SIZE);

	// Fire pal_mc_error_inject procedure.
	sprintf(fn, "%s/call_start", path);
	wr(fn,mode);

	if (rd_status(path, &status)<0) {
		vbprintf("fail: read status\n");
		return -100;
	}

	if (status!=0) {
		log_info(cpu, "fail: status=%d\n", status);
		return status;
	}

	return status;
  }

  static int construct_data_buf(char *path, err_type_info_t err_type_info,
		err_struct_info_t err_struct_info,
		err_data_buffer_t *err_data_buffer,
		void *va1)
  {
	char fn[MAX_FN_SIZE];
	u64 virt_addr=0, phys_addr=0;

	vbprintf("va1=%lx\n", (u64)va1);
	memset(&err_data_buffer->err_data_buffer_cache, 0, ERR_DATA_BUFFER_SIZE*8);

	switch (err_type_info.err_type_info_u.err_struct) {
		case 1: // Cache
			switch (err_struct_info.err_struct_info_cache.cl_id) {
				case 1: //Virtual addr
					err_data_buffer->err_data_buffer_cache.inj_addr=(u64)va1;
					break;
				case 2: //Phys addr
					sprintf(fn, "%s/virtual_to_phys", path);
					virt_addr=(u64)va1;
					if (wr(fn,virt_addr)<0)
						return -1;
					rd(fn, &phys_addr);
					err_data_buffer->err_data_buffer_cache.inj_addr=phys_addr;
					break;
				default:
					printf("Not supported cl_id\n");
					break;
			}
			break;
		case 2: //  TLB
			break;
		case 3: //  Register file
			break;
		case 4: //  Bus/system interconnect
		default:
			printf("Not supported err_struct\n");
			break;
	}

	return 0;
  }

  typedef struct {
	u64 cpu;
	u64 loop;
	u64 interval;
	u64 err_type_info;
	u64 err_struct_info;
	u64 err_data_buffer[ERR_DATA_BUFFER_SIZE];
  } parameters_t;

  parameters_t line_para;
  int para;

  static int empty_data_buffer(u64 *err_data_buffer)
  {
	int empty=1;
	int i;

	for (i=0;i<ERR_DATA_BUFFER_SIZE; i++)
	   if (err_data_buffer[i]!=-1)
		empty=0;

	return empty;
  }

  int err_inj()
  {
	err_type_info_t err_type_info;
	err_struct_info_t err_struct_info;
	err_data_buffer_t err_data_buffer;
	int count;
	FILE *fp;
	unsigned long cpu, loop, interval, err_type_info_conf, err_struct_info_conf;
	u64 err_data_buffer_conf[ERR_DATA_BUFFER_SIZE];
	int num;
	int i;
	char path[MAX_FN_SIZE];
	parameters_t parameters[MAX_TASK_NUM]={};
	pid_t child_pid[MAX_TASK_NUM];
	time_t current_time;
	int status;

	if (!para) {
	    fp=fopen("err.conf", "r");
	    if (fp==NULL) {
		perror("Error open err.conf");
		return -1;
	    }

	    num=0;
	    while (!feof(fp)) {
		char buf[256];
		memset(buf,0,256);
		fgets(buf, 256, fp);
		count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
				&cpu, &loop, &interval,&err_type_info_conf,
				&err_struct_info_conf,
				&err_data_buffer_conf[0],
				&err_data_buffer_conf[1],
				&err_data_buffer_conf[2]);
		if (count!=PARA_FIELD_NUM+3) {
			err_data_buffer_conf[0]=-1;
			err_data_buffer_conf[1]=-1;
			err_data_buffer_conf[2]=-1;
			count=sscanf(buf, "%lx, %lx, %lx, %lx, %lx\n",
				&cpu, &loop, &interval,&err_type_info_conf,
				&err_struct_info_conf);
			if (count!=PARA_FIELD_NUM)
				continue;
		}

		parameters[num].cpu=cpu;
		parameters[num].loop=loop;
		parameters[num].interval= interval>MIN_INTERVAL
					  ?interval:MIN_INTERVAL;
		parameters[num].err_type_info=err_type_info_conf;
		parameters[num].err_struct_info=err_struct_info_conf;
		memcpy(parameters[num++].err_data_buffer,
			err_data_buffer_conf,ERR_DATA_BUFFER_SIZE*8) ;

		if (num>=MAX_TASK_NUM)
			break;
	    }
	}
	else {
		parameters[0].cpu=line_para.cpu;
		parameters[0].loop=line_para.loop;
		parameters[0].interval= line_para.interval>MIN_INTERVAL
					  ?line_para.interval:MIN_INTERVAL;
		parameters[0].err_type_info=line_para.err_type_info;
		parameters[0].err_struct_info=line_para.err_struct_info;
		memcpy(parameters[0].err_data_buffer,
			line_para.err_data_buffer,ERR_DATA_BUFFER_SIZE*8) ;

		num=1;
	}

	/* Create semaphore: If one_lock, one semaphore for all processors.
	   Otherwise, one semaphore for each processor. */
	if (one_lock) {
		if (create_sem(0)) {
			printf("Can not create semaphore...exit\n");
			free_sem(0);
			return -1;
		}
	}
	else {
		for (i=0;i<num;i++) {
		   if (create_sem(parameters[i].cpu)) {
			printf("Can not create semaphore for cpu%d...exit\n",i);
			free_sem(parameters[num].cpu);
			return -1;
		   }
		}
	}

	/* Create a shm segment which will be used to inject/consume errors on.*/
	if (create_shm()==-1) {
		printf("Error to create shm...exit\n");
		return -1;
	}

	for (i=0;i<num;i++) {
		pid_t pid;

		current_time=time(NULL);
		log_info(parameters[i].cpu, "\nBegine at %s", ctime(&current_time));
		log_info(parameters[i].cpu, "Configurations:\n");
		log_info(parameters[i].cpu,"On cpu%ld: loop=%lx, interval=%lx(s)",
			parameters[i].cpu,
			parameters[i].loop,
			parameters[i].interval);
		log_info(parameters[i].cpu," err_type_info=%lx,err_struct_info=%lx\n",
			parameters[i].err_type_info,
			parameters[i].err_struct_info);

		sprintf(path, PATH_FORMAT, (int)parameters[i].cpu);
		err_type_info.err_type_info=parameters[i].err_type_info;
		err_struct_info.err_struct_info=parameters[i].err_struct_info;
		memcpy(err_data_buffer.err_data_buffer,
			parameters[i].err_data_buffer,
			ERR_DATA_BUFFER_SIZE*8);

		pid=fork();
		if (pid==0) {
			unsigned long mask[MASK_SIZE];
			int j, k;

			void *va1, *va2;

			/* Allocate two memory areas va1 and va2 in shm */
			va1=shmaddr+parameters[i].cpu*PAGE_SIZE;
			va2=shmaddr+parameters[i].cpu*PAGE_SIZE+PAGE_SIZE;

			vbprintf("va1=%lx, va2=%lx\n", (u64)va1, (u64)va2);
			memset(va1, 0x1, PAGE_SIZE);
			memset(va2, 0x2, PAGE_SIZE);

			if (empty_data_buffer(err_data_buffer.err_data_buffer))
				/* If not specified yet, construct data buffer
				 * with va1
				 */
				construct_data_buf(path, err_type_info,
					err_struct_info, &err_data_buffer,va1);

			for (j=0;j<MASK_SIZE;j++)
				mask[j]=0;

			cpu=parameters[i].cpu;
			k = cpu%64;
			j = cpu/64;
			mask[j] = 1UL << k;

			if (sched_setaffinity(0, MASK_SIZE*8, mask)==-1) {
				perror("Error sched_setaffinity:");
				return -1;
			}

			for (j=0; j<parameters[i].loop; j++) {
				log_info(parameters[i].cpu,"Injection ");
				log_info(parameters[i].cpu,"on cpu%ld: #%d/%ld ",

					parameters[i].cpu,j+1, parameters[i].loop);

				/* Hold the lock */
				if (one_lock)
					lock(0);
				else
				/* Hold lock on this cpu */
					lock(parameters[i].cpu);

				if ((status=err_inject(parameters[i].cpu,
					   path, err_type_info,
					   err_struct_info, err_data_buffer))
					   ==0) {
					/* consume the error for "inject only"*/
					memcpy(va2, va1, PAGE_SIZE);
					memcpy(va1, va2, PAGE_SIZE);
					log_info(parameters[i].cpu,
						"successful\n");
				}
				else {
					log_info(parameters[i].cpu,"fail:");
					log_info(parameters[i].cpu,
						"status=%d\n", status);
					unlock(parameters[i].cpu);
					break;
				}
				if (one_lock)
				/* Release the lock */
					unlock(0);
				/* Release lock on this cpu */
				else
					unlock(parameters[i].cpu);

				if (j < parameters[i].loop-1)
					sleep(parameters[i].interval);
			}
			current_time=time(NULL);
			log_info(parameters[i].cpu, "Done at %s", ctime(&current_time));
			return 0;
		}
		else if (pid<0) {
			perror("Error fork:");
			continue;
		}
		child_pid[i]=pid;
	}
	for (i=0;i<num;i++)
		waitpid(child_pid[i], NULL, 0);

	if (one_lock)
		free_sem(0);
	else
		for (i=0;i<num;i++)
			free_sem(parameters[i].cpu);

	printf("All done.\n");

	return 0;
  }

  void help()
  {
	printf("err_inject_tool:\n");
	printf("\t-q: query all capabilities. default: off\n");
	printf("\t-m: procedure mode. 1: physical 2: virtual. default: 1\n");
	printf("\t-i: inject errors. default: off\n");
	printf("\t-l: one lock per cpu. default: one lock for all\n");
	printf("\t-e: error parameters:\n");
	printf("\t\tcpu,loop,interval,err_type_info,err_struct_info[,err_data_buffer[0],err_data_buffer[1],err_data_buffer[2]]\n");
	printf("\t\t   cpu: logical cpu number the error will be inject in.\n");
	printf("\t\t   loop: times the error will be injected.\n");
	printf("\t\t   interval: In second. every so often one error is injected.\n");
	printf("\t\t   err_type_info, err_struct_info: PAL parameters.\n");
	printf("\t\t   err_data_buffer: PAL parameter. Optional. If not present,\n");
	printf("\t\t                    it's constructed by tool automatically. Be\n");
	printf("\t\t                    careful to provide err_data_buffer and make\n");
	printf("\t\t                    sure it's working with the environment.\n");
	printf("\t    Note:no space between error parameters.\n");
	printf("\t    default: Take error parameters from err.conf instead of command line.\n");
	printf("\t-v: verbose. default: off\n");
	printf("\t-h: help\n\n");
	printf("The tool will take err.conf file as ");
	printf("input to inject single or multiple errors ");
	printf("on one or multiple cpus in parallel.\n");
  }

  int main(int argc, char **argv)
  {
	char c;
	int do_err_inj=0;
	int do_query_all=0;
	int count;
	u32 m;

	/* Default one lock for all cpu's */
	one_lock=1;
	while ((c = getopt(argc, argv, "m:iqvhle:")) != EOF)
		switch (c) {
			case 'm':	/* Procedure mode. 1: phys 2: virt */
				count=sscanf(optarg, "%x", &m);
				if (count!=1 || (m!=1 && m!=2)) {
					printf("Wrong mode number.\n");
					help();
					return -1;
				}
				mode=m;
				break;
			case 'i':	/* Inject errors */
				do_err_inj=1;
				break;
			case 'q':	/* Query */
				do_query_all=1;
				break;
			case 'v':	/* Verbose */
				verbose=1;
				break;
			case 'l':	/* One lock per cpu */
				one_lock=0;
				break;
			case 'e':	/* error arguments */
				/* Take parameters:
				 * #cpu, loop, interval, err_type_info, err_struct_info[, err_data_buffer]
				 * err_data_buffer is optional. Recommend not to specify
				 * err_data_buffer. Better to use tool to generate it.
				 */
				count=sscanf(optarg,
					"%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx\n",
					&line_para.cpu,
					&line_para.loop,
					&line_para.interval,
					&line_para.err_type_info,
					&line_para.err_struct_info,
					&line_para.err_data_buffer[0],
					&line_para.err_data_buffer[1],
					&line_para.err_data_buffer[2]);
				if (count!=PARA_FIELD_NUM+3) {
				    line_para.err_data_buffer[0]=-1,
				    line_para.err_data_buffer[1]=-1,
				    line_para.err_data_buffer[2]=-1;
				    count=sscanf(optarg, "%lx, %lx, %lx, %lx, %lx\n",
						&line_para.cpu,
						&line_para.loop,
						&line_para.interval,
						&line_para.err_type_info,
						&line_para.err_struct_info);
				    if (count!=PARA_FIELD_NUM) {
					printf("Wrong error arguments.\n");
					help();
					return -1;
				    }
				}
				para=1;
				break;
			continue;
				break;
			case 'h':
				help();
				return 0;
			default:
				break;
		}

	if (do_query_all)
		query_all_capabilities();
	if (do_err_inj)
		err_inj();

	if (!do_query_all &&  !do_err_inj)
		help();

	return 0;
  }


code:
.. SPDX-License-Identifier: GPL-2.0

.. kernel-feat:: $srctree/Documentation/features ia64