Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 051e1674 authored by Linus Walleij's avatar Linus Walleij
Browse files

Merge tag 'sh-pfc-for-v4.15-tag2' of...

Merge tag 'sh-pfc-for-v4.15-tag2' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers into devel

pinctrl: sh-pfc: Updates for v4.15 (take two)

  - Add Audio, HSCIF, I2C, and INTC-EX pin groups on R-Car H3 ES2.0,
  - Add Audio and PWM pin groups on R-Car D3,
  - Add support for RZ/A1M and RZ/A1L,
  - Add INTC-EX pin groups on R-Car M3-W,
  - Add SDHI voltage switching on RZ/G1E,
  - Make bias control and IOCTRL support more generic,
  - Add suspend/resume support for R-Car Gen3,
  - Small fixes and cleanups.
parents ff0f2ce7 8843797d
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -12,8 +12,10 @@ Pin controller node
-------------------

Required properties:
  - compatible
    this shall be "renesas,r7s72100-ports".
  - compatible: should be:
    - "renesas,r7s72100-ports": for RZ/A1H
    - "renesas,r7s72101-ports", "renesas,r7s72100-ports": for RZ/A1M
    - "renesas,r7s72102-ports": for RZ/A1L

  - reg
    address base and length of the memory area where the pin controller
+134 −0
Original line number Diff line number Diff line
@@ -302,6 +302,134 @@ static const struct rza1_pinmux_conf rza1h_pmx_conf = {
	.swio_entries	= rza1h_swio_entries,
};

/* ----------------------------------------------------------------------------
 * RZ/A1L (r7s72102) pinmux flags
 */

static const struct rza1_bidir_pin rza1l_bidir_pins_p1[] = {
	{ .pin = 0, .func = 1 },
	{ .pin = 1, .func = 1 },
	{ .pin = 2, .func = 1 },
	{ .pin = 3, .func = 1 },
	{ .pin = 4, .func = 1 },
	{ .pin = 5, .func = 1 },
	{ .pin = 6, .func = 1 },
	{ .pin = 7, .func = 1 },
};

static const struct rza1_bidir_pin rza1l_bidir_pins_p3[] = {
	{ .pin = 0, .func = 2 },
	{ .pin = 1, .func = 2 },
	{ .pin = 2, .func = 2 },
	{ .pin = 4, .func = 2 },
	{ .pin = 5, .func = 2 },
	{ .pin = 10, .func = 2 },
	{ .pin = 11, .func = 2 },
	{ .pin = 12, .func = 2 },
	{ .pin = 13, .func = 2 },
};

static const struct rza1_bidir_pin rza1l_bidir_pins_p4[] = {
	{ .pin = 1, .func = 4 },
	{ .pin = 2, .func = 2 },
	{ .pin = 3, .func = 2 },
	{ .pin = 6, .func = 2 },
	{ .pin = 7, .func = 2 },
};

static const struct rza1_bidir_pin rza1l_bidir_pins_p5[] = {
	{ .pin = 0, .func = 1 },
	{ .pin = 1, .func = 1 },
	{ .pin = 2, .func = 1 },
	{ .pin = 3, .func = 1 },
	{ .pin = 4, .func = 1 },
	{ .pin = 5, .func = 1 },
	{ .pin = 6, .func = 1 },
	{ .pin = 7, .func = 1 },
	{ .pin = 8, .func = 1 },
	{ .pin = 9, .func = 1 },
	{ .pin = 10, .func = 1 },
	{ .pin = 11, .func = 1 },
	{ .pin = 12, .func = 1 },
	{ .pin = 13, .func = 1 },
	{ .pin = 14, .func = 1 },
	{ .pin = 15, .func = 1 },
	{ .pin = 0, .func = 2 },
	{ .pin = 1, .func = 2 },
	{ .pin = 2, .func = 2 },
	{ .pin = 3, .func = 2 },
};

