// SPDX-License-Identifier: GPL-2.0-or-later/* * Copyright 2015 IBM Corp. * * Joel Stanley <joel@jms.id.au> */#include<linux/clk.h>#include<linux/gpio/aspeed.h>#include<linux/gpio/driver.h>#include<linux/hashtable.h>#include<linux/init.h>#include<linux/io.h>#include<linux/kernel.h>#include<linux/module.h>#include<linux/pinctrl/consumer.h>#include<linux/platform_device.h>#include<linux/seq_file.h>#include<linux/spinlock.h>#include<linux/string.h>#include<asm/div64.h>/* * These two headers aren't meant to be used by GPIO drivers. We need * them in order to access gpio_chip_hwgpio() which we need to implement * the aspeed specific API which allows the coprocessor to request * access to some GPIOs and to arbitrate between coprocessor and ARM. */#include<linux/gpio/consumer.h>#include"gpiolib.h"/* Non-constant mask variant of FIELD_GET() and FIELD_PREP() */#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))#define GPIO_G7_IRQ_STS_BASE 0x100#define GPIO_G7_IRQ_STS_OFFSET(x) (GPIO_G7_IRQ_STS_BASE + (x) * 0x4)#define GPIO_G7_CTRL_REG_BASE 0x180#define GPIO_G7_CTRL_REG_OFFSET(x) (GPIO_G7_CTRL_REG_BASE + (x) * 0x4)#define GPIO_G7_CTRL_OUT_DATA BIT(0)#define GPIO_G7_CTRL_DIR BIT(1)#define GPIO_G7_CTRL_IRQ_EN BIT(2)#define GPIO_G7_CTRL_IRQ_TYPE0 BIT(3)#define GPIO_G7_CTRL_IRQ_TYPE1 BIT(4)#define GPIO_G7_CTRL_IRQ_TYPE2 BIT(5)#define GPIO_G7_CTRL_RST_TOLERANCE BIT(6)#define GPIO_G7_CTRL_DEBOUNCE_SEL1 BIT(7)#define GPIO_G7_CTRL_DEBOUNCE_SEL2 BIT(8)#define GPIO_G7_CTRL_INPUT_MASK BIT(9)#define GPIO_G7_CTRL_IRQ_STS BIT(12)#define GPIO_G7_CTRL_IN_DATA BIT(13)structaspeed_bank_props{unsignedintbank;u32input;u32output;};structaspeed_gpio_config{unsignedintnr_gpios;conststructaspeed_bank_props*props;conststructaspeed_gpio_llops*llops;constint*debounce_timers_array;intdebounce_timers_num;boolrequire_dcache;};/* * @offset_timer: Maps an offset to an @timer_users index, or zero if disabled * @timer_users: Tracks the number of users for each timer * * The @timer_users has four elements but the first element is unused. This is * to simplify accounting and indexing, as a zero value in @offset_timer * represents disabled debouncing for the GPIO. Any other value for an element * of @offset_timer is used as an index into @timer_users. This behaviour of * the zero value aligns with the behaviour of zero built from the timer * configuration registers (i.e. debouncing is disabled). */structaspeed_gpio{structgpio_chipchip;structdevice*dev;raw_spinlock_tlock;void__iomem*base;intirq;conststruct