// SPDX-License-Identifier: GPL-2.0+ /* * Generic driver for memory-mapped GPIO controllers. * * Copyright 2008 MontaVista Software, Inc. * Copyright 2008,2010 Anton Vorontsov <cbouatmailru@gmail.com> * * ....``.```~~~~````.`.`.`.`.```````'',,,.........`````......`....... * ...`` ```````.. * ..The simplest form of a GPIO controller that the driver supports is`` * `.just a single "data" register, where GPIO state can be read and/or ` * `,..written. ,,..``~~~~ .....``.`.`.~~.```.`.........``````.``````` * ````````` ___ _/~~|___/~| . ```~~~~~~ ___/___\___ ,~.`.`.`.`````.~~...,,,,... __________|~$@~~~ %~ /o*o*o*o*o*o\ .. Implementing such a GPIO . o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` `....trivial..'~`.```.``` * ``````` * .```````~~~~`..`.``.``. * . The driver supports `... ,..```.`~~~```````````````....````.``,, * . big-endian notation, just`. .. A bit more sophisticated controllers , * . register the device with -be`. .with a pair of set/clear-bit registers , * `.. suffix. ```~~`````....`.` . affecting the data register and the .` * ``.`.``...``` ```.. output pins are also supported.` * ^^ `````.`````````.,``~``~``~~`````` * . ^^ * ,..`.`.`...````````````......`.`.`.`.`.`..`.`.`.. * .. The expectation is that in at least some cases . ,-~~~-, * .this will be used with roll-your-own ASIC/FPGA .` \ / * .logic in Verilog or VHDL. ~~~`````````..`````~~` \ / * ..````````......``````````` \o_ * | * ^^ / \ * * ...`````~~`.....``.`..........``````.`.``.```........``. * ` 8, 16, 32 and 64 bits registers are supported, and``. * . the number of GPIOs is determined by the width of ~ * .. the registers. ,............```.`.`..`.`.~~~.`.`.`~ * `.......````.```
*/
/* * This assumes that the bits in the GPIO register are in native endianness. * We only assign the function pointer if we have that.
*/ staticint bgpio_get_set_multiple(struct gpio_chip *gc, unsignedlong *mask, unsignedlong *bits)
{ unsignedlong get_mask = 0; unsignedlong set_mask = 0;
/* Make sure we first clear any bits that are zero when we read the register */
*bits &= ~*mask;
/* * This only works if the bits in the GPIO register are in native endianness.
*/ staticint bgpio_get_multiple(struct gpio_chip *gc, unsignedlong *mask, unsignedlong *bits)
{ /* Make sure we first clear any bits that are zero when we read the register */
*bits &= ~*mask;
*bits |= gc->read_reg(gc->reg_dat) & *mask; return 0;
}
/* * With big endian mirrored bit order it becomes more tedious.
*/ staticint bgpio_get_multiple_be(struct gpio_chip *gc, unsignedlong *mask, unsignedlong *bits)
{ unsignedlong readmask = 0; unsignedlong val; int bit;
/* Make sure we first clear any bits that are zero when we read the register */
*bits &= ~*mask;
/* Read the register */
val = gc->read_reg(gc->reg_dat) & readmask;
/* * Mirror the result into the "bits" result, this will give line 0 * in bit 0 ... line 31 in bit 31 for a 32bit register.
*/
for_each_set_bit(bit, &val, gc->ngpio)
*bits |= bgpio_line2mask(gc, bit);
switch (gc->bgpio_bits) { case 8:
gc->read_reg = bgpio_read8;
gc->write_reg = bgpio_write8; break; case 16: if (byte_be) {
gc->read_reg = bgpio_read16be;
gc->write_reg = bgpio_write16be;
} else {
gc->read_reg = bgpio_read16;
gc->write_reg = bgpio_write16;
} break; case 32: if (byte_be) {
gc->read_reg = bgpio_read32be;
gc->write_reg = bgpio_write32be;
} else {
gc->read_reg = bgpio_read32;
gc->write_reg = bgpio_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 {
gc->read_reg = bgpio_read64;
gc->write_reg = bgpio_write64;
} break; #endif/* BITS_PER_LONG >= 64 */ default:
dev_err(dev, "unsupported data width %u bits\n", gc->bgpio_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.
*/ staticint bgpio_setup_io(struct gpio_chip *gc, void __iomem *dat, void __iomem *set, void __iomem *clr, unsignedlong flags)
{
gc->reg_dat = dat; if (!gc->reg_dat) return -EINVAL;
if (!(flags & BGPIOF_UNREADABLE_REG_SET) &&
(flags & BGPIOF_READ_OUTPUT_REG_SET)) {
gc->get = bgpio_get_set; if (!gc->be_bits)
gc->get_multiple = bgpio_get_set_multiple; /* * We deliberately avoid assigning the ->get_multiple() call * for big endian mirrored registers which are ALSO reflecting * their value in the set register when used as output. It is * simply too much complexity, let the GPIO core fall back to * reading each line individually in that fringe case.
*/
} else {
gc->get = bgpio_get; if (gc->be_bits)
gc->get_multiple = bgpio_get_multiple_be; else
gc->get_multiple = bgpio_get_multiple;
}
if (chip->bgpio_pinctrl) return gpiochip_generic_request(chip, gpio_pin);
return 0;
}
/** * bgpio_init() - Initialize generic GPIO accessor functions * @gc: the GPIO chip to set up * @dev: the parent device of the new GPIO chip (compulsory) * @sz: the size (width) of the MMIO registers in bytes, typically 1, 2 or 4 * @dat: MMIO address for the register to READ the value of the GPIO lines, it * is expected that a 1 in the corresponding bit in this register means the * line is asserted * @set: MMIO address for the register to SET the value of the GPIO lines, it is * expected that we write the line with 1 in this register to drive the GPIO line * high. * @clr: MMIO address for the register to CLEAR the value of the GPIO lines, it is * expected that we write the line with 1 in this register to drive the GPIO line * low. It is allowed to leave this address as NULL, in that case the SET register * will be assumed to also clear the GPIO lines, by actively writing the line * with 0. * @dirout: MMIO address for the register to set the line as OUTPUT. It is assumed * that setting a line to 1 in this register will turn that line into an * output line. Conversely, setting the line to 0 will turn that line into * an input. * @dirin: MMIO address for the register to set this line as INPUT. It is assumed * that setting a line to 1 in this register will turn that line into an * input line. Conversely, setting the line to 0 will turn that line into * an output. * @flags: Different flags that will affect the behaviour of the device, such as * endianness etc.
*/ int bgpio_init(struct gpio_chip *gc, struct device *dev, unsignedlong sz, void __iomem *dat, void __iomem *set, void __iomem *clr, void __iomem *dirout, void __iomem *dirin, unsignedlong flags)
{ int ret;
ret = gpiochip_get_ngpios(gc, dev); if (ret)
gc->ngpio = gc->bgpio_bits;
ret = bgpio_setup_io(gc, dat, set, clr, flags); if (ret) return ret;
ret = bgpio_setup_accessors(dev, gc, flags & BGPIOF_BIG_ENDIAN_BYTE_ORDER); if (ret) return ret;
ret = bgpio_setup_direction(gc, dirout, dirin, flags); if (ret) return ret;
if (flags & BGPIOF_PINCTRL_BACKEND) {
gc->bgpio_pinctrl = true; /* Currently this callback is only used for pincontrol */
gc->free = gpiochip_generic_free;
}
if (flags & BGPIOF_UNREADABLE_REG_DIR)
gc->bgpio_dir_unreadable = true;
/* * Inspect hardware to find initial direction setting.
*/ if ((gc->reg_dir_out || gc->reg_dir_in) &&
!(flags & BGPIOF_UNREADABLE_REG_DIR)) { if (gc->reg_dir_out)
gc->bgpio_dir = gc->read_reg(gc->reg_dir_out); elseif (gc->reg_dir_in)
gc->bgpio_dir = ~gc->read_reg(gc->reg_dir_in); /* * If we have two direction registers, synchronise * input setting to output setting, the library * can not handle a line being input and output at * the same time.
*/ if (gc->reg_dir_out && gc->reg_dir_in)
gc->write_reg(gc->reg_dir_in, ~gc->bgpio_dir);
}
err = device_property_read_string(dev, "label", &label); if (!err)
gc->label = label;
/* * This property *must not* be used in device-tree sources, it's only * meant to be passed to the driver from board files and MFD core.
*/
err = device_property_read_u32(dev, "gpio-mmio,base", &base); if (!err && base <= INT_MAX)
gc->base = base;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.