static const struct rza1_bidir_pin rza1l_bidir_pins_p6[] = {
	{ .pin = 0, .func = 1 },
	{ .pin = 1, .func = 1 },
	{ .pin = 2, .func = 1 },
	{ .pin = 3, .func = 1 },
	{ .pin = 4, .func = 1 },
	{ .pin = 5, .func = 1 },
	{ .pin = 6, .func = 1 },
	{ .pin = 7, .func = 1 },
	{ .pin = 8, .func = 1 },
	{ .pin = 9, .func = 1 },
	{ .pin = 10, .func = 1 },
	{ .pin = 11, .func = 1 },
	{ .pin = 12, .func = 1 },
	{ .pin = 13, .func = 1 },
	{ .pin = 14, .func = 1 },
	{ .pin = 15, .func = 1 },
};

static const struct rza1_bidir_pin rza1l_bidir_pins_p7[] = {
	{ .pin = 2, .func = 2 },
	{ .pin = 3, .func = 2 },
	{ .pin = 5, .func = 2 },
	{ .pin = 6, .func = 2 },
	{ .pin = 7, .func = 2 },
	{ .pin = 2, .func = 3 },
	{ .pin = 3, .func = 3 },
	{ .pin = 5, .func = 3 },
	{ .pin = 6, .func = 3 },
	{ .pin = 7, .func = 3 },
};

static const struct rza1_bidir_pin rza1l_bidir_pins_p9[] = {
	{ .pin = 1, .func = 2 },
	{ .pin = 0, .func = 3 },
	{ .pin = 1, .func = 3 },
	{ .pin = 3, .func = 3 },
	{ .pin = 4, .func = 3 },
	{ .pin = 5, .func = 3 },
};

static const struct rza1_swio_pin rza1l_swio_pins[] = {
	{ .port = 2, .pin = 8, .func = 2, .input = 0 },
	{ .port = 5, .pin = 6, .func = 3, .input = 0 },
	{ .port = 6, .pin = 6, .func = 3, .input = 0 },
	{ .port = 6, .pin = 10, .func = 3, .input = 0 },
	{ .port = 7, .pin = 10, .func = 2, .input = 0 },
	{ .port = 8, .pin = 2, .func = 3, .input = 0 },
};

static const struct rza1_bidir_entry rza1l_bidir_entries[RZA1_NPORTS] = {
	[1] = { ARRAY_SIZE(rza1l_bidir_pins_p1), rza1l_bidir_pins_p1 },
	[3] = { ARRAY_SIZE(rza1l_bidir_pins_p3), rza1l_bidir_pins_p3 },
	[4] = { ARRAY_SIZE(rza1l_bidir_pins_p4), rza1l_bidir_pins_p4 },
	[5] = { ARRAY_SIZE(rza1l_bidir_pins_p4), rza1l_bidir_pins_p5 },
	[6] = { ARRAY_SIZE(rza1l_bidir_pins_p6), rza1l_bidir_pins_p6 },
	[7] = { ARRAY_SIZE(rza1l_bidir_pins_p7), rza1l_bidir_pins_p7 },
	[9] = { ARRAY_SIZE(rza1l_bidir_pins_p9), rza1l_bidir_pins_p9 },
};

static const struct rza1_swio_entry rza1l_swio_entries[] = {
	[0] = { ARRAY_SIZE(rza1h_swio_pins), rza1h_swio_pins },
};

/* RZ/A1L (r7s72102x) pinmux flags table */
static const struct rza1_pinmux_conf rza1l_pmx_conf = {
	.bidir_entries	= rza1l_bidir_entries,
	.swio_entries	= rza1l_swio_entries,
};

/* ----------------------------------------------------------------------------
 * RZ/A1 types
 */
@@ -1283,9 +1411,15 @@ static int rza1_pinctrl_probe(struct platform_device *pdev)

static const struct of_device_id rza1_pinctrl_of_match[] = {
	{
		/* RZ/A1H, RZ/A1M */
		.compatible	= "renesas,r7s72100-ports",
		.data		= &rza1h_pmx_conf,
	},
	{
		/* RZ/A1L */
		.compatible	= "renesas,r7s72102-ports",
		.data		= &rza1l_pmx_conf,
	},
	{ }
};

+114 −17
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/of_device.h>
#include <linux/pinctrl/machine.h>
#include <linux/platform_device.h>
#include <linux/psci.h>
#include <linux/slab.h>

