Commit 1f02c8ef authored by Linus Walleij's avatar Linus Walleij
Browse files

Merge tag 'renesas-pinctrl-for-v5.18-tag2' of...

Merge tag 'renesas-pinctrl-for-v5.18-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers into devel

pinctrl: renesas: Updates for v5.18 (take two)

  - Share more pin group data, to reduce kernel size and ease review,
  - Improve the pin control table validator,
  - Add support for the new R-Car S4-8 SoC,
  - Miscellaneous fixes and improvements.
parents 4649b970 babe298e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ properties:
      - renesas,pfc-r8a77990    # R-Car E3
      - renesas,pfc-r8a77995    # R-Car D3
      - renesas,pfc-r8a779a0    # R-Car V3U
      - renesas,pfc-r8a779f0    # R-Car S4-8
      - renesas,pfc-sh73a0      # SH-Mobile AG5

  reg:
+5 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ config PINCTRL_RENESAS
	select PINCTRL_PFC_R8A77990 if ARCH_R8A77990
	select PINCTRL_PFC_R8A77995 if ARCH_R8A77995
	select PINCTRL_PFC_R8A779A0 if ARCH_R8A779A0
	select PINCTRL_PFC_R8A779F0 if ARCH_R8A779F0
	select PINCTRL_RZG2L if ARCH_R9A07G044
	select PINCTRL_RZG2L if ARCH_R9A07G054
	select PINCTRL_PFC_SH7203 if CPU_SUBTYPE_SH7203
@@ -133,6 +134,10 @@ config PINCTRL_PFC_R8A77961
	bool "pin control support for R-Car M3-W+" if COMPILE_TEST
	select PINCTRL_SH_PFC

config PINCTRL_PFC_R8A779F0
	bool "pin control support for R-Car S4-8" if COMPILE_TEST
	select PINCTRL_SH_PFC

config PINCTRL_PFC_R8A7792
	bool "pin control support for R-Car V2H" if COMPILE_TEST
	select PINCTRL_SH_PFC
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A77980) += pfc-r8a77980.o
obj-$(CONFIG_PINCTRL_PFC_R8A77990)	+= pfc-r8a77990.o
obj-$(CONFIG_PINCTRL_PFC_R8A77995)	+= pfc-r8a77995.o
obj-$(CONFIG_PINCTRL_PFC_R8A779A0)	+= pfc-r8a779a0.o
obj-$(CONFIG_PINCTRL_PFC_R8A779F0)	+= pfc-r8a779f0.o
obj-$(CONFIG_PINCTRL_PFC_SH7203)	+= pfc-sh7203.o
obj-$(CONFIG_PINCTRL_PFC_SH7264)	+= pfc-sh7264.o
obj-$(CONFIG_PINCTRL_PFC_SH7269)	+= pfc-sh7269.o
+199 −20
Original line number Diff line number Diff line
@@ -636,6 +636,12 @@ static const struct of_device_id sh_pfc_of_table[] = {
		.data = &r8a779a0_pinmux_info,
	},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A779F0
	{
		.compatible = "renesas,pfc-r8a779f0",
		.data = &r8a779f0_pinmux_info,
	},
#endif
#ifdef CONFIG_PINCTRL_PFC_SH73A0
	{
		.compatible = "renesas,pfc-sh73a0",
@@ -741,10 +747,13 @@ static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; }

#ifdef DEBUG
#define SH_PFC_MAX_REGS		300
#define SH_PFC_MAX_ENUMS	3000
#define SH_PFC_MAX_ENUMS	5000

