Skip to content

Commit 274ea0f

Browse files
billy-tsaiBartosz Golaszewski
authored andcommitted
gpio: aspeed-sgpio: Support G7 Aspeed sgpiom controller
In the 7th generation of the SoC from Aspeed, the control logic of the SGPIO controller has been updated to support per-pin control. Each pin now has its own 32-bit register, allowing for individual control of the pin's value, interrupt type, and other settings. Reviewed-by: Linus Walleij <linusw@kernel.org> Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com> Link: https://lore.kernel.org/r/20260123-upstream_sgpio-v2-6-69cfd1631400@aspeedtech.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
1 parent 1494700 commit 274ea0f

1 file changed

Lines changed: 108 additions & 2 deletions

File tree

drivers/gpio/gpio-aspeed-sgpio.c

Lines changed: 108 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,31 @@
1919
#include <linux/spinlock.h>
2020
#include <linux/string.h>
2121

22-
#define ASPEED_SGPIO_CTRL 0x54
22+
#define SGPIO_G7_IRQ_STS_BASE 0x40
23+
#define SGPIO_G7_IRQ_STS_OFFSET(x) (SGPIO_G7_IRQ_STS_BASE + (x) * 0x4)
24+
#define SGPIO_G7_CTRL_REG_BASE 0x80
25+
#define SGPIO_G7_CTRL_REG_OFFSET(x) (SGPIO_G7_CTRL_REG_BASE + (x) * 0x4)
26+
#define SGPIO_G7_OUT_DATA BIT(0)
27+
#define SGPIO_G7_PARALLEL_OUT_DATA BIT(1)
28+
#define SGPIO_G7_IRQ_EN BIT(2)
29+
#define SGPIO_G7_IRQ_TYPE0 BIT(3)
30+
#define SGPIO_G7_IRQ_TYPE1 BIT(4)
31+
#define SGPIO_G7_IRQ_TYPE2 BIT(5)
32+
#define SGPIO_G7_RST_TOLERANCE BIT(6)
33+
#define SGPIO_G7_INPUT_MASK BIT(9)
34+
#define SGPIO_G7_HW_BYPASS_EN BIT(10)
35+
#define SGPIO_G7_HW_IN_SEL BIT(11)
36+
#define SGPIO_G7_IRQ_STS BIT(12)
37+
#define SGPIO_G7_IN_DATA BIT(13)
38+
#define SGPIO_G7_PARALLEL_IN_DATA BIT(14)
39+
#define SGPIO_G7_SERIAL_OUT_SEL GENMASK(17, 16)
40+
#define SGPIO_G7_PARALLEL_OUT_SEL GENMASK(19, 18)
41+
#define SELECT_FROM_CSR 0
42+
#define SELECT_FROM_PARALLEL_IN 1
43+
#define SELECT_FROM_SERIAL_IN 2
44+
45+
#define ASPEED_SGPIO_G4_CFG_OFFSET 0x54
46+
#define ASPEED_SGPIO_G7_CFG_OFFSET 0x0
2347

2448
#define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16)
2549
#define ASPEED_SGPIO_ENABLE BIT(0)
@@ -28,6 +52,7 @@
2852
struct aspeed_sgpio_pdata {
2953
const u32 pin_mask;
3054
const struct aspeed_sgpio_llops *llops;
55+
const u32 cfg_offset;
3156
};
3257

3358
struct aspeed_sgpio {
@@ -135,6 +160,30 @@ static void __iomem *aspeed_sgpio_g4_bank_reg(struct aspeed_sgpio *gpio,
135160
}
136161
}
137162

