162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * gpio-max3191x.c - GPIO driver for Maxim MAX3191x industrial serializer 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2017 KUNBUS GmbH 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * The MAX3191x makes 8 digital 24V inputs available via SPI. 862306a36Sopenharmony_ci * Multiple chips can be daisy-chained, the spec does not impose 962306a36Sopenharmony_ci * a limit on the number of chips and neither does this driver. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Either of two modes is selectable: In 8-bit mode, only the state 1262306a36Sopenharmony_ci * of the inputs is clocked out to achieve high readout speeds; 1362306a36Sopenharmony_ci * In 16-bit mode, an additional status byte is clocked out with 1462306a36Sopenharmony_ci * a CRC and indicator bits for undervoltage and overtemperature. 1562306a36Sopenharmony_ci * The driver returns an error instead of potentially bogus data 1662306a36Sopenharmony_ci * if any of these fault conditions occur. However it does allow 1762306a36Sopenharmony_ci * readout of non-faulting chips in the same daisy-chain. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * MAX3191x supports four debounce settings and the driver is 2062306a36Sopenharmony_ci * capable of configuring these differently for each chip in the 2162306a36Sopenharmony_ci * daisy-chain. 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * If the chips are hardwired to 8-bit mode ("modesel" pulled high), 2462306a36Sopenharmony_ci * gpio-pisosr.c can be used alternatively to this driver. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * https://datasheets.maximintegrated.com/en/ds/MAX31910.pdf 2762306a36Sopenharmony_ci * https://datasheets.maximintegrated.com/en/ds/MAX31911.pdf 2862306a36Sopenharmony_ci * https://datasheets.maximintegrated.com/en/ds/MAX31912.pdf 2962306a36Sopenharmony_ci * https://datasheets.maximintegrated.com/en/ds/MAX31913.pdf 3062306a36Sopenharmony_ci * https://datasheets.maximintegrated.com/en/ds/MAX31953-MAX31963.pdf 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#include <linux/bitmap.h> 3462306a36Sopenharmony_ci#include <linux/bitops.h> 3562306a36Sopenharmony_ci#include <linux/crc8.h> 3662306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 3762306a36Sopenharmony_ci#include <linux/gpio/driver.h> 3862306a36Sopenharmony_ci#include <linux/module.h> 3962306a36Sopenharmony_ci#include <linux/spi/spi.h> 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cienum max3191x_mode { 4262306a36Sopenharmony_ci STATUS_BYTE_ENABLED, 4362306a36Sopenharmony_ci STATUS_BYTE_DISABLED, 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/** 4762306a36Sopenharmony_ci * struct max3191x_chip - max3191x daisy-chain 4862306a36Sopenharmony_ci * @gpio: GPIO controller struct 4962306a36Sopenharmony_ci * @lock: protects read sequences 5062306a36Sopenharmony_ci * @nchips: number of chips in the daisy-chain 5162306a36Sopenharmony_ci * @mode: current mode, 0 for 16-bit, 1 for 8-bit; 5262306a36Sopenharmony_ci * for simplicity, all chips in the daisy-chain are assumed 5362306a36Sopenharmony_ci * to use the same mode 5462306a36Sopenharmony_ci * @modesel_pins: GPIO pins to configure modesel of each chip 5562306a36Sopenharmony_ci * @fault_pins: GPIO pins to detect fault of each chip 5662306a36Sopenharmony_ci * @db0_pins: GPIO pins to configure debounce of each chip 5762306a36Sopenharmony_ci * @db1_pins: GPIO pins to configure debounce of each chip 5862306a36Sopenharmony_ci * @mesg: SPI message to perform a readout 5962306a36Sopenharmony_ci * @xfer: SPI transfer used by @mesg 6062306a36Sopenharmony_ci * @crc_error: bitmap signaling CRC error for each chip 6162306a36Sopenharmony_ci * @overtemp: bitmap signaling overtemperature alarm for each chip 6262306a36Sopenharmony_ci * @undervolt1: bitmap signaling undervoltage alarm for each chip 6362306a36Sopenharmony_ci * @undervolt2: bitmap signaling undervoltage warning for each chip 6462306a36Sopenharmony_ci * @fault: bitmap signaling assertion of @fault_pins for each chip 6562306a36Sopenharmony_ci * @ignore_uv: whether to ignore undervoltage alarms; 6662306a36Sopenharmony_ci * set by a device property if the chips are powered through 6762306a36Sopenharmony_ci * 5VOUT instead of VCC24V, in which case they will constantly 6862306a36Sopenharmony_ci * signal undervoltage; 6962306a36Sopenharmony_ci * for simplicity, all chips in the daisy-chain are assumed 7062306a36Sopenharmony_ci * to be powered the same way 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_cistruct max3191x_chip { 7362306a36Sopenharmony_ci struct gpio_chip gpio; 7462306a36Sopenharmony_ci struct mutex lock; 7562306a36Sopenharmony_ci u32 nchips; 7662306a36Sopenharmony_ci enum max3191x_mode mode; 7762306a36Sopenharmony_ci struct gpio_descs *modesel_pins; 7862306a36Sopenharmony_ci struct gpio_descs *fault_pins; 7962306a36Sopenharmony_ci struct gpio_descs *db0_pins; 8062306a36Sopenharmony_ci struct gpio_descs *db1_pins; 8162306a36Sopenharmony_ci struct spi_message mesg; 8262306a36Sopenharmony_ci struct spi_transfer xfer; 8362306a36Sopenharmony_ci unsigned long *crc_error; 8462306a36Sopenharmony_ci unsigned long *overtemp; 8562306a36Sopenharmony_ci unsigned long *undervolt1; 8662306a36Sopenharmony_ci unsigned long *undervolt2; 8762306a36Sopenharmony_ci unsigned long *fault; 8862306a36Sopenharmony_ci bool ignore_uv; 8962306a36Sopenharmony_ci}; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#define MAX3191X_NGPIO 8 9262306a36Sopenharmony_ci#define MAX3191X_CRC8_POLYNOMIAL 0xa8 /* (x^5) + x^4 + x^2 + x^0 */ 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ciDECLARE_CRC8_TABLE(max3191x_crc8); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic int max3191x_get_direction(struct gpio_chip *gpio, unsigned int offset) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci return GPIO_LINE_DIRECTION_IN; /* always in */ 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic int max3191x_direction_input(struct gpio_chip *gpio, unsigned int offset) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci return 0; 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic int max3191x_direction_output(struct gpio_chip *gpio, 10762306a36Sopenharmony_ci unsigned int offset, int value) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci return -EINVAL; 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic void max3191x_set(struct gpio_chip *gpio, unsigned int offset, int value) 11362306a36Sopenharmony_ci{ } 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic void max3191x_set_multiple(struct gpio_chip *gpio, unsigned long *mask, 11662306a36Sopenharmony_ci unsigned long *bits) 11762306a36Sopenharmony_ci{ } 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic unsigned int max3191x_wordlen(struct max3191x_chip *max3191x) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci return max3191x->mode == STATUS_BYTE_ENABLED ? 2 : 1; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic int max3191x_readout_locked(struct max3191x_chip *max3191x) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci struct device *dev = max3191x->gpio.parent; 12762306a36Sopenharmony_ci struct spi_device *spi = to_spi_device(dev); 12862306a36Sopenharmony_ci int val, i, ot = 0, uv1 = 0; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci val = spi_sync(spi, &max3191x->mesg); 13162306a36Sopenharmony_ci if (val) { 13262306a36Sopenharmony_ci dev_err_ratelimited(dev, "SPI receive error %d\n", val); 13362306a36Sopenharmony_ci return val; 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci for (i = 0; i < max3191x->nchips; i++) { 13762306a36Sopenharmony_ci if (max3191x->mode == STATUS_BYTE_ENABLED) { 13862306a36Sopenharmony_ci u8 in = ((u8 *)max3191x->xfer.rx_buf)[i * 2]; 13962306a36Sopenharmony_ci u8 status = ((u8 *)max3191x->xfer.rx_buf)[i * 2 + 1]; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci val = (status & 0xf8) != crc8(max3191x_crc8, &in, 1, 0); 14262306a36Sopenharmony_ci __assign_bit(i, max3191x->crc_error, val); 14362306a36Sopenharmony_ci if (val) 14462306a36Sopenharmony_ci dev_err_ratelimited(dev, 14562306a36Sopenharmony_ci "chip %d: CRC error\n", i); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci ot = (status >> 1) & 1; 14862306a36Sopenharmony_ci __assign_bit(i, max3191x->overtemp, ot); 14962306a36Sopenharmony_ci if (ot) 15062306a36Sopenharmony_ci dev_err_ratelimited(dev, 15162306a36Sopenharmony_ci "chip %d: overtemperature\n", i); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (!max3191x->ignore_uv) { 15462306a36Sopenharmony_ci uv1 = !((status >> 2) & 1); 15562306a36Sopenharmony_ci __assign_bit(i, max3191x->undervolt1, uv1); 15662306a36Sopenharmony_ci if (uv1) 15762306a36Sopenharmony_ci dev_err_ratelimited(dev, 15862306a36Sopenharmony_ci "chip %d: undervoltage\n", i); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci val = !(status & 1); 16162306a36Sopenharmony_ci __assign_bit(i, max3191x->undervolt2, val); 16262306a36Sopenharmony_ci if (val && !uv1) 16362306a36Sopenharmony_ci dev_warn_ratelimited(dev, 16462306a36Sopenharmony_ci "chip %d: voltage warn\n", i); 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (max3191x->fault_pins && !max3191x->ignore_uv) { 16962306a36Sopenharmony_ci /* fault pin shared by all chips or per chip */ 17062306a36Sopenharmony_ci struct gpio_desc *fault_pin = 17162306a36Sopenharmony_ci (max3191x->fault_pins->ndescs == 1) 17262306a36Sopenharmony_ci ? max3191x->fault_pins->desc[0] 17362306a36Sopenharmony_ci : max3191x->fault_pins->desc[i]; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci val = gpiod_get_value_cansleep(fault_pin); 17662306a36Sopenharmony_ci if (val < 0) { 17762306a36Sopenharmony_ci dev_err_ratelimited(dev, 17862306a36Sopenharmony_ci "GPIO read error %d\n", val); 17962306a36Sopenharmony_ci return val; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci __assign_bit(i, max3191x->fault, val); 18262306a36Sopenharmony_ci if (val && !uv1 && !ot) 18362306a36Sopenharmony_ci dev_err_ratelimited(dev, 18462306a36Sopenharmony_ci "chip %d: fault\n", i); 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci return 0; 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic bool max3191x_chip_is_faulting(struct max3191x_chip *max3191x, 19262306a36Sopenharmony_ci unsigned int chipnum) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci /* without status byte the only diagnostic is the fault pin */ 19562306a36Sopenharmony_ci if (!max3191x->ignore_uv && test_bit(chipnum, max3191x->fault)) 19662306a36Sopenharmony_ci return true; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci if (max3191x->mode == STATUS_BYTE_DISABLED) 19962306a36Sopenharmony_ci return false; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci return test_bit(chipnum, max3191x->crc_error) || 20262306a36Sopenharmony_ci test_bit(chipnum, max3191x->overtemp) || 20362306a36Sopenharmony_ci (!max3191x->ignore_uv && 20462306a36Sopenharmony_ci test_bit(chipnum, max3191x->undervolt1)); 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_cistatic int max3191x_get(struct gpio_chip *gpio, unsigned int offset) 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci struct max3191x_chip *max3191x = gpiochip_get_data(gpio); 21062306a36Sopenharmony_ci int ret, chipnum, wordlen = max3191x_wordlen(max3191x); 21162306a36Sopenharmony_ci u8 in; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci mutex_lock(&max3191x->lock); 21462306a36Sopenharmony_ci ret = max3191x_readout_locked(max3191x); 21562306a36Sopenharmony_ci if (ret) 21662306a36Sopenharmony_ci goto out_unlock; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci chipnum = offset / MAX3191X_NGPIO; 21962306a36Sopenharmony_ci if (max3191x_chip_is_faulting(max3191x, chipnum)) { 22062306a36Sopenharmony_ci ret = -EIO; 22162306a36Sopenharmony_ci goto out_unlock; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci in = ((u8 *)max3191x->xfer.rx_buf)[chipnum * wordlen]; 22562306a36Sopenharmony_ci ret = (in >> (offset % MAX3191X_NGPIO)) & 1; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ciout_unlock: 22862306a36Sopenharmony_ci mutex_unlock(&max3191x->lock); 22962306a36Sopenharmony_ci return ret; 23062306a36Sopenharmony_ci} 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cistatic int max3191x_get_multiple(struct gpio_chip *gpio, unsigned long *mask, 23362306a36Sopenharmony_ci unsigned long *bits) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci struct max3191x_chip *max3191x = gpiochip_get_data(gpio); 23662306a36Sopenharmony_ci const unsigned int wordlen = max3191x_wordlen(max3191x); 23762306a36Sopenharmony_ci int ret; 23862306a36Sopenharmony_ci unsigned long bit; 23962306a36Sopenharmony_ci unsigned long gpio_mask; 24062306a36Sopenharmony_ci unsigned long in; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci mutex_lock(&max3191x->lock); 24362306a36Sopenharmony_ci ret = max3191x_readout_locked(max3191x); 24462306a36Sopenharmony_ci if (ret) 24562306a36Sopenharmony_ci goto out_unlock; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci bitmap_zero(bits, gpio->ngpio); 24862306a36Sopenharmony_ci for_each_set_clump8(bit, gpio_mask, mask, gpio->ngpio) { 24962306a36Sopenharmony_ci unsigned int chipnum = bit / MAX3191X_NGPIO; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci if (max3191x_chip_is_faulting(max3191x, chipnum)) { 25262306a36Sopenharmony_ci ret = -EIO; 25362306a36Sopenharmony_ci goto out_unlock; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci in = ((u8 *)max3191x->xfer.rx_buf)[chipnum * wordlen]; 25762306a36Sopenharmony_ci in &= gpio_mask; 25862306a36Sopenharmony_ci bitmap_set_value8(bits, in, bit); 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ciout_unlock: 26262306a36Sopenharmony_ci mutex_unlock(&max3191x->lock); 26362306a36Sopenharmony_ci return ret; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic int max3191x_set_config(struct gpio_chip *gpio, unsigned int offset, 26762306a36Sopenharmony_ci unsigned long config) 26862306a36Sopenharmony_ci{ 26962306a36Sopenharmony_ci struct max3191x_chip *max3191x = gpiochip_get_data(gpio); 27062306a36Sopenharmony_ci u32 debounce, chipnum, db0_val, db1_val; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE) 27362306a36Sopenharmony_ci return -ENOTSUPP; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci if (!max3191x->db0_pins || !max3191x->db1_pins) 27662306a36Sopenharmony_ci return -EINVAL; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci debounce = pinconf_to_config_argument(config); 27962306a36Sopenharmony_ci switch (debounce) { 28062306a36Sopenharmony_ci case 0: 28162306a36Sopenharmony_ci db0_val = 0; 28262306a36Sopenharmony_ci db1_val = 0; 28362306a36Sopenharmony_ci break; 28462306a36Sopenharmony_ci case 1 ... 25: 28562306a36Sopenharmony_ci db0_val = 0; 28662306a36Sopenharmony_ci db1_val = 1; 28762306a36Sopenharmony_ci break; 28862306a36Sopenharmony_ci case 26 ... 750: 28962306a36Sopenharmony_ci db0_val = 1; 29062306a36Sopenharmony_ci db1_val = 0; 29162306a36Sopenharmony_ci break; 29262306a36Sopenharmony_ci case 751 ... 3000: 29362306a36Sopenharmony_ci db0_val = 1; 29462306a36Sopenharmony_ci db1_val = 1; 29562306a36Sopenharmony_ci break; 29662306a36Sopenharmony_ci default: 29762306a36Sopenharmony_ci return -EINVAL; 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci if (max3191x->db0_pins->ndescs == 1) 30162306a36Sopenharmony_ci chipnum = 0; /* all chips use the same pair of debounce pins */ 30262306a36Sopenharmony_ci else 30362306a36Sopenharmony_ci chipnum = offset / MAX3191X_NGPIO; /* per chip debounce pins */ 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci mutex_lock(&max3191x->lock); 30662306a36Sopenharmony_ci gpiod_set_value_cansleep(max3191x->db0_pins->desc[chipnum], db0_val); 30762306a36Sopenharmony_ci gpiod_set_value_cansleep(max3191x->db1_pins->desc[chipnum], db1_val); 30862306a36Sopenharmony_ci mutex_unlock(&max3191x->lock); 30962306a36Sopenharmony_ci return 0; 31062306a36Sopenharmony_ci} 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_cistatic void gpiod_set_array_single_value_cansleep(unsigned int ndescs, 31362306a36Sopenharmony_ci struct gpio_desc **desc, 31462306a36Sopenharmony_ci struct gpio_array *info, 31562306a36Sopenharmony_ci int value) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci unsigned long *values; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci values = bitmap_alloc(ndescs, GFP_KERNEL); 32062306a36Sopenharmony_ci if (!values) 32162306a36Sopenharmony_ci return; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (value) 32462306a36Sopenharmony_ci bitmap_fill(values, ndescs); 32562306a36Sopenharmony_ci else 32662306a36Sopenharmony_ci bitmap_zero(values, ndescs); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci gpiod_set_array_value_cansleep(ndescs, desc, info, values); 32962306a36Sopenharmony_ci bitmap_free(values); 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic struct gpio_descs *devm_gpiod_get_array_optional_count( 33362306a36Sopenharmony_ci struct device *dev, const char *con_id, 33462306a36Sopenharmony_ci enum gpiod_flags flags, unsigned int expected) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci struct gpio_descs *descs; 33762306a36Sopenharmony_ci int found = gpiod_count(dev, con_id); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci if (found == -ENOENT) 34062306a36Sopenharmony_ci return NULL; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci if (found != expected && found != 1) { 34362306a36Sopenharmony_ci dev_err(dev, "ignoring %s-gpios: found %d, expected %u or 1\n", 34462306a36Sopenharmony_ci con_id, found, expected); 34562306a36Sopenharmony_ci return NULL; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci descs = devm_gpiod_get_array_optional(dev, con_id, flags); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci if (IS_ERR(descs)) { 35162306a36Sopenharmony_ci dev_err(dev, "failed to get %s-gpios: %ld\n", 35262306a36Sopenharmony_ci con_id, PTR_ERR(descs)); 35362306a36Sopenharmony_ci return NULL; 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci return descs; 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_cistatic int max3191x_probe(struct spi_device *spi) 36062306a36Sopenharmony_ci{ 36162306a36Sopenharmony_ci struct device *dev = &spi->dev; 36262306a36Sopenharmony_ci struct max3191x_chip *max3191x; 36362306a36Sopenharmony_ci int n, ret; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci max3191x = devm_kzalloc(dev, sizeof(*max3191x), GFP_KERNEL); 36662306a36Sopenharmony_ci if (!max3191x) 36762306a36Sopenharmony_ci return -ENOMEM; 36862306a36Sopenharmony_ci spi_set_drvdata(spi, max3191x); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci max3191x->nchips = 1; 37162306a36Sopenharmony_ci device_property_read_u32(dev, "#daisy-chained-devices", 37262306a36Sopenharmony_ci &max3191x->nchips); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci n = BITS_TO_LONGS(max3191x->nchips); 37562306a36Sopenharmony_ci max3191x->crc_error = devm_kcalloc(dev, n, sizeof(long), GFP_KERNEL); 37662306a36Sopenharmony_ci max3191x->undervolt1 = devm_kcalloc(dev, n, sizeof(long), GFP_KERNEL); 37762306a36Sopenharmony_ci max3191x->undervolt2 = devm_kcalloc(dev, n, sizeof(long), GFP_KERNEL); 37862306a36Sopenharmony_ci max3191x->overtemp = devm_kcalloc(dev, n, sizeof(long), GFP_KERNEL); 37962306a36Sopenharmony_ci max3191x->fault = devm_kcalloc(dev, n, sizeof(long), GFP_KERNEL); 38062306a36Sopenharmony_ci max3191x->xfer.rx_buf = devm_kcalloc(dev, max3191x->nchips, 38162306a36Sopenharmony_ci 2, GFP_KERNEL); 38262306a36Sopenharmony_ci if (!max3191x->crc_error || !max3191x->undervolt1 || 38362306a36Sopenharmony_ci !max3191x->overtemp || !max3191x->undervolt2 || 38462306a36Sopenharmony_ci !max3191x->fault || !max3191x->xfer.rx_buf) 38562306a36Sopenharmony_ci return -ENOMEM; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci max3191x->modesel_pins = devm_gpiod_get_array_optional_count(dev, 38862306a36Sopenharmony_ci "maxim,modesel", GPIOD_ASIS, max3191x->nchips); 38962306a36Sopenharmony_ci max3191x->fault_pins = devm_gpiod_get_array_optional_count(dev, 39062306a36Sopenharmony_ci "maxim,fault", GPIOD_IN, max3191x->nchips); 39162306a36Sopenharmony_ci max3191x->db0_pins = devm_gpiod_get_array_optional_count(dev, 39262306a36Sopenharmony_ci "maxim,db0", GPIOD_OUT_LOW, max3191x->nchips); 39362306a36Sopenharmony_ci max3191x->db1_pins = devm_gpiod_get_array_optional_count(dev, 39462306a36Sopenharmony_ci "maxim,db1", GPIOD_OUT_LOW, max3191x->nchips); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci max3191x->mode = device_property_read_bool(dev, "maxim,modesel-8bit") 39762306a36Sopenharmony_ci ? STATUS_BYTE_DISABLED : STATUS_BYTE_ENABLED; 39862306a36Sopenharmony_ci if (max3191x->modesel_pins) 39962306a36Sopenharmony_ci gpiod_set_array_single_value_cansleep( 40062306a36Sopenharmony_ci max3191x->modesel_pins->ndescs, 40162306a36Sopenharmony_ci max3191x->modesel_pins->desc, 40262306a36Sopenharmony_ci max3191x->modesel_pins->info, max3191x->mode); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci max3191x->ignore_uv = device_property_read_bool(dev, 40562306a36Sopenharmony_ci "maxim,ignore-undervoltage"); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci if (max3191x->db0_pins && max3191x->db1_pins && 40862306a36Sopenharmony_ci max3191x->db0_pins->ndescs != max3191x->db1_pins->ndescs) { 40962306a36Sopenharmony_ci dev_err(dev, "ignoring maxim,db*-gpios: array len mismatch\n"); 41062306a36Sopenharmony_ci devm_gpiod_put_array(dev, max3191x->db0_pins); 41162306a36Sopenharmony_ci devm_gpiod_put_array(dev, max3191x->db1_pins); 41262306a36Sopenharmony_ci max3191x->db0_pins = NULL; 41362306a36Sopenharmony_ci max3191x->db1_pins = NULL; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci max3191x->xfer.len = max3191x->nchips * max3191x_wordlen(max3191x); 41762306a36Sopenharmony_ci spi_message_init_with_transfers(&max3191x->mesg, &max3191x->xfer, 1); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci max3191x->gpio.label = spi->modalias; 42062306a36Sopenharmony_ci max3191x->gpio.owner = THIS_MODULE; 42162306a36Sopenharmony_ci max3191x->gpio.parent = dev; 42262306a36Sopenharmony_ci max3191x->gpio.base = -1; 42362306a36Sopenharmony_ci max3191x->gpio.ngpio = max3191x->nchips * MAX3191X_NGPIO; 42462306a36Sopenharmony_ci max3191x->gpio.can_sleep = true; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci max3191x->gpio.get_direction = max3191x_get_direction; 42762306a36Sopenharmony_ci max3191x->gpio.direction_input = max3191x_direction_input; 42862306a36Sopenharmony_ci max3191x->gpio.direction_output = max3191x_direction_output; 42962306a36Sopenharmony_ci max3191x->gpio.set = max3191x_set; 43062306a36Sopenharmony_ci max3191x->gpio.set_multiple = max3191x_set_multiple; 43162306a36Sopenharmony_ci max3191x->gpio.get = max3191x_get; 43262306a36Sopenharmony_ci max3191x->gpio.get_multiple = max3191x_get_multiple; 43362306a36Sopenharmony_ci max3191x->gpio.set_config = max3191x_set_config; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci mutex_init(&max3191x->lock); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci ret = gpiochip_add_data(&max3191x->gpio, max3191x); 43862306a36Sopenharmony_ci if (ret) { 43962306a36Sopenharmony_ci mutex_destroy(&max3191x->lock); 44062306a36Sopenharmony_ci return ret; 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci return 0; 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_cistatic void max3191x_remove(struct spi_device *spi) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci struct max3191x_chip *max3191x = spi_get_drvdata(spi); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci gpiochip_remove(&max3191x->gpio); 45162306a36Sopenharmony_ci mutex_destroy(&max3191x->lock); 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic int __init max3191x_register_driver(struct spi_driver *sdrv) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci crc8_populate_msb(max3191x_crc8, MAX3191X_CRC8_POLYNOMIAL); 45762306a36Sopenharmony_ci return spi_register_driver(sdrv); 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_cistatic const struct of_device_id max3191x_of_id[] = { 46162306a36Sopenharmony_ci { .compatible = "maxim,max31910" }, 46262306a36Sopenharmony_ci { .compatible = "maxim,max31911" }, 46362306a36Sopenharmony_ci { .compatible = "maxim,max31912" }, 46462306a36Sopenharmony_ci { .compatible = "maxim,max31913" }, 46562306a36Sopenharmony_ci { .compatible = "maxim,max31953" }, 46662306a36Sopenharmony_ci { .compatible = "maxim,max31963" }, 46762306a36Sopenharmony_ci { } 46862306a36Sopenharmony_ci}; 46962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, max3191x_of_id); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_cistatic const struct spi_device_id max3191x_spi_id[] = { 47262306a36Sopenharmony_ci { "max31910" }, 47362306a36Sopenharmony_ci { "max31911" }, 47462306a36Sopenharmony_ci { "max31912" }, 47562306a36Sopenharmony_ci { "max31913" }, 47662306a36Sopenharmony_ci { "max31953" }, 47762306a36Sopenharmony_ci { "max31963" }, 47862306a36Sopenharmony_ci { } 47962306a36Sopenharmony_ci}; 48062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, max3191x_spi_id); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistatic struct spi_driver max3191x_driver = { 48362306a36Sopenharmony_ci .driver = { 48462306a36Sopenharmony_ci .name = "max3191x", 48562306a36Sopenharmony_ci .of_match_table = max3191x_of_id, 48662306a36Sopenharmony_ci }, 48762306a36Sopenharmony_ci .probe = max3191x_probe, 48862306a36Sopenharmony_ci .remove = max3191x_remove, 48962306a36Sopenharmony_ci .id_table = max3191x_spi_id, 49062306a36Sopenharmony_ci}; 49162306a36Sopenharmony_cimodule_driver(max3191x_driver, max3191x_register_driver, spi_unregister_driver); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ciMODULE_AUTHOR("Lukas Wunner <lukas@wunner.de>"); 49462306a36Sopenharmony_ciMODULE_DESCRIPTION("GPIO driver for Maxim MAX3191x industrial serializer"); 49562306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 496