static unsigned int sh_pfc_errors __initdata;
static unsigned int sh_pfc_warnings __initdata;
static bool sh_pfc_bias_done __initdata;
static bool sh_pfc_drive_done __initdata;
static bool sh_pfc_power_done __initdata;
static struct {
	u32 reg;
	u32 bits;
@@ -758,6 +767,15 @@ static u32 sh_pfc_num_enums __initdata;
		pr_err("%s: " fmt, drvname, ##__VA_ARGS__);	\
		sh_pfc_errors++;				\
	} while (0)

#define sh_pfc_err_once(type, fmt, ...)				\
	do {							\
		if (!sh_pfc_ ## type ## _done) {		\
			sh_pfc_ ## type ## _done = true;	\
			sh_pfc_err(fmt, ##__VA_ARGS__);		\
		}						\
	} while (0)

#define sh_pfc_warn(fmt, ...)					\
	do {							\
		pr_warn("%s: " fmt, drvname, ##__VA_ARGS__);	\
@@ -777,10 +795,7 @@ static bool __init is0s(const u16 *enum_ids, unsigned int n)

static bool __init same_name(const char *a, const char *b)
{
	if (!a || !b)
		return false;

	return !strcmp(a, b);
	return a && b && !strcmp(a, b);
}

static void __init sh_pfc_check_reg(const char *drvname, u32 reg, u32 bits)
@@ -839,21 +854,22 @@ static void __init sh_pfc_check_reg_enums(const char *drvname, u32 reg,
	}
}

static void __init sh_pfc_check_pin(const struct sh_pfc_soc_info *info,
				    u32 reg, unsigned int pin)
static const struct sh_pfc_pin __init *sh_pfc_find_pin(
	const struct sh_pfc_soc_info *info, u32 reg, unsigned int pin)
{
	const char *drvname = info->name;
	unsigned int i;

	if (pin == SH_PFC_PIN_NONE)
		return;
		return NULL;

	for (i = 0; i < info->nr_pins; i++) {
		if (pin == info->pins[i].pin)
			return;
			return &info->pins[i];
	}

	sh_pfc_err("reg 0x%x: pin %u not found\n", reg, pin);
	return NULL;
}

static void __init sh_pfc_check_cfg_reg(const char *drvname,
@@ -865,7 +881,8 @@ static void __init sh_pfc_check_cfg_reg(const char *drvname,
			 GENMASK(cfg_reg->reg_width - 1, 0));

	if (cfg_reg->field_width) {
		n = cfg_reg->reg_width / cfg_reg->field_width;
		fw = cfg_reg->field_width;
		n = (cfg_reg->reg_width / fw) << fw;
		/* Skip field checks (done at build time) */
		goto check_enum_ids;
	}
@@ -893,6 +910,8 @@ static void __init sh_pfc_check_cfg_reg(const char *drvname,
static void __init sh_pfc_check_drive_reg(const struct sh_pfc_soc_info *info,
					  const struct pinmux_drive_reg *drive)
{
	const char *drvname = info->name;
	const struct sh_pfc_pin *pin;
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(drive->fields); i++) {
@@ -905,13 +924,18 @@ static void __init sh_pfc_check_drive_reg(const struct sh_pfc_soc_info *info,
				 GENMASK(field->offset + field->size - 1,
					 field->offset));

		sh_pfc_check_pin(info, drive->reg, field->pin);
		pin = sh_pfc_find_pin(info, drive->reg, field->pin);
		if (pin && !(pin->configs & SH_PFC_PIN_CFG_DRIVE_STRENGTH))
			sh_pfc_err("drive_reg 0x%x: field %u: pin %s lacks SH_PFC_PIN_CFG_DRIVE_STRENGTH flag\n",
				   drive->reg, i, pin->name);
	}
}

static void __init sh_pfc_check_bias_reg(const struct sh_pfc_soc_info *info,
					 const struct pinmux_bias_reg *bias)
{
	const char *drvname = info->name;
	const struct sh_pfc_pin *pin;
	unsigned int i;
	u32 bits;

@@ -923,12 +947,66 @@ static void __init sh_pfc_check_bias_reg(const struct sh_pfc_soc_info *info,
		sh_pfc_check_reg(info->name, bias->puen, bits);
	if (bias->pud)
		sh_pfc_check_reg(info->name, bias->pud, bits);
	for (i = 0; i < ARRAY_SIZE(bias->pins); i++)
		sh_pfc_check_pin(info, bias->puen, bias->pins[i]);
	for (i = 0; i < ARRAY_SIZE(bias->pins); i++) {
		pin = sh_pfc_find_pin(info, bias->puen, bias->pins[i]);
		if (!pin)
			continue;

		if (bias->puen && bias->pud) {
			/*
			 * Pull-enable and pull-up/down control registers
			 * As some SoCs have pins that support only pull-up
			 * or pull-down, we just check for one of them
			 */
			if (!(pin->configs & SH_PFC_PIN_CFG_PULL_UP_DOWN))
				sh_pfc_err("bias_reg 0x%x:%u: pin %s lacks one or more SH_PFC_PIN_CFG_PULL_* flags\n",
					   bias->puen, i, pin->name);
		} else if (bias->puen) {
			/* Pull-up control register only */
			if (!(pin->configs & SH_PFC_PIN_CFG_PULL_UP))
				sh_pfc_err("bias_reg 0x%x:%u: pin %s lacks SH_PFC_PIN_CFG_PULL_UP flag\n",
					   bias->puen, i, pin->name);
		} else if (bias->pud) {
			/* Pull-down control register only */
			if (!(pin->configs & SH_PFC_PIN_CFG_PULL_DOWN))
				sh_pfc_err("bias_reg 0x%x:%u: pin %s lacks SH_PFC_PIN_CFG_PULL_DOWN flag\n",
					   bias->pud, i, pin->name);
		}
	}
}

static void __init sh_pfc_compare_groups(const char *drvname,
					 const struct sh_pfc_pin_group *a,
					 const struct sh_pfc_pin_group *b)
{
	unsigned int i;
	size_t len;

	if (same_name(a->name, b->name))
		sh_pfc_err("group %s: name conflict\n", a->name);

	if (a->nr_pins > b->nr_pins)
		swap(a, b);

	len = a->nr_pins * sizeof(a->pins[0]);
	for (i = 0; i <= b->nr_pins - a->nr_pins; i++) {
		if (a->pins == b->pins + i || a->mux == b->mux + i ||
		    memcmp(a->pins, b->pins + i, len) ||
		    memcmp(a->mux, b->mux + i, len))
			continue;

		if (a->nr_pins == b->nr_pins)
			sh_pfc_warn("group %s can be an alias for %s\n",
				    a->name, b->name);
		else
			sh_pfc_warn("group %s is a subset of %s\n", a->name,
				    b->name);
	}
}

static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info)
{
	const struct pinmux_drive_reg *drive_regs = info->drive_regs;
	const struct pinmux_bias_reg *bias_regs = info->bias_regs;
	const char *drvname = info->name;
	unsigned int *refcnts;
@@ -937,10 +1015,14 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info)
	pr_info("sh_pfc: Checking %s\n", drvname);
	sh_pfc_num_regs = 0;
	sh_pfc_num_enums = 0;
	sh_pfc_bias_done = false;
	sh_pfc_drive_done = false;
	sh_pfc_power_done = false;

	/* Check pins */
	for (i = 0; i < info->nr_pins; i++) {
		const struct sh_pfc_pin *pin = &info->pins[i];
		unsigned int x;

		if (!pin->name) {
			sh_pfc_err("empty pin %u\n", i);
@@ -962,6 +1044,65 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info)
					   pin->name, pin2->name,
					   pin->enum_id);
		}

		if (pin->configs & SH_PFC_PIN_CFG_PULL_UP_DOWN) {
			if (!info->ops || !info->ops->get_bias ||
			    !info->ops->set_bias)
				sh_pfc_err_once(bias, "SH_PFC_PIN_CFG_PULL_* flag set but .[gs]et_bias() not implemented\n");

			if (!bias_regs &&
			     (!info->ops || !info->ops->pin_to_portcr))
				sh_pfc_err_once(bias, "SH_PFC_PIN_CFG_PULL_UP flag set but no bias_regs defined and .pin_to_portcr() not implemented\n");
		}

		if ((pin->configs & SH_PFC_PIN_CFG_PULL_UP_DOWN) && bias_regs) {
			const struct pinmux_bias_reg *bias_reg =
				rcar_pin_to_bias_reg(info, pin->pin, &x);

			if (!bias_reg ||
			    ((pin->configs & SH_PFC_PIN_CFG_PULL_UP) &&
			     !bias_reg->puen))
				sh_pfc_err("pin %s: SH_PFC_PIN_CFG_PULL_UP flag set but pin not in bias_regs\n",
					   pin->name);

			if (!bias_reg ||
			    ((pin->configs & SH_PFC_PIN_CFG_PULL_DOWN) &&
			     !bias_reg->pud))
				sh_pfc_err("pin %s: SH_PFC_PIN_CFG_PULL_DOWN flag set but pin not in bias_regs\n",
					   pin->name);
		}

		if (pin->configs & SH_PFC_PIN_CFG_DRIVE_STRENGTH) {
			if (!drive_regs) {
				sh_pfc_err_once(drive, "SH_PFC_PIN_CFG_DRIVE_STRENGTH flag set but drive_regs missing\n");
			} else {
				for (j = 0; drive_regs[j / 8].reg; j++) {
					if (!drive_regs[j / 8].fields[j % 8].pin &&
					    !drive_regs[j / 8].fields[j % 8].offset &&
					    !drive_regs[j / 8].fields[j % 8].size)
						continue;

					if (drive_regs[j / 8].fields[j % 8].pin == pin->pin)
						break;
				}

				if (!drive_regs[j / 8].reg)
					sh_pfc_err("pin %s: SH_PFC_PIN_CFG_DRIVE_STRENGTH flag set but not in drive_regs\n",
						   pin->name);
			}
		}

		if (pin->configs & SH_PFC_PIN_CFG_IO_VOLTAGE) {
			if (!info->ops || !info->ops->pin_to_pocctrl)
				sh_pfc_err_once(power, "SH_PFC_PIN_CFG_IO_VOLTAGE flag set but .pin_to_pocctrl() not implemented\n");
			else if (info->ops->pin_to_pocctrl(pin->pin, &x) < 0)
				sh_pfc_err("pin %s: SH_PFC_PIN_CFG_IO_VOLTAGE set but invalid pin_to_pocctrl()\n",
					   pin->name);
		} else if (info->ops && info->ops->pin_to_pocctrl &&
			   info->ops->pin_to_pocctrl(pin->pin, &x) >= 0) {
			sh_pfc_warn("pin %s: SH_PFC_PIN_CFG_IO_VOLTAGE not set but valid pin_to_pocctrl()\n",
				    pin->name);
		}
	}

	/* Check groups and functions */
@@ -1003,11 +1144,9 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info)
			sh_pfc_err("empty group %u\n", i);
			continue;
		}
		for (j = 0; j < i; j++) {
			if (same_name(group->name, info->groups[j].name))
				sh_pfc_err("group %s: name conflict\n",
					   group->name);
		}
		for (j = 0; j < i; j++)
			sh_pfc_compare_groups(drvname, group, &info->groups[j]);

		if (!refcnts[i])
			sh_pfc_err("orphan group %s\n", group->name);
		else if (refcnts[i] > 1)