163+
static u32 aspeed_sgpio_g7_reg_mask(const enum aspeed_sgpio_reg reg)
164+
{
165+
switch (reg) {
166+
case reg_val:
167+
case reg_rdata:
168+
return SGPIO_G7_OUT_DATA;
169+
case reg_irq_enable:
170+
return SGPIO_G7_IRQ_EN;
171+
case reg_irq_type0:
172+
return SGPIO_G7_IRQ_TYPE0;
173+
case reg_irq_type1:
174+
return SGPIO_G7_IRQ_TYPE1;
175+
case reg_irq_type2:
176+
return SGPIO_G7_IRQ_TYPE2;
177+
case reg_irq_status:
178+
return SGPIO_G7_IRQ_STS;
179+
case reg_tolerance:
180+
return SGPIO_G7_RST_TOLERANCE;
181+
default:
182+
WARN_ON_ONCE(1);
183+
return 0;
184+
}
185+
}
186+
138187
#define GPIO_BANK(x) ((x) >> 6)
139188
#define GPIO_OFFSET(x) ((x) & GENMASK(5, 0))
140189
#define GPIO_BIT(x) BIT(GPIO_OFFSET(x) >> 1)
@@ -457,6 +506,7 @@ static const struct aspeed_sgpio_llops aspeed_sgpio_g4_llops = {
457506
static const struct aspeed_sgpio_pdata ast2400_sgpio_pdata = {
458507
.pin_mask = GENMASK(9, 6),
459508
.llops = &aspeed_sgpio_g4_llops,
509+
.cfg_offset = ASPEED_SGPIO_G4_CFG_OFFSET,
460510
};
461511

462512
static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip,
@@ -486,12 +536,68 @@ static int aspeed_sgpio_set_config(struct gpio_chip *chip, unsigned int offset,
486536
static const struct aspeed_sgpio_pdata ast2600_sgpiom_pdata = {
487537
.pin_mask = GENMASK(10, 6),
488538
.llops = &aspeed_sgpio_g4_llops,
539+
.cfg_offset = ASPEED_SGPIO_G4_CFG_OFFSET,
540+
};
541+
542+
static void aspeed_sgpio_g7_reg_bit_set(struct aspeed_sgpio *gpio, unsigned int offset,
543+
const enum aspeed_sgpio_reg reg, bool val)
544+
{
545+
u32 mask = aspeed_sgpio_g7_reg_mask(reg);
546+
void __iomem *addr = gpio->base + SGPIO_G7_CTRL_REG_OFFSET(offset >> 1);
547+
u32 write_val;
548+
549+
if (mask) {
550+
write_val = (ioread32(addr) & ~(mask)) | field_prep(mask, val);
551+
iowrite32(write_val, addr);
552+
}
553+
}
554+
555+
static bool aspeed_sgpio_g7_reg_bit_get(struct aspeed_sgpio *gpio, unsigned int offset,
556+
const enum aspeed_sgpio_reg reg)
557+
{
558+
u32 mask = aspeed_sgpio_g7_reg_mask(reg);
559+
void __iomem *addr;
560+
561+
addr = gpio->base + SGPIO_G7_CTRL_REG_OFFSET(offset >> 1);
562+
if (reg == reg_val)
563+
mask = SGPIO_G7_IN_DATA;
564+
565+
if (mask)
566+
return field_get(mask, ioread32(addr));
567+
else
568+
return 0;
569+
}
570+
571+
static int aspeed_sgpio_g7_reg_bank_get(struct aspeed_sgpio *gpio, unsigned int offset,
572+
const enum aspeed_sgpio_reg reg)
573+
{
574+
void __iomem *addr;
575+
576+
if (reg == reg_irq_status) {
577+
addr = gpio->base + SGPIO_G7_IRQ_STS_OFFSET(offset >> 6);
578+
return ioread32(addr);
579+
} else {
580+
return -EOPNOTSUPP;
581+
}
582+
}
583+
584+
static const struct aspeed_sgpio_llops aspeed_sgpio_g7_llops = {
585+
.reg_bit_set = aspeed_sgpio_g7_reg_bit_set,
586+
.reg_bit_get = aspeed_sgpio_g7_reg_bit_get,
587+
.reg_bank_get = aspeed_sgpio_g7_reg_bank_get,
588+
};
589+
590+
static const struct aspeed_sgpio_pdata ast2700_sgpiom_pdata = {
591+
.pin_mask = GENMASK(11, 6),
592+
.llops = &aspeed_sgpio_g7_llops,
593+
.cfg_offset = ASPEED_SGPIO_G7_CFG_OFFSET,
489594
};
490595

491596
static const struct of_device_id aspeed_sgpio_of_table[] = {
492597
{ .compatible = "aspeed,ast2400-sgpio", .data = &ast2400_sgpio_pdata, },
493598
{ .compatible = "aspeed,ast2500-sgpio", .data = &ast2400_sgpio_pdata, },
494599
{ .compatible = "aspeed,ast2600-sgpiom", .data = &ast2600_sgpiom_pdata, },
600+
{ .compatible = "aspeed,ast2700-sgpiom", .data = &ast2700_sgpiom_pdata, },
495601
{}
496602
};
497603

@@ -562,7 +668,7 @@ static int aspeed_sgpio_probe(struct platform_device *pdev)
562668

563669
gpio_cnt_regval = ((nr_gpios / 8) << ASPEED_SGPIO_PINS_SHIFT) & pin_mask;
564670
iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | gpio_cnt_regval |
565-
ASPEED_SGPIO_ENABLE, gpio->base + ASPEED_SGPIO_CTRL);
671+
ASPEED_SGPIO_ENABLE, gpio->base + gpio->pdata->cfg_offset);
566672

567673
raw_spin_lock_init(&gpio->lock);
568674

0 commit comments

Comments
 (0)