18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * gpio-max3191x.c - GPIO driver for Maxim MAX3191x industrial serializer 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2017 KUNBUS GmbH 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * The MAX3191x makes 8 digital 24V inputs available via SPI. 88c2ecf20Sopenharmony_ci * Multiple chips can be daisy-chained, the spec does not impose 98c2ecf20Sopenharmony_ci * a limit on the number of chips and neither does this driver. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Either of two modes is selectable: In 8-bit mode, only the state 128c2ecf20Sopenharmony_ci * of the inputs is clocked out to achieve high readout speeds; 138c2ecf20Sopenharmony_ci * In 16-bit mode, an additional status byte is clocked out with 148c2ecf20Sopenharmony_ci * a CRC and indicator bits for undervoltage and overtemperature. 158c2ecf20Sopenharmony_ci * The driver returns an error instead of potentially bogus data 168c2ecf20Sopenharmony_ci * if any of these fault conditions occur. However it does allow 178c2ecf20Sopenharmony_ci * readout of non-faulting chips in the same daisy-chain. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * MAX3191x supports four debounce settings and the driver is 208c2ecf20Sopenharmony_ci * capable of configuring these differently for each chip in the 218c2ecf20Sopenharmony_ci * daisy-chain. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * If the chips are hardwired to 8-bit mode ("modesel" pulled high), 248c2ecf20Sopenharmony_ci * gpio-pisosr.c can be used alternatively to this driver. 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * https://datasheets.maximintegrated.com/en/ds/MAX31910.pdf 278c2ecf20Sopenharmony_ci * https://datasheets.maximintegrated.com/en/ds/MAX31911.pdf 288c2ecf20Sopenharmony_ci * https://datasheets.maximintegrated.com/en/ds/MAX31912.pdf 298c2ecf20Sopenharmony_ci * https://datasheets.maximintegrated.com/en/ds/MAX31913.pdf 308c2ecf20Sopenharmony_ci * https://datasheets.maximintegrated.com/en/ds/MAX31953-MAX31963.pdf 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include <linux/bitmap.h> 348c2ecf20Sopenharmony_ci#include <linux/bitops.h> 358c2ecf20Sopenharmony_ci#include <linux/crc8.h> 368c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h> 378c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h> 388c2ecf20Sopenharmony_ci#include <linux/module.h> 398c2ecf20Sopenharmony_ci#include <linux/spi/spi.h> 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cienum max3191x_mode { 428c2ecf20Sopenharmony_ci STATUS_BYTE_ENABLED, 438c2ecf20Sopenharmony_ci STATUS_BYTE_DISABLED, 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci/** 478c2ecf20Sopenharmony_ci * struct max3191x_chip - max3191x daisy-chain 488c2ecf20Sopenharmony_ci * @gpio: GPIO controller struct 498c2ecf20Sopenharmony_ci * @lock: protects read sequences 508c2ecf20Sopenharmony_ci * @nchips: number of chips in the daisy-chain 518c2ecf20Sopenharmony_ci * @mode: current mode, 0 for 16-bit, 1 for 8-bit; 528c2ecf20Sopenharmony_ci * for simplicity, all chips in the daisy-chain are assumed 538c2ecf20Sopenharmony_ci * to use the same mode 548c2ecf20Sopenharmony_ci * @modesel_pins: GPIO pins to configure modesel of each chip 558c2ecf20Sopenharmony_ci * @fault_pins: GPIO pins to detect fault of each chip 568c2ecf20Sopenharmony_ci * @db0_pins: GPIO pins to configure debounce of each chip 578c2ecf20Sopenharmony_ci * @db1_pins: GPIO pins to configure debounce of each chip 588c2ecf20Sopenharmony_ci * @mesg: SPI message to perform a readout 598c2ecf20Sopenharmony_ci * @xfer: SPI transfer used by @mesg 608c2ecf20Sopenharmony_ci * @crc_error: bitmap signaling CRC error for each chip 618c2ecf20Sopenharmony_ci * @overtemp: bitmap signaling overtemperature alarm for each chip 628c2ecf20Sopenharmony_ci * @undervolt1: bitmap signaling undervoltage alarm for each chip 638c2ecf20Sopenharmony_ci * @undervolt2: bitmap signaling undervoltage warning for each chip 648c2ecf20Sopenharmony_ci * @fault: bitmap signaling assertion of @fault_pins for each chip 658c2ecf20Sopenharmony_ci * @ignore_uv: whether to ignore undervoltage alarms; 668c2ecf20Sopenharmony_ci * set by a device property if the chips are powered through 678c2ecf20Sopenharmony_ci * 5VOUT instead of VCC24V, in which case they will constantly 688c2ecf20Sopenharmony_ci * signal undervoltage; 698c2ecf20Sopenharmony_ci * for simplicity, all chips in the daisy-chain are assumed 708c2ecf20Sopenharmony_ci * to be powered the same way 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_cistruct max3191x_chip { 738c2ecf20Sopenharmony_ci struct gpio_chip gpio; 748c2ecf20Sopenharmony_ci struct mutex lock; 758c2ecf20Sopenharmony_ci u32 nchips; 768c2ecf20Sopenharmony_ci enum max3191x_mode mode; 778c2ecf20Sopenharmony_ci struct gpio_descs *modesel_pins; 788c2ecf20Sopenharmony_ci struct gpio_descs *fault_pins; 798c2ecf20Sopenharmony_ci struct gpio_descs *db0_pins; 808c2ecf20Sopenharmony_ci struct gpio_descs *db1_pins; 818c2ecf20Sopenharmony_ci struct spi_message mesg; 828c2ecf20Sopenharmony_ci struct spi_transfer xfer; 838c2ecf20Sopenharmony_ci unsigned long *crc_error; 848c2ecf20Sopenharmony_ci unsigned long *overtemp; 858c2ecf20Sopenharmony_ci unsigned long *undervolt1; 868c2ecf20Sopenharmony_ci unsigned long *undervolt2; 878c2ecf20Sopenharmony_ci unsigned long *fault; 888c2ecf20Sopenharmony_ci bool ignore_uv; 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci#define MAX3191X_NGPIO 8 928c2ecf20Sopenharmony_ci#define MAX3191X_CRC8_POLYNOMIAL 0xa8 /* (x^5) + x^4 + x^2 + x^0 */ 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ciDECLARE_CRC8_TABLE(max3191x_crc8); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic int max3191x_get_direction(struct gpio_chip *gpio, unsigned int offset) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci return GPIO_LINE_DIRECTION_IN; /* always in */ 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic int max3191x_direction_input(struct gpio_chip *gpio, unsigned int offset) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci return 0; 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic int max3191x_direction_output(struct gpio_chip *gpio, 1078c2ecf20Sopenharmony_ci unsigned int offset, int value) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci return -EINVAL; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic void max3191x_set(struct gpio_chip *gpio, unsigned int offset, int value) 1138c2ecf20Sopenharmony_ci{ } 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic void max3191x_set_multiple(struct gpio_chip *gpio, unsigned long *mask, 1168c2ecf20Sopenharmony_ci unsigned long *bits) 1178c2ecf20Sopenharmony_ci{ } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic unsigned int max3191x_wordlen(struct max3191x_chip *max3191x) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci return max3191x->mode == STATUS_BYTE_ENABLED ? 2 : 1; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic int max3191x_readout_locked(struct max3191x_chip *max3191x) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci struct device *dev = max3191x->gpio.parent; 1278c2ecf20Sopenharmony_ci struct spi_device *spi = to_spi_device(dev); 1288c2ecf20Sopenharmony_ci int val, i, ot = 0, uv1 = 0; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci val = spi_sync(spi, &max3191x->mesg); 1318c2ecf20Sopenharmony_ci if (val) { 1328c2ecf20Sopenharmony_ci dev_err_ratelimited(dev, "SPI receive error %d\n", val); 1338c2ecf20Sopenharmony_ci return val; 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci for (i = 0; i < max3191x->nchips; i++) { 1378c2ecf20Sopenharmony_ci if (max3191x->mode == STATUS_BYTE_ENABLED) { 1388c2ecf20Sopenharmony_ci u8 in = ((u8 *)max3191x->xfer.rx_buf)[i * 2]; 1398c2ecf20Sopenharmony_ci u8 status = ((u8 *)max3191x->xfer.rx_buf)[i * 2 + 1]; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci val = (status & 0xf8) != crc8(max3191x_crc8, &in, 1, 0); 1428c2ecf20Sopenharmony_ci __assign_bit(i, max3191x->crc_error, val); 1438c2ecf20Sopenharmony_ci if (val) 1448c2ecf20Sopenharmony_ci dev_err_ratelimited(dev, 1458c2ecf20Sopenharmony_ci "chip %d: CRC error\n", i); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci ot = (status >> 1) & 1; 1488c2ecf20Sopenharmony_ci __assign_bit(i, max3191x->overtemp, ot); 1498c2ecf20Sopenharmony_ci if (ot) 1508c2ecf20Sopenharmony_ci dev_err_ratelimited(dev, 1518c2ecf20Sopenharmony_ci "chip %d: overtemperature\n", i); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (!max3191x->ignore_uv) { 1548c2ecf20Sopenharmony_ci uv1 = !((status >> 2) & 1); 1558c2ecf20Sopenharmony_ci __assign_bit(i, max3191x->undervolt1, uv1); 1568c2ecf20Sopenharmony_ci if (uv1) 1578c2ecf20Sopenharmony_ci dev_err_ratelimited(dev, 1588c2ecf20Sopenharmony_ci "chip %d: undervoltage\n", i); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci val = !(status & 1); 1618c2ecf20Sopenharmony_ci __assign_bit(i, max3191x->undervolt2, val); 1628c2ecf20Sopenharmony_ci if (val && !uv1) 1638c2ecf20Sopenharmony_ci dev_warn_ratelimited(dev, 1648c2ecf20Sopenharmony_ci "chip %d: voltage warn\n", i); 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci if (max3191x->fault_pins && !max3191x->ignore_uv) { 1698c2ecf20Sopenharmony_ci /* fault pin shared by all chips or per chip */ 1708c2ecf20Sopenharmony_ci struct gpio_desc *fault_pin = 1718c2ecf20Sopenharmony_ci (max3191x->fault_pins->ndescs == 1) 1728c2ecf20Sopenharmony_ci ? max3191x->fault_pins->desc[0] 1738c2ecf20Sopenharmony_ci : max3191x->fault_pins->desc[i]; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci val = gpiod_get_value_cansleep(fault_pin); 1768c2ecf20Sopenharmony_ci if (val < 0) { 1778c2ecf20Sopenharmony_ci dev_err_ratelimited(dev, 1788c2ecf20Sopenharmony_ci "GPIO read error %d\n", val); 1798c2ecf20Sopenharmony_ci return val; 1808c2ecf20Sopenharmony_ci } 1818c2ecf20Sopenharmony_ci __assign_bit(i, max3191x->fault, val); 1828c2ecf20Sopenharmony_ci if (val && !uv1 && !ot) 1838c2ecf20Sopenharmony_ci dev_err_ratelimited(dev, 1848c2ecf20Sopenharmony_ci "chip %d: fault\n", i); 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci return 0; 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_cistatic bool max3191x_chip_is_faulting(struct max3191x_chip *max3191x, 1928c2ecf20Sopenharmony_ci unsigned int chipnum) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci /* without status byte the only diagnostic is the fault pin */ 1958c2ecf20Sopenharmony_ci if (!max3191x->ignore_uv && test_bit(chipnum, max3191x->fault)) 1968c2ecf20Sopenharmony_ci return true; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci if (max3191x->mode == STATUS_BYTE_DISABLED) 1998c2ecf20Sopenharmony_ci return false; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci return test_bit(chipnum, max3191x->crc_error) || 2028c2ecf20Sopenharmony_ci test_bit(chipnum, max3191x->overtemp) || 2038c2ecf20Sopenharmony_ci (!max3191x->ignore_uv && 2048c2ecf20Sopenharmony_ci test_bit(chipnum, max3191x->undervolt1)); 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic int max3191x_get(struct gpio_chip *gpio, unsigned int offset) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci struct max3191x_chip *max3191x = gpiochip_get_data(gpio); 2108c2ecf20Sopenharmony_ci int ret, chipnum, wordlen = max3191x_wordlen(max3191x); 2118c2ecf20Sopenharmony_ci u8 in; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci mutex_lock(&max3191x->lock); 2148c2ecf20Sopenharmony_ci ret = max3191x_readout_locked(max3191x); 2158c2ecf20Sopenharmony_ci if (ret) 2168c2ecf20Sopenharmony_ci goto out_unlock; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci chipnum = offset / MAX3191X_NGPIO; 2198c2ecf20Sopenharmony_ci if (max3191x_chip_is_faulting(max3191x, chipnum)) { 2208c2ecf20Sopenharmony_ci ret = -EIO; 2218c2ecf20Sopenharmony_ci goto out_unlock; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci in = ((u8 *)max3191x->xfer.rx_buf)[chipnum * wordlen]; 2258c2ecf20Sopenharmony_ci ret = (in >> (offset % MAX3191X_NGPIO)) & 1; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ciout_unlock: 2288c2ecf20Sopenharmony_ci mutex_unlock(&max3191x->lock); 2298c2ecf20Sopenharmony_ci return ret; 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic int max3191x_get_multiple(struct gpio_chip *gpio, unsigned long *mask, 2338c2ecf20Sopenharmony_ci unsigned long *bits) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci struct max3191x_chip *max3191x = gpiochip_get_data(gpio); 2368c2ecf20Sopenharmony_ci const unsigned int wordlen = max3191x_wordlen(max3191x); 2378c2ecf20Sopenharmony_ci int ret; 2388c2ecf20Sopenharmony_ci unsigned long bit; 2398c2ecf20Sopenharmony_ci unsigned long gpio_mask; 2408c2ecf20Sopenharmony_ci unsigned long in; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci mutex_lock(&max3191x->lock); 2438c2ecf20Sopenharmony_ci ret = max3191x_readout_locked(max3191x); 2448c2ecf20Sopenharmony_ci if (ret) 2458c2ecf20Sopenharmony_ci goto out_unlock; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci bitmap_zero(bits, gpio->ngpio); 2488c2ecf20Sopenharmony_ci for_each_set_clump8(bit, gpio_mask, mask, gpio->ngpio) { 2498c2ecf20Sopenharmony_ci unsigned int chipnum = bit / MAX3191X_NGPIO; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci if (max3191x_chip_is_faulting(max3191x, chipnum)) { 2528c2ecf20Sopenharmony_ci ret = -EIO; 2538c2ecf20Sopenharmony_ci goto out_unlock; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci in = ((u8 *)max3191x->xfer.rx_buf)[chipnum * wordlen]; 2578c2ecf20Sopenharmony_ci in &= gpio_mask; 2588c2ecf20Sopenharmony_ci bitmap_set_value8(bits, in, bit); 2598c2ecf20Sopenharmony_ci } 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ciout_unlock: 2628c2ecf20Sopenharmony_ci mutex_unlock(&max3191x->lock); 2638c2ecf20Sopenharmony_ci return ret; 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic int max3191x_set_config(struct gpio_chip *gpio, unsigned int offset, 2678c2ecf20Sopenharmony_ci unsigned long config) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci struct max3191x_chip *max3191x = gpiochip_get_data(gpio); 2708c2ecf20Sopenharmony_ci u32 debounce, chipnum, db0_val, db1_val; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE) 2738c2ecf20Sopenharmony_ci return -ENOTSUPP; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (!max3191x->db0_pins || !max3191x->db1_pins) 2768c2ecf20Sopenharmony_ci return -EINVAL; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci debounce = pinconf_to_config_argument(config); 2798c2ecf20Sopenharmony_ci switch (debounce) { 2808c2ecf20Sopenharmony_ci case 0: 2818c2ecf20Sopenharmony_ci db0_val = 0; 2828c2ecf20Sopenharmony_ci db1_val = 0; 2838c2ecf20Sopenharmony_ci break; 2848c2ecf20Sopenharmony_ci case 1 ... 25: 2858c2ecf20Sopenharmony_ci db0_val = 0; 2868c2ecf20Sopenharmony_ci db1_val = 1; 2878c2ecf20Sopenharmony_ci break; 2888c2ecf20Sopenharmony_ci case 26 ... 750: 2898c2ecf20Sopenharmony_ci db0_val = 1; 2908c2ecf20Sopenharmony_ci db1_val = 0; 2918c2ecf20Sopenharmony_ci break; 2928c2ecf20Sopenharmony_ci case 751 ... 3000: 2938c2ecf20Sopenharmony_ci db0_val = 1; 2948c2ecf20Sopenharmony_ci db1_val = 1; 2958c2ecf20Sopenharmony_ci break; 2968c2ecf20Sopenharmony_ci default: 2978c2ecf20Sopenharmony_ci return -EINVAL; 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci if (max3191x->db0_pins->ndescs == 1) 3018c2ecf20Sopenharmony_ci chipnum = 0; /* all chips use the same pair of debounce pins */ 3028c2ecf20Sopenharmony_ci else 3038c2ecf20Sopenharmony_ci chipnum = offset / MAX3191X_NGPIO; /* per chip debounce pins */ 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci mutex_lock(&max3191x->lock); 3068c2ecf20Sopenharmony_ci gpiod_set_value_cansleep(max3191x->db0_pins->desc[chipnum], db0_val); 3078c2ecf20Sopenharmony_ci gpiod_set_value_cansleep(max3191x->db1_pins->desc[chipnum], db1_val); 3088c2ecf20Sopenharmony_ci mutex_unlock(&max3191x->lock); 3098c2ecf20Sopenharmony_ci return 0; 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic void gpiod_set_array_single_value_cansleep(unsigned int ndescs, 3138c2ecf20Sopenharmony_ci struct gpio_desc **desc, 3148c2ecf20Sopenharmony_ci struct gpio_array *info, 3158c2ecf20Sopenharmony_ci int value) 3168c2ecf20Sopenharmony_ci{ 3178c2ecf20Sopenharmony_ci unsigned long *values; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci values = bitmap_alloc(ndescs, GFP_KERNEL); 3208c2ecf20Sopenharmony_ci if (!values) 3218c2ecf20Sopenharmony_ci return; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci if (value) 3248c2ecf20Sopenharmony_ci bitmap_fill(values, ndescs); 3258c2ecf20Sopenharmony_ci else 3268c2ecf20Sopenharmony_ci bitmap_zero(values, ndescs); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci gpiod_set_array_value_cansleep(ndescs, desc, info, values); 3298c2ecf20Sopenharmony_ci kfree(values); 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic struct gpio_descs *devm_gpiod_get_array_optional_count( 3338c2ecf20Sopenharmony_ci struct device *dev, const char *con_id, 3348c2ecf20Sopenharmony_ci enum gpiod_flags flags, unsigned int expected) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci struct gpio_descs *descs; 3378c2ecf20Sopenharmony_ci int found = gpiod_count(dev, con_id); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci if (found == -ENOENT) 3408c2ecf20Sopenharmony_ci return NULL; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci if (found != expected && found != 1) { 3438c2ecf20Sopenharmony_ci dev_err(dev, "ignoring %s-gpios: found %d, expected %u or 1\n", 3448c2ecf20Sopenharmony_ci con_id, found, expected); 3458c2ecf20Sopenharmony_ci return NULL; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci descs = devm_gpiod_get_array_optional(dev, con_id, flags); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci if (IS_ERR(descs)) { 3518c2ecf20Sopenharmony_ci dev_err(dev, "failed to get %s-gpios: %ld\n", 3528c2ecf20Sopenharmony_ci con_id, PTR_ERR(descs)); 3538c2ecf20Sopenharmony_ci return NULL; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci return descs; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic int max3191x_probe(struct spi_device *spi) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci struct device *dev = &spi->dev; 3628c2ecf20Sopenharmony_ci struct max3191x_chip *max3191x; 3638c2ecf20Sopenharmony_ci int n, ret; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci max3191x = devm_kzalloc(dev, sizeof(*max3191x), GFP_KERNEL); 3668c2ecf20Sopenharmony_ci if (!max3191x) 3678c2ecf20Sopenharmony_ci return -ENOMEM; 3688c2ecf20Sopenharmony_ci spi_set_drvdata(spi, max3191x); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci max3191x->nchips = 1; 3718c2ecf20Sopenharmony_ci device_property_read_u32(dev, "#daisy-chained-devices", 3728c2ecf20Sopenharmony_ci &max3191x->nchips); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci n = BITS_TO_LONGS(max3191x->nchips); 3758c2ecf20Sopenharmony_ci max3191x->crc_error = devm_kcalloc(dev, n, sizeof(long), GFP_KERNEL); 3768c2ecf20Sopenharmony_ci max3191x->undervolt1 = devm_kcalloc(dev, n, sizeof(long), GFP_KERNEL); 3778c2ecf20Sopenharmony_ci max3191x->undervolt2 = devm_kcalloc(dev, n, sizeof(long), GFP_KERNEL); 3788c2ecf20Sopenharmony_ci max3191x->overtemp = devm_kcalloc(dev, n, sizeof(long), GFP_KERNEL); 3798c2ecf20Sopenharmony_ci max3191x->fault = devm_kcalloc(dev, n, sizeof(long), GFP_KERNEL); 3808c2ecf20Sopenharmony_ci max3191x->xfer.rx_buf = devm_kcalloc(dev, max3191x->nchips, 3818c2ecf20Sopenharmony_ci 2, GFP_KERNEL); 3828c2ecf20Sopenharmony_ci if (!max3191x->crc_error || !max3191x->undervolt1 || 3838c2ecf20Sopenharmony_ci !max3191x->overtemp || !max3191x->undervolt2 || 3848c2ecf20Sopenharmony_ci !max3191x->fault || !max3191x->xfer.rx_buf) 3858c2ecf20Sopenharmony_ci return -ENOMEM; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci max3191x->modesel_pins = devm_gpiod_get_array_optional_count(dev, 3888c2ecf20Sopenharmony_ci "maxim,modesel", GPIOD_ASIS, max3191x->nchips); 3898c2ecf20Sopenharmony_ci max3191x->fault_pins = devm_gpiod_get_array_optional_count(dev, 3908c2ecf20Sopenharmony_ci "maxim,fault", GPIOD_IN, max3191x->nchips); 3918c2ecf20Sopenharmony_ci max3191x->db0_pins = devm_gpiod_get_array_optional_count(dev, 3928c2ecf20Sopenharmony_ci "maxim,db0", GPIOD_OUT_LOW, max3191x->nchips); 3938c2ecf20Sopenharmony_ci max3191x->db1_pins = devm_gpiod_get_array_optional_count(dev, 3948c2ecf20Sopenharmony_ci "maxim,db1", GPIOD_OUT_LOW, max3191x->nchips); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci max3191x->mode = device_property_read_bool(dev, "maxim,modesel-8bit") 3978c2ecf20Sopenharmony_ci ? STATUS_BYTE_DISABLED : STATUS_BYTE_ENABLED; 3988c2ecf20Sopenharmony_ci if (max3191x->modesel_pins) 3998c2ecf20Sopenharmony_ci gpiod_set_array_single_value_cansleep( 4008c2ecf20Sopenharmony_ci max3191x->modesel_pins->ndescs, 4018c2ecf20Sopenharmony_ci max3191x->modesel_pins->desc, 4028c2ecf20Sopenharmony_ci max3191x->modesel_pins->info, max3191x->mode); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci max3191x->ignore_uv = device_property_read_bool(dev, 4058c2ecf20Sopenharmony_ci "maxim,ignore-undervoltage"); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci if (max3191x->db0_pins && max3191x->db1_pins && 4088c2ecf20Sopenharmony_ci max3191x->db0_pins->ndescs != max3191x->db1_pins->ndescs) { 4098c2ecf20Sopenharmony_ci dev_err(dev, "ignoring maxim,db*-gpios: array len mismatch\n"); 4108c2ecf20Sopenharmony_ci devm_gpiod_put_array(dev, max3191x->db0_pins); 4118c2ecf20Sopenharmony_ci devm_gpiod_put_array(dev, max3191x->db1_pins); 4128c2ecf20Sopenharmony_ci max3191x->db0_pins = NULL; 4138c2ecf20Sopenharmony_ci max3191x->db1_pins = NULL; 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci max3191x->xfer.len = max3191x->nchips * max3191x_wordlen(max3191x); 4178c2ecf20Sopenharmony_ci spi_message_init_with_transfers(&max3191x->mesg, &max3191x->xfer, 1); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci max3191x->gpio.label = spi->modalias; 4208c2ecf20Sopenharmony_ci max3191x->gpio.owner = THIS_MODULE; 4218c2ecf20Sopenharmony_ci max3191x->gpio.parent = dev; 4228c2ecf20Sopenharmony_ci max3191x->gpio.base = -1; 4238c2ecf20Sopenharmony_ci max3191x->gpio.ngpio = max3191x->nchips * MAX3191X_NGPIO; 4248c2ecf20Sopenharmony_ci max3191x->gpio.can_sleep = true; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci max3191x->gpio.get_direction = max3191x_get_direction; 4278c2ecf20Sopenharmony_ci max3191x->gpio.direction_input = max3191x_direction_input; 4288c2ecf20Sopenharmony_ci max3191x->gpio.direction_output = max3191x_direction_output; 4298c2ecf20Sopenharmony_ci max3191x->gpio.set = max3191x_set; 4308c2ecf20Sopenharmony_ci max3191x->gpio.set_multiple = max3191x_set_multiple; 4318c2ecf20Sopenharmony_ci max3191x->gpio.get = max3191x_get; 4328c2ecf20Sopenharmony_ci max3191x->gpio.get_multiple = max3191x_get_multiple; 4338c2ecf20Sopenharmony_ci max3191x->gpio.set_config = max3191x_set_config; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci mutex_init(&max3191x->lock); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci ret = gpiochip_add_data(&max3191x->gpio, max3191x); 4388c2ecf20Sopenharmony_ci if (ret) { 4398c2ecf20Sopenharmony_ci mutex_destroy(&max3191x->lock); 4408c2ecf20Sopenharmony_ci return ret; 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci return 0; 4448c2ecf20Sopenharmony_ci} 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic int max3191x_remove(struct spi_device *spi) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci struct max3191x_chip *max3191x = spi_get_drvdata(spi); 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci gpiochip_remove(&max3191x->gpio); 4518c2ecf20Sopenharmony_ci mutex_destroy(&max3191x->lock); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci return 0; 4548c2ecf20Sopenharmony_ci} 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_cistatic int __init max3191x_register_driver(struct spi_driver *sdrv) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci crc8_populate_msb(max3191x_crc8, MAX3191X_CRC8_POLYNOMIAL); 4598c2ecf20Sopenharmony_ci return spi_register_driver(sdrv); 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 4638c2ecf20Sopenharmony_cistatic const struct of_device_id max3191x_of_id[] = { 4648c2ecf20Sopenharmony_ci { .compatible = "maxim,max31910" }, 4658c2ecf20Sopenharmony_ci { .compatible = "maxim,max31911" }, 4668c2ecf20Sopenharmony_ci { .compatible = "maxim,max31912" }, 4678c2ecf20Sopenharmony_ci { .compatible = "maxim,max31913" }, 4688c2ecf20Sopenharmony_ci { .compatible = "maxim,max31953" }, 4698c2ecf20Sopenharmony_ci { .compatible = "maxim,max31963" }, 4708c2ecf20Sopenharmony_ci { } 4718c2ecf20Sopenharmony_ci}; 4728c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, max3191x_of_id); 4738c2ecf20Sopenharmony_ci#endif 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic const struct spi_device_id max3191x_spi_id[] = { 4768c2ecf20Sopenharmony_ci { "max31910" }, 4778c2ecf20Sopenharmony_ci { "max31911" }, 4788c2ecf20Sopenharmony_ci { "max31912" }, 4798c2ecf20Sopenharmony_ci { "max31913" }, 4808c2ecf20Sopenharmony_ci { "max31953" }, 4818c2ecf20Sopenharmony_ci { "max31963" }, 4828c2ecf20Sopenharmony_ci { } 4838c2ecf20Sopenharmony_ci}; 4848c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(spi, max3191x_spi_id); 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_cistatic struct spi_driver max3191x_driver = { 4878c2ecf20Sopenharmony_ci .driver = { 4888c2ecf20Sopenharmony_ci .name = "max3191x", 4898c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(max3191x_of_id), 4908c2ecf20Sopenharmony_ci }, 4918c2ecf20Sopenharmony_ci .probe = max3191x_probe, 4928c2ecf20Sopenharmony_ci .remove = max3191x_remove, 4938c2ecf20Sopenharmony_ci .id_table = max3191x_spi_id, 4948c2ecf20Sopenharmony_ci}; 4958c2ecf20Sopenharmony_cimodule_driver(max3191x_driver, max3191x_register_driver, spi_unregister_driver); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ciMODULE_AUTHOR("Lukas Wunner <lukas@wunner.de>"); 4988c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("GPIO driver for Maxim MAX3191x industrial serializer"); 4998c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 500