Commit ec0794a1 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven
Browse files

pinctrl: renesas: Factor out common R-Mobile bias handling



The pin control sub-drivers for SH/R-Mobile SoCs contain almost
identical bias handling.  The only SoC-specific part is the mapping from
pin numbers to PORTnCR registers.

Reduce code duplication by factoring out the bias handling to the common
pinctrl.c code.  Use a callback to handle the pin/register mapping.

Signed-off-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: default avatarNiklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Link: https://lore.kernel.org/r/20210303132619.3938128-4-geert+renesas@glider.be
parent 4b6e6c19
Loading
Loading
Loading
Loading
+5 −43
Original line number Diff line number Diff line
@@ -2649,59 +2649,21 @@ static const struct pinmux_irq pinmux_irqs[] = {
	PINMUX_IRQ(329),	/* IRQ57 */
};

#define PORTCR_PULMD_OFF (0 << 6)
#define PORTCR_PULMD_DOWN (2 << 6)
#define PORTCR_PULMD_UP (3 << 6)
#define PORTCR_PULMD_MASK (3 << 6)

static const unsigned int r8a73a4_portcr_offsets[] = {
	0x00000000, 0x00001000, 0x00000000, 0x00001000,
	0x00001000, 0x00002000, 0x00002000, 0x00002000,
	0x00002000, 0x00003000, 0x00003000,
};

static unsigned int r8a73a4_pinmux_get_bias(struct sh_pfc *pfc,
					    unsigned int pin)
static void __iomem *r8a73a4_pin_to_portcr(struct sh_pfc *pfc, unsigned int pin)
{
	void __iomem *addr;

	addr = pfc->windows->virt + r8a73a4_portcr_offsets[pin >> 5] + pin;

	switch (ioread8(addr) & PORTCR_PULMD_MASK) {
	case PORTCR_PULMD_UP:
		return PIN_CONFIG_BIAS_PULL_UP;
	case PORTCR_PULMD_DOWN:
		return PIN_CONFIG_BIAS_PULL_DOWN;
	case PORTCR_PULMD_OFF:
	default:
		return PIN_CONFIG_BIAS_DISABLE;
	}
}

static void r8a73a4_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
				   unsigned int bias)
{
	void __iomem *addr;
	u32 value;

	addr = pfc->windows->virt + r8a73a4_portcr_offsets[pin >> 5] + pin;
	value = ioread8(addr) & ~PORTCR_PULMD_MASK;

	switch (bias) {
	case PIN_CONFIG_BIAS_PULL_UP:
		value |= PORTCR_PULMD_UP;
		break;
	case PIN_CONFIG_BIAS_PULL_DOWN:
		value |= PORTCR_PULMD_DOWN;
		break;
	}

	iowrite8(value, addr);
	return pfc->windows->virt + r8a73a4_portcr_offsets[pin >> 5] + pin;
}

static const struct sh_pfc_soc_operations r8a73a4_pfc_ops = {
	.get_bias = r8a73a4_pinmux_get_bias,
	.set_bias = r8a73a4_pinmux_set_bias,
	.get_bias = rmobile_pinmux_get_bias,
	.set_bias = rmobile_pinmux_set_bias,
	.pin_to_portcr = r8a73a4_pin_to_portcr,
};

const struct sh_pfc_soc_info r8a73a4_pinmux_info = {
+4 −42
Original line number Diff line number Diff line
@@ -3672,11 +3672,6 @@ static const struct pinmux_irq pinmux_irqs[] = {
	PINMUX_IRQ(41,  167),	/* IRQ31A */
};

#define PORTnCR_PULMD_OFF	(0 << 6)
#define PORTnCR_PULMD_DOWN	(2 << 6)
#define PORTnCR_PULMD_UP	(3 << 6)
#define PORTnCR_PULMD_MASK	(3 << 6)

struct r8a7740_portcr_group {
	unsigned int end_pin;
	unsigned int offset;
@@ -3686,7 +3681,7 @@ static const struct r8a7740_portcr_group r8a7740_portcr_offsets[] = {
	{ 83, 0x0000 }, { 114, 0x1000 }, { 209, 0x2000 }, { 211, 0x3000 },
};

static void __iomem *r8a7740_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin)
static void __iomem *r8a7740_pin_to_portcr(struct sh_pfc *pfc, unsigned int pin)
{
	unsigned int i;

@@ -3701,43 +3696,10 @@ static void __iomem *r8a7740_pinmux_portcr(struct sh_pfc *pfc, unsigned int pin)
	return NULL;
}

static unsigned int r8a7740_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin)
{
	void __iomem *addr = r8a7740_pinmux_portcr(pfc, pin);
	u32 value = ioread8(addr) & PORTnCR_PULMD_MASK;

	switch (value) {
	case PORTnCR_PULMD_UP:
		return PIN_CONFIG_BIAS_PULL_UP;
	case PORTnCR_PULMD_DOWN:
		return PIN_CONFIG_BIAS_PULL_DOWN;
	case PORTnCR_PULMD_OFF:
	default:
		return PIN_CONFIG_BIAS_DISABLE;
	}
}

static void r8a7740_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
				   unsigned int bias)
{
	void __iomem *addr = r8a7740_pinmux_portcr(pfc, pin);
	u32 value = ioread8(addr) & ~PORTnCR_PULMD_MASK;

	switch (bias) {
	case PIN_CONFIG_BIAS_PULL_UP:
		value |= PORTnCR_PULMD_UP;
		break;
	case PIN_CONFIG_BIAS_PULL_DOWN:
		value |= PORTnCR_PULMD_DOWN;
		break;
	}

	iowrite8(value, addr);
}