#include "core.h"
@@ -175,19 +176,19 @@ void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width,
	BUG();
}

u32 sh_pfc_read_reg(struct sh_pfc *pfc, u32 reg, unsigned int width)
u32 sh_pfc_read(struct sh_pfc *pfc, u32 reg)
{
	return sh_pfc_read_raw_reg(sh_pfc_phys_to_virt(pfc, reg), width);
	return sh_pfc_read_raw_reg(sh_pfc_phys_to_virt(pfc, reg), 32);
}

void sh_pfc_write_reg(struct sh_pfc *pfc, u32 reg, unsigned int width, u32 data)
void sh_pfc_write(struct sh_pfc *pfc, u32 reg, u32 data)
{
	if (pfc->info->unlock_reg)
		sh_pfc_write_raw_reg(
			sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
			~data);

	sh_pfc_write_raw_reg(sh_pfc_phys_to_virt(pfc, reg), width, data);
	sh_pfc_write_raw_reg(sh_pfc_phys_to_virt(pfc, reg), 32, data);
}

static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
@@ -389,15 +390,20 @@ int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
	return 0;
}

const struct sh_pfc_bias_info *
sh_pfc_pin_to_bias_info(const struct sh_pfc_bias_info *info,
			unsigned int num, unsigned int pin)
const struct pinmux_bias_reg *
sh_pfc_pin_to_bias_reg(const struct sh_pfc *pfc, unsigned int pin,
		       unsigned int *bit)
{
	unsigned int i;
	unsigned int i, j;

	for (i = 0; i < num; i++)
		if (info[i].pin == pin)
			return &info[i];
	for (i = 0; pfc->info->bias_regs[i].puen; i++) {
		for (j = 0; j < ARRAY_SIZE(pfc->info->bias_regs[i].pins); j++) {
			if (pfc->info->bias_regs[i].pins[j] == pin) {
				*bit = j;
				return &pfc->info->bias_regs[i];
			}
		}
	}

	WARN_ONCE(1, "Pin %u is not in bias info list\n", pin);

@@ -567,9 +573,99 @@ static const struct of_device_id sh_pfc_of_table[] = {
};
#endif

#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
static void sh_pfc_nop_reg(struct sh_pfc *pfc, u32 reg, unsigned int idx)
{
}

static void sh_pfc_save_reg(struct sh_pfc *pfc, u32 reg, unsigned int idx)
{
	pfc->saved_regs[idx] = sh_pfc_read(pfc, reg);
}

static void sh_pfc_restore_reg(struct sh_pfc *pfc, u32 reg, unsigned int idx)
{
	sh_pfc_write(pfc, reg, pfc->saved_regs[idx]);
}

static unsigned int sh_pfc_walk_regs(struct sh_pfc *pfc,
	void (*do_reg)(struct sh_pfc *pfc, u32 reg, unsigned int idx))
{
	unsigned int i, n = 0;

	if (pfc->info->cfg_regs)
		for (i = 0; pfc->info->cfg_regs[i].reg; i++)
			do_reg(pfc, pfc->info->cfg_regs[i].reg, n++);

	if (pfc->info->drive_regs)
		for (i = 0; pfc->info->drive_regs[i].reg; i++)
			do_reg(pfc, pfc->info->drive_regs[i].reg, n++);

	if (pfc->info->bias_regs)
		for (i = 0; pfc->info->bias_regs[i].puen; i++) {
			do_reg(pfc, pfc->info->bias_regs[i].puen, n++);
			if (pfc->info->bias_regs[i].pud)
				do_reg(pfc, pfc->info->bias_regs[i].pud, n++);
		}

	if (pfc->info->ioctrl_regs)
		for (i = 0; pfc->info->ioctrl_regs[i].reg; i++)
			do_reg(pfc, pfc->info->ioctrl_regs[i].reg, n++);

	return n;
}

static int sh_pfc_suspend_init(struct sh_pfc *pfc)
{
	unsigned int n;

	/* This is the best we can do to check for the presence of PSCI */
	if (!psci_ops.cpu_suspend)
		return 0;

	n = sh_pfc_walk_regs(pfc, sh_pfc_nop_reg);
	if (!n)
		return 0;

	pfc->saved_regs = devm_kmalloc_array(pfc->dev, n,
					     sizeof(*pfc->saved_regs),
					     GFP_KERNEL);
	if (!pfc->saved_regs)
		return -ENOMEM;

	dev_dbg(pfc->dev, "Allocated space to save %u regs\n", n);
	return 0;
}

static int sh_pfc_suspend_noirq(struct device *dev)
{
	struct sh_pfc *pfc = dev_get_drvdata(dev);

	if (pfc->saved_regs)
		sh_pfc_walk_regs(pfc, sh_pfc_save_reg);
	return 0;
}

static int sh_pfc_resume_noirq(struct device *dev)
{
	struct sh_pfc *pfc = dev_get_drvdata(dev);

	if (pfc->saved_regs)
		sh_pfc_walk_regs(pfc, sh_pfc_restore_reg);
	return 0;
}

static const struct dev_pm_ops sh_pfc_pm  = {
	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sh_pfc_suspend_noirq, sh_pfc_resume_noirq)
};
#define DEV_PM_OPS	&sh_pfc_pm
#else
static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; }
#define DEV_PM_OPS	NULL
#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */

static int sh_pfc_probe(struct platform_device *pdev)
{
	const struct platform_device_id *platid = platform_get_device_id(pdev);
#ifdef CONFIG_OF
	struct device_node *np = pdev->dev.of_node;
#endif
@@ -582,10 +678,7 @@ static int sh_pfc_probe(struct platform_device *pdev)
		info = of_device_get_match_data(&pdev->dev);
	else
#endif
		info = platid ? (const void *)platid->driver_data : NULL;

	if (info == NULL)
		return -ENODEV;
		info = (const void *)platform_get_device_id(pdev)->driver_data;

	pfc = devm_kzalloc(&pdev->dev, sizeof(*pfc), GFP_KERNEL);
	if (pfc == NULL)
@@ -609,6 +702,10 @@ static int sh_pfc_probe(struct platform_device *pdev)
		info = pfc->info;
	}

	ret = sh_pfc_suspend_init(pfc);
	if (ret)
		return ret;

	/* Enable dummy states for those platforms without pinctrl support */
	if (!of_have_populated_dt())
		pinctrl_provide_dummies();
@@ -683,7 +780,6 @@ static const struct platform_device_id sh_pfc_id_table[] = {
#ifdef CONFIG_PINCTRL_PFC_SHX3
	{ "pfc-shx3", (kernel_ulong_t)&shx3_pinmux_info },
#endif
	{ "sh-pfc", 0 },
	{ },
};

@@ -693,6 +789,7 @@ static struct platform_driver sh_pfc_driver = {
	.driver		= {
		.name	= DRV_NAME,
		.of_match_table = of_match_ptr(sh_pfc_of_table),
		.pm     = DEV_PM_OPS,
	},
};

+5 −6
Original line number Diff line number Diff line
@@ -26,15 +26,14 @@ int sh_pfc_register_pinctrl(struct sh_pfc *pfc);
u32 sh_pfc_read_raw_reg(void __iomem *mapped_reg, unsigned int reg_width);
void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width,
			  u32 data);
u32 sh_pfc_read_reg(struct sh_pfc *pfc, u32 reg, unsigned int width);
void sh_pfc_write_reg(struct sh_pfc *pfc, u32 reg, unsigned int width,
		      u32 data);
u32 sh_pfc_read(struct sh_pfc *pfc, u32 reg);
void sh_pfc_write(struct sh_pfc *pfc, u32 reg, u32 data);

int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin);
int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type);

const struct sh_pfc_bias_info *
sh_pfc_pin_to_bias_info(const struct sh_pfc_bias_info *info,
			unsigned int num, unsigned int pin);
const struct pinmux_bias_reg *
sh_pfc_pin_to_bias_reg(const struct sh_pfc *pfc, unsigned int pin,
		       unsigned int *bit);

#endif /* __SH_PFC_CORE_H__ */
+222 −181

File changed.

Preview size limit exceeded, changes collapsed.

Loading