drivers/gpio/gpio-max3191x.c

Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-max3191x.c

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-max3191x.c
Extension
.c
Size
13855 bytes
Lines
476
Domain
Driver Families
Bucket
drivers/gpio
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct max3191x_chip {
	struct gpio_chip gpio;
	struct mutex lock;
	u32 nchips;
	enum max3191x_mode mode;
	struct gpio_descs *modesel_pins;
	struct gpio_descs *fault_pins;
	struct gpio_descs *db0_pins;
	struct gpio_descs *db1_pins;
	struct spi_message mesg;
	struct spi_transfer xfer;
	unsigned long *crc_error;
	unsigned long *overtemp;
	unsigned long *undervolt1;
	unsigned long *undervolt2;
	unsigned long *fault;
	bool ignore_uv;
};

#define MAX3191X_NGPIO 8
#define MAX3191X_CRC8_POLYNOMIAL 0xa8 /* (x^5) + x^4 + x^2 + x^0 */

DECLARE_CRC8_TABLE(max3191x_crc8);

static int max3191x_get_direction(struct gpio_chip *gpio, unsigned int offset)
{
	return GPIO_LINE_DIRECTION_IN; /* always in */
}

static int max3191x_direction_input(struct gpio_chip *gpio, unsigned int offset)
{
	return 0;
}

static unsigned int max3191x_wordlen(struct max3191x_chip *max3191x)
{
	return max3191x->mode == STATUS_BYTE_ENABLED ? 2 : 1;
}

static int max3191x_readout_locked(struct max3191x_chip *max3191x)
{
	struct device *dev = max3191x->gpio.parent;
	struct spi_device *spi = to_spi_device(dev);
	int val, i, ot = 0, uv1 = 0;

	val = spi_sync(spi, &max3191x->mesg);
	if (val) {
		dev_err_ratelimited(dev, "SPI receive error %d\n", val);
		return val;
	}

	for (i = 0; i < max3191x->nchips; i++) {
		if (max3191x->mode == STATUS_BYTE_ENABLED) {
			u8 in	  = ((u8 *)max3191x->xfer.rx_buf)[i * 2];
			u8 status = ((u8 *)max3191x->xfer.rx_buf)[i * 2 + 1];

			val = (status & 0xf8) != crc8(max3191x_crc8, &in, 1, 0);
			__assign_bit(i, max3191x->crc_error, val);
			if (val)
				dev_err_ratelimited(dev,
					"chip %d: CRC error\n", i);

			ot  = (status >> 1) & 1;
			__assign_bit(i, max3191x->overtemp, ot);
			if (ot)
				dev_err_ratelimited(dev,
					"chip %d: overtemperature\n", i);

			if (!max3191x->ignore_uv) {
				uv1 = !((status >> 2) & 1);
				__assign_bit(i, max3191x->undervolt1, uv1);
				if (uv1)
					dev_err_ratelimited(dev,
						"chip %d: undervoltage\n", i);

				val = !(status & 1);
				__assign_bit(i, max3191x->undervolt2, val);
				if (val && !uv1)
					dev_warn_ratelimited(dev,
						"chip %d: voltage warn\n", i);
			}
		}

		if (max3191x->fault_pins && !max3191x->ignore_uv) {
			/* fault pin shared by all chips or per chip */
			struct gpio_desc *fault_pin =
				(max3191x->fault_pins->ndescs == 1)
					? max3191x->fault_pins->desc[0]
					: max3191x->fault_pins->desc[i];

Annotation

Implementation Notes