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

Commit 3f15815e authored by Anant Goel's avatar Anant Goel
Browse files

drivers: msm: pinctrl: Add custom TLMM direct connect list feature support



Add support to provide a custom list of TLMM GPIOs, associated with
hardware IRQs, for direct connect interrupt support on the
sdmshrike target.

Change-Id: Ied5934e6d0162806370b636d343cc525e3b15954
Signed-off-by: default avatarAnant Goel <anantg@codeaurora.org>
parent d55696ba
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -47,6 +47,13 @@ sdmshrike platform.
	Definition: must be 2. Specifying the pin number and flags, as defined
		    in <dt-bindings/gpio/gpio.h>

- dirconn-list:
	Usage: optional
	Value type: <prop-encoded-array>
	Definition: a 3-tuple list which contains the mapping of GPIO pin to
		    hardware IRQ, and a boolean for enabling the TLMM direct
		    connect interrupt for the pin.

Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
a general description of GPIO and interrupt bindings.

+57 −1
Original line number Diff line number Diff line
@@ -2257,7 +2257,7 @@ static struct msm_dir_conn sdmshrike_dir_conn[] = {
	{-1, 209},
};

static const struct msm_pinctrl_soc_data sdmshrike_pinctrl = {
static struct msm_pinctrl_soc_data sdmshrike_pinctrl = {
	.pins = sdmshrike_pins,
	.npins = ARRAY_SIZE(sdmshrike_pins),
	.functions = sdmshrike_functions,
@@ -2270,8 +2270,64 @@ static const struct msm_pinctrl_soc_data sdmshrike_pinctrl = {
	.dir_conn_irq_base = 216,
};

static int sdmshrike_pinctrl_parse_dt(struct platform_device *pdev)
{
	const __be32 *prop;
	struct msm_dir_conn *dir_conn_list;
	uint32_t dir_conn_length, iterator = 0;
	int i, length, *dir_conn_entries, num_dir_conns;

	prop = of_get_property(pdev->dev.of_node, "dirconn-list",
			&length);

	dir_conn_length = length / sizeof(u32);

	dir_conn_entries = devm_kcalloc(&pdev->dev,
				dir_conn_length, sizeof(uint32_t), GFP_KERNEL);
	if (!dir_conn_entries)
		return -ENOMEM;

	for (i = 0; i < dir_conn_length; i++)
		dir_conn_entries[i] = be32_to_cpu(prop[i]);

	if (dir_conn_length % 3) {
		dev_err(&pdev->dev,
			"Can't parse an entry with fewer than three values\n");
		return -EINVAL;
	};

	num_dir_conns = (dir_conn_length / 3);

	dir_conn_list = devm_kcalloc(&pdev->dev,
			num_dir_conns, sizeof(*dir_conn_list), GFP_KERNEL);
	if (!dir_conn_list)
		return -ENOMEM;

	for (i = 0; i < num_dir_conns; i++) {
		dir_conn_list[i].gpio = dir_conn_entries[iterator++];
		dir_conn_list[i].hwirq = dir_conn_entries[iterator++];
		dir_conn_list[i].tlmm_dc = dir_conn_entries[iterator++];
	}

	sdmshrike_pinctrl.dir_conn = dir_conn_list;
	sdmshrike_pinctrl.n_dir_conns = num_dir_conns;

	return 0;
}

static int sdmshrike_pinctrl_probe(struct platform_device *pdev)
{
	int len, ret;

	if (of_find_property(pdev->dev.of_node, "dirconn-list", &len)) {
		ret = sdmshrike_pinctrl_parse_dt(pdev);
		if (ret) {
			dev_err(&pdev->dev,
				"Unable to parse TLMM direct connects\n");
			return ret;
		}
	}

	return msm_pinctrl_probe(pdev, &sdmshrike_pinctrl);
}