static const struct sh_pfc_soc_operations r8a7740_pfc_ops = {
	.get_bias = r8a7740_pinmux_get_bias,
	.set_bias = r8a7740_pinmux_set_bias,
	.get_bias = rmobile_pinmux_get_bias,
	.set_bias = rmobile_pinmux_set_bias,
	.pin_to_portcr = r8a7740_pin_to_portcr,
};

const struct sh_pfc_soc_info r8a7740_pinmux_info = {
+5 −41
Original line number Diff line number Diff line
@@ -13,7 +13,6 @@
#include <linux/regulator/machine.h>
#include <linux/slab.h>

#include "core.h"
#include "sh_pfc.h"

#define CPU_ALL_PORT(fn, pfx, sfx)					\
@@ -4310,50 +4309,14 @@ static const struct regulator_init_data sh73a0_vccq_mc0_init_data = {
 * Pin bias
 */

#define PORTnCR_PULMD_OFF	(0 << 6)
#define PORTnCR_PULMD_DOWN	(2 << 6)
#define PORTnCR_PULMD_UP	(3 << 6)
#define PORTnCR_PULMD_MASK	(3 << 6)

static const unsigned int sh73a0_portcr_offsets[] = {
	0x00000000, 0x00001000, 0x00001000, 0x00002000, 0x00002000,
	0x00002000, 0x00002000, 0x00003000, 0x00003000, 0x00002000,
};

static unsigned int sh73a0_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin)
static void __iomem *sh73a0_pin_to_portcr(struct sh_pfc *pfc, unsigned int pin)
{
	void __iomem *addr = pfc->windows->virt
			   + sh73a0_portcr_offsets[pin >> 5] + pin;
	u32 value = ioread8(addr) & PORTnCR_PULMD_MASK;

	switch (value) {
	case PORTnCR_PULMD_UP:
		return PIN_CONFIG_BIAS_PULL_UP;
	case PORTnCR_PULMD_DOWN:
		return PIN_CONFIG_BIAS_PULL_DOWN;
	case PORTnCR_PULMD_OFF:
	default:
		return PIN_CONFIG_BIAS_DISABLE;
	}
}

static void sh73a0_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
				   unsigned int bias)
{
	void __iomem *addr = pfc->windows->virt
			   + sh73a0_portcr_offsets[pin >> 5] + pin;
	u32 value = ioread8(addr) & ~PORTnCR_PULMD_MASK;

	switch (bias) {
	case PIN_CONFIG_BIAS_PULL_UP:
		value |= PORTnCR_PULMD_UP;
		break;
	case PIN_CONFIG_BIAS_PULL_DOWN:
		value |= PORTnCR_PULMD_DOWN;
		break;
	}

	iowrite8(value, addr);
	return pfc->windows->virt + sh73a0_portcr_offsets[pin >> 5] + pin;
}

/* -----------------------------------------------------------------------------
@@ -4383,8 +4346,9 @@ static int sh73a0_pinmux_soc_init(struct sh_pfc *pfc)

static const struct sh_pfc_soc_operations sh73a0_pfc_ops = {
	.init = sh73a0_pinmux_soc_init,
	.get_bias = sh73a0_pinmux_get_bias,
	.set_bias = sh73a0_pinmux_set_bias,
	.get_bias = rmobile_pinmux_get_bias,
	.set_bias = rmobile_pinmux_set_bias,
	.pin_to_portcr = sh73a0_pin_to_portcr,
};

const struct sh_pfc_soc_info sh73a0_pinmux_info = {
+40 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
@@ -902,3 +903,42 @@ void rcar_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,

	sh_pfc_write(pfc, reg->puen, enable);
}

#define PORTnCR_PULMD_OFF	(0 << 6)
#define PORTnCR_PULMD_DOWN	(2 << 6)
#define PORTnCR_PULMD_UP	(3 << 6)
#define PORTnCR_PULMD_MASK	(3 << 6)

unsigned int rmobile_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin)
{
	void __iomem *reg = pfc->info->ops->pin_to_portcr(pfc, pin);
	u32 value = ioread8(reg) & PORTnCR_PULMD_MASK;

	switch (value) {
	case PORTnCR_PULMD_UP:
		return PIN_CONFIG_BIAS_PULL_UP;
	case PORTnCR_PULMD_DOWN:
		return PIN_CONFIG_BIAS_PULL_DOWN;
	case PORTnCR_PULMD_OFF:
	default:
		return PIN_CONFIG_BIAS_DISABLE;
	}
}

void rmobile_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
			     unsigned int bias)
{
	void __iomem *reg = pfc->info->ops->pin_to_portcr(pfc, pin);
	u32 value = ioread8(reg) & ~PORTnCR_PULMD_MASK;

	switch (bias) {
	case PIN_CONFIG_BIAS_PULL_UP:
		value |= PORTnCR_PULMD_UP;
		break;
	case PIN_CONFIG_BIAS_PULL_DOWN:
		value |= PORTnCR_PULMD_DOWN;
		break;
	}

	iowrite8(value, reg);
}
+5 −0
Original line number Diff line number Diff line
@@ -273,6 +273,7 @@ struct sh_pfc_soc_operations {
	void (*set_bias)(struct sh_pfc *pfc, unsigned int pin,
			 unsigned int bias);
	int (*pin_to_pocctrl)(struct sh_pfc *pfc, unsigned int pin, u32 *pocctrl);
	void __iomem * (*pin_to_portcr)(struct sh_pfc *pfc, unsigned int pin);
};

struct sh_pfc_soc_info {
@@ -780,4 +781,8 @@ unsigned int rcar_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin);
void rcar_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
			  unsigned int bias);

unsigned int rmobile_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin);
void rmobile_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin,
			     unsigned int bias);

#endif /* __SH_PFC_H */