The LTC4306 is a 4-channel, 2-wire bus multiplexer with bus buffers to provide capacitive isolation between the upstream bus and downstream buses. Through software control, the LTC4306 connects the upstream 2-wire bus to any desired combination of downstream buses. Each channel can be pulled up to a supply voltage ranging from 2.2 V to 5.5 V, independent of the LTC4306 supply voltage. The downstream channels are also provided with ALERT1-ALERT4 inputs for fault reporting.
Programmable timeout circuitry disconnects the downstream buses if the bus is stuck low. When activated, rise time accelerators source currents into the 2-wire bus pins to reduce rise time. Driving the ENABLE pin low restores all features to their default states. Three address pins provide 27 distinct addresses.
The goal of the ADI Microcontroller No-OS is to provide reference projects for lower end processors, which can't run Linux or aren't running a specific operating system, and to help those customers using microcontrollers with ADI parts. ADI No-OS offers generic drivers, which can be used as a base for any microcontroller platforms; and also provides example projects, which are using these drivers on various microcontroller platforms.
For more information about ADI No-OS and supported microcontroller platforms, visit the No-OS User Guide.
The source code for LTC4306 driver can be found here:
This driver also uses the ADI utility library, so make sure you also add the necessary files to your project. The source code for the utility library can be found here:
To use the LTC4306 No-OS driver, you need to provide the specific implementation for the communication APIs and the specific types they use.
If the I2C communication is chosen, these are the functions to be called by the LTC4306 driver and have to be implemented:
no_os_i2c_init() | initializes the communication peripheral |
no_os_i2c_write() | writes data to the device |
no_os_i2c_read() | reads data from the device |
no_os_i2c_remove() | deinitializes the communication peripheral |
And these are the two data types that have to be defined:
no_os_i2c_desc | structure holding the I2C descriptor |
no_os_i2c_init_param | structure holding the parameters for I2C initialization |
An example of a header file containing the prototypes of the functions which have to be implemented, along with some generic data types they are using, can be found below:
Source code documentation for the driver is automatically generated using the Doxygen tool and can be accessed in these links:
To use the device, you need to provide the support for the communication protocol (I2C) as mentioned above.
The first API function to be called is ltc4306_addr_gen to generate the corresponding device's slave address. Once a proper address is generated, use the function ltc4306_init to initialize the device and make sure that it returns 0. This indicates a successful driver initialization.
The LTC4306 has the provision for multiple I2C slave addresses through the ADR0, ADR1, ADR2 pins. To generate the proper address, supply the voltage level going into pins ADR0, ADR1, ADR2 to the ltc4306_addr_gen function.
The LTC4306's register 0 contains status indicators for different operational cases. The following driver functions can be used to get the status of any selected operational indicators and use for decision making or other purposes:
ltc4306_downstream_check | indicates whether one or more downstream buses is connected to upstream |
ltc4306_read_alert_logic_state | indicates the logic state of the selected pin |
ltc4306_read_failed_conn | checks for any failure in upstream-downstream/s connection |
ltc4306_get_latched_timeout | determines whether a timeout has occurred and not yet been cleared |
ltc4306_get_realtime_timeout | checks the real-time status of the Stuck Low timeout circuitry |
The LTC4306 contains rise time accelerators that source current to the 2-wire bus pins to reduce rise time for both upstream (host side) and downstream (slave). When activated using the ltc4306_set_upstream_accel or ltc4306_set_downstream_accel, the accelerators turn on in a controlled manner and source currents during positive transitions.
The accelerator enable status can be checked using the ltc4306_get_upstream_accel or ltc4306_downstream_accel driver functions.
The LTC4306 also contains 2 GPIO pins. The logic level can be changed and queried using the ltc4306_set_gpio_output_state and the logic level checking process is best described by the ltc4306_get_gpio_output_state or ltc4306_read_gpio_logic_state functions below:
ltc4306_get_gpio_output_state | ltc4306_read_gpio_logic_state | |
---|---|---|
General operation | checks the logic state of the corresponding GPIOs 1 or 2; both functions can be used to confirm the actual status of the GPIOs | |
Specific operation | reads from the same bit field that the ltc4306_set_gpio_output_state manipulates | reads from a different read-only bit field in the same register |
The LTC4306 GPIO pins can be configured for either input or output operation. When at output mode, the GPIO can be configured as either push-pull or open-drain pull down architecture to match external circuitry requirements, if any. These can be easily achieved using the ltc4306_gpio_configure driver function. The function automatically checks whether the GPIO is configured for input or output and only considers the output architecture when the GPIO is configured as an output.
Depending on the requirements, the downstream buses (slave) can be immediately connected to the upstream (host) or not. This is controlled using the ltc4306_set_conn_req and can be polled using the ltc4306_get_conn_req functions.
When enabled, the device requires that the corresponding bus logic state to be HIGH. This can also be queried using ltc4306_read_bus_logic_state separately. This means that a connection will only be allowed from slave to host when SDAx and SCLx are both above 1 V, which can also serve as protection for all connected devices.
Aside from the pin configured address, the LTC4306 also responds to the mass write address 0xBA. This allows multiple LTC4306's to be configured using a single command. This functionality is enabled by default, but can be toggled or queried using the ltc4306_set_mass_write and ltc4306_get_mass_write functions.
The LTC4306 also includes a timeout circuitry. Depending on the timeout programmed using ltc4306_set_timeout_mode, the stuck low circuitry will wait for a specified amount of time before disconnecting any downstream bus that is stuck at LOW level logic. The currently programmed timeout mode can be queried using ltc4306_get_timeout_mode, if needed.
The valid timeout values are as follows:
LTC4306_DISABLED | disable timeout circuitry |
LTC4306_30MS | 30 mS timeout |
LTC4306_15MS | 15 mS timeout |
LTC4306_7P5MS | 7.5 mS timeout |
The LTC4306 contains 4 downstream channels where other I2C devices can be connected. The driver function ltc4306_set_downstream_channel allows connection or disconnection of a selected channel.
The status of any channel can be queried using either ltc4306_get_downstream_channel or ltc4306_read_bus_logic_state.
The difference between the two functions lies in the bit field accessed. The field accessed by both the ltc4306_set_downstream_channel and ltc4306_get_downstream_channel is a Read-Write fields, while ltc4306_read_bus_logic_state accesses a Read-only field. Both functions can be used for verification of any channel's connection status in some instances.
int ret; struct max_i2c_init_param ltc4306_extra = { .vssel = MXC_GPIO_VSSEL_VDDIOH, }; struct ltc4306_init_param ltc4306_ip = { .i2c_init.device_id = 0, .i2c_init.max_speed_hz = 100000, .i2c_init.extra = <c4306_extra, .i2c_init.platform_ops = &max_i2c_ops, }; ret = ltc4306_addr_gen(<c4306_ip, LTC4306_HIGH, LTC4306_HIGH, LTC4306_HIGH); if (ret) return ret; struct ltc4306_dev *ltc4306_device; ret = ltc4306_init(<c4306_device, ltc4306_ip); if (ret) return ret;
int ret; struct ltc4306_init_param ltc4306_ip = { .i2c_init.device_id = 0, .i2c_init.max_speed_hz = 100000, .i2c_init.extra = NULL, .i2c_init.platform_ops = &aducm_i2c_ops, }; ret = ltc4306_addr_gen(<c4306_ip, LTC4306_HIGH, LTC4306_HIGH, LTC4306_HIGH); if (ret) return ret; struct ltc4306_dev *ltc4306_device; ret = ltc4306_init(<c4306_device, ltc4306_ip); if (ret) return ret;