From 330d9949ce436e2cd0761991b1405414096a11bb Mon Sep 17 00:00:00 2001 From: Chekhov Ma Date: Wed, 11 Sep 2024 17:56:01 +0800 Subject: [PATCH] drivers: gpio: retire pca953x driver pca953x driver can be replaced by pca_series driver, which covers a larger number of devices. Signed-off-by: Chekhov Ma --- .../bl5340_dvk_nrf5340_cpuapp_common.dtsi | 2 +- boards/ezurio/bt610/Kconfig.defconfig | 2 +- drivers/gpio/Kconfig | 1 - drivers/gpio/Kconfig.pca953x | 23 - drivers/gpio/gpio_pca953x.c | 508 ------------------ dts/bindings/gpio/ti,tca9538.yaml | 43 -- 6 files changed, 2 insertions(+), 577 deletions(-) delete mode 100644 drivers/gpio/Kconfig.pca953x delete mode 100644 drivers/gpio/gpio_pca953x.c delete mode 100644 dts/bindings/gpio/ti,tca9538.yaml diff --git a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi index af4f1cddeae5a53..4747a247a3f89cd 100644 --- a/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi @@ -201,7 +201,7 @@ }; gpio_exp0: tca9538@70 { - compatible = "ti,tca9538"; + compatible = "nxp,pca9538"; reg = <0x70>; gpio-controller; #gpio-cells = <2>; diff --git a/boards/ezurio/bt610/Kconfig.defconfig b/boards/ezurio/bt610/Kconfig.defconfig index 9a82770655ef076..eecd3f2b0c0d0e9 100644 --- a/boards/ezurio/bt610/Kconfig.defconfig +++ b/boards/ezurio/bt610/Kconfig.defconfig @@ -9,6 +9,6 @@ config BT_CTLR default BT config I2C - default $(dt_compat_on_bus,$(DT_COMPAT_TI_TCA9538),i2c) + default $(dt_compat_on_bus,$(DT_COMPAT_NXP_PCA9538),i2c) endif # BOARD_BT610 diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 90cad25cebe96a3..771e25f59c7767a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -148,7 +148,6 @@ source "drivers/gpio/Kconfig.nrfx" source "drivers/gpio/Kconfig.numaker" source "drivers/gpio/Kconfig.numicro" source "drivers/gpio/Kconfig.nxp_s32" -source "drivers/gpio/Kconfig.pca953x" source "drivers/gpio/Kconfig.pca95xx" source "drivers/gpio/Kconfig.pca_series" source "drivers/gpio/Kconfig.pcal64xxa" diff --git a/drivers/gpio/Kconfig.pca953x b/drivers/gpio/Kconfig.pca953x deleted file mode 100644 index 0bcb54cb8e5ac63..000000000000000 --- a/drivers/gpio/Kconfig.pca953x +++ /dev/null @@ -1,23 +0,0 @@ -# PCA953X GPIO configuration options - -# Copyright (c) 2018 Aapo Vienamo -# Copyright (c) 2021 Laird Connectivity -# SPDX-License-Identifier: Apache-2.0 - -menuconfig GPIO_PCA953X - bool "PCA953X I2C GPIO chip" - default y - depends on DT_HAS_TI_TCA9538_ENABLED - select I2C - help - Enable driver for PCA953X I2C GPIO chip. - -if GPIO_PCA953X - -config GPIO_PCA953X_INIT_PRIORITY - int "Init priority" - default 70 - help - Device driver initialization priority. - -endif # GPIO_PCA953X diff --git a/drivers/gpio/gpio_pca953x.c b/drivers/gpio/gpio_pca953x.c deleted file mode 100644 index 81898e83382b408..000000000000000 --- a/drivers/gpio/gpio_pca953x.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright (c) 2018 Peter Bigot Consulting, LLC - * Copyright (c) 2018 Aapo Vienamo - * Copyright (c) 2019 Nordic Semiconductor ASA - * Copyright (c) 2019 Vestas Wind Systems A/S - * Copyright (c) 2020 ZedBlox Ltd. - * Copyright (c) 2021 Laird Connectivity - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -LOG_MODULE_REGISTER(pca953x, CONFIG_GPIO_LOG_LEVEL); - -#include - -/* PCA953X Register addresses */ -#define PCA953X_INPUT_PORT 0x00 -#define PCA953X_OUTPUT_PORT 0x01 -#define PCA953X_CONFIGURATION 0x03 -#define REG_INPUT_LATCH_PORT0 0x42 -#define REG_INT_MASK_PORT0 0x45 - -/* Number of pins supported by the device */ -#define NUM_PINS 8 - -/* Max to select all pins supported on the device. */ -#define ALL_PINS ((uint8_t)BIT_MASK(NUM_PINS)) - -/** Cache of the output configuration and data of the pins. */ -struct pca953x_pin_state { - uint8_t dir; - uint8_t input; - uint8_t output; -}; - -struct pca953x_irq_state { - uint8_t rising; - uint8_t falling; -}; - -/** Runtime driver data */ -struct pca953x_drv_data { - /* gpio_driver_data needs to be first */ - struct gpio_driver_data common; - struct pca953x_pin_state pin_state; - struct k_sem lock; - struct gpio_callback gpio_cb; - struct k_work work; - struct pca953x_irq_state irq_state; - const struct device *dev; - /* user ISR cb */ - sys_slist_t cb; -}; - -/** Configuration data */ -struct pca953x_config { - /* gpio_driver_config needs to be first */ - struct gpio_driver_config common; - struct i2c_dt_spec i2c; - const struct gpio_dt_spec gpio_int; - bool interrupt_enabled; - int interrupt_mask; - int input_latch; -}; - -/** - * @brief Gets the state of input pins of the PCA953X I/O Port and - * stores in driver data struct. - * - * @param dev Pointer to the device structure for the driver instance. - * - * @retval 0 If successful. - * @retval Negative value for error code. - */ -static int update_input(const struct device *dev) -{ - const struct pca953x_config *cfg = dev->config; - struct pca953x_drv_data *drv_data = dev->data; - uint8_t input_states; - int rc = 0; - - rc = i2c_reg_read_byte_dt(&cfg->i2c, PCA953X_INPUT_PORT, &input_states); - - if (rc == 0) { - drv_data->pin_state.input = input_states; - } - return rc; -} - -/** - * @brief Handles interrupt triggered by the interrupt pin of PCA953X I/O Port. - * - * If nint_gpios is configured in device tree then this will be triggered each - * time a gpio configured as an input changes state. The gpio input states are - * read in this function which clears the interrupt. - * - * @param dev Pointer to the device structure for the driver instance. - */ -static void gpio_pca953x_handle_interrupt(const struct device *dev) -{ - struct pca953x_drv_data *drv_data = dev->data; - struct pca953x_irq_state *irq_state = &drv_data->irq_state; - int rc; - uint8_t previous_state; - uint8_t current_state; - uint8_t transitioned_pins; - uint8_t interrupt_status = 0; - - k_sem_take(&drv_data->lock, K_FOREVER); - - /* Any interrupts enabled? */ - if (!irq_state->rising && !irq_state->falling) { - rc = -EINVAL; - goto out; - } - - /* Store previous input state then read new value */ - previous_state = drv_data->pin_state.input; - rc = update_input(dev); - if (rc != 0) { - goto out; - } - - /* Find out which input pins have changed state */ - current_state = drv_data->pin_state.input; - transitioned_pins = previous_state ^ current_state; - - /* Mask gpio transactions with rising/falling edge interrupt config */ - interrupt_status = (irq_state->rising & transitioned_pins & - current_state); - interrupt_status |= (irq_state->falling & transitioned_pins & - previous_state); - -out: - k_sem_give(&drv_data->lock); - - if ((rc == 0) && (interrupt_status)) { - gpio_fire_callbacks(&drv_data->cb, dev, interrupt_status); - } -} - -/** - * @brief Work handler for PCA953X interrupt - * - * @param work Work struct that contains pointer to interrupt handler function - */ -static void gpio_pca953x_work_handler(struct k_work *work) -{ - struct pca953x_drv_data *drv_data = - CONTAINER_OF(work, struct pca953x_drv_data, work); - - gpio_pca953x_handle_interrupt(drv_data->dev); -} - -/** - * @brief ISR for interrupt pin of PCA953X - * - * @param dev Pointer to the device structure for the driver instance. - * @param gpio_cb Pointer to callback function struct - * @param pins Bitmask of pins that triggered interrupt - */ -static void gpio_pca953x_init_cb(const struct device *dev, - struct gpio_callback *gpio_cb, uint32_t pins) -{ - struct pca953x_drv_data *drv_data = - CONTAINER_OF(gpio_cb, struct pca953x_drv_data, gpio_cb); - - ARG_UNUSED(pins); - - k_work_submit(&drv_data->work); -} - -static int gpio_pca953x_config(const struct device *dev, gpio_pin_t pin, - gpio_flags_t flags) -{ - const struct pca953x_config *cfg = dev->config; - struct pca953x_drv_data *drv_data = dev->data; - struct pca953x_pin_state *pins = &drv_data->pin_state; - int rc = 0; - bool data_first = false; - - /* Can't do I2C bus operations from an ISR */ - if (k_is_in_isr()) { - return -EWOULDBLOCK; - } - - /* Single Ended lines (Open drain and open source) not supported */ - if ((flags & GPIO_SINGLE_ENDED) != 0) { - return -ENOTSUP; - } - - /* The PCA953X has no internal pull up support */ - if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) { - return -ENOTSUP; - } - - /* Simultaneous input & output mode not supported */ - if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) { - return -ENOTSUP; - } - - k_sem_take(&drv_data->lock, K_FOREVER); - - /* Ensure either Output or Input is specified */ - if ((flags & GPIO_OUTPUT) != 0) { - pins->dir &= ~BIT(pin); - if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) { - pins->output &= ~BIT(pin); - data_first = true; - } else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) { - pins->output |= BIT(pin); - data_first = true; - } - } else if ((flags & GPIO_INPUT) != 0) { - pins->dir |= BIT(pin); - } else { - rc = -ENOTSUP; - goto out; - } - - /* Set output values */ - if (data_first) { - rc = i2c_reg_write_byte_dt(&cfg->i2c, PCA953X_OUTPUT_PORT, pins->output); - } - - if (rc == 0) { - /* Set pin directions */ - rc = i2c_reg_write_byte_dt(&cfg->i2c, PCA953X_CONFIGURATION, pins->dir); - } - - if (rc == 0) { - /* Refresh input status */ - rc = update_input(dev); - } - -out: - k_sem_give(&drv_data->lock); - return rc; -} - -static int gpio_pca953x_port_read(const struct device *dev, - gpio_port_value_t *value) -{ - const struct pca953x_config *cfg = dev->config; - struct pca953x_drv_data *drv_data = dev->data; - uint8_t input_pin_data; - int rc = 0; - - /* Can't do I2C bus operations from an ISR */ - if (k_is_in_isr()) { - return -EWOULDBLOCK; - } - - k_sem_take(&drv_data->lock, K_FOREVER); - - /* Read Input Register */ - rc = i2c_reg_read_byte_dt(&cfg->i2c, PCA953X_INPUT_PORT, &input_pin_data); - - LOG_DBG("read %x got %d", input_pin_data, rc); - - if (rc == 0) { - drv_data->pin_state.input = input_pin_data; - *value = (gpio_port_value_t)(drv_data->pin_state.input); - } - - k_sem_give(&drv_data->lock); - return rc; -} - -static int gpio_pca953x_port_write(const struct device *dev, - gpio_port_pins_t mask, - gpio_port_value_t value, - gpio_port_value_t toggle) -{ - const struct pca953x_config *cfg = dev->config; - struct pca953x_drv_data *drv_data = dev->data; - uint8_t *outp = &drv_data->pin_state.output; - int rc; - uint8_t orig_out; - uint8_t out; - - /* Can't do I2C bus operations from an ISR */ - if (k_is_in_isr()) { - return -EWOULDBLOCK; - } - - k_sem_take(&drv_data->lock, K_FOREVER); - - orig_out = *outp; - out = ((orig_out & ~mask) | (value & mask)) ^ toggle; - - rc = i2c_reg_write_byte_dt(&cfg->i2c, PCA953X_OUTPUT_PORT, out); - - if (rc == 0) { - *outp = out; - } - - k_sem_give(&drv_data->lock); - - LOG_DBG("write %x msk %08x val %08x => %x: %d", orig_out, mask, - value, out, rc); - - return rc; -} - -static int gpio_pca953x_port_set_masked(const struct device *dev, - gpio_port_pins_t mask, - gpio_port_value_t value) -{ - return gpio_pca953x_port_write(dev, mask, value, 0); -} - -static int gpio_pca953x_port_set_bits(const struct device *dev, - gpio_port_pins_t pins) -{ - return gpio_pca953x_port_write(dev, pins, pins, 0); -} - -static int gpio_pca953x_port_clear_bits(const struct device *dev, - gpio_port_pins_t pins) -{ - return gpio_pca953x_port_write(dev, pins, 0, 0); -} - -static int gpio_pca953x_port_toggle_bits(const struct device *dev, - gpio_port_pins_t pins) -{ - return gpio_pca953x_port_write(dev, 0, 0, pins); -} - -static int gpio_pca953x_pin_interrupt_configure(const struct device *dev, - gpio_pin_t pin, - enum gpio_int_mode mode, - enum gpio_int_trig trig) -{ - const struct pca953x_config *cfg = dev->config; - struct pca953x_drv_data *drv_data = dev->data; - struct pca953x_irq_state *irq = &drv_data->irq_state; - - if (!cfg->interrupt_enabled) { - return -ENOTSUP; - } - /* Device does not support level-triggered interrupts. */ - if (mode == GPIO_INT_MODE_LEVEL) { - return -ENOTSUP; - } - - k_sem_take(&drv_data->lock, K_FOREVER); - - if (mode == GPIO_INT_MODE_DISABLED) { - irq->falling &= ~BIT(pin); - irq->rising &= ~BIT(pin); - } else { /* GPIO_INT_MODE_EDGE */ - if (trig == GPIO_INT_TRIG_BOTH) { - irq->falling |= BIT(pin); - irq->rising |= BIT(pin); - } else if (trig == GPIO_INT_TRIG_LOW) { - irq->falling |= BIT(pin); - irq->rising &= ~BIT(pin); - } else if (trig == GPIO_INT_TRIG_HIGH) { - irq->falling &= ~BIT(pin); - irq->rising |= BIT(pin); - } - } - - k_sem_give(&drv_data->lock); - - return 0; -} - -static int gpio_pca953x_manage_callback(const struct device *dev, - struct gpio_callback *callback, - bool set) -{ - struct pca953x_drv_data *data = dev->data; - - return gpio_manage_callback(&data->cb, callback, set); -} - -/** - * @brief Initialization function of PCA953X - * - * This sets initial input/ output configuration and output states. - * The interrupt is configured if this is enabled. - * - * @param dev Device struct - * @return 0 if successful, failed otherwise. - */ -static int gpio_pca953x_init(const struct device *dev) -{ - const struct pca953x_config *cfg = dev->config; - struct pca953x_drv_data *drv_data = dev->data; - int rc = 0; - - if (!device_is_ready(cfg->i2c.bus)) { - LOG_ERR("I2C bus device not found"); - goto out; - } - - /* Do an initial read, this clears the interrupt pin and sets - * up the initial value of the pin state input data. - */ - rc = update_input(dev); - if (rc) { - goto out; - } - - if (cfg->interrupt_enabled) { - if (!gpio_is_ready_dt(&cfg->gpio_int)) { - LOG_ERR("Cannot get pointer to gpio interrupt device"); - rc = -EINVAL; - goto out; - } - - drv_data->dev = dev; - - k_work_init(&drv_data->work, gpio_pca953x_work_handler); - - rc = gpio_pin_configure_dt(&cfg->gpio_int, GPIO_INPUT); - if (rc) { - goto out; - } - - rc = gpio_pin_interrupt_configure_dt(&cfg->gpio_int, - GPIO_INT_EDGE_TO_ACTIVE); - if (rc) { - goto out; - } - - gpio_init_callback(&drv_data->gpio_cb, - gpio_pca953x_init_cb, - BIT(cfg->gpio_int.pin)); - - rc = gpio_add_callback(cfg->gpio_int.port, - &drv_data->gpio_cb); - - if (rc) { - goto out; - } - - /* This may not present on all variants of device */ - if (cfg->input_latch > -1) { - rc = i2c_reg_write_byte_dt(&cfg->i2c, REG_INPUT_LATCH_PORT0, - cfg->input_latch); - } - if (cfg->interrupt_mask > -1) { - rc = i2c_reg_write_byte_dt(&cfg->i2c, REG_INT_MASK_PORT0, - cfg->interrupt_mask); - } - } -out: - if (rc) { - LOG_ERR("%s init failed: %d", dev->name, rc); - } else { - LOG_INF("%s init ok", dev->name); - } - return rc; -} - -static const struct gpio_driver_api api_table = { - .pin_configure = gpio_pca953x_config, - .port_get_raw = gpio_pca953x_port_read, - .port_set_masked_raw = gpio_pca953x_port_set_masked, - .port_set_bits_raw = gpio_pca953x_port_set_bits, - .port_clear_bits_raw = gpio_pca953x_port_clear_bits, - .port_toggle_bits = gpio_pca953x_port_toggle_bits, - .pin_interrupt_configure = gpio_pca953x_pin_interrupt_configure, - .manage_callback = gpio_pca953x_manage_callback, -}; - -#define GPIO_PCA953X_INIT(n) \ - static const struct pca953x_config pca953x_cfg_##n = { \ - .i2c = I2C_DT_SPEC_INST_GET(n), \ - .common = { \ - .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ - }, \ - .interrupt_enabled = DT_INST_NODE_HAS_PROP(n, nint_gpios), \ - .gpio_int = GPIO_DT_SPEC_INST_GET_OR(n, nint_gpios, {0}), \ - .interrupt_mask = DT_INST_PROP_OR(n, interrupt_mask, -1), \ - .input_latch = DT_INST_PROP_OR(n, input_latch, -1), \ - }; \ - \ - static struct pca953x_drv_data pca953x_drvdata_##n = { \ - .lock = Z_SEM_INITIALIZER(pca953x_drvdata_##n.lock, 1, 1), \ - .pin_state.dir = ALL_PINS, \ - .pin_state.output = ALL_PINS, \ - }; \ - DEVICE_DT_INST_DEFINE(n, \ - gpio_pca953x_init, \ - NULL, \ - &pca953x_drvdata_##n, \ - &pca953x_cfg_##n, \ - POST_KERNEL, \ - CONFIG_GPIO_PCA953X_INIT_PRIORITY, \ - &api_table); - -#define DT_DRV_COMPAT ti_tca9538 -DT_INST_FOREACH_STATUS_OKAY(GPIO_PCA953X_INIT) diff --git a/dts/bindings/gpio/ti,tca9538.yaml b/dts/bindings/gpio/ti,tca9538.yaml deleted file mode 100644 index 9200a9a16061a3a..000000000000000 --- a/dts/bindings/gpio/ti,tca9538.yaml +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2018, Aapo Vienamo -# Copyright (c) 2021, Laird Connectivity -# SPDX-License-Identifier: Apache-2.0 - -description: TCA9538 GPIO node - -compatible: "ti,tca9538" - -include: [i2c-device.yaml, gpio-controller.yaml] - -properties: - "#gpio-cells": - const: 2 - - ngpios: - required: true - const: 8 - description: | - Number of GPIOs available on port expander. - - nint-gpios: - type: phandle-array - description: | - Connection for the NINT signal. This signal is active-low when - produced by tca9538 GPIO node. - - input-latch: - type: int - description: | - Input latch register bit is 0 by default and the input pin state - is not latched. When input latch register bit is 1 and the input - pin state is latched. - - interrupt-mask: - type: int - description: | - Interrupt mask register is set to logic 1 by default without - enabling interrupts. Setting corresponding mask bits to logic - 0 to enable the interrupts. - -gpio-cells: - - pin - - flags