u8 pin, u8 off, u8 func)
{
unsigned long flags;
- u32 reg;
+ u32 reg, pfc;
+ /* Switching to GPIO is not required if reset value is same as func */
raw_spin_lock_irqsave(&pctrl->lock, flags);
+ reg = readb(pctrl->base + PMC(off));
+ pfc = readl(pctrl->base + PFC(off));
+ if ((reg & BIT(pin)) && (((pfc >> (pin * 4)) & PFC_MASK) == func)) {
+ raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+ return;
+ }
/* Set pin to 'Non-use (Hi-Z input protection)' */
reg = readw(pctrl->base + PM(off));
writeb(reg & ~BIT(pin), pctrl->base + PMC(off));
/* Select Pin function mode with PFC register */
- reg = readl(pctrl->base + PFC(off));
- reg &= ~(PFC_MASK << (pin * 4));
- writel(reg | (func << (pin * 4)), pctrl->base + PFC(off));
+ pfc &= ~(PFC_MASK << (pin * 4));
+ writel(pfc | (func << (pin * 4)), pctrl->base + PFC(off));
/* Switch to Peripheral pin function with PMC register */
reg = readb(pctrl->base + PMC(off));
pm = readw(pctrl->base + PM(off));
for_each_set_bit(pin, &pinmap, max_pin) {
struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache;
+ u32 pfc_val, pfc_mask;
/* Nothing to do if PFC was not configured before. */
if (!(cache->pmc[port] & BIT(pin)))
continue;
+ pfc_val = readl(pctrl->base + PFC(off));
+ pfc_mask = PFC_MASK << (pin * 4);
+ /* Nothing to do if reset value of the pin is same as cached value */
+ if ((cache->pfc[port] & pfc_mask) == (pfc_val & pfc_mask))
+ continue;
+
/* Set pin to 'Non-use (Hi-Z input protection)' */
pm &= ~(PM_MASK << (pin * 2));
writew(pm, pctrl->base + PM(off));
writeb(pmc, pctrl->base + PMC(off));
/* Select Pin function mode. */
- pfc &= ~(PFC_MASK << (pin * 4));
- pfc |= (cache->pfc[port] & (PFC_MASK << (pin * 4)));
+ pfc &= ~pfc_mask;
+ pfc |= (cache->pfc[port] & pfc_mask);
writel(pfc, pctrl->base + PFC(off));
/* Switch to Peripheral pin function. */