drivers/gpio/gpio-mmio.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-mmio.c
Extension
.c
Size
22399 bytes
Lines
840
Domain
Driver Families
Bucket
drivers/gpio
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (byte_be) {
			chip->read_reg	= gpio_mmio_read16be;
			chip->write_reg	= gpio_mmio_write16be;
		} else {
			chip->read_reg	= gpio_mmio_read16;
			chip->write_reg	= gpio_mmio_write16;
		}
		break;
	case 32:
		if (byte_be) {
			chip->read_reg	= gpio_mmio_read32be;
			chip->write_reg	= gpio_mmio_write32be;
		} else {
			chip->read_reg	= gpio_mmio_read32;
			chip->write_reg	= gpio_mmio_write32;
		}
		break;
#if BITS_PER_LONG >= 64
	case 64:
		if (byte_be) {
			dev_err(dev,
				"64 bit big endian byte order unsupported\n");
			return -EINVAL;
		} else {
			chip->read_reg	= gpio_mmio_read64;
			chip->write_reg	= gpio_mmio_write64;
		}
		break;
#endif /* BITS_PER_LONG >= 64 */
	default:
		dev_err(dev, "unsupported data width %u bits\n", chip->bits);
		return -EINVAL;
	}

	return 0;
}

/*
 * Create the device and allocate the resources.  For setting GPIO's there are
 * three supported configurations:
 *
 *	- single input/output register resource (named "dat").
 *	- set/clear pair (named "set" and "clr").
 *	- single output register resource and single input resource ("set" and
 *	dat").
 *
 * For the single output register, this drives a 1 by setting a bit and a zero
 * by clearing a bit.  For the set clr pair, this drives a 1 by setting a bit
 * in the set register and clears it by setting a bit in the clear register.
 * The configuration is detected by which resources are present.
 *
 * For setting the GPIO direction, there are three supported configurations:
 *
 *	- simple bidirection GPIO that requires no configuration.
 *	- an output direction register (named "dirout") where a 1 bit
 *	indicates the GPIO is an output.
 *	- an input direction register (named "dirin") where a 1 bit indicates
 *	the GPIO is an input.
 */
static int gpio_mmio_setup_io(struct gpio_generic_chip *chip,
			      const struct gpio_generic_chip_config *cfg)
{
	struct gpio_chip *gc = &chip->gc;

	chip->reg_dat = cfg->dat;
	if (!chip->reg_dat)
		return -EINVAL;

	if (cfg->set && cfg->clr) {
		chip->reg_set = cfg->set;
		chip->reg_clr = cfg->clr;
		gc->set = gpio_mmio_set_with_clear;
		gc->set_multiple = gpio_mmio_set_multiple_with_clear;
	} else if (cfg->set && !cfg->clr) {
		chip->reg_set = cfg->set;
		gc->set = gpio_mmio_set_set;
		gc->set_multiple = gpio_mmio_set_multiple_set;
	} else if (cfg->flags & GPIO_GENERIC_NO_OUTPUT) {
		gc->set = gpio_mmio_set_none;
		gc->set_multiple = NULL;
	} else {
		gc->set = gpio_mmio_set;
		gc->set_multiple = gpio_mmio_set_multiple;
	}

	if (!(cfg->flags & GPIO_GENERIC_UNREADABLE_REG_SET) &&
	    (cfg->flags & GPIO_GENERIC_READ_OUTPUT_REG_SET)) {
		gc->get = gpio_mmio_get_set;
		if (!chip->be_bits)
			gc->get_multiple = gpio_mmio_get_set_multiple;

Annotation

Implementation Notes