@@ -1022,13 +1161,53 @@ static void __init sh_pfc_check_info(const struct sh_pfc_soc_info *info)
		sh_pfc_check_cfg_reg(drvname, &info->cfg_regs[i]);

	/* Check drive strength registers */
	for (i = 0; info->drive_regs && info->drive_regs[i].reg; i++)
		sh_pfc_check_drive_reg(info, &info->drive_regs[i]);
	for (i = 0; drive_regs && drive_regs[i].reg; i++)
		sh_pfc_check_drive_reg(info, &drive_regs[i]);

	for (i = 0; drive_regs && drive_regs[i / 8].reg; i++) {
		if (!drive_regs[i / 8].fields[i % 8].pin &&
		    !drive_regs[i / 8].fields[i % 8].offset &&
		    !drive_regs[i / 8].fields[i % 8].size)
			continue;

		for (j = 0; j < i; j++) {
			if (drive_regs[i / 8].fields[i % 8].pin ==
			    drive_regs[j / 8].fields[j % 8].pin &&
			    drive_regs[j / 8].fields[j % 8].offset &&
			    drive_regs[j / 8].fields[j % 8].size) {
				sh_pfc_err("drive_reg 0x%x:%u/0x%x:%u: pin conflict\n",
					   drive_regs[i / 8].reg, i % 8,
					   drive_regs[j / 8].reg, j % 8);
			}
		}
	}

	/* Check bias registers */
	for (i = 0; bias_regs && (bias_regs[i].puen || bias_regs[i].pud); i++)
		sh_pfc_check_bias_reg(info, &bias_regs[i]);

	for (i = 0; bias_regs &&
		    (bias_regs[i / 32].puen || bias_regs[i / 32].pud); i++) {
		if (bias_regs[i / 32].pins[i % 32] == SH_PFC_PIN_NONE)
			continue;

		for (j = 0; j < i; j++) {
			if (bias_regs[i / 32].pins[i % 32] !=
			    bias_regs[j / 32].pins[j % 32])
				continue;

			if (bias_regs[i / 32].puen && bias_regs[j / 32].puen)
				sh_pfc_err("bias_reg 0x%x:%u/0x%x:%u: pin conflict\n",
					   bias_regs[i / 32].puen, i % 32,
					   bias_regs[j / 32].puen, j % 32);
			if (bias_regs[i / 32].pud && bias_regs[j / 32].pud)
				sh_pfc_err("bias_reg 0x%x:%u/0x%x:%u: pin conflict\n",
					   bias_regs[i / 32].pud, i % 32,
					   bias_regs[j / 32].pud, j % 32);
		}

	}

	/* Check ioctrl registers */
	for (i = 0; info->ioctrl_regs && info->ioctrl_regs[i].reg; i++)
		sh_pfc_check_reg(drvname, info->ioctrl_regs[i].reg, U32_MAX);
+17 −54
Original line number Diff line number Diff line
@@ -749,23 +749,14 @@ static const unsigned int cf_ctrl_mux[] = {
	CF_CDB2_MARK,
};

static const unsigned int cf_data8_pins[] = {
	/* CF_D[0:7] */
	77, 78, 79, 80,
	81, 82, 83, 84,
};
static const unsigned int cf_data8_mux[] = {
	CF_D00_MARK, CF_D01_MARK, CF_D02_MARK, CF_D03_MARK,
	CF_D04_MARK, CF_D05_MARK, CF_D06_MARK, CF_D07_MARK,
};
static const unsigned int cf_data16_pins[] = {
static const unsigned int cf_data_pins[] = {
	/* CF_D[0:15] */
	77, 78, 79, 80,
	81, 82, 83, 84,
	85, 86, 87, 88,
	89, 90, 91, 92,
};
static const unsigned int cf_data16_mux[] = {
static const unsigned int cf_data_mux[] = {
	CF_D00_MARK, CF_D01_MARK, CF_D02_MARK, CF_D03_MARK,
	CF_D04_MARK, CF_D05_MARK, CF_D06_MARK, CF_D07_MARK,
	CF_D08_MARK, CF_D09_MARK, CF_D10_MARK, CF_D11_MARK,
@@ -895,26 +886,12 @@ static const unsigned int sdi0_ctrl_mux[] = {
	SDI0_CKO_MARK, SDI0_CKI_MARK, SDI0_CMD_MARK,
};

static const unsigned int sdi0_data1_pins[] = {
	/* SDI0_DATA[0] */
	53,
};
static const unsigned int sdi0_data1_mux[] = {
	SDI0_DATA0_MARK,
};
static const unsigned int sdi0_data4_pins[] = {
	/* SDI0_DATA[0:3] */
	53, 54, 55, 56,
};
static const unsigned int sdi0_data4_mux[] = {
	SDI0_DATA0_MARK, SDI0_DATA1_MARK, SDI0_DATA2_MARK, SDI0_DATA3_MARK,
};
static const unsigned int sdi0_data8_pins[] = {
static const unsigned int sdi0_data_pins[] = {
	/* SDI0_DATA[0:7] */
	53, 54, 55, 56,
	57, 58, 59, 60
};
static const unsigned int sdi0_data8_mux[] = {
static const unsigned int sdi0_data_mux[] = {
	SDI0_DATA0_MARK, SDI0_DATA1_MARK, SDI0_DATA2_MARK, SDI0_DATA3_MARK,
	SDI0_DATA4_MARK, SDI0_DATA5_MARK, SDI0_DATA6_MARK, SDI0_DATA7_MARK,
};
@@ -928,18 +905,11 @@ static const unsigned int sdi1_ctrl_mux[] = {
	SDI1_CKO_MARK, SDI1_CKI_MARK, SDI1_CMD_MARK,
};

static const unsigned int sdi1_data1_pins[] = {
	/* SDI1_DATA[0] */
	64,
};
static const unsigned int sdi1_data1_mux[] = {
	SDI1_DATA0_MARK,
};
static const unsigned int sdi1_data4_pins[] = {
static const unsigned int sdi1_data_pins[] = {
	/* SDI1_DATA[0:3] */
	64, 65, 66, 67,
};
static const unsigned int sdi1_data4_mux[] = {
static const unsigned int sdi1_data_mux[] = {
	SDI1_DATA0_MARK, SDI1_DATA1_MARK, SDI1_DATA2_MARK, SDI1_DATA3_MARK,
};

@@ -952,18 +922,11 @@ static const unsigned int sdi2_ctrl_mux[] = {
	SDI2_CKO_MARK, SDI2_CKI_MARK, SDI2_CMD_MARK,
};

static const unsigned int sdi2_data1_pins[] = {
	/* SDI2_DATA[0] */
	89,
};
static const unsigned int sdi2_data1_mux[] = {
	SDI2_DATA0_MARK,
};
static const unsigned int sdi2_data4_pins[] = {
static const unsigned int sdi2_data_pins[] = {
	/* SDI2_DATA[0:3] */
	89, 90, 91, 92,
};
static const unsigned int sdi2_data4_mux[] = {
static const unsigned int sdi2_data_mux[] = {
	SDI2_DATA0_MARK, SDI2_DATA1_MARK, SDI2_DATA2_MARK, SDI2_DATA3_MARK,
};

@@ -1131,8 +1094,8 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
	SH_PFC_PIN_GROUP(cam),

	SH_PFC_PIN_GROUP(cf_ctrl),
	SH_PFC_PIN_GROUP(cf_data8),
	SH_PFC_PIN_GROUP(cf_data16),
	BUS_DATA_PIN_GROUP(cf_data, 8),
	BUS_DATA_PIN_GROUP(cf_data, 16),

	SH_PFC_PIN_GROUP(dtv_a),
	SH_PFC_PIN_GROUP(dtv_b),
@@ -1161,17 +1124,17 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
	SH_PFC_PIN_GROUP(sd_cki),

	SH_PFC_PIN_GROUP(sdi0_ctrl),
	SH_PFC_PIN_GROUP(sdi0_data1),
	SH_PFC_PIN_GROUP(sdi0_data4),
	SH_PFC_PIN_GROUP(sdi0_data8),
	BUS_DATA_PIN_GROUP(sdi0_data, 1),
	BUS_DATA_PIN_GROUP(sdi0_data, 4),
	BUS_DATA_PIN_GROUP(sdi0_data, 8),

	SH_PFC_PIN_GROUP(sdi1_ctrl),
	SH_PFC_PIN_GROUP(sdi1_data1),
	SH_PFC_PIN_GROUP(sdi1_data4),
	BUS_DATA_PIN_GROUP(sdi1_data, 1),
	BUS_DATA_PIN_GROUP(sdi1_data, 4),

	SH_PFC_PIN_GROUP(sdi2_ctrl),
	SH_PFC_PIN_GROUP(sdi2_data1),
	SH_PFC_PIN_GROUP(sdi2_data4),
	BUS_DATA_PIN_GROUP(sdi2_data, 1),
	BUS_DATA_PIN_GROUP(sdi2_data, 4),

	SH_PFC_PIN_GROUP(tp33),

Loading