/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2016, 2017 Cavium Inc.
*/
/* * Check (and WARN) that the pin is available for GPIO. We will not * allow modification of the state of non-GPIO pins from this driver.
*/ staticbool thunderx_gpio_is_gpio(struct thunderx_gpio *txgpio, unsignedint line)
{ bool rv = thunderx_gpio_is_gpio_nowarn(txgpio, line);
WARN_RATELIMIT(!rv, "Pin %d not available for GPIO\n", line);
staticint thunderx_gpio_set(struct gpio_chip *chip, unsignedint line, int value)
{ struct thunderx_gpio *txgpio = gpiochip_get_data(chip); int bank = line / 64; int bank_bit = line % 64;
if (!thunderx_gpio_is_gpio_nowarn(txgpio, line)) /* * Say it is input for now to avoid WARNing on * gpiochip_add_data(). We will WARN if someone * requests it or tries to use it.
*/ return 1;
if (bit_cfg & GPIO_BIT_CFG_TX_OE) return GPIO_LINE_DIRECTION_OUT;
return GPIO_LINE_DIRECTION_IN;
}
staticint thunderx_gpio_set_config(struct gpio_chip *chip, unsignedint line, unsignedlong cfg)
{ bool orig_invert, orig_od, orig_dat, new_invert, new_od;
u32 arg, sel;
u64 bit_cfg; int bank = line / 64; int bank_bit = line % 64; int ret = -ENOTSUPP; struct thunderx_gpio *txgpio = gpiochip_get_data(chip); void __iomem *reg = txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET;
if (!thunderx_gpio_is_gpio(txgpio, line)) return -EIO;
raw_spin_lock(&txgpio->lock);
orig_invert = test_bit(line, txgpio->invert_mask);
new_invert = orig_invert;
orig_od = test_bit(line, txgpio->od_mask);
new_od = orig_od;
orig_dat = ((readq(reg) >> bank_bit) & 1) ^ orig_invert;
bit_cfg = readq(txgpio->register_base + bit_cfg_reg(line)); switch (pinconf_to_config_param(cfg)) { case PIN_CONFIG_DRIVE_OPEN_DRAIN: /* * Weird, setting open-drain mode causes signal * inversion. Note this so we can compensate in the * dir_out function.
*/
set_bit(line, txgpio->invert_mask);
new_invert = true;
set_bit(line, txgpio->od_mask);
new_od = true;
ret = 0; break; case PIN_CONFIG_DRIVE_PUSH_PULL:
clear_bit(line, txgpio->invert_mask);
new_invert = false;
clear_bit(line, txgpio->od_mask);
new_od = false;
ret = 0; break; case PIN_CONFIG_INPUT_DEBOUNCE:
arg = pinconf_to_config_argument(cfg); if (arg > 1228) { /* 15 * 2^15 * 2.5nS maximum */
ret = -EINVAL; break;
}
arg *= 400; /* scale to 2.5nS clocks. */
sel = 0; while (arg > 15) {
sel++;
arg++; /* always round up */
arg >>= 1;
}
txgpio->line_entries[line].fil_bits =
(sel << GPIO_BIT_CFG_FIL_SEL_SHIFT) |
(arg << GPIO_BIT_CFG_FIL_CNT_SHIFT);
bit_cfg &= ~GPIO_BIT_CFG_FIL_MASK;
bit_cfg |= txgpio->line_entries[line].fil_bits;
writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(line));
ret = 0; break; default: break;
}
raw_spin_unlock(&txgpio->lock);
/* * If currently output and OPEN_DRAIN changed, install the new * settings
*/ if ((new_invert != orig_invert || new_od != orig_od) &&
(bit_cfg & GPIO_BIT_CFG_TX_OE))
ret = thunderx_gpio_dir_out(chip, line, orig_dat ^ new_invert);
return ret;
}
staticint thunderx_gpio_get(struct gpio_chip *chip, unsignedint line)
{ struct thunderx_gpio *txgpio = gpiochip_get_data(chip); int bank = line / 64; int bank_bit = line % 64;
u64 read_bits = readq(txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_RX_DAT);
u64 masked_bits = read_bits & BIT_ULL(bank_bit);
for (i = 0; i < ngpio; i++) {
u64 bit_cfg = readq(txgpio->register_base + bit_cfg_reg(i));
txgpio->msix_entries[i].entry = txgpio->base_msi + (2 * i);
txgpio->line_entries[i].line = i;
txgpio->line_entries[i].txgpio = txgpio; /* * If something has already programmed the pin, use * the existing glitch filter settings, otherwise go * to 400nS.
*/
txgpio->line_entries[i].fil_bits = bit_cfg ?
(bit_cfg & GPIO_BIT_CFG_FIL_MASK) : GLITCH_FILTER_400NS;
if ((bit_cfg & GPIO_BIT_CFG_TX_OE) && (bit_cfg & GPIO_BIT_CFG_TX_OD))
set_bit(i, txgpio->od_mask); if (bit_cfg & GPIO_BIT_CFG_PIN_XOR)
set_bit(i, txgpio->invert_mask);
}
/* Enable all MSI-X for interrupts on all possible lines. */
err = pci_enable_msix_range(pdev, txgpio->msix_entries, ngpio, ngpio); if (err < 0) goto out;
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.