Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * License.  See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2016, 2017 Cavium Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/gpio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <asm-generic/msi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define GPIO_RX_DAT	0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define GPIO_TX_SET	0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define GPIO_TX_CLR	0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define GPIO_CONST	0x90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #define  GPIO_CONST_GPIOS_MASK 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define GPIO_BIT_CFG	0x400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define  GPIO_BIT_CFG_TX_OE		BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define  GPIO_BIT_CFG_PIN_XOR		BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define  GPIO_BIT_CFG_INT_EN		BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define  GPIO_BIT_CFG_INT_TYPE		BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define  GPIO_BIT_CFG_FIL_MASK		GENMASK(11, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define  GPIO_BIT_CFG_FIL_CNT_SHIFT	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define  GPIO_BIT_CFG_FIL_SEL_SHIFT	8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define  GPIO_BIT_CFG_TX_OD		BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define  GPIO_BIT_CFG_PIN_SEL_MASK	GENMASK(25, 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define GPIO_INTR	0x800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define  GPIO_INTR_INTR			BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define  GPIO_INTR_INTR_W1S		BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define  GPIO_INTR_ENA_W1C		BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define  GPIO_INTR_ENA_W1S		BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define GPIO_2ND_BANK	0x1400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define GLITCH_FILTER_400NS ((4u << GPIO_BIT_CFG_FIL_SEL_SHIFT) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 			     (9u << GPIO_BIT_CFG_FIL_CNT_SHIFT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) struct thunderx_gpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) struct thunderx_line {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	struct thunderx_gpio	*txgpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	unsigned int		line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	unsigned int		fil_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) struct thunderx_gpio {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	struct gpio_chip	chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	u8 __iomem		*register_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	struct msix_entry	*msix_entries;	/* per line MSI-X */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	struct thunderx_line	*line_entries;	/* per line irq info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	raw_spinlock_t		lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	unsigned long		invert_mask[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	unsigned long		od_mask[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	int			base_msi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) static unsigned int bit_cfg_reg(unsigned int line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	return 8 * line + GPIO_BIT_CFG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) static unsigned int intr_reg(unsigned int line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	return 8 * line + GPIO_INTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) static bool thunderx_gpio_is_gpio_nowarn(struct thunderx_gpio *txgpio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 					 unsigned int line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	u64 bit_cfg = readq(txgpio->register_base + bit_cfg_reg(line));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	return (bit_cfg & GPIO_BIT_CFG_PIN_SEL_MASK) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * Check (and WARN) that the pin is available for GPIO.  We will not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * allow modification of the state of non-GPIO pins from this driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) static bool thunderx_gpio_is_gpio(struct thunderx_gpio *txgpio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 				  unsigned int line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	bool rv = thunderx_gpio_is_gpio_nowarn(txgpio, line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	WARN_RATELIMIT(!rv, "Pin %d not available for GPIO\n", line);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	return rv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) static int thunderx_gpio_request(struct gpio_chip *chip, unsigned int line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	return thunderx_gpio_is_gpio(txgpio, line) ? 0 : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int thunderx_gpio_dir_in(struct gpio_chip *chip, unsigned int line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	if (!thunderx_gpio_is_gpio(txgpio, line))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	raw_spin_lock(&txgpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	clear_bit(line, txgpio->invert_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	clear_bit(line, txgpio->od_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	writeq(txgpio->line_entries[line].fil_bits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	       txgpio->register_base + bit_cfg_reg(line));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	raw_spin_unlock(&txgpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static void thunderx_gpio_set(struct gpio_chip *chip, unsigned int line,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			      int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	int bank = line / 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	int bank_bit = line % 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	void __iomem *reg = txgpio->register_base +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		(bank * GPIO_2ND_BANK) + (value ? GPIO_TX_SET : GPIO_TX_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	writeq(BIT_ULL(bank_bit), reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int thunderx_gpio_dir_out(struct gpio_chip *chip, unsigned int line,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 				 int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	u64 bit_cfg = txgpio->line_entries[line].fil_bits | GPIO_BIT_CFG_TX_OE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	if (!thunderx_gpio_is_gpio(txgpio, line))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	raw_spin_lock(&txgpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	thunderx_gpio_set(chip, line, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	if (test_bit(line, txgpio->invert_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		bit_cfg |= GPIO_BIT_CFG_PIN_XOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	if (test_bit(line, txgpio->od_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		bit_cfg |= GPIO_BIT_CFG_TX_OD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(line));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	raw_spin_unlock(&txgpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int thunderx_gpio_get_direction(struct gpio_chip *chip, unsigned int line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	u64 bit_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	if (!thunderx_gpio_is_gpio_nowarn(txgpio, line))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		 * Say it is input for now to avoid WARNing on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		 * gpiochip_add_data().  We will WARN if someone
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		 * requests it or tries to use it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	bit_cfg = readq(txgpio->register_base + bit_cfg_reg(line));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	if (bit_cfg & GPIO_BIT_CFG_TX_OE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		return GPIO_LINE_DIRECTION_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	return GPIO_LINE_DIRECTION_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int thunderx_gpio_set_config(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 				    unsigned int line,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 				    unsigned long cfg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	bool orig_invert, orig_od, orig_dat, new_invert, new_od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	u32 arg, sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	u64 bit_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	int bank = line / 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	int bank_bit = line % 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	int ret = -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	void __iomem *reg = txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	if (!thunderx_gpio_is_gpio(txgpio, line))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	raw_spin_lock(&txgpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	orig_invert = test_bit(line, txgpio->invert_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	new_invert  = orig_invert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	orig_od = test_bit(line, txgpio->od_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	new_od = orig_od;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	orig_dat = ((readq(reg) >> bank_bit) & 1) ^ orig_invert;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	bit_cfg = readq(txgpio->register_base + bit_cfg_reg(line));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	switch (pinconf_to_config_param(cfg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		 * Weird, setting open-drain mode causes signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		 * inversion.  Note this so we can compensate in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		 * dir_out function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		set_bit(line, txgpio->invert_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		new_invert  = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		set_bit(line, txgpio->od_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		new_od = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	case PIN_CONFIG_DRIVE_PUSH_PULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		clear_bit(line, txgpio->invert_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		new_invert  = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		clear_bit(line, txgpio->od_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		new_od  = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	case PIN_CONFIG_INPUT_DEBOUNCE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		arg = pinconf_to_config_argument(cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		if (arg > 1228) { /* 15 * 2^15 * 2.5nS maximum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 			ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		arg *= 400; /* scale to 2.5nS clocks. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		sel = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		while (arg > 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 			sel++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 			arg++; /* always round up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 			arg >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 		txgpio->line_entries[line].fil_bits =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 			(sel << GPIO_BIT_CFG_FIL_SEL_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 			(arg << GPIO_BIT_CFG_FIL_CNT_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		bit_cfg &= ~GPIO_BIT_CFG_FIL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		bit_cfg |= txgpio->line_entries[line].fil_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(line));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	raw_spin_unlock(&txgpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	 * If currently output and OPEN_DRAIN changed, install the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	 * settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	if ((new_invert != orig_invert || new_od != orig_od) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	    (bit_cfg & GPIO_BIT_CFG_TX_OE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		ret = thunderx_gpio_dir_out(chip, line, orig_dat ^ new_invert);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static int thunderx_gpio_get(struct gpio_chip *chip, unsigned int line)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	int bank = line / 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	int bank_bit = line % 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	u64 read_bits = readq(txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_RX_DAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	u64 masked_bits = read_bits & BIT_ULL(bank_bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	if (test_bit(line, txgpio->invert_mask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		return masked_bits == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		return masked_bits != 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static void thunderx_gpio_set_multiple(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 				       unsigned long *mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 				       unsigned long *bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	int bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	u64 set_bits, clear_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	for (bank = 0; bank <= chip->ngpio / 64; bank++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		set_bits = bits[bank] & mask[bank];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		clear_bits = ~bits[bank] & mask[bank];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		writeq(set_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_SET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		writeq(clear_bits, txgpio->register_base + (bank * GPIO_2ND_BANK) + GPIO_TX_CLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) static void thunderx_gpio_irq_ack(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	writeq(GPIO_INTR_INTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	       txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static void thunderx_gpio_irq_mask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	writeq(GPIO_INTR_ENA_W1C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	       txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static void thunderx_gpio_irq_mask_ack(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	       txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static void thunderx_gpio_irq_unmask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	writeq(GPIO_INTR_ENA_W1S,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	       txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static int thunderx_gpio_irq_set_type(struct irq_data *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 				      unsigned int flow_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	struct thunderx_line *txline =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		&txgpio->line_entries[irqd_to_hwirq(d)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	u64 bit_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	irqd_set_trigger_type(d, flow_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	if (flow_type & IRQ_TYPE_EDGE_BOTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		irq_set_handler_locked(d, handle_fasteoi_ack_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		bit_cfg |= GPIO_BIT_CFG_INT_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		irq_set_handler_locked(d, handle_fasteoi_mask_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	raw_spin_lock(&txgpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	if (flow_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		bit_cfg |= GPIO_BIT_CFG_PIN_XOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		set_bit(txline->line, txgpio->invert_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		clear_bit(txline->line, txgpio->invert_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	clear_bit(txline->line, txgpio->od_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	writeq(bit_cfg, txgpio->register_base + bit_cfg_reg(txline->line));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	raw_spin_unlock(&txgpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	return IRQ_SET_MASK_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) static void thunderx_gpio_irq_enable(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	irq_chip_enable_parent(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	thunderx_gpio_irq_unmask(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static void thunderx_gpio_irq_disable(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	thunderx_gpio_irq_mask(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	irq_chip_disable_parent(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)  * Interrupts are chained from underlying MSI-X vectors.  We have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)  * these irq_chip functions to be able to handle level triggering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)  * semantics and other acknowledgment tasks associated with the GPIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)  * mechanism.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static struct irq_chip thunderx_gpio_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	.name			= "GPIO",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	.irq_enable		= thunderx_gpio_irq_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	.irq_disable		= thunderx_gpio_irq_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	.irq_ack		= thunderx_gpio_irq_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	.irq_mask		= thunderx_gpio_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 	.irq_mask_ack		= thunderx_gpio_irq_mask_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 	.irq_unmask		= thunderx_gpio_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	.irq_eoi		= irq_chip_eoi_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	.irq_set_affinity	= irq_chip_set_affinity_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	.irq_set_type		= thunderx_gpio_irq_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	.flags			= IRQCHIP_SET_TYPE_MASKED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 					       unsigned int child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 					       unsigned int child_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 					       unsigned int *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 					       unsigned int *parent_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	struct irq_data *irqd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	unsigned int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	irq = txgpio->msix_entries[child].vector;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	irqd = irq_domain_get_irq_data(gc->irq.parent_domain, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	if (!irqd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	*parent = irqd_to_hwirq(irqd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	*parent_type = IRQ_TYPE_LEVEL_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static void *thunderx_gpio_populate_parent_alloc_info(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 						      unsigned int parent_hwirq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 						      unsigned int parent_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	msi_alloc_info_t *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	info = kmalloc(sizeof(*info), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	info->hwirq = parent_hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	return info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int thunderx_gpio_probe(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 			       const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	void __iomem * const *tbl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	struct thunderx_gpio *txgpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	struct gpio_chip *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	struct gpio_irq_chip *girq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	int ngpio, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 	int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	txgpio = devm_kzalloc(dev, sizeof(*txgpio), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	if (!txgpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	raw_spin_lock_init(&txgpio->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	chip = &txgpio->chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	pci_set_drvdata(pdev, txgpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	err = pcim_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		dev_err(dev, "Failed to enable PCI device: err %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	err = pcim_iomap_regions(pdev, 1 << 0, KBUILD_MODNAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) 	if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 		dev_err(dev, "Failed to iomap PCI device: err %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	tbl = pcim_iomap_table(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	txgpio->register_base = tbl[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	if (!txgpio->register_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 		dev_err(dev, "Cannot map PCI resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 		err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	if (pdev->subsystem_device == 0xa10a) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 		/* CN88XX has no GPIO_CONST register*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 		ngpio = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 		txgpio->base_msi = 48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		u64 c = readq(txgpio->register_base + GPIO_CONST);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 		ngpio = c & GPIO_CONST_GPIOS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		txgpio->base_msi = (c >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	txgpio->msix_entries = devm_kcalloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 					    ngpio, sizeof(struct msix_entry),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 					    GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	if (!txgpio->msix_entries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	txgpio->line_entries = devm_kcalloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 					    ngpio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 					    sizeof(struct thunderx_line),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 					    GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	if (!txgpio->line_entries) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	for (i = 0; i < ngpio; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		u64 bit_cfg = readq(txgpio->register_base + bit_cfg_reg(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 		txgpio->msix_entries[i].entry = txgpio->base_msi + (2 * i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 		txgpio->line_entries[i].line = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 		txgpio->line_entries[i].txgpio = txgpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 		 * If something has already programmed the pin, use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		 * the existing glitch filter settings, otherwise go
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 		 * to 400nS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 		txgpio->line_entries[i].fil_bits = bit_cfg ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 			(bit_cfg & GPIO_BIT_CFG_FIL_MASK) : GLITCH_FILTER_400NS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 		if ((bit_cfg & GPIO_BIT_CFG_TX_OE) && (bit_cfg & GPIO_BIT_CFG_TX_OD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 			set_bit(i, txgpio->od_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		if (bit_cfg & GPIO_BIT_CFG_PIN_XOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 			set_bit(i, txgpio->invert_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 	/* Enable all MSI-X for interrupts on all possible lines. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 	err = pci_enable_msix_range(pdev, txgpio->msix_entries, ngpio, ngpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 	if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	chip->label = KBUILD_MODNAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	chip->parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	chip->owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	chip->request = thunderx_gpio_request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	chip->base = -1; /* System allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 	chip->can_sleep = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 	chip->ngpio = ngpio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	chip->get_direction = thunderx_gpio_get_direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	chip->direction_input = thunderx_gpio_dir_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	chip->get = thunderx_gpio_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	chip->direction_output = thunderx_gpio_dir_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	chip->set = thunderx_gpio_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	chip->set_multiple = thunderx_gpio_set_multiple;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	chip->set_config = thunderx_gpio_set_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 	girq = &chip->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 	girq->chip = &thunderx_gpio_irq_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 	girq->fwnode = of_node_to_fwnode(dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 	girq->parent_domain =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 		irq_get_irq_data(txgpio->msix_entries[0].vector)->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	girq->populate_parent_alloc_arg = thunderx_gpio_populate_parent_alloc_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	girq->handler = handle_bad_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	girq->default_type = IRQ_TYPE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	err = devm_gpiochip_add_data(dev, chip, txgpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	/* Push on irq_data and the domain for each line. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	for (i = 0; i < ngpio; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		struct irq_fwspec fwspec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		fwspec.fwnode = of_node_to_fwnode(dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 		fwspec.param_count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 		fwspec.param[0] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		fwspec.param[1] = IRQ_TYPE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		err = irq_domain_push_irq(girq->domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 					  txgpio->msix_entries[i].vector,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 					  &fwspec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 		if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 			dev_err(dev, "irq_domain_push_irq: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		 ngpio, chip->base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 	pci_set_drvdata(pdev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) static void thunderx_gpio_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	struct thunderx_gpio *txgpio = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	for (i = 0; i < txgpio->chip.ngpio; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 		irq_domain_pop_irq(txgpio->chip.irq.domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 				   txgpio->msix_entries[i].vector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	irq_domain_remove(txgpio->chip.irq.domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	pci_set_drvdata(pdev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static const struct pci_device_id thunderx_gpio_id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xA00A) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 	{ 0, }	/* end of table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) MODULE_DEVICE_TABLE(pci, thunderx_gpio_id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static struct pci_driver thunderx_gpio_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 	.name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 	.id_table = thunderx_gpio_id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	.probe = thunderx_gpio_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 	.remove = thunderx_gpio_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) module_pci_driver(thunderx_gpio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) MODULE_DESCRIPTION("Cavium Inc. ThunderX/OCTEON-TX GPIO Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) MODULE_LICENSE("GPL");