2019-08-20 21:05:28 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
/*
|
|
|
|
* Copyright 2019 American Megatrends International LLC.
|
|
|
|
*
|
|
|
|
* Author: Karthikeyan Mani <karthikeyanm@amiindia.co.in>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/bitfield.h>
|
|
|
|
#include <linux/clk.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/platform_device.h>
|
2023-03-09 07:45:53 +00:00
|
|
|
#include <linux/seq_file.h>
|
2019-08-20 21:05:28 +00:00
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/string.h>
|
|
|
|
|
|
|
|
#define ASPEED_SGPIO_CTRL 0x54
|
|
|
|
|
|
|
|
#define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16)
|
|
|
|
#define ASPEED_SGPIO_ENABLE BIT(0)
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
#define ASPEED_SGPIO_PINS_SHIFT 6
|
|
|
|
|
|
|
|
struct aspeed_sgpio_pdata {
|
|
|
|
const u32 pin_mask;
|
|
|
|
};
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
struct aspeed_sgpio {
|
|
|
|
struct gpio_chip chip;
|
2023-03-09 07:45:53 +00:00
|
|
|
struct device *dev;
|
2019-08-20 21:05:28 +00:00
|
|
|
struct clk *pclk;
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spinlock_t lock;
|
2019-08-20 21:05:28 +00:00
|
|
|
void __iomem *base;
|
|
|
|
int irq;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct aspeed_sgpio_bank {
|
2021-07-12 10:03:13 +00:00
|
|
|
u16 val_regs;
|
|
|
|
u16 rdata_reg;
|
|
|
|
u16 irq_regs;
|
|
|
|
u16 tolerance_regs;
|
2019-08-20 21:05:28 +00:00
|
|
|
const char names[4][3];
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note: The "value" register returns the input value when the GPIO is
|
|
|
|
* configured as an input.
|
|
|
|
*
|
|
|
|
* The "rdata" register returns the output value when the GPIO is
|
|
|
|
* configured as an output.
|
|
|
|
*/
|
|
|
|
static const struct aspeed_sgpio_bank aspeed_sgpio_banks[] = {
|
|
|
|
{
|
|
|
|
.val_regs = 0x0000,
|
|
|
|
.rdata_reg = 0x0070,
|
|
|
|
.irq_regs = 0x0004,
|
2021-07-12 10:03:13 +00:00
|
|
|
.tolerance_regs = 0x0018,
|
2019-08-20 21:05:28 +00:00
|
|
|
.names = { "A", "B", "C", "D" },
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.val_regs = 0x001C,
|
|
|
|
.rdata_reg = 0x0074,
|
|
|
|
.irq_regs = 0x0020,
|
2021-07-12 10:03:13 +00:00
|
|
|
.tolerance_regs = 0x0034,
|
2019-08-20 21:05:28 +00:00
|
|
|
.names = { "E", "F", "G", "H" },
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.val_regs = 0x0038,
|
|
|
|
.rdata_reg = 0x0078,
|
|
|
|
.irq_regs = 0x003C,
|
2021-07-12 10:03:13 +00:00
|
|
|
.tolerance_regs = 0x0050,
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
.names = { "I", "J", "K", "L" },
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.val_regs = 0x0090,
|
|
|
|
.rdata_reg = 0x007C,
|
|
|
|
.irq_regs = 0x0094,
|
2021-07-12 10:03:13 +00:00
|
|
|
.tolerance_regs = 0x00A8,
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
.names = { "M", "N", "O", "P" },
|
2019-08-20 21:05:28 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
enum aspeed_sgpio_reg {
|
|
|
|
reg_val,
|
|
|
|
reg_rdata,
|
|
|
|
reg_irq_enable,
|
|
|
|
reg_irq_type0,
|
|
|
|
reg_irq_type1,
|
|
|
|
reg_irq_type2,
|
|
|
|
reg_irq_status,
|
2021-07-12 10:03:13 +00:00
|
|
|
reg_tolerance,
|
2019-08-20 21:05:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define GPIO_VAL_VALUE 0x00
|
|
|
|
#define GPIO_IRQ_ENABLE 0x00
|
|
|
|
#define GPIO_IRQ_TYPE0 0x04
|
|
|
|
#define GPIO_IRQ_TYPE1 0x08
|
|
|
|
#define GPIO_IRQ_TYPE2 0x0C
|
|
|
|
#define GPIO_IRQ_STATUS 0x10
|
|
|
|
|
|
|
|
static void __iomem *bank_reg(struct aspeed_sgpio *gpio,
|
|
|
|
const struct aspeed_sgpio_bank *bank,
|
|
|
|
const enum aspeed_sgpio_reg reg)
|
|
|
|
{
|
|
|
|
switch (reg) {
|
|
|
|
case reg_val:
|
|
|
|
return gpio->base + bank->val_regs + GPIO_VAL_VALUE;
|
|
|
|
case reg_rdata:
|
|
|
|
return gpio->base + bank->rdata_reg;
|
|
|
|
case reg_irq_enable:
|
|
|
|
return gpio->base + bank->irq_regs + GPIO_IRQ_ENABLE;
|
|
|
|
case reg_irq_type0:
|
|
|
|
return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE0;
|
|
|
|
case reg_irq_type1:
|
|
|
|
return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE1;
|
|
|
|
case reg_irq_type2:
|
|
|
|
return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2;
|
|
|
|
case reg_irq_status:
|
|
|
|
return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS;
|
2021-07-12 10:03:13 +00:00
|
|
|
case reg_tolerance:
|
|
|
|
return gpio->base + bank->tolerance_regs;
|
2019-08-20 21:05:28 +00:00
|
|
|
default:
|
|
|
|
/* acturally if code runs to here, it's an error case */
|
2019-12-10 20:28:31 +00:00
|
|
|
BUG();
|
2019-08-20 21:05:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
#define GPIO_BANK(x) ((x) >> 6)
|
|
|
|
#define GPIO_OFFSET(x) ((x) & GENMASK(5, 0))
|
|
|
|
#define GPIO_BIT(x) BIT(GPIO_OFFSET(x) >> 1)
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
|
|
|
|
{
|
2020-09-11 01:51:04 +00:00
|
|
|
unsigned int bank;
|
|
|
|
|
|
|
|
bank = GPIO_BANK(offset);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
WARN_ON(bank >= ARRAY_SIZE(aspeed_sgpio_banks));
|
|
|
|
return &aspeed_sgpio_banks[bank];
|
|
|
|
}
|
|
|
|
|
2020-09-11 01:51:04 +00:00
|
|
|
static int aspeed_sgpio_init_valid_mask(struct gpio_chip *gc,
|
|
|
|
unsigned long *valid_mask, unsigned int ngpios)
|
|
|
|
{
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
bitmap_set(valid_mask, 0, ngpios);
|
2020-09-11 01:51:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc,
|
|
|
|
unsigned long *valid_mask, unsigned int ngpios)
|
|
|
|
{
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
unsigned int i;
|
2020-09-11 01:51:04 +00:00
|
|
|
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
/* input GPIOs are even bits */
|
|
|
|
for (i = 0; i < ngpios; i++) {
|
|
|
|
if (i % 2)
|
|
|
|
clear_bit(i, valid_mask);
|
|
|
|
}
|
2020-09-11 01:51:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool aspeed_sgpio_is_input(unsigned int offset)
|
|
|
|
{
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
return !(offset % 2);
|
2020-09-11 01:51:04 +00:00
|
|
|
}
|
|
|
|
|
2019-08-20 21:05:28 +00:00
|
|
|
static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
|
|
|
|
{
|
|
|
|
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
|
|
|
const struct aspeed_sgpio_bank *bank = to_bank(offset);
|
|
|
|
unsigned long flags;
|
|
|
|
enum aspeed_sgpio_reg reg;
|
|
|
|
int rc = 0;
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_lock_irqsave(&gpio->lock, flags);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
2020-09-11 01:51:04 +00:00
|
|
|
reg = aspeed_sgpio_is_input(offset) ? reg_val : reg_rdata;
|
2019-08-20 21:05:28 +00:00
|
|
|
rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_unlock_irqrestore(&gpio->lock, flags);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2020-09-11 01:51:04 +00:00
|
|
|
static int sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
|
2019-08-20 21:05:28 +00:00
|
|
|
{
|
|
|
|
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
|
|
|
const struct aspeed_sgpio_bank *bank = to_bank(offset);
|
2020-09-11 01:51:04 +00:00
|
|
|
void __iomem *addr_r, *addr_w;
|
2019-08-20 21:05:28 +00:00
|
|
|
u32 reg = 0;
|
|
|
|
|
2020-09-11 01:51:04 +00:00
|
|
|
if (aspeed_sgpio_is_input(offset))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* Since this is an output, read the cached value from rdata, then
|
|
|
|
* update val. */
|
|
|
|
addr_r = bank_reg(gpio, bank, reg_rdata);
|
|
|
|
addr_w = bank_reg(gpio, bank, reg_val);
|
|
|
|
|
|
|
|
reg = ioread32(addr_r);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
if (val)
|
|
|
|
reg |= GPIO_BIT(offset);
|
|
|
|
else
|
|
|
|
reg &= ~GPIO_BIT(offset);
|
|
|
|
|
2020-09-11 01:51:04 +00:00
|
|
|
iowrite32(reg, addr_w);
|
|
|
|
|
|
|
|
return 0;
|
2019-08-20 21:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
|
|
|
|
{
|
|
|
|
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
|
|
|
unsigned long flags;
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_lock_irqsave(&gpio->lock, flags);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
sgpio_set_value(gc, offset, val);
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_unlock_irqrestore(&gpio->lock, flags);
|
2019-08-20 21:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
|
|
|
|
{
|
2020-09-11 01:51:04 +00:00
|
|
|
return aspeed_sgpio_is_input(offset) ? 0 : -EINVAL;
|
2019-08-20 21:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
|
|
|
|
{
|
|
|
|
struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
|
|
|
|
unsigned long flags;
|
2020-09-11 01:51:04 +00:00
|
|
|
int rc;
|
2019-08-20 21:05:28 +00:00
|
|
|
|
2020-09-11 01:51:04 +00:00
|
|
|
/* No special action is required for setting the direction; we'll
|
|
|
|
* error-out in sgpio_set_value if this isn't an output GPIO */
|
2019-08-20 21:05:28 +00:00
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_lock_irqsave(&gpio->lock, flags);
|
2020-09-11 01:51:04 +00:00
|
|
|
rc = sgpio_set_value(gc, offset, val);
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_unlock_irqrestore(&gpio->lock, flags);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
2020-09-11 01:51:04 +00:00
|
|
|
return rc;
|
2019-08-20 21:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int aspeed_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
|
|
|
{
|
2020-09-11 01:51:04 +00:00
|
|
|
return !!aspeed_sgpio_is_input(offset);
|
2019-08-20 21:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void irqd_to_aspeed_sgpio_data(struct irq_data *d,
|
|
|
|
struct aspeed_sgpio **gpio,
|
|
|
|
const struct aspeed_sgpio_bank **bank,
|
|
|
|
u32 *bit, int *offset)
|
|
|
|
{
|
|
|
|
struct aspeed_sgpio *internal;
|
|
|
|
|
|
|
|
*offset = irqd_to_hwirq(d);
|
|
|
|
internal = irq_data_get_irq_chip_data(d);
|
|
|
|
WARN_ON(!internal);
|
|
|
|
|
|
|
|
*gpio = internal;
|
|
|
|
*bank = to_bank(*offset);
|
|
|
|
*bit = GPIO_BIT(*offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void aspeed_sgpio_irq_ack(struct irq_data *d)
|
|
|
|
{
|
|
|
|
const struct aspeed_sgpio_bank *bank;
|
|
|
|
struct aspeed_sgpio *gpio;
|
|
|
|
unsigned long flags;
|
|
|
|
void __iomem *status_addr;
|
|
|
|
int offset;
|
|
|
|
u32 bit;
|
|
|
|
|
|
|
|
irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
|
|
|
|
|
|
|
|
status_addr = bank_reg(gpio, bank, reg_irq_status);
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_lock_irqsave(&gpio->lock, flags);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
iowrite32(bit, status_addr);
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_unlock_irqrestore(&gpio->lock, flags);
|
2019-08-20 21:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void aspeed_sgpio_irq_set_mask(struct irq_data *d, bool set)
|
|
|
|
{
|
|
|
|
const struct aspeed_sgpio_bank *bank;
|
|
|
|
struct aspeed_sgpio *gpio;
|
|
|
|
unsigned long flags;
|
|
|
|
u32 reg, bit;
|
|
|
|
void __iomem *addr;
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
|
|
|
|
addr = bank_reg(gpio, bank, reg_irq_enable);
|
|
|
|
|
2023-03-09 07:45:53 +00:00
|
|
|
/* Unmasking the IRQ */
|
|
|
|
if (set)
|
|
|
|
gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(d));
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_lock_irqsave(&gpio->lock, flags);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
reg = ioread32(addr);
|
|
|
|
if (set)
|
|
|
|
reg |= bit;
|
|
|
|
else
|
|
|
|
reg &= ~bit;
|
|
|
|
|
|
|
|
iowrite32(reg, addr);
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_unlock_irqrestore(&gpio->lock, flags);
|
2023-03-09 07:45:53 +00:00
|
|
|
|
|
|
|
/* Masking the IRQ */
|
|
|
|
if (!set)
|
|
|
|
gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(d));
|
|
|
|
|
|
|
|
|
2019-08-20 21:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void aspeed_sgpio_irq_mask(struct irq_data *d)
|
|
|
|
{
|
|
|
|
aspeed_sgpio_irq_set_mask(d, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void aspeed_sgpio_irq_unmask(struct irq_data *d)
|
|
|
|
{
|
|
|
|
aspeed_sgpio_irq_set_mask(d, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type)
|
|
|
|
{
|
|
|
|
u32 type0 = 0;
|
|
|
|
u32 type1 = 0;
|
|
|
|
u32 type2 = 0;
|
|
|
|
u32 bit, reg;
|
|
|
|
const struct aspeed_sgpio_bank *bank;
|
|
|
|
irq_flow_handler_t handler;
|
|
|
|
struct aspeed_sgpio *gpio;
|
|
|
|
unsigned long flags;
|
|
|
|
void __iomem *addr;
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
|
|
|
|
|
|
|
|
switch (type & IRQ_TYPE_SENSE_MASK) {
|
|
|
|
case IRQ_TYPE_EDGE_BOTH:
|
|
|
|
type2 |= bit;
|
2020-08-23 22:36:59 +00:00
|
|
|
fallthrough;
|
2019-08-20 21:05:28 +00:00
|
|
|
case IRQ_TYPE_EDGE_RISING:
|
|
|
|
type0 |= bit;
|
2020-08-23 22:36:59 +00:00
|
|
|
fallthrough;
|
2019-08-20 21:05:28 +00:00
|
|
|
case IRQ_TYPE_EDGE_FALLING:
|
|
|
|
handler = handle_edge_irq;
|
|
|
|
break;
|
|
|
|
case IRQ_TYPE_LEVEL_HIGH:
|
|
|
|
type0 |= bit;
|
2020-08-23 22:36:59 +00:00
|
|
|
fallthrough;
|
2019-08-20 21:05:28 +00:00
|
|
|
case IRQ_TYPE_LEVEL_LOW:
|
|
|
|
type1 |= bit;
|
|
|
|
handler = handle_level_irq;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_lock_irqsave(&gpio->lock, flags);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
addr = bank_reg(gpio, bank, reg_irq_type0);
|
|
|
|
reg = ioread32(addr);
|
|
|
|
reg = (reg & ~bit) | type0;
|
|
|
|
iowrite32(reg, addr);
|
|
|
|
|
|
|
|
addr = bank_reg(gpio, bank, reg_irq_type1);
|
|
|
|
reg = ioread32(addr);
|
|
|
|
reg = (reg & ~bit) | type1;
|
|
|
|
iowrite32(reg, addr);
|
|
|
|
|
|
|
|
addr = bank_reg(gpio, bank, reg_irq_type2);
|
|
|
|
reg = ioread32(addr);
|
|
|
|
reg = (reg & ~bit) | type2;
|
|
|
|
iowrite32(reg, addr);
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_unlock_irqrestore(&gpio->lock, flags);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
irq_set_handler_locked(d, handler);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void aspeed_sgpio_irq_handler(struct irq_desc *desc)
|
|
|
|
{
|
|
|
|
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
|
|
|
struct irq_chip *ic = irq_desc_get_chip(desc);
|
|
|
|
struct aspeed_sgpio *data = gpiochip_get_data(gc);
|
2021-05-04 16:42:18 +00:00
|
|
|
unsigned int i, p;
|
2019-08-20 21:05:28 +00:00
|
|
|
unsigned long reg;
|
|
|
|
|
|
|
|
chained_irq_enter(ic, desc);
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
|
|
|
|
const struct aspeed_sgpio_bank *bank = &aspeed_sgpio_banks[i];
|
|
|
|
|
|
|
|
reg = ioread32(bank_reg(data, bank, reg_irq_status));
|
|
|
|
|
2021-05-04 16:42:18 +00:00
|
|
|
for_each_set_bit(p, ®, 32)
|
2021-12-14 04:02:38 +00:00
|
|
|
generic_handle_domain_irq(gc->irq.domain, (i * 32 + p) * 2);
|
2019-08-20 21:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
chained_irq_exit(ic, desc);
|
|
|
|
}
|
|
|
|
|
2023-03-09 07:45:53 +00:00
|
|
|
static void aspeed_sgpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
|
|
|
|
{
|
|
|
|
const struct aspeed_sgpio_bank *bank;
|
|
|
|
struct aspeed_sgpio *gpio;
|
|
|
|
u32 bit;
|
|
|
|
int offset;
|
|
|
|
|
|
|
|
irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
|
|
|
|
seq_printf(p, dev_name(gpio->dev));
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct irq_chip aspeed_sgpio_irq_chip = {
|
|
|
|
.irq_ack = aspeed_sgpio_irq_ack,
|
|
|
|
.irq_mask = aspeed_sgpio_irq_mask,
|
|
|
|
.irq_unmask = aspeed_sgpio_irq_unmask,
|
|
|
|
.irq_set_type = aspeed_sgpio_set_type,
|
|
|
|
.irq_print_chip = aspeed_sgpio_irq_print_chip,
|
|
|
|
.flags = IRQCHIP_IMMUTABLE,
|
|
|
|
GPIOCHIP_IRQ_RESOURCE_HELPERS,
|
|
|
|
};
|
|
|
|
|
2019-08-20 21:05:28 +00:00
|
|
|
static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio,
|
|
|
|
struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
int rc, i;
|
|
|
|
const struct aspeed_sgpio_bank *bank;
|
|
|
|
struct gpio_irq_chip *irq;
|
|
|
|
|
|
|
|
rc = platform_get_irq(pdev, 0);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
gpio->irq = rc;
|
|
|
|
|
2020-01-18 10:53:19 +00:00
|
|
|
/* Disable IRQ and clear Interrupt status registers for all SGPIO Pins. */
|
2019-08-20 21:05:28 +00:00
|
|
|
for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
|
|
|
|
bank = &aspeed_sgpio_banks[i];
|
|
|
|
/* disable irq enable bits */
|
|
|
|
iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_enable));
|
|
|
|
/* clear status bits */
|
|
|
|
iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status));
|
|
|
|
}
|
|
|
|
|
|
|
|
irq = &gpio->chip.irq;
|
2023-03-09 07:45:53 +00:00
|
|
|
gpio_irq_chip_set_chip(irq, &aspeed_sgpio_irq_chip);
|
2020-09-11 01:51:04 +00:00
|
|
|
irq->init_valid_mask = aspeed_sgpio_irq_init_valid_mask;
|
2019-08-20 21:05:28 +00:00
|
|
|
irq->handler = handle_bad_irq;
|
|
|
|
irq->default_type = IRQ_TYPE_NONE;
|
|
|
|
irq->parent_handler = aspeed_sgpio_irq_handler;
|
|
|
|
irq->parent_handler_data = gpio;
|
|
|
|
irq->parents = &gpio->irq;
|
|
|
|
irq->num_parents = 1;
|
|
|
|
|
2020-09-11 01:51:05 +00:00
|
|
|
/* Apply default IRQ settings */
|
2019-08-20 21:05:28 +00:00
|
|
|
for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
|
|
|
|
bank = &aspeed_sgpio_banks[i];
|
|
|
|
/* set falling or level-low irq */
|
|
|
|
iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type0));
|
|
|
|
/* trigger type is edge */
|
|
|
|
iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type1));
|
2020-09-11 01:51:05 +00:00
|
|
|
/* single edge trigger */
|
|
|
|
iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type2));
|
2019-08-20 21:05:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
static const struct aspeed_sgpio_pdata ast2400_sgpio_pdata = {
|
|
|
|
.pin_mask = GENMASK(9, 6),
|
|
|
|
};
|
|
|
|
|
2021-07-12 10:03:13 +00:00
|
|
|
static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip,
|
|
|
|
unsigned int offset, bool enable)
|
|
|
|
{
|
|
|
|
struct aspeed_sgpio *gpio = gpiochip_get_data(chip);
|
|
|
|
unsigned long flags;
|
|
|
|
void __iomem *reg;
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
reg = bank_reg(gpio, to_bank(offset), reg_tolerance);
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_lock_irqsave(&gpio->lock, flags);
|
2021-07-12 10:03:13 +00:00
|
|
|
|
|
|
|
val = readl(reg);
|
|
|
|
|
|
|
|
if (enable)
|
|
|
|
val |= GPIO_BIT(offset);
|
|
|
|
else
|
|
|
|
val &= ~GPIO_BIT(offset);
|
|
|
|
|
|
|
|
writel(val, reg);
|
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_unlock_irqrestore(&gpio->lock, flags);
|
2021-07-12 10:03:13 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int aspeed_sgpio_set_config(struct gpio_chip *chip, unsigned int offset,
|
|
|
|
unsigned long config)
|
|
|
|
{
|
|
|
|
unsigned long param = pinconf_to_config_param(config);
|
|
|
|
u32 arg = pinconf_to_config_argument(config);
|
|
|
|
|
|
|
|
if (param == PIN_CONFIG_PERSIST_STATE)
|
|
|
|
return aspeed_sgpio_reset_tolerance(chip, offset, arg);
|
|
|
|
|
|
|
|
return -ENOTSUPP;
|
|
|
|
}
|
|
|
|
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
static const struct aspeed_sgpio_pdata ast2600_sgpiom_pdata = {
|
|
|
|
.pin_mask = GENMASK(10, 6),
|
|
|
|
};
|
|
|
|
|
2019-08-20 21:05:28 +00:00
|
|
|
static const struct of_device_id aspeed_sgpio_of_table[] = {
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
{ .compatible = "aspeed,ast2400-sgpio", .data = &ast2400_sgpio_pdata, },
|
|
|
|
{ .compatible = "aspeed,ast2500-sgpio", .data = &ast2400_sgpio_pdata, },
|
|
|
|
{ .compatible = "aspeed,ast2600-sgpiom", .data = &ast2600_sgpiom_pdata, },
|
2019-08-20 21:05:28 +00:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table);
|
|
|
|
|
|
|
|
static int __init aspeed_sgpio_probe(struct platform_device *pdev)
|
|
|
|
{
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
u32 nr_gpios, sgpio_freq, sgpio_clk_div, gpio_cnt_regval, pin_mask;
|
|
|
|
const struct aspeed_sgpio_pdata *pdata;
|
2019-08-20 21:05:28 +00:00
|
|
|
struct aspeed_sgpio *gpio;
|
|
|
|
unsigned long apb_freq;
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
int rc;
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
|
|
|
|
if (!gpio)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
gpio->base = devm_platform_ioremap_resource(pdev, 0);
|
|
|
|
if (IS_ERR(gpio->base))
|
|
|
|
return PTR_ERR(gpio->base);
|
|
|
|
|
2023-03-09 07:45:53 +00:00
|
|
|
gpio->dev = &pdev->dev;
|
|
|
|
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
pdata = device_get_match_data(&pdev->dev);
|
|
|
|
if (!pdata)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
pin_mask = pdata->pin_mask;
|
|
|
|
|
2021-07-12 10:03:15 +00:00
|
|
|
rc = device_property_read_u32(&pdev->dev, "ngpios", &nr_gpios);
|
2019-08-20 21:05:28 +00:00
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(&pdev->dev, "Could not read ngpios property\n");
|
|
|
|
return -EINVAL;
|
2021-07-12 10:03:16 +00:00
|
|
|
} else if (nr_gpios % 8) {
|
|
|
|
dev_err(&pdev->dev, "Number of GPIOs not multiple of 8: %d\n",
|
|
|
|
nr_gpios);
|
2019-08-20 21:05:28 +00:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2021-07-12 10:03:15 +00:00
|
|
|
rc = device_property_read_u32(&pdev->dev, "bus-frequency", &sgpio_freq);
|
2019-08-20 21:05:28 +00:00
|
|
|
if (rc < 0) {
|
|
|
|
dev_err(&pdev->dev, "Could not read bus-frequency property\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
gpio->pclk = devm_clk_get(&pdev->dev, NULL);
|
|
|
|
if (IS_ERR(gpio->pclk)) {
|
|
|
|
dev_err(&pdev->dev, "devm_clk_get failed\n");
|
|
|
|
return PTR_ERR(gpio->pclk);
|
|
|
|
}
|
|
|
|
|
|
|
|
apb_freq = clk_get_rate(gpio->pclk);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* From the datasheet,
|
|
|
|
* SGPIO period = 1/PCLK * 2 * (GPIO254[31:16] + 1)
|
|
|
|
* period = 2 * (GPIO254[31:16] + 1) / PCLK
|
|
|
|
* frequency = 1 / (2 * (GPIO254[31:16] + 1) / PCLK)
|
|
|
|
* frequency = PCLK / (2 * (GPIO254[31:16] + 1))
|
|
|
|
* frequency * 2 * (GPIO254[31:16] + 1) = PCLK
|
|
|
|
* GPIO254[31:16] = PCLK / (frequency * 2) - 1
|
|
|
|
*/
|
|
|
|
if (sgpio_freq == 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
sgpio_clk_div = (apb_freq / (sgpio_freq * 2)) - 1;
|
|
|
|
|
|
|
|
if (sgpio_clk_div > (1 << 16) - 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
gpio_cnt_regval = ((nr_gpios / 8) << ASPEED_SGPIO_PINS_SHIFT) & pin_mask;
|
|
|
|
iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | gpio_cnt_regval |
|
|
|
|
ASPEED_SGPIO_ENABLE, gpio->base + ASPEED_SGPIO_CTRL);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
2021-12-04 17:10:27 +00:00
|
|
|
raw_spin_lock_init(&gpio->lock);
|
2019-08-20 21:05:28 +00:00
|
|
|
|
|
|
|
gpio->chip.parent = &pdev->dev;
|
gpio: gpio-aspeed-sgpio: Add AST2600 sgpio support
The maximum number of gpio pins of SoC is hardcoded as 80 and the gpio pin
count mask for GPIO Configuration register is hardcode as GENMASK(9,6).
However, AST2600 has 2 sgpio master interfaces, one of them supports up
to 128 gpio pins and pin count mask of GPIO Configuration Register is 5
bits.
The patch adds ast2600 compatibles, removes MAX_NR_HW_SGPIO and
corresponding design to make the gpio input/output pin base are determined
by ngpios.
The patch also removed hardcoded pin mask and adds ast2400, ast2500,
ast2600 platform data that include gpio pin count mask for GPIO
Configuration Register.
The original pin order is as follows:
(suppose MAX_NR_HW_SGPIO is 80 and ngpios is 10 as well)
Input:
0 1 2 3 ... 9
Output:
80 81 82 ... 89
The new pin order is as follows:
Input:
0 2 4 6 ... 18
Output:
1 3 5 7 ... 19
SGPIO pin id and input/output pin mapping is as follows:
SGPIO0(0,1), SGPIO1(2,3), ..., SGPIO79(158,159)
For example:
Access SGPIO5(10,11)
Get SGPIO pin 5 (suppose sgpio chip id is 2)
gpioget 2 10
Set SGPIO pin 5 (suppose sgpio chip id is 2)
gpioset 2 11=1
gpioset 2 11=0
Signed-off-by: Steven Lee <steven_lee@aspeedtech.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
2021-07-12 10:03:12 +00:00
|
|
|
gpio->chip.ngpio = nr_gpios * 2;
|
2020-09-11 01:51:04 +00:00
|
|
|
gpio->chip.init_valid_mask = aspeed_sgpio_init_valid_mask;
|
2019-08-20 21:05:28 +00:00
|
|
|
gpio->chip.direction_input = aspeed_sgpio_dir_in;
|
|
|
|
gpio->chip.direction_output = aspeed_sgpio_dir_out;
|
|
|
|
gpio->chip.get_direction = aspeed_sgpio_get_direction;
|
|
|
|
gpio->chip.request = NULL;
|
|
|
|
gpio->chip.free = NULL;
|
|
|
|
gpio->chip.get = aspeed_sgpio_get;
|
|
|
|
gpio->chip.set = aspeed_sgpio_set;
|
2021-07-12 10:03:13 +00:00
|
|
|
gpio->chip.set_config = aspeed_sgpio_set_config;
|
2019-08-20 21:05:28 +00:00
|
|
|
gpio->chip.label = dev_name(&pdev->dev);
|
|
|
|
gpio->chip.base = -1;
|
|
|
|
|
|
|
|
aspeed_sgpio_setup_irqs(gpio, pdev);
|
|
|
|
|
|
|
|
rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
|
|
|
|
if (rc < 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct platform_driver aspeed_sgpio_driver = {
|
|
|
|
.driver = {
|
|
|
|
.name = KBUILD_MODNAME,
|
|
|
|
.of_match_table = aspeed_sgpio_of_table,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
module_platform_driver_probe(aspeed_sgpio_driver, aspeed_sgpio_probe);
|
|
|
|
MODULE_DESCRIPTION("Aspeed Serial GPIO Driver");
|