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

Commit 27618795 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.

Change-Id: I390f0b6ec52aafe2eac49e8207c7754b9166491e
Signed-off-by: default avatarAnant Goel <anantg@codeaurora.org>
parent dc9a2b8f
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -46,6 +46,12 @@ SM6150 platform.
	Value type: <u32>
	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 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
@@ -1642,7 +1642,7 @@ static struct msm_dir_conn sm6150_dir_conn[] = {
	{-1, 209},
};

static const struct msm_pinctrl_soc_data sm6150_pinctrl = {
static struct msm_pinctrl_soc_data sm6150_pinctrl = {
	.pins = sm6150_pins,
	.npins = ARRAY_SIZE(sm6150_pins),
	.functions = sm6150_functions,
@@ -1655,8 +1655,64 @@ static const struct msm_pinctrl_soc_data sm6150_pinctrl = {
	.dir_conn_irq_base = 216,
};

static int sm6150_pinctrl_dir_conn_probe(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_kzalloc(&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_kzalloc(&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++];
	}

	sm6150_pinctrl.dir_conn = dir_conn_list;
	sm6150_pinctrl.n_dir_conns = num_dir_conns;

	return 0;
}

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

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

	return msm_pinctrl_probe(pdev, &sm6150_pinctrl);
}