mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-15 10:16:43 +07:00
pinctrl: iproc-gpio: Fix incorrect pinconf configurations
Fix drive strength for AON/CRMU controller; fix pull-up/down setting
for CCM/CDRU controller.
Fixes: 616043d58a
("pinctrl: Rename gpio driver from cygnus to iproc")
Signed-off-by: Li Jin <li.jin@broadcom.com>
Link: https://lore.kernel.org/r/1567054348-19685-2-git-send-email-srinath.mannam@broadcom.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
1fdbc02ce1
commit
398a1f50e3
@ -54,8 +54,12 @@
|
||||
/* drive strength control for ASIU GPIO */
|
||||
#define IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET 0x58
|
||||
|
||||
/* drive strength control for CCM/CRMU (AON) GPIO */
|
||||
#define IPROC_GPIO_DRV0_CTRL_OFFSET 0x00
|
||||
/* pinconf for CCM GPIO */
|
||||
#define IPROC_GPIO_PULL_DN_OFFSET 0x10
|
||||
#define IPROC_GPIO_PULL_UP_OFFSET 0x14
|
||||
|
||||
/* pinconf for CRMU(aon) GPIO and CCM GPIO*/
|
||||
#define IPROC_GPIO_DRV_CTRL_OFFSET 0x00
|
||||
|
||||
#define GPIO_BANK_SIZE 0x200
|
||||
#define NGPIOS_PER_BANK 32
|
||||
@ -76,6 +80,12 @@ enum iproc_pinconf_param {
|
||||
IPROC_PINCON_MAX,
|
||||
};
|
||||
|
||||
enum iproc_pinconf_ctrl_type {
|
||||
IOCTRL_TYPE_AON = 1,
|
||||
IOCTRL_TYPE_CDRU,
|
||||
IOCTRL_TYPE_INVALID,
|
||||
};
|
||||
|
||||
/*
|
||||
* Iproc GPIO core
|
||||
*
|
||||
@ -100,6 +110,7 @@ struct iproc_gpio {
|
||||
|
||||
void __iomem *base;
|
||||
void __iomem *io_ctrl;
|
||||
enum iproc_pinconf_ctrl_type io_ctrl_type;
|
||||
|
||||
raw_spinlock_t lock;
|
||||
|
||||
@ -461,20 +472,44 @@ static const struct pinctrl_ops iproc_pctrl_ops = {
|
||||
static int iproc_gpio_set_pull(struct iproc_gpio *chip, unsigned gpio,
|
||||
bool disable, bool pull_up)
|
||||
{
|
||||
void __iomem *base;
|
||||
unsigned long flags;
|
||||
unsigned int shift;
|
||||
u32 val_1, val_2;
|
||||
|
||||
raw_spin_lock_irqsave(&chip->lock, flags);
|
||||
if (chip->io_ctrl_type == IOCTRL_TYPE_CDRU) {
|
||||
base = chip->io_ctrl;
|
||||
shift = IPROC_GPIO_SHIFT(gpio);
|
||||
|
||||
if (disable) {
|
||||
iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, false);
|
||||
val_1 = readl(base + IPROC_GPIO_PULL_UP_OFFSET);
|
||||
val_2 = readl(base + IPROC_GPIO_PULL_DN_OFFSET);
|
||||
if (disable) {
|
||||
/* no pull-up or pull-down */
|
||||
val_1 &= ~BIT(shift);
|
||||
val_2 &= ~BIT(shift);
|
||||
} else if (pull_up) {
|
||||
val_1 |= BIT(shift);
|
||||
val_2 &= ~BIT(shift);
|
||||
} else {
|
||||
val_1 &= ~BIT(shift);
|
||||
val_2 |= BIT(shift);
|
||||
}
|
||||
writel(val_1, base + IPROC_GPIO_PULL_UP_OFFSET);
|
||||
writel(val_2, base + IPROC_GPIO_PULL_DN_OFFSET);
|
||||
} else {
|
||||
iproc_set_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio,
|
||||
pull_up);
|
||||
iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, true);
|
||||
if (disable) {
|
||||
iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio,
|
||||
false);
|
||||
} else {
|
||||
iproc_set_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio,
|
||||
pull_up);
|
||||
iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
raw_spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
dev_dbg(chip->dev, "gpio:%u set pullup:%d\n", gpio, pull_up);
|
||||
|
||||
return 0;
|
||||
@ -483,14 +518,35 @@ static int iproc_gpio_set_pull(struct iproc_gpio *chip, unsigned gpio,
|
||||
static void iproc_gpio_get_pull(struct iproc_gpio *chip, unsigned gpio,
|
||||
bool *disable, bool *pull_up)
|
||||
{
|
||||
void __iomem *base;
|
||||
unsigned long flags;
|
||||
unsigned int shift;
|
||||
u32 val_1, val_2;
|
||||
|
||||
raw_spin_lock_irqsave(&chip->lock, flags);
|
||||
*disable = !iproc_get_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio);
|
||||
*pull_up = iproc_get_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio);
|
||||
if (chip->io_ctrl_type == IOCTRL_TYPE_CDRU) {
|
||||
base = chip->io_ctrl;
|
||||
shift = IPROC_GPIO_SHIFT(gpio);
|
||||
|
||||
val_1 = readl(base + IPROC_GPIO_PULL_UP_OFFSET) & BIT(shift);
|
||||
val_2 = readl(base + IPROC_GPIO_PULL_DN_OFFSET) & BIT(shift);
|
||||
|
||||
*pull_up = val_1 ? true : false;
|
||||
*disable = (val_1 | val_2) ? false : true;
|
||||
|
||||
} else {
|
||||
*disable = !iproc_get_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio);
|
||||
*pull_up = iproc_get_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio);
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&chip->lock, flags);
|
||||
}
|
||||
|
||||
#define DRV_STRENGTH_OFFSET(gpio, bit, type) ((type) == IOCTRL_TYPE_AON ? \
|
||||
((2 - (bit)) * 4 + IPROC_GPIO_DRV_CTRL_OFFSET) : \
|
||||
((type) == IOCTRL_TYPE_CDRU) ? \
|
||||
((bit) * 4 + IPROC_GPIO_DRV_CTRL_OFFSET) : \
|
||||
((bit) * 4 + IPROC_GPIO_REG(gpio, IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET)))
|
||||
|
||||
static int iproc_gpio_set_strength(struct iproc_gpio *chip, unsigned gpio,
|
||||
unsigned strength)
|
||||
{
|
||||
@ -505,11 +561,8 @@ static int iproc_gpio_set_strength(struct iproc_gpio *chip, unsigned gpio,
|
||||
|
||||
if (chip->io_ctrl) {
|
||||
base = chip->io_ctrl;
|
||||
offset = IPROC_GPIO_DRV0_CTRL_OFFSET;
|
||||
} else {
|
||||
base = chip->base;
|
||||
offset = IPROC_GPIO_REG(gpio,
|
||||
IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET);
|
||||
}
|
||||
|
||||
shift = IPROC_GPIO_SHIFT(gpio);
|
||||
@ -520,11 +573,11 @@ static int iproc_gpio_set_strength(struct iproc_gpio *chip, unsigned gpio,
|
||||
raw_spin_lock_irqsave(&chip->lock, flags);
|
||||
strength = (strength / 2) - 1;
|
||||
for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) {
|
||||
offset = DRV_STRENGTH_OFFSET(gpio, i, chip->io_ctrl_type);
|
||||
val = readl(base + offset);
|
||||
val &= ~BIT(shift);
|
||||
val |= ((strength >> i) & 0x1) << shift;
|
||||
writel(val, base + offset);
|
||||
offset += 4;
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&chip->lock, flags);
|
||||
|
||||
@ -541,11 +594,8 @@ static int iproc_gpio_get_strength(struct iproc_gpio *chip, unsigned gpio,
|
||||
|
||||
if (chip->io_ctrl) {
|
||||
base = chip->io_ctrl;
|
||||
offset = IPROC_GPIO_DRV0_CTRL_OFFSET;
|
||||
} else {
|
||||
base = chip->base;
|
||||
offset = IPROC_GPIO_REG(gpio,
|
||||
IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET);
|
||||
}
|
||||
|
||||
shift = IPROC_GPIO_SHIFT(gpio);
|
||||
@ -553,10 +603,10 @@ static int iproc_gpio_get_strength(struct iproc_gpio *chip, unsigned gpio,
|
||||
raw_spin_lock_irqsave(&chip->lock, flags);
|
||||
*strength = 0;
|
||||
for (i = 0; i < GPIO_DRV_STRENGTH_BITS; i++) {
|
||||
offset = DRV_STRENGTH_OFFSET(gpio, i, chip->io_ctrl_type);
|
||||
val = readl(base + offset) & BIT(shift);
|
||||
val >>= shift;
|
||||
*strength += (val << i);
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
/* convert to mA */
|
||||
@ -734,6 +784,7 @@ static int iproc_gpio_probe(struct platform_device *pdev)
|
||||
u32 ngpios, pinconf_disable_mask = 0;
|
||||
int irq, ret;
|
||||
bool no_pinconf = false;
|
||||
enum iproc_pinconf_ctrl_type io_ctrl_type = IOCTRL_TYPE_INVALID;
|
||||
|
||||
/* NSP does not support drive strength config */
|
||||
if (of_device_is_compatible(dev->of_node, "brcm,iproc-nsp-gpio"))
|
||||
@ -764,8 +815,15 @@ static int iproc_gpio_probe(struct platform_device *pdev)
|
||||
dev_err(dev, "unable to map I/O memory\n");
|
||||
return PTR_ERR(chip->io_ctrl);
|
||||
}
|
||||
if (of_device_is_compatible(dev->of_node,
|
||||
"brcm,cygnus-ccm-gpio"))
|
||||
io_ctrl_type = IOCTRL_TYPE_CDRU;
|
||||
else
|
||||
io_ctrl_type = IOCTRL_TYPE_AON;
|
||||
}
|
||||
|
||||
chip->io_ctrl_type = io_ctrl_type;
|
||||
|
||||
if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) {
|
||||
dev_err(&pdev->dev, "missing ngpios DT property\n");
|
||||
return -ENODEV;
|
||||
|
Loading…
Reference in New Issue
Block a user