| /* |
| * Copyright (c) 2024 Analog Devices Inc. |
| * Copyright (c) 2024 Baylibre SAS |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/drivers/gpio.h> |
| #include <zephyr/drivers/spi.h> |
| #include <zephyr/kernel.h> |
| #include <zephyr/sys/byteorder.h> |
| |
| #define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL |
| #include <zephyr/logging/log.h> |
| |
| LOG_MODULE_REGISTER(gpio_max22190); |
| |
| #include <zephyr/drivers/gpio/gpio_utils.h> |
| |
| #define MAX22190_ENABLE 1 |
| #define MAX22190_DISABLE 0 |
| |
| #define MAX22190_READ 0 |
| #define MAX22190_WRITE 1 |
| |
| #define MAX22190_MAX_PKT_SIZE 3 |
| #define MAX22190_CHANNELS 8 |
| #define MAX22190_FAULT2_ENABLES 5 |
| |
| #define MAX22190_WB_REG 0x0 |
| #define MAX22190_DI_REG 0x2 |
| #define MAX22190_FAULT1_REG 0x4 |
| #define MAX22190_FILTER_IN_REG(x) (0x6 + (2 * (x))) |
| #define MAX22190_CFG_REG 0x18 |
| #define MAX22190_IN_EN_REG 0x1A |
| #define MAX22190_FAULT2_REG 0x1C |
| #define MAX22190_FAULT2_EN_REG 0x1E |
| #define MAX22190_GPO_REG 0x22 |
| #define MAX22190_FAULT1_EN_REG 0x24 |
| #define MAX22190_NOP_REG 0x26 |
| |
| #define MAX22190_CH_STATE_MASK(x) BIT(x) |
| #define MAX22190_DELAY_MASK GENMASK(2, 0) |
| #define MAX22190_FBP_MASK BIT(3) |
| #define MAX22190_WBE_MASK BIT(4) |
| #define MAX22190_RW_MASK BIT(7) |
| #define MAX22190_ADDR_MASK GENMASK(6, 0) |
| #define MAX22190_ALARM_MASK GENMASK(4, 3) |
| #define MAX22190_POR_MASK BIT(6) |
| |
| #define MAX22190_FAULT_MASK(x) BIT(x) |
| #define MAX22190_FAULT2_WBE_MASK BIT(4) |
| |
| #define MAX22190_FAULT2_EN_MASK GENMASK(5, 0) |
| |
| #define MAX22190_CFG_REFDI_MASK BIT(0) |
| #define MAX22190_CFG_CLRF_MASK BIT(3) |
| #define MAX22190_CFG_24VF_MASK BIT(4) |
| |
| #define PRINT_ERR_BIT(bit1, bit2) \ |
| if (bit1 & bit2) { \ |
| LOG_ERR("[%s] %d", #bit1, bit1); \ |
| } |
| |
| #define MAX22190_CLEAN_POR(dev) \ |
| max22190_reg_update(dev, MAX22190_FAULT1_REG, MAX22190_POR_MASK, \ |
| FIELD_PREP(MAX22190_POR_MASK, 0)) |
| |
| enum max22190_variants { |
| MAX22190, |
| MAX22199, |
| }; |
| |
| enum max22190_ch_state { |
| MAX22190_CH_OFF, |
| MAX22190_CH_ON |
| }; |
| |
| enum max22190_ch_wb_state { |
| MAX22190_CH_NO_WB_BREAK, |
| MAX22190_CH_WB_COND_DET |
| }; |
| |
| enum max22190_mode { |
| MAX22190_MODE_0, |
| MAX22190_MODE_1, |
| MAX22190_MODE_2, |
| MAX22190_MODE_3, |
| }; |
| |
| union max22190_fault1 { |
| uint8_t reg_raw; |
| struct { |
| uint8_t max22190_WBG: 1; /* BIT 0 */ |
| uint8_t max22190_24VM: 1; |
| uint8_t max22190_24VL: 1; |
| uint8_t max22190_ALRMT1: 1; |
| uint8_t max22190_ALRMT2: 1; |
| uint8_t max22190_FAULT2: 1; |
| uint8_t max22190_POR: 1; |
| uint8_t max22190_CRC: 1; /* BIT 7 */ |
| } reg_bits; |
| }; |
| |
| union max22190_fault1_en { |
| uint8_t reg_raw; |
| struct { |
| uint8_t max22190_WBGE: 1; /* BIT 0 */ |
| uint8_t max22190_24VME: 1; |
| uint8_t max22190_24VLE: 1; |
| uint8_t max22190_ALRMT1E: 1; |
| uint8_t max22190_ALRMT2E: 1; |
| uint8_t max22190_FAULT2E: 1; |
| uint8_t max22190_PORE: 1; |
| uint8_t max22190_CRCE: 1; /* BIT 7 */ |
| } reg_bits; |
| }; |
| |
| union max22190_fault2 { |
| uint8_t reg_raw; |
| struct { |
| uint8_t max22190_RFWBS: 1; /* BIT 0 */ |
| uint8_t max22190_RFWBO: 1; |
| uint8_t max22190_RFDIS: 1; |
| uint8_t max22190_RFDIO: 1; |
| uint8_t max22190_OTSHDN: 1; |
| uint8_t max22190_FAULT8CK: 1; |
| uint8_t max22190_DUMMY: 2; /* BIT 7 */ |
| } reg_bits; |
| }; |
| |
| union max22190_fault2_en { |
| uint8_t reg_raw; |
| struct { |
| uint8_t max22190_RFWBSE: 1; /* BIT 0 */ |
| uint8_t max22190_RFWBOE: 1; |
| uint8_t max22190_RFDISE: 1; |
| uint8_t max22190_RFDIOE: 1; |
| uint8_t max22190_OTSHDNE: 1; |
| uint8_t max22190_FAULT8CKE: 1; |
| uint8_t max22190_DUMMY: 2; /* BIT 7 */ |
| } reg_bits; |
| }; |
| |
| union max22190_cfg { |
| uint8_t reg_raw; |
| struct { |
| uint8_t max22190_DUMMY1: 3; /* BIT 0 */ |
| uint8_t max22190_24VF: 1; |
| uint8_t max22190_CLRF: 1; |
| uint8_t max22190_DUMMY2: 2; |
| uint8_t max22190_REFDI_SH_EN: 1; /* BIT 7 */ |
| } reg_bits; |
| }; |
| |
| union max22190_filter { |
| uint8_t reg_raw; |
| struct { |
| uint8_t max22190_DELAY: 3; /* BIT 0 */ |
| uint8_t max22190_FBP: 1; |
| uint8_t max22190_WBE: 1; |
| uint8_t max22190_DUMMY: 2; /* BIT 7 */ |
| } reg_bits; |
| }; |
| |
| enum max22190_delay { |
| MAX22190_DELAY_50US, |
| MAX22190_DELAY_100US, |
| MAX22190_DELAY_400US, |
| MAX22190_DELAY_800US, |
| MAX22190_DELAY_1800US, |
| MAX22190_DELAY_3200US, |
| MAX22190_DELAY_12800US, |
| MAX22190_DELAY_20000US |
| }; |
| |
| struct max22190_config { |
| struct spi_dt_spec spi; |
| struct gpio_dt_spec fault_gpio; |
| struct gpio_dt_spec ready_gpio; |
| struct gpio_dt_spec latch_gpio; |
| union max22190_filter filter[8]; |
| bool crc_en; |
| enum max22190_mode mode; |
| uint8_t pkt_size; |
| uint8_t variant; |
| }; |
| |
| struct max22190_data { |
| struct gpio_driver_data common; |
| enum max22190_ch_state channels[MAX22190_CHANNELS]; |
| enum max22190_ch_wb_state wb[MAX22190_CHANNELS]; |
| union max22190_cfg cfg; |
| union max22190_fault1 fault1; |
| union max22190_fault1_en fault1_en; |
| union max22190_fault2 fault2; |
| union max22190_fault2_en fault2_en; |
| }; |
| |
| /* |
| * @brief Compute the CRC5 value for MAX22190 |
| * @param data - Data array to calculate CRC for. |
| * @return CRC result. |
| */ |
| static uint8_t max22190_crc(uint8_t *data) |
| { |
| int length = 19; |
| uint8_t crc_step, tmp; |
| uint8_t crc_init = 0x7; |
| uint8_t crc_poly = 0x35; |
| int i; |
| |
| /* |
| * This is the C custom implementation of CRC function for MAX22190, and |
| * can be found here: |
| * https://www.analog.com/en/design-notes/guidelines-to-implement-crc-algorithm.html |
| */ |
| uint32_t datainput = (uint32_t)((data[0] << 16) + (data[1] << 8) + data[2]); |
| |
| datainput = (datainput & 0xFFFFE0) + crc_init; |
| |
| tmp = (uint8_t)((datainput & 0xFC0000) >> 18); |
| |
| if ((tmp & 0x20) == 0x20) { |
| crc_step = (uint8_t)(tmp ^ crc_poly); |
| } else { |
| crc_step = tmp; |
| } |
| |
| for (i = 0; i < length - 1; i++) { |
| tmp = (uint8_t)(((crc_step & 0x1F) << 1) + |
| ((datainput >> (length - 2 - i)) & 0x01)); |
| |
| if ((tmp & 0x20) == 0x20) { |
| crc_step = (uint8_t)(tmp ^ crc_poly); |
| } else { |
| crc_step = tmp; |
| } |
| } |
| |
| return (uint8_t)(crc_step & 0x1F); |
| } |
| |
| /* |
| * @brief Update chan WB state in max22190_data |
| * |
| * @param dev - MAX22190 device. |
| * @param val - value to be set. |
| */ |
| static void max22190_update_wb_stat(const struct device *dev, uint8_t val) |
| { |
| struct max22190_data *data = dev->data; |
| |
| for (int ch_n = 0; ch_n < 8; ch_n++) { |
| data->wb[ch_n] = (val >> ch_n) & 0x1; |
| } |
| } |
| |
| /* |
| * @brief Update chan IN state in max22190_data |
| * |
| * @param dev - MAX22190 device. |
| * @param val - value to be set. |
| */ |
| static void max22190_update_in_stat(const struct device *dev, uint8_t val) |
| { |
| struct max22190_data *data = dev->data; |
| |
| for (int ch_n = 0; ch_n < 8; ch_n++) { |
| data->channels[ch_n] = (val >> ch_n) & 0x1; |
| } |
| } |
| |
| /* |
| * @brief Register write function for MAX22190 |
| * |
| * @param dev - MAX22190 device config. |
| * @param addr - Register value to which data is written. |
| * @param val - Value which is to be written to requested register. |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int max22190_reg_transceive(const struct device *dev, uint8_t addr, uint8_t val, uint8_t rw) |
| { |
| uint8_t crc; |
| int ret; |
| |
| uint8_t local_rx_buff[MAX22190_MAX_PKT_SIZE] = {0}; |
| uint8_t local_tx_buff[MAX22190_MAX_PKT_SIZE] = {0}; |
| |
| const struct max22190_config *config = dev->config; |
| |
| struct spi_buf tx_buf = { |
| .buf = &local_tx_buff, |
| .len = config->pkt_size, |
| }; |
| const struct spi_buf_set tx = {.buffers = &tx_buf, .count = 1}; |
| |
| struct spi_buf rx_buf = { |
| .buf = &local_rx_buff, |
| .len = config->pkt_size, |
| }; |
| const struct spi_buf_set rx = {.buffers = &rx_buf, .count = 1}; |
| |
| local_tx_buff[0] = |
| FIELD_PREP(MAX22190_ADDR_MASK, addr) | FIELD_PREP(MAX22190_RW_MASK, rw & 0x1); |
| local_tx_buff[1] = val; |
| |
| /* If CRC enabled calculate it */ |
| if (config->crc_en) { |
| local_tx_buff[2] = max22190_crc(&local_tx_buff[0]); |
| } |
| |
| /* write cmd & read resp at once */ |
| ret = spi_transceive_dt(&config->spi, &tx, &rx); |
| |
| if (ret) { |
| LOG_ERR("Err spi_transcieve_dt [%d]\n", ret); |
| return ret; |
| } |
| |
| /* if CRC enabled check readed */ |
| if (config->crc_en) { |
| crc = max22190_crc(&local_rx_buff[0]); |
| if (crc != (local_rx_buff[2] & 0x1F)) { |
| LOG_ERR("READ CRC ERR (%d)-(%d)\n", crc, (local_rx_buff[2] & 0x1F)); |
| return -EINVAL; |
| } |
| } |
| |
| /* always (R/W) get DI reg in first byte */ |
| max22190_update_in_stat(dev, local_rx_buff[0]); |
| |
| /* in case of writing register we get as second byte WB reg */ |
| if (rw == MAX22190_WRITE) { |
| max22190_update_wb_stat(dev, local_rx_buff[1]); |
| } else { |
| /* in case of READ second byte is value we are looking for */ |
| ret = local_rx_buff[1]; |
| } |
| |
| return ret; |
| } |
| |
| #define max22190_reg_read(dev, addr) max22190_reg_transceive(dev, addr, 0, MAX22190_READ) |
| #define max22190_reg_write(dev, addr, val) max22190_reg_transceive(dev, addr, val, MAX22190_WRITE) |
| |
| /* |
| * @brief Register update function for MAX22190 |
| * |
| * @param dev - MAX22190 device. |
| * @param addr - Register valueto wich data is updated. |
| * @param mask - Corresponding mask to the data that will be updated. |
| * @param val - Updated value to be written in the register at update. |
| * @return 0 in case of success, negative error code otherwise. |
| */ |
| static int max22190_reg_update(const struct device *dev, uint8_t addr, uint8_t mask, uint8_t val) |
| { |
| int ret; |
| uint32_t reg_val = 0; |
| |
| ret = max22190_reg_read(dev, addr); |
| |
| reg_val = ret; |
| reg_val &= ~mask; |
| reg_val |= mask & val; |
| |
| return max22190_reg_write(dev, addr, reg_val); |
| } |
| |
| /* |
| * @brief Check FAULT1 and FAULT2 |
| * |
| * @param dev - MAX22190 device |
| */ |
| static void max22190_fault_check(const struct device *dev) |
| { |
| struct max22190_data *data = dev->data; |
| const struct max22190_config *config = dev->config; |
| |
| /* FAULT1 */ |
| data->fault1.reg_raw = max22190_reg_read(dev, MAX22190_FAULT1_REG); |
| |
| if (data->fault1.reg_raw) { |
| /* FAULT1_EN */ |
| data->fault1_en.reg_raw = max22190_reg_read(dev, MAX22190_FAULT1_EN_REG); |
| |
| PRINT_ERR_BIT(data->fault1.reg_bits.max22190_CRC, |
| data->fault1_en.reg_bits.max22190_CRCE); |
| PRINT_ERR_BIT(data->fault1.reg_bits.max22190_POR, |
| data->fault1_en.reg_bits.max22190_PORE); |
| PRINT_ERR_BIT(data->fault1.reg_bits.max22190_FAULT2, |
| data->fault1_en.reg_bits.max22190_FAULT2E); |
| PRINT_ERR_BIT(data->fault1.reg_bits.max22190_24VL, |
| data->fault1_en.reg_bits.max22190_24VLE); |
| PRINT_ERR_BIT(data->fault1.reg_bits.max22190_24VM, |
| data->fault1_en.reg_bits.max22190_24VME); |
| if (config->variant == MAX22190) { |
| PRINT_ERR_BIT(data->fault1.reg_bits.max22190_ALRMT2, |
| data->fault1_en.reg_bits.max22190_ALRMT2E); |
| PRINT_ERR_BIT(data->fault1.reg_bits.max22190_ALRMT1, |
| data->fault1_en.reg_bits.max22190_ALRMT1E); |
| PRINT_ERR_BIT(data->fault1.reg_bits.max22190_WBG, |
| data->fault1_en.reg_bits.max22190_WBGE); |
| if (data->fault1.reg_bits.max22190_WBG & |
| data->fault1_en.reg_bits.max22190_WBGE) { |
| uint8_t wb_val = max22190_reg_read(dev, MAX22190_WB_REG); |
| |
| max22190_update_wb_stat(dev, (uint8_t)wb_val); |
| } |
| } |
| if (data->fault1.reg_bits.max22190_FAULT2) { |
| /* FAULT2 */ |
| data->fault2.reg_raw = max22190_reg_read(dev, MAX22190_FAULT2_REG); |
| |
| /* FAULT2_EN */ |
| data->fault2_en.reg_raw = max22190_reg_read(dev, MAX22190_FAULT2_EN_REG); |
| |
| PRINT_ERR_BIT(data->fault2.reg_bits.max22190_OTSHDN, |
| data->fault2_en.reg_bits.max22190_OTSHDNE); |
| PRINT_ERR_BIT(data->fault2.reg_bits.max22190_FAULT8CK, |
| data->fault2_en.reg_bits.max22190_FAULT8CKE); |
| if (config->variant == MAX22190) { |
| PRINT_ERR_BIT(data->fault2.reg_bits.max22190_RFWBS, |
| data->fault2_en.reg_bits.max22190_RFWBSE); |
| PRINT_ERR_BIT(data->fault2.reg_bits.max22190_RFWBO, |
| data->fault2_en.reg_bits.max22190_RFWBOE); |
| PRINT_ERR_BIT(data->fault2.reg_bits.max22190_RFDIS, |
| data->fault2_en.reg_bits.max22190_RFDISE); |
| PRINT_ERR_BIT(data->fault2.reg_bits.max22190_RFDIO, |
| data->fault2_en.reg_bits.max22190_RFDIOE); |
| } |
| } |
| } |
| } |
| |
| static void max22190_state_get(const struct device *dev) |
| { |
| const struct max22190_config *config = dev->config; |
| |
| if (gpio_pin_get_dt(&config->fault_gpio)) { |
| max22190_fault_check(dev); |
| } |
| |
| /* We are reading WB reg because on first byte will be clocked out DI reg |
| * on second byte we will ge WB value. |
| */ |
| uint8_t wb_val = max22190_reg_read(dev, MAX22190_WB_REG); |
| |
| max22190_update_wb_stat(dev, (uint8_t)wb_val); |
| } |
| |
| static int gpio_max22190_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) |
| { |
| int err = 0; |
| |
| if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == GPIO_DISCONNECTED) { |
| return -ENOTSUP; |
| } |
| |
| if ((flags & GPIO_SINGLE_ENDED) != 0) { |
| return -ENOTSUP; |
| } |
| |
| if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0) { |
| return -ENOTSUP; |
| } |
| |
| if (flags & GPIO_INT_ENABLE) { |
| return -ENOTSUP; |
| } |
| |
| switch (flags & GPIO_DIR_MASK) { |
| case GPIO_INPUT: |
| LOG_INF("Nothing to do, only INPUT supported"); |
| break; |
| default: |
| LOG_ERR("On MAX22190 only input option is available!"); |
| return -ENOTSUP; |
| } |
| |
| return err; |
| } |
| |
| static void max22190_filter_set(const struct device *dev) |
| { |
| const struct max22190_config *config = dev->config; |
| |
| for (int ch_n = 0; ch_n < 8; ch_n++) { |
| max22190_reg_write(dev, MAX22190_FILTER_IN_REG(ch_n), config->filter[ch_n].reg_raw); |
| } |
| } |
| |
| static int max22190_fault_set(const struct device *dev) |
| { |
| const struct max22190_data *data = dev->data; |
| int ret = 0; |
| |
| ret = max22190_reg_write(dev, MAX22190_FAULT1_EN_REG, data->fault1_en.reg_raw); |
| if (ret) { |
| goto exit_fault_set; |
| } |
| |
| ret = max22190_reg_write(dev, MAX22190_FAULT1_REG, data->fault1.reg_raw); |
| if (ret) { |
| goto exit_fault_set; |
| } |
| |
| ret = max22190_reg_write(dev, MAX22190_FAULT2_EN_REG, data->fault2_en.reg_raw); |
| if (ret) { |
| goto exit_fault_set; |
| } |
| |
| ret = max22190_reg_write(dev, MAX22190_FAULT2_REG, data->fault2.reg_raw); |
| if (ret) { |
| goto exit_fault_set; |
| } |
| |
| return ret; |
| |
| exit_fault_set: |
| LOG_ERR("Err spi_transcieve_dt [%d]\n", ret); |
| |
| return ret; |
| } |
| |
| static int gpio_max22190_port_get_raw(const struct device *dev, gpio_port_value_t *value) |
| { |
| const struct max22190_data *data = dev->data; |
| |
| max22190_state_get(dev); |
| *value = 0; |
| for (int ch_n = 0; ch_n < 8; ch_n++) { |
| /* IN ch state */ |
| *value |= data->channels[ch_n] << ch_n; |
| } |
| |
| return 0; |
| } |
| |
| static int gpio_max22190_init(const struct device *dev) |
| { |
| const struct max22190_config *config = dev->config; |
| struct max22190_data *data = dev->data; |
| |
| LOG_DBG("GPIO MAX22190 init IN\n"); |
| |
| int err = 0; |
| |
| if (!spi_is_ready_dt(&config->spi)) { |
| LOG_ERR("SPI bus is not ready\n"); |
| return -ENODEV; |
| } |
| |
| /* setup READY gpio - normal low */ |
| if (!gpio_is_ready_dt(&config->ready_gpio)) { |
| LOG_ERR("READY GPIO device not ready"); |
| return -ENODEV; |
| } |
| |
| err = gpio_pin_configure_dt(&config->ready_gpio, GPIO_INPUT); |
| if (err < 0) { |
| LOG_ERR("Failed to configure reset GPIO"); |
| return err; |
| } |
| |
| /* setup FAULT gpio - normal high */ |
| if (!gpio_is_ready_dt(&config->fault_gpio)) { |
| LOG_ERR("FAULT GPIO device not ready"); |
| return -ENODEV; |
| } |
| |
| err = gpio_pin_configure_dt(&config->fault_gpio, GPIO_INPUT | GPIO_PULL_UP); |
| if (err < 0) { |
| LOG_ERR("Failed to configure DC GPIO"); |
| return err; |
| } |
| |
| /* setup LATCH gpio - normal high */ |
| if (!gpio_is_ready_dt(&config->latch_gpio)) { |
| LOG_ERR("LATCH GPIO device not ready"); |
| return -ENODEV; |
| } |
| |
| err = gpio_pin_configure_dt(&config->latch_gpio, GPIO_OUTPUT_INACTIVE); |
| if (err < 0) { |
| LOG_ERR("Failed to configure busy GPIO"); |
| return err; |
| } |
| |
| for (int i = 0; i < 8; i++) { |
| if (config->variant == MAX22190) { |
| LOG_DBG("IN%d WBE [%d] FBP[%d] DELAY[%d]\n", i, |
| config->filter[i].reg_bits.max22190_WBE, |
| config->filter[i].reg_bits.max22190_FBP, |
| config->filter[i].reg_bits.max22190_DELAY); |
| } else { |
| LOG_DBG("IN%d FBP[%d] DELAY[%d]\n", i, |
| config->filter[i].reg_bits.max22190_FBP, |
| config->filter[i].reg_bits.max22190_DELAY); |
| } |
| } |
| |
| LOG_DBG(" > MAX22190 MODE: %x", config->mode); |
| LOG_DBG(" > MAX22190 PKT SIZE: %dbits (%dbytes)", config->pkt_size * 8, config->pkt_size); |
| LOG_DBG(" > MAX22190 CRC: %s", config->crc_en ? "enable" : "disable"); |
| |
| if (config->variant == MAX22190) { |
| data->fault1_en.reg_bits.max22190_WBGE = 1; |
| } |
| data->fault1_en.reg_bits.max22190_PORE = 1; |
| |
| /* Set all FAULT and FAULT_EN regs */ |
| max22190_fault_set(dev); |
| |
| /* Set channels filters */ |
| max22190_filter_set(dev); |
| |
| /* POR bit need to be cleared after start */ |
| MAX22190_CLEAN_POR(dev); |
| |
| LOG_DBG("GPIO MAX22190 init OUT\n"); |
| return 0; |
| } |
| |
| static DEVICE_API(gpio, gpio_max22190_api) = { |
| .pin_configure = gpio_max22190_config, |
| .port_get_raw = gpio_max22190_port_get_raw, |
| }; |
| |
| /* Assign appropriate value for FILTER delay*/ |
| #define MAX22190_FILTER_SET_DELAY(delay) \ |
| delay == 20000 ? MAX22190_DELAY_20000US \ |
| : delay == 12800 ? MAX22190_DELAY_12800US \ |
| : delay == 3200 ? MAX22190_DELAY_3200US \ |
| : delay == 1600 ? MAX22190_DELAY_1800US \ |
| : delay == 800 ? MAX22190_DELAY_800US \ |
| : delay == 400 ? MAX22190_DELAY_400US \ |
| : delay == 100 ? MAX22190_DELAY_100US \ |
| : delay == 50 ? MAX22190_DELAY_50US \ |
| : MAX22190_DELAY_20000US |
| |
| /* Assigning proper variant for differentiating register map */ |
| #define MAX22190_CONFIG_SET_VARIANT(model) \ |
| model == 22190 ? MAX22190 /* MAX22190 */ \ |
| : model == 22199 ? MAX22199 /* MAX22199 */ \ |
| : MAX22190 /* Default fallback */ |
| |
| /* Set FILTERx reg */ |
| #define MAX22190_FILTER_BY_IDX(id, model, idx) \ |
| { \ |
| .reg_bits.max22190_DELAY = \ |
| MAX22190_FILTER_SET_DELAY(DT_INST_PROP_BY_IDX(id, filter_delays, idx)), \ |
| .reg_bits.max22190_FBP = DT_INST_PROP_BY_IDX(id, filter_fbps, idx), \ |
| .reg_bits.max22190_WBE = \ |
| (model == 22190) ? DT_INST_PROP_BY_IDX(id, filter_wbes, idx) : 0, \ |
| } |
| |
| #define GPIO_MAX22190_DEVICE(id, model) \ |
| static const struct max22190_config max##model##_##id##_cfg = { \ |
| .spi = SPI_DT_SPEC_INST_GET(id, SPI_OP_MODE_MASTER | SPI_WORD_SET(8U), 0U), \ |
| .ready_gpio = GPIO_DT_SPEC_INST_GET(id, drdy_gpios), \ |
| .fault_gpio = GPIO_DT_SPEC_INST_GET(id, fault_gpios), \ |
| .latch_gpio = GPIO_DT_SPEC_INST_GET(id, latch_gpios), \ |
| .mode = DT_INST_PROP(id, max22190_mode), \ |
| .crc_en = !(DT_INST_PROP(id, max22190_mode) & 0x1), \ |
| .pkt_size = !(DT_INST_PROP(id, max22190_mode) & 0x1) ? 3 : 2, \ |
| .variant = MAX22190_CONFIG_SET_VARIANT(model), \ |
| .filter = \ |
| { \ |
| MAX22190_FILTER_BY_IDX(id, model, 0), \ |
| MAX22190_FILTER_BY_IDX(id, model, 1), \ |
| MAX22190_FILTER_BY_IDX(id, model, 2), \ |
| MAX22190_FILTER_BY_IDX(id, model, 3), \ |
| MAX22190_FILTER_BY_IDX(id, model, 4), \ |
| MAX22190_FILTER_BY_IDX(id, model, 5), \ |
| MAX22190_FILTER_BY_IDX(id, model, 6), \ |
| MAX22190_FILTER_BY_IDX(id, model, 7), \ |
| }, \ |
| }; \ |
| \ |
| static struct max22190_data max##model##_##id##_data; \ |
| \ |
| DEVICE_DT_INST_DEFINE(id, &gpio_max22190_init, NULL, &max##model##_##id##_data, \ |
| &max##model##_##id##_cfg, POST_KERNEL, \ |
| CONFIG_GPIO_MAX22190_INIT_PRIORITY, &gpio_max22190_api); |
| |
| #undef DT_DRV_COMPAT |
| #define DT_DRV_COMPAT adi_max22190_gpio |
| DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MAX22190_DEVICE, 22190) |
| |
| #undef DT_DRV_COMPAT |
| #define DT_DRV_COMPAT adi_max22199_gpio |
| DT_INST_FOREACH_STATUS_OKAY_VARGS(GPIO_MAX22190_DEVICE, 22199) |
| |
| #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0 |
| #warning "GPIO MAX22190 driver enabled without any devices" |
| #endif |