1
0
Fork 0

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>
alistair/sunxi64-5.4-dsi
Li Jin 2019-08-29 10:22:27 +05:30 committed by Linus Walleij
parent 1fdbc02ce1
commit 398a1f50e3
1 changed files with 76 additions and 18 deletions

View File

@ -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;