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