diff --git a/boards/xtensa/esp32/common/include/esp32_tca9548a.h b/boards/xtensa/esp32/common/include/esp32_tca9548a.h new file mode 100644 index 00000000000..7c453791ccd --- /dev/null +++ b/boards/xtensa/esp32/common/include/esp32_tca9548a.h @@ -0,0 +1,88 @@ +/**************************************************************************** + * boards/xtensa/esp32/common/include/esp32_tca9548a.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32_TCA9548A_H +#define __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32_TCA9548A_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: board_tca9548a_initialize + * + * Description: + * Initialize and register the TCA9548A Pressure Sensor driver. + * + * Input Parameters: + * devno - The device number, used to build the device path as /dev/pressN + * busno - The I2C bus number + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int board_tca9548a_initialize(int devno, int busno); + +/**************************************************************************** + * Name: esp32_i2cmux_getmaster + * + * Description: + * Returns an I2C Master for TCA9548A multiplexer channel. + * + * NOTE: esp32_i2cmux_getmaster() is generic name, it can be used to return + * an I2C Master for others I2C Master, not only TCA9548A. + * + * Input Parameters: + * devno - The device number, it is the TCA9548A I2C_Addr minus 0x70. + * channel - The TCA9548A's channel where the device will be added. + * + * Returned Value: + * Common i2c multiplexer device instance; NULL on failure. + * + ****************************************************************************/ + +struct i2c_master_s *esp32_i2cmux_getmaster(int devno, uint8_t channel); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __BOARDS_XTENSA_ESP32_COMMON_INCLUDE_ESP32_TCA9548A_H */ diff --git a/boards/xtensa/esp32/common/src/Make.defs b/boards/xtensa/esp32/common/src/Make.defs index 1feb574f665..5de05384de5 100644 --- a/boards/xtensa/esp32/common/src/Make.defs +++ b/boards/xtensa/esp32/common/src/Make.defs @@ -30,6 +30,10 @@ ifeq ($(CONFIG_I2C_DRIVER),y) CSRCS += esp32_board_i2c.c endif +ifeq ($(CONFIG_I2CMULTIPLEXER_TCA9548A),y) + CSRCS += esp32_tca9548a.c +endif + ifeq ($(CONFIG_ESP32_SPI),y) CSRCS += esp32_board_spi.c endif diff --git a/boards/xtensa/esp32/common/src/esp32_ms5611.c b/boards/xtensa/esp32/common/src/esp32_ms5611.c index e8bc3e40225..ced72963041 100644 --- a/boards/xtensa/esp32/common/src/esp32_ms5611.c +++ b/boards/xtensa/esp32/common/src/esp32_ms5611.c @@ -35,6 +35,10 @@ #include "esp32_i2c.h" #include "esp32_ms5611.h" +#ifdef CONFIG_I2CMULTIPLEXER_TCA9548A +# include "esp32_tca9548a.h" +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -57,20 +61,28 @@ int board_ms5611_initialize(int devno, int busno) { struct i2c_master_s *i2c; - char devpath[12]; int ret; sninfo("Initializing MS5611!\n"); /* Initialize MS5611 */ +#ifdef CONFIG_BOARD_HAVE_I2CMUX + /* We will use the devno as channel to avoid modifying the + * board_ms5611_initialize() function. If you connected your + * MS5611 to another channel, pass it to the devno of the + * board_ms5611_initialize() function. + */ + + i2c = esp32_i2cmux_getmaster(busno, devno); +#else i2c = esp32_i2cbus_initialize(busno); +#endif + if (i2c != NULL) { /* Then try to register the barometer sensor in I2C0 */ - snprintf(devpath, sizeof(devpath), "/dev/press%d", devno); - ret = ms5611_register(i2c, devno, MS5611_ADDR0); if (ret < 0) { diff --git a/boards/xtensa/esp32/common/src/esp32_tca9548a.c b/boards/xtensa/esp32/common/src/esp32_tca9548a.c new file mode 100644 index 00000000000..74584f1fb40 --- /dev/null +++ b/boards/xtensa/esp32/common/src/esp32_tca9548a.c @@ -0,0 +1,156 @@ +/**************************************************************************** + * boards/xtensa/esp32/common/src/esp32_tca9548a.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "esp32_board_i2c.h" +#include "esp32_i2c.h" +#include "esp32_tca9548a.h" + +struct tca9548a_dev_s *g_tca9448a_devs[8] = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_tca9548a_initialize + * + * Description: + * Initialize and register the TCA9548A Multiplexer. + * + * Input Parameters: + * devno - The device number associated to I2C address, 0=0x70 ... 7=0x77 + * busno - The I2C bus number + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int board_tca9548a_initialize(int devno, int busno) +{ + struct i2c_master_s *i2c; + uint8_t addr; + + i2cinfo("Initializing TCA9548A!\n"); + + /* TCA9548A valid addresses are 0:0x70 - 7:0x77 */ + + addr = TCA9548A_BASEADDR0 + devno; + + if (addr < TCA9548A_BASEADDR0 || addr > TCA9548A_BASEADDR7) + { + i2cerr("Invalid devno: %d! Valid range: 0 to 7!\n", devno); + return -EINVAL; + } + + /* Initialize TCA9548A */ + + i2c = esp32_i2cbus_initialize(busno); + if (i2c != NULL) + { + /* Check if this position is not used */ + + if (g_tca9448a_devs[devno] != NULL) + { + i2cerr("ERROR: This tca9548a_devs[%d] is in use!\n", devno); + return -EFAULT; + } + + /* Then try to initialize the TCA9548A */ + + g_tca9448a_devs[devno] = tca9548a_initialize(i2c, addr); + + if (g_tca9448a_devs[devno] == NULL) + { + i2cerr("ERROR: Error registering TCA9548A in I2C%d\n", busno); + return -ENODEV; + } + } + else + { + return -ENODEV; + } + + return OK; +} + +/**************************************************************************** + * Name: esp32_i2cmux_getmaster + * + * Description: + * Returns an I2C Master for TCA9548A multiplexer channel. + * + * NOTE: esp32_i2cmux_getmaster() is generic name, it can be used to return + * an I2C Master for others I2C Master, not only TCA9548A. + * + * Input Parameters: + * devno - The device number, it is the TCA9548A I2C_Addr minus 0x70. + * channel - The TCA9548A's channel where the device will be added. + * + * Returned Value: + * Common i2c multiplexer device instance; NULL on failure. + * + ****************************************************************************/ + +struct i2c_master_s *esp32_i2cmux_getmaster(int devno, uint8_t channel) +{ + int addr = devno + TCA9548A_BASEADDR0; + + /* Check if we have a valid device number */ + + if (addr < TCA9548A_BASEADDR0 || addr > TCA9548A_BASEADDR7) + { + i2cerr("Invalid devno: %d! Valid range: 0 to 7!\n", devno); + return NULL; + } + + /* Check if we have a valid channel */ + + if (channel > TCA9548A_SEL_CH7) + { + snerr("Invalid channel: %d! Valid range: 0 to 7!\n", channel); + return NULL; + } + + return tca9548a_lower_half(g_tca9448a_devs[devno], channel); +} diff --git a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c index ae9bd683e4f..873dfd7ab65 100644 --- a/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c +++ b/boards/xtensa/esp32/esp32-devkitc/src/esp32_bringup.c @@ -81,6 +81,10 @@ # include "esp32_board_i2c.h" #endif +#ifdef CONFIG_I2CMULTIPLEXER_TCA9548A +# include "esp32_tca9548a.h" +#endif + #ifdef CONFIG_SENSORS_BMP180 # include "esp32_bmp180.h" #endif @@ -369,6 +373,21 @@ int esp32_bringup(void) } #endif + /* Register the TCA9548A Multiplexer before others I2C drivers to allow it + * be used by other drivers. Look at esp32_ms5611.c how to use it. + */ + +#ifdef CONFIG_I2CMULTIPLEXER_TCA9548A + /* Add the TCA9548A Mux as device 0 (0x70) in I2C Bus 0 */ + + ret = board_tca9548a_initialize(0, 0); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to initialize TCA9548A driver: %d\n", ret); + return ret; + } +#endif + #ifdef CONFIG_I2C_DRIVER #ifdef CONFIG_ESP32_I2C0