162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Pinctrl for Cirrus Logic Madera codecs
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2016-2018 Cirrus Logic
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/err.h>
962306a36Sopenharmony_ci#include <linux/module.h>
1062306a36Sopenharmony_ci#include <linux/platform_device.h>
1162306a36Sopenharmony_ci#include <linux/property.h>
1262306a36Sopenharmony_ci#include <linux/regmap.h>
1362306a36Sopenharmony_ci#include <linux/seq_file.h>
1462306a36Sopenharmony_ci#include <linux/slab.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <linux/pinctrl/machine.h>
1762306a36Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h>
1862306a36Sopenharmony_ci#include <linux/pinctrl/pinconf.h>
1962306a36Sopenharmony_ci#include <linux/pinctrl/pinctrl.h>
2062306a36Sopenharmony_ci#include <linux/pinctrl/pinmux.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include <linux/mfd/madera/core.h>
2362306a36Sopenharmony_ci#include <linux/mfd/madera/registers.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include "../pinctrl-utils.h"
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include "pinctrl-madera.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/*
3062306a36Sopenharmony_ci * Use pin GPIO names for consistency
3162306a36Sopenharmony_ci * NOTE: IDs are zero-indexed for coding convenience
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_cistatic const struct pinctrl_pin_desc madera_pins[] = {
3462306a36Sopenharmony_ci	PINCTRL_PIN(0, "gpio1"),
3562306a36Sopenharmony_ci	PINCTRL_PIN(1, "gpio2"),
3662306a36Sopenharmony_ci	PINCTRL_PIN(2, "gpio3"),
3762306a36Sopenharmony_ci	PINCTRL_PIN(3, "gpio4"),
3862306a36Sopenharmony_ci	PINCTRL_PIN(4, "gpio5"),
3962306a36Sopenharmony_ci	PINCTRL_PIN(5, "gpio6"),
4062306a36Sopenharmony_ci	PINCTRL_PIN(6, "gpio7"),
4162306a36Sopenharmony_ci	PINCTRL_PIN(7, "gpio8"),
4262306a36Sopenharmony_ci	PINCTRL_PIN(8, "gpio9"),
4362306a36Sopenharmony_ci	PINCTRL_PIN(9, "gpio10"),
4462306a36Sopenharmony_ci	PINCTRL_PIN(10, "gpio11"),
4562306a36Sopenharmony_ci	PINCTRL_PIN(11, "gpio12"),
4662306a36Sopenharmony_ci	PINCTRL_PIN(12, "gpio13"),
4762306a36Sopenharmony_ci	PINCTRL_PIN(13, "gpio14"),
4862306a36Sopenharmony_ci	PINCTRL_PIN(14, "gpio15"),
4962306a36Sopenharmony_ci	PINCTRL_PIN(15, "gpio16"),
5062306a36Sopenharmony_ci	PINCTRL_PIN(16, "gpio17"),
5162306a36Sopenharmony_ci	PINCTRL_PIN(17, "gpio18"),
5262306a36Sopenharmony_ci	PINCTRL_PIN(18, "gpio19"),
5362306a36Sopenharmony_ci	PINCTRL_PIN(19, "gpio20"),
5462306a36Sopenharmony_ci	PINCTRL_PIN(20, "gpio21"),
5562306a36Sopenharmony_ci	PINCTRL_PIN(21, "gpio22"),
5662306a36Sopenharmony_ci	PINCTRL_PIN(22, "gpio23"),
5762306a36Sopenharmony_ci	PINCTRL_PIN(23, "gpio24"),
5862306a36Sopenharmony_ci	PINCTRL_PIN(24, "gpio25"),
5962306a36Sopenharmony_ci	PINCTRL_PIN(25, "gpio26"),
6062306a36Sopenharmony_ci	PINCTRL_PIN(26, "gpio27"),
6162306a36Sopenharmony_ci	PINCTRL_PIN(27, "gpio28"),
6262306a36Sopenharmony_ci	PINCTRL_PIN(28, "gpio29"),
6362306a36Sopenharmony_ci	PINCTRL_PIN(29, "gpio30"),
6462306a36Sopenharmony_ci	PINCTRL_PIN(30, "gpio31"),
6562306a36Sopenharmony_ci	PINCTRL_PIN(31, "gpio32"),
6662306a36Sopenharmony_ci	PINCTRL_PIN(32, "gpio33"),
6762306a36Sopenharmony_ci	PINCTRL_PIN(33, "gpio34"),
6862306a36Sopenharmony_ci	PINCTRL_PIN(34, "gpio35"),
6962306a36Sopenharmony_ci	PINCTRL_PIN(35, "gpio36"),
7062306a36Sopenharmony_ci	PINCTRL_PIN(36, "gpio37"),
7162306a36Sopenharmony_ci	PINCTRL_PIN(37, "gpio38"),
7262306a36Sopenharmony_ci	PINCTRL_PIN(38, "gpio39"),
7362306a36Sopenharmony_ci	PINCTRL_PIN(39, "gpio40"),
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci/*
7762306a36Sopenharmony_ci * All single-pin functions can be mapped to any GPIO, however pinmux applies
7862306a36Sopenharmony_ci * functions to pin groups and only those groups declared as supporting that
7962306a36Sopenharmony_ci * function. To make this work we must put each pin in its own dummy group so
8062306a36Sopenharmony_ci * that the functions can be described as applying to all pins.
8162306a36Sopenharmony_ci * Since these do not correspond to anything in the actual hardware - they are
8262306a36Sopenharmony_ci * merely an adaptation to pinctrl's view of the world - we use the same name
8362306a36Sopenharmony_ci * as the pin to avoid confusion when comparing with datasheet instructions
8462306a36Sopenharmony_ci */
8562306a36Sopenharmony_cistatic const char * const madera_pin_single_group_names[] = {
8662306a36Sopenharmony_ci	"gpio1",  "gpio2",  "gpio3",  "gpio4",  "gpio5",  "gpio6",  "gpio7",
8762306a36Sopenharmony_ci	"gpio8",  "gpio9",  "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
8862306a36Sopenharmony_ci	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
8962306a36Sopenharmony_ci	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
9062306a36Sopenharmony_ci	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
9162306a36Sopenharmony_ci	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40",
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci/* set of pin numbers for single-pin groups, zero-indexed */
9562306a36Sopenharmony_cistatic const unsigned int madera_pin_single_group_pins[] = {
9662306a36Sopenharmony_ci	  0,  1,  2,  3,  4,  5,  6,
9762306a36Sopenharmony_ci	  7,  8,  9, 10, 11, 12, 13,
9862306a36Sopenharmony_ci	 14, 15, 16, 17, 18, 19, 20,
9962306a36Sopenharmony_ci	 21, 22, 23, 24, 25, 26, 27,
10062306a36Sopenharmony_ci	 28, 29, 30, 31, 32, 33, 34,
10162306a36Sopenharmony_ci	 35, 36, 37, 38, 39,
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic const char * const madera_aif1_group_names[] = { "aif1" };
10562306a36Sopenharmony_cistatic const char * const madera_aif2_group_names[] = { "aif2" };
10662306a36Sopenharmony_cistatic const char * const madera_aif3_group_names[] = { "aif3" };
10762306a36Sopenharmony_cistatic const char * const madera_aif4_group_names[] = { "aif4" };
10862306a36Sopenharmony_cistatic const char * const madera_mif1_group_names[] = { "mif1" };
10962306a36Sopenharmony_cistatic const char * const madera_mif2_group_names[] = { "mif2" };
11062306a36Sopenharmony_cistatic const char * const madera_mif3_group_names[] = { "mif3" };
11162306a36Sopenharmony_cistatic const char * const madera_dmic3_group_names[] = { "dmic3" };
11262306a36Sopenharmony_cistatic const char * const madera_dmic4_group_names[] = { "dmic4" };
11362306a36Sopenharmony_cistatic const char * const madera_dmic5_group_names[] = { "dmic5" };
11462306a36Sopenharmony_cistatic const char * const madera_dmic6_group_names[] = { "dmic6" };
11562306a36Sopenharmony_cistatic const char * const madera_spk1_group_names[] = { "pdmspk1" };
11662306a36Sopenharmony_cistatic const char * const madera_spk2_group_names[] = { "pdmspk2" };
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/*
11962306a36Sopenharmony_ci * alt-functions always apply to a single pin group, other functions always
12062306a36Sopenharmony_ci * apply to all pins
12162306a36Sopenharmony_ci */
12262306a36Sopenharmony_cistatic const struct {
12362306a36Sopenharmony_ci	const char *name;
12462306a36Sopenharmony_ci	const char * const *group_names;
12562306a36Sopenharmony_ci	u32 func;
12662306a36Sopenharmony_ci} madera_mux_funcs[] = {
12762306a36Sopenharmony_ci	{
12862306a36Sopenharmony_ci		.name = "aif1",
12962306a36Sopenharmony_ci		.group_names = madera_aif1_group_names,
13062306a36Sopenharmony_ci		.func = 0x000
13162306a36Sopenharmony_ci	},
13262306a36Sopenharmony_ci	{
13362306a36Sopenharmony_ci		.name = "aif2",
13462306a36Sopenharmony_ci		.group_names = madera_aif2_group_names,
13562306a36Sopenharmony_ci		.func = 0x000
13662306a36Sopenharmony_ci	},
13762306a36Sopenharmony_ci	{
13862306a36Sopenharmony_ci		.name = "aif3",
13962306a36Sopenharmony_ci		.group_names = madera_aif3_group_names,
14062306a36Sopenharmony_ci		.func = 0x000
14162306a36Sopenharmony_ci	},
14262306a36Sopenharmony_ci	{
14362306a36Sopenharmony_ci		.name = "aif4",
14462306a36Sopenharmony_ci		.group_names = madera_aif4_group_names,
14562306a36Sopenharmony_ci		.func = 0x000
14662306a36Sopenharmony_ci	},
14762306a36Sopenharmony_ci	{
14862306a36Sopenharmony_ci		.name = "mif1",
14962306a36Sopenharmony_ci		.group_names = madera_mif1_group_names,
15062306a36Sopenharmony_ci		.func = 0x000
15162306a36Sopenharmony_ci	},
15262306a36Sopenharmony_ci	{
15362306a36Sopenharmony_ci		.name = "mif2",
15462306a36Sopenharmony_ci		.group_names = madera_mif2_group_names,
15562306a36Sopenharmony_ci		.func = 0x000
15662306a36Sopenharmony_ci	},
15762306a36Sopenharmony_ci	{
15862306a36Sopenharmony_ci		.name = "mif3",
15962306a36Sopenharmony_ci		.group_names = madera_mif3_group_names,
16062306a36Sopenharmony_ci		.func = 0x000
16162306a36Sopenharmony_ci	},
16262306a36Sopenharmony_ci	{
16362306a36Sopenharmony_ci		.name = "dmic3",
16462306a36Sopenharmony_ci		.group_names = madera_dmic3_group_names,
16562306a36Sopenharmony_ci		.func = 0x000
16662306a36Sopenharmony_ci	},
16762306a36Sopenharmony_ci	{
16862306a36Sopenharmony_ci		.name = "dmic4",
16962306a36Sopenharmony_ci		.group_names = madera_dmic4_group_names,
17062306a36Sopenharmony_ci		.func = 0x000
17162306a36Sopenharmony_ci	},
17262306a36Sopenharmony_ci	{
17362306a36Sopenharmony_ci		.name = "dmic5",
17462306a36Sopenharmony_ci		.group_names = madera_dmic5_group_names,
17562306a36Sopenharmony_ci		.func = 0x000
17662306a36Sopenharmony_ci	},
17762306a36Sopenharmony_ci	{
17862306a36Sopenharmony_ci		.name = "dmic6",
17962306a36Sopenharmony_ci		.group_names = madera_dmic6_group_names,
18062306a36Sopenharmony_ci		.func = 0x000
18162306a36Sopenharmony_ci	},
18262306a36Sopenharmony_ci	{
18362306a36Sopenharmony_ci		.name = "pdmspk1",
18462306a36Sopenharmony_ci		.group_names = madera_spk1_group_names,
18562306a36Sopenharmony_ci		.func = 0x000
18662306a36Sopenharmony_ci	},
18762306a36Sopenharmony_ci	{
18862306a36Sopenharmony_ci		.name = "pdmspk2",
18962306a36Sopenharmony_ci		.group_names = madera_spk2_group_names,
19062306a36Sopenharmony_ci		.func = 0x000
19162306a36Sopenharmony_ci	},
19262306a36Sopenharmony_ci	{
19362306a36Sopenharmony_ci		.name = "io",
19462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
19562306a36Sopenharmony_ci		.func = 0x001
19662306a36Sopenharmony_ci	},
19762306a36Sopenharmony_ci	{
19862306a36Sopenharmony_ci		.name = "dsp-gpio",
19962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
20062306a36Sopenharmony_ci		.func = 0x002
20162306a36Sopenharmony_ci	},
20262306a36Sopenharmony_ci	{
20362306a36Sopenharmony_ci		.name = "irq1",
20462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
20562306a36Sopenharmony_ci		.func = 0x003
20662306a36Sopenharmony_ci	},
20762306a36Sopenharmony_ci	{
20862306a36Sopenharmony_ci		.name = "irq2",
20962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
21062306a36Sopenharmony_ci		.func = 0x004
21162306a36Sopenharmony_ci	},
21262306a36Sopenharmony_ci	{
21362306a36Sopenharmony_ci		.name = "fll1-clk",
21462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
21562306a36Sopenharmony_ci		.func = 0x010
21662306a36Sopenharmony_ci	},
21762306a36Sopenharmony_ci	{
21862306a36Sopenharmony_ci		.name = "fll2-clk",
21962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
22062306a36Sopenharmony_ci		.func = 0x011
22162306a36Sopenharmony_ci	},
22262306a36Sopenharmony_ci	{
22362306a36Sopenharmony_ci		.name = "fll3-clk",
22462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
22562306a36Sopenharmony_ci		.func = 0x012
22662306a36Sopenharmony_ci	},
22762306a36Sopenharmony_ci	{
22862306a36Sopenharmony_ci		.name = "fllao-clk",
22962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
23062306a36Sopenharmony_ci		.func = 0x013
23162306a36Sopenharmony_ci	},
23262306a36Sopenharmony_ci	{
23362306a36Sopenharmony_ci		.name = "fll1-lock",
23462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
23562306a36Sopenharmony_ci		.func = 0x018
23662306a36Sopenharmony_ci	},
23762306a36Sopenharmony_ci	{
23862306a36Sopenharmony_ci		.name = "fll2-lock",
23962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
24062306a36Sopenharmony_ci		.func = 0x019
24162306a36Sopenharmony_ci	},
24262306a36Sopenharmony_ci	{
24362306a36Sopenharmony_ci		.name = "fll3-lock",
24462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
24562306a36Sopenharmony_ci		.func = 0x01a
24662306a36Sopenharmony_ci	},
24762306a36Sopenharmony_ci	{
24862306a36Sopenharmony_ci		.name = "fllao-lock",
24962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
25062306a36Sopenharmony_ci		.func = 0x01b
25162306a36Sopenharmony_ci	},
25262306a36Sopenharmony_ci	{
25362306a36Sopenharmony_ci		.name = "opclk",
25462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
25562306a36Sopenharmony_ci		.func = 0x040
25662306a36Sopenharmony_ci	},
25762306a36Sopenharmony_ci	{
25862306a36Sopenharmony_ci		.name = "opclk-async",
25962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
26062306a36Sopenharmony_ci		.func = 0x041
26162306a36Sopenharmony_ci	},
26262306a36Sopenharmony_ci	{
26362306a36Sopenharmony_ci		.name = "pwm1",
26462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
26562306a36Sopenharmony_ci		.func = 0x048
26662306a36Sopenharmony_ci	},
26762306a36Sopenharmony_ci	{
26862306a36Sopenharmony_ci		.name = "pwm2",
26962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
27062306a36Sopenharmony_ci		.func = 0x049
27162306a36Sopenharmony_ci	},
27262306a36Sopenharmony_ci	{
27362306a36Sopenharmony_ci		.name = "spdif",
27462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
27562306a36Sopenharmony_ci		.func = 0x04c
27662306a36Sopenharmony_ci	},
27762306a36Sopenharmony_ci	{
27862306a36Sopenharmony_ci		.name = "asrc1-in1-lock",
27962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
28062306a36Sopenharmony_ci		.func = 0x088
28162306a36Sopenharmony_ci	},
28262306a36Sopenharmony_ci	{
28362306a36Sopenharmony_ci		.name = "asrc1-in2-lock",
28462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
28562306a36Sopenharmony_ci		.func = 0x089
28662306a36Sopenharmony_ci	},
28762306a36Sopenharmony_ci	{
28862306a36Sopenharmony_ci		.name = "asrc2-in1-lock",
28962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
29062306a36Sopenharmony_ci		.func = 0x08a
29162306a36Sopenharmony_ci	},
29262306a36Sopenharmony_ci	{
29362306a36Sopenharmony_ci		.name = "asrc2-in2-lock",
29462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
29562306a36Sopenharmony_ci		.func = 0x08b
29662306a36Sopenharmony_ci	},
29762306a36Sopenharmony_ci	{
29862306a36Sopenharmony_ci		.name = "spkl-short-circuit",
29962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
30062306a36Sopenharmony_ci		.func = 0x0b6
30162306a36Sopenharmony_ci	},
30262306a36Sopenharmony_ci	{
30362306a36Sopenharmony_ci		.name = "spkr-short-circuit",
30462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
30562306a36Sopenharmony_ci		.func = 0x0b7
30662306a36Sopenharmony_ci	},
30762306a36Sopenharmony_ci	{
30862306a36Sopenharmony_ci		.name = "spk-shutdown",
30962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
31062306a36Sopenharmony_ci		.func = 0x0e0
31162306a36Sopenharmony_ci	},
31262306a36Sopenharmony_ci	{
31362306a36Sopenharmony_ci		.name = "spk-overheat-shutdown",
31462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
31562306a36Sopenharmony_ci		.func = 0x0e1
31662306a36Sopenharmony_ci	},
31762306a36Sopenharmony_ci	{
31862306a36Sopenharmony_ci		.name = "spk-overheat-warn",
31962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
32062306a36Sopenharmony_ci		.func = 0x0e2
32162306a36Sopenharmony_ci	},
32262306a36Sopenharmony_ci	{
32362306a36Sopenharmony_ci		.name = "timer1-sts",
32462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
32562306a36Sopenharmony_ci		.func = 0x140
32662306a36Sopenharmony_ci	},
32762306a36Sopenharmony_ci	{
32862306a36Sopenharmony_ci		.name = "timer2-sts",
32962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
33062306a36Sopenharmony_ci		.func = 0x141
33162306a36Sopenharmony_ci	},
33262306a36Sopenharmony_ci	{
33362306a36Sopenharmony_ci		.name = "timer3-sts",
33462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
33562306a36Sopenharmony_ci		.func = 0x142
33662306a36Sopenharmony_ci	},
33762306a36Sopenharmony_ci	{
33862306a36Sopenharmony_ci		.name = "timer4-sts",
33962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
34062306a36Sopenharmony_ci		.func = 0x143
34162306a36Sopenharmony_ci	},
34262306a36Sopenharmony_ci	{
34362306a36Sopenharmony_ci		.name = "timer5-sts",
34462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
34562306a36Sopenharmony_ci		.func = 0x144
34662306a36Sopenharmony_ci	},
34762306a36Sopenharmony_ci	{
34862306a36Sopenharmony_ci		.name = "timer6-sts",
34962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
35062306a36Sopenharmony_ci		.func = 0x145
35162306a36Sopenharmony_ci	},
35262306a36Sopenharmony_ci	{
35362306a36Sopenharmony_ci		.name = "timer7-sts",
35462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
35562306a36Sopenharmony_ci		.func = 0x146
35662306a36Sopenharmony_ci	},
35762306a36Sopenharmony_ci	{
35862306a36Sopenharmony_ci		.name = "timer8-sts",
35962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
36062306a36Sopenharmony_ci		.func = 0x147
36162306a36Sopenharmony_ci	},
36262306a36Sopenharmony_ci	{
36362306a36Sopenharmony_ci		.name = "log1-fifo-ne",
36462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
36562306a36Sopenharmony_ci		.func = 0x150
36662306a36Sopenharmony_ci	},
36762306a36Sopenharmony_ci	{
36862306a36Sopenharmony_ci		.name = "log2-fifo-ne",
36962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
37062306a36Sopenharmony_ci		.func = 0x151
37162306a36Sopenharmony_ci	},
37262306a36Sopenharmony_ci	{
37362306a36Sopenharmony_ci		.name = "log3-fifo-ne",
37462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
37562306a36Sopenharmony_ci		.func = 0x152
37662306a36Sopenharmony_ci	},
37762306a36Sopenharmony_ci	{
37862306a36Sopenharmony_ci		.name = "log4-fifo-ne",
37962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
38062306a36Sopenharmony_ci		.func = 0x153
38162306a36Sopenharmony_ci	},
38262306a36Sopenharmony_ci	{
38362306a36Sopenharmony_ci		.name = "log5-fifo-ne",
38462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
38562306a36Sopenharmony_ci		.func = 0x154
38662306a36Sopenharmony_ci	},
38762306a36Sopenharmony_ci	{
38862306a36Sopenharmony_ci		.name = "log6-fifo-ne",
38962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
39062306a36Sopenharmony_ci		.func = 0x155
39162306a36Sopenharmony_ci	},
39262306a36Sopenharmony_ci	{
39362306a36Sopenharmony_ci		.name = "log7-fifo-ne",
39462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
39562306a36Sopenharmony_ci		.func = 0x156
39662306a36Sopenharmony_ci	},
39762306a36Sopenharmony_ci	{
39862306a36Sopenharmony_ci		.name = "log8-fifo-ne",
39962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
40062306a36Sopenharmony_ci		.func = 0x157
40162306a36Sopenharmony_ci	},
40262306a36Sopenharmony_ci	{
40362306a36Sopenharmony_ci		.name = "aux-pdm-clk",
40462306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
40562306a36Sopenharmony_ci		.func = 0x280
40662306a36Sopenharmony_ci	},
40762306a36Sopenharmony_ci	{
40862306a36Sopenharmony_ci		.name = "aux-pdm-dat",
40962306a36Sopenharmony_ci		.group_names = madera_pin_single_group_names,
41062306a36Sopenharmony_ci		.func = 0x281
41162306a36Sopenharmony_ci	},
41262306a36Sopenharmony_ci};
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_cistatic u16 madera_pin_make_drv_str(struct madera_pin_private *priv,
41562306a36Sopenharmony_ci				      unsigned int milliamps)
41662306a36Sopenharmony_ci{
41762306a36Sopenharmony_ci	switch (milliamps) {
41862306a36Sopenharmony_ci	case 4:
41962306a36Sopenharmony_ci		return 0;
42062306a36Sopenharmony_ci	case 8:
42162306a36Sopenharmony_ci		return 2 << MADERA_GP1_DRV_STR_SHIFT;
42262306a36Sopenharmony_ci	default:
42362306a36Sopenharmony_ci		break;
42462306a36Sopenharmony_ci	}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	dev_warn(priv->dev, "%u mA not a valid drive strength", milliamps);
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	return 0;
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_cistatic unsigned int madera_pin_unmake_drv_str(struct madera_pin_private *priv,
43262306a36Sopenharmony_ci					      u16 regval)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	regval = (regval & MADERA_GP1_DRV_STR_MASK) >> MADERA_GP1_DRV_STR_SHIFT;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	switch (regval) {
43762306a36Sopenharmony_ci	case 0:
43862306a36Sopenharmony_ci		return 4;
43962306a36Sopenharmony_ci	case 2:
44062306a36Sopenharmony_ci		return 8;
44162306a36Sopenharmony_ci	default:
44262306a36Sopenharmony_ci		return 0;
44362306a36Sopenharmony_ci	}
44462306a36Sopenharmony_ci}
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_cistatic int madera_get_groups_count(struct pinctrl_dev *pctldev)
44762306a36Sopenharmony_ci{
44862306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	/* Number of alt function groups plus number of single-pin groups */
45162306a36Sopenharmony_ci	return priv->chip->n_pin_groups + priv->chip->n_pins;
45262306a36Sopenharmony_ci}
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_cistatic const char *madera_get_group_name(struct pinctrl_dev *pctldev,
45562306a36Sopenharmony_ci					 unsigned int selector)
45662306a36Sopenharmony_ci{
45762306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	if (selector < priv->chip->n_pin_groups)
46062306a36Sopenharmony_ci		return priv->chip->pin_groups[selector].name;
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	selector -= priv->chip->n_pin_groups;
46362306a36Sopenharmony_ci	return madera_pin_single_group_names[selector];
46462306a36Sopenharmony_ci}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_cistatic int madera_get_group_pins(struct pinctrl_dev *pctldev,
46762306a36Sopenharmony_ci				 unsigned int selector,
46862306a36Sopenharmony_ci				 const unsigned int **pins,
46962306a36Sopenharmony_ci				 unsigned int *num_pins)
47062306a36Sopenharmony_ci{
47162306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	if (selector < priv->chip->n_pin_groups) {
47462306a36Sopenharmony_ci		*pins = priv->chip->pin_groups[selector].pins;
47562306a36Sopenharmony_ci		*num_pins = priv->chip->pin_groups[selector].n_pins;
47662306a36Sopenharmony_ci	} else {
47762306a36Sopenharmony_ci		/* return the dummy group for a single pin */
47862306a36Sopenharmony_ci		selector -= priv->chip->n_pin_groups;
47962306a36Sopenharmony_ci		*pins = &madera_pin_single_group_pins[selector];
48062306a36Sopenharmony_ci		*num_pins = 1;
48162306a36Sopenharmony_ci	}
48262306a36Sopenharmony_ci	return 0;
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic void madera_pin_dbg_show_fn(struct madera_pin_private *priv,
48662306a36Sopenharmony_ci				   struct seq_file *s,
48762306a36Sopenharmony_ci				   unsigned int pin, unsigned int fn)
48862306a36Sopenharmony_ci{
48962306a36Sopenharmony_ci	const struct madera_pin_chip *chip = priv->chip;
49062306a36Sopenharmony_ci	int i, g_pin;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	if (fn != 0) {
49362306a36Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(madera_mux_funcs); ++i) {
49462306a36Sopenharmony_ci			if (madera_mux_funcs[i].func == fn) {
49562306a36Sopenharmony_ci				seq_printf(s, " FN=%s",
49662306a36Sopenharmony_ci					   madera_mux_funcs[i].name);
49762306a36Sopenharmony_ci				return;
49862306a36Sopenharmony_ci			}
49962306a36Sopenharmony_ci		}
50062306a36Sopenharmony_ci		return;	/* ignore unknown function values */
50162306a36Sopenharmony_ci	}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	/* alt function */
50462306a36Sopenharmony_ci	for (i = 0; i < chip->n_pin_groups; ++i) {
50562306a36Sopenharmony_ci		for (g_pin = 0; g_pin < chip->pin_groups[i].n_pins; ++g_pin) {
50662306a36Sopenharmony_ci			if (chip->pin_groups[i].pins[g_pin] == pin) {
50762306a36Sopenharmony_ci				seq_printf(s, " FN=%s",
50862306a36Sopenharmony_ci					   chip->pin_groups[i].name);
50962306a36Sopenharmony_ci				return;
51062306a36Sopenharmony_ci			}
51162306a36Sopenharmony_ci		}
51262306a36Sopenharmony_ci	}
51362306a36Sopenharmony_ci}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_cistatic void __maybe_unused madera_pin_dbg_show(struct pinctrl_dev *pctldev,
51662306a36Sopenharmony_ci					       struct seq_file *s,
51762306a36Sopenharmony_ci					       unsigned int pin)
51862306a36Sopenharmony_ci{
51962306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
52062306a36Sopenharmony_ci	unsigned int conf[2];
52162306a36Sopenharmony_ci	unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);
52262306a36Sopenharmony_ci	unsigned int fn;
52362306a36Sopenharmony_ci	int ret;
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	ret = regmap_read(priv->madera->regmap, reg, &conf[0]);
52662306a36Sopenharmony_ci	if (ret)
52762306a36Sopenharmony_ci		return;
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	ret = regmap_read(priv->madera->regmap, reg + 1, &conf[1]);
53062306a36Sopenharmony_ci	if (ret)
53162306a36Sopenharmony_ci		return;
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	seq_printf(s, "%04x:%04x", conf[0], conf[1]);
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	fn = (conf[0] & MADERA_GP1_FN_MASK) >> MADERA_GP1_FN_SHIFT;
53662306a36Sopenharmony_ci	madera_pin_dbg_show_fn(priv, s, pin, fn);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	/* State of direction bit is only relevant if function==1 */
53962306a36Sopenharmony_ci	if (fn == 1) {
54062306a36Sopenharmony_ci		if (conf[1] & MADERA_GP1_DIR_MASK)
54162306a36Sopenharmony_ci			seq_puts(s, " IN");
54262306a36Sopenharmony_ci		else
54362306a36Sopenharmony_ci			seq_puts(s, " OUT");
54462306a36Sopenharmony_ci	}
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	if (conf[1] & MADERA_GP1_PU_MASK)
54762306a36Sopenharmony_ci		seq_puts(s, " PU");
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	if (conf[1] & MADERA_GP1_PD_MASK)
55062306a36Sopenharmony_ci		seq_puts(s, " PD");
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	if (conf[0] & MADERA_GP1_DB_MASK)
55362306a36Sopenharmony_ci		seq_puts(s, " DB");
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	if (conf[0] & MADERA_GP1_OP_CFG_MASK)
55662306a36Sopenharmony_ci		seq_puts(s, " OD");
55762306a36Sopenharmony_ci	else
55862306a36Sopenharmony_ci		seq_puts(s, " CMOS");
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	seq_printf(s, " DRV=%umA", madera_pin_unmake_drv_str(priv, conf[1]));
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	if (conf[0] & MADERA_GP1_IP_CFG_MASK)
56362306a36Sopenharmony_ci		seq_puts(s, " SCHMITT");
56462306a36Sopenharmony_ci}
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_cistatic const struct pinctrl_ops madera_pin_group_ops = {
56762306a36Sopenharmony_ci	.get_groups_count = madera_get_groups_count,
56862306a36Sopenharmony_ci	.get_group_name = madera_get_group_name,
56962306a36Sopenharmony_ci	.get_group_pins = madera_get_group_pins,
57062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_OF)
57162306a36Sopenharmony_ci	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
57262306a36Sopenharmony_ci	.dt_free_map = pinctrl_utils_free_map,
57362306a36Sopenharmony_ci#endif
57462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_DEBUG_FS)
57562306a36Sopenharmony_ci	.pin_dbg_show = madera_pin_dbg_show,
57662306a36Sopenharmony_ci#endif
57762306a36Sopenharmony_ci};
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_cistatic int madera_mux_get_funcs_count(struct pinctrl_dev *pctldev)
58062306a36Sopenharmony_ci{
58162306a36Sopenharmony_ci	return ARRAY_SIZE(madera_mux_funcs);
58262306a36Sopenharmony_ci}
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_cistatic const char *madera_mux_get_func_name(struct pinctrl_dev *pctldev,
58562306a36Sopenharmony_ci					    unsigned int selector)
58662306a36Sopenharmony_ci{
58762306a36Sopenharmony_ci	return madera_mux_funcs[selector].name;
58862306a36Sopenharmony_ci}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_cistatic int madera_mux_get_groups(struct pinctrl_dev *pctldev,
59162306a36Sopenharmony_ci				 unsigned int selector,
59262306a36Sopenharmony_ci				 const char * const **groups,
59362306a36Sopenharmony_ci				 unsigned int * const num_groups)
59462306a36Sopenharmony_ci{
59562306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	*groups = madera_mux_funcs[selector].group_names;
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	if (madera_mux_funcs[selector].func == 0) {
60062306a36Sopenharmony_ci		/* alt func always maps to a single group */
60162306a36Sopenharmony_ci		*num_groups = 1;
60262306a36Sopenharmony_ci	} else {
60362306a36Sopenharmony_ci		/* other funcs map to all available gpio pins */
60462306a36Sopenharmony_ci		*num_groups = priv->chip->n_pins;
60562306a36Sopenharmony_ci	}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	return 0;
60862306a36Sopenharmony_ci}
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_cistatic int madera_mux_set_mux(struct pinctrl_dev *pctldev,
61162306a36Sopenharmony_ci			      unsigned int selector,
61262306a36Sopenharmony_ci			      unsigned int group)
61362306a36Sopenharmony_ci{
61462306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
61562306a36Sopenharmony_ci	struct madera *madera = priv->madera;
61662306a36Sopenharmony_ci	const struct madera_pin_groups *pin_group = priv->chip->pin_groups;
61762306a36Sopenharmony_ci	unsigned int n_chip_groups = priv->chip->n_pin_groups;
61862306a36Sopenharmony_ci	const char *func_name = madera_mux_funcs[selector].name;
61962306a36Sopenharmony_ci	unsigned int reg;
62062306a36Sopenharmony_ci	int i, ret = 0;
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	dev_dbg(priv->dev, "%s selecting %u (%s) for group %u (%s)\n",
62362306a36Sopenharmony_ci		__func__, selector, func_name, group,
62462306a36Sopenharmony_ci		madera_get_group_name(pctldev, group));
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	if (madera_mux_funcs[selector].func == 0) {
62762306a36Sopenharmony_ci		/* alt func pin assignments are codec-specific */
62862306a36Sopenharmony_ci		for (i = 0; i < n_chip_groups; ++i) {
62962306a36Sopenharmony_ci			if (strcmp(func_name, pin_group->name) == 0)
63062306a36Sopenharmony_ci				break;
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci			++pin_group;
63362306a36Sopenharmony_ci		}
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci		if (i == n_chip_groups)
63662306a36Sopenharmony_ci			return -EINVAL;
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci		for (i = 0; i < pin_group->n_pins; ++i) {
63962306a36Sopenharmony_ci			reg = MADERA_GPIO1_CTRL_1 + (2 * pin_group->pins[i]);
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci			dev_dbg(priv->dev, "%s setting 0x%x func bits to 0\n",
64262306a36Sopenharmony_ci				__func__, reg);
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci			ret = regmap_update_bits(madera->regmap, reg,
64562306a36Sopenharmony_ci						 MADERA_GP1_FN_MASK, 0);
64662306a36Sopenharmony_ci			if (ret)
64762306a36Sopenharmony_ci				break;
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci		}
65062306a36Sopenharmony_ci	} else {
65162306a36Sopenharmony_ci		/*
65262306a36Sopenharmony_ci		 * for other funcs the group will be the gpio number and will
65362306a36Sopenharmony_ci		 * be offset by the number of chip-specific functions at the
65462306a36Sopenharmony_ci		 * start of the group list
65562306a36Sopenharmony_ci		 */
65662306a36Sopenharmony_ci		group -= n_chip_groups;
65762306a36Sopenharmony_ci		reg = MADERA_GPIO1_CTRL_1 + (2 * group);
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci		dev_dbg(priv->dev, "%s setting 0x%x func bits to 0x%x\n",
66062306a36Sopenharmony_ci			__func__, reg, madera_mux_funcs[selector].func);
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci		ret = regmap_update_bits(madera->regmap,
66362306a36Sopenharmony_ci					 reg,
66462306a36Sopenharmony_ci					 MADERA_GP1_FN_MASK,
66562306a36Sopenharmony_ci					 madera_mux_funcs[selector].func);
66662306a36Sopenharmony_ci	}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci	if (ret)
66962306a36Sopenharmony_ci		dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	return ret;
67262306a36Sopenharmony_ci}
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_cistatic int madera_gpio_set_direction(struct pinctrl_dev *pctldev,
67562306a36Sopenharmony_ci				     struct pinctrl_gpio_range *range,
67662306a36Sopenharmony_ci				     unsigned int offset,
67762306a36Sopenharmony_ci				     bool input)
67862306a36Sopenharmony_ci{
67962306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
68062306a36Sopenharmony_ci	struct madera *madera = priv->madera;
68162306a36Sopenharmony_ci	unsigned int reg = MADERA_GPIO1_CTRL_2 + (2 * offset);
68262306a36Sopenharmony_ci	unsigned int val;
68362306a36Sopenharmony_ci	int ret;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	if (input)
68662306a36Sopenharmony_ci		val = MADERA_GP1_DIR;
68762306a36Sopenharmony_ci	else
68862306a36Sopenharmony_ci		val = 0;
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci	ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_DIR_MASK, val);
69162306a36Sopenharmony_ci	if (ret)
69262306a36Sopenharmony_ci		dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	return ret;
69562306a36Sopenharmony_ci}
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_cistatic int madera_gpio_request_enable(struct pinctrl_dev *pctldev,
69862306a36Sopenharmony_ci				      struct pinctrl_gpio_range *range,
69962306a36Sopenharmony_ci				      unsigned int offset)
70062306a36Sopenharmony_ci{
70162306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
70262306a36Sopenharmony_ci	struct madera *madera = priv->madera;
70362306a36Sopenharmony_ci	unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset);
70462306a36Sopenharmony_ci	int ret;
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	/* put the pin into GPIO mode */
70762306a36Sopenharmony_ci	ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_FN_MASK, 1);
70862306a36Sopenharmony_ci	if (ret)
70962306a36Sopenharmony_ci		dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	return ret;
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_cistatic void madera_gpio_disable_free(struct pinctrl_dev *pctldev,
71562306a36Sopenharmony_ci				     struct pinctrl_gpio_range *range,
71662306a36Sopenharmony_ci				     unsigned int offset)
71762306a36Sopenharmony_ci{
71862306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
71962306a36Sopenharmony_ci	struct madera *madera = priv->madera;
72062306a36Sopenharmony_ci	unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset);
72162306a36Sopenharmony_ci	int ret;
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci	/* disable GPIO by setting to GPIO IN */
72462306a36Sopenharmony_ci	madera_gpio_set_direction(pctldev, range, offset, true);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	ret = regmap_update_bits(madera->regmap, reg, MADERA_GP1_FN_MASK, 1);
72762306a36Sopenharmony_ci	if (ret)
72862306a36Sopenharmony_ci		dev_err(priv->dev, "Failed to write to 0x%x (%d)\n", reg, ret);
72962306a36Sopenharmony_ci}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_cistatic const struct pinmux_ops madera_pin_mux_ops = {
73262306a36Sopenharmony_ci	.get_functions_count = madera_mux_get_funcs_count,
73362306a36Sopenharmony_ci	.get_function_name = madera_mux_get_func_name,
73462306a36Sopenharmony_ci	.get_function_groups = madera_mux_get_groups,
73562306a36Sopenharmony_ci	.set_mux = madera_mux_set_mux,
73662306a36Sopenharmony_ci	.gpio_request_enable = madera_gpio_request_enable,
73762306a36Sopenharmony_ci	.gpio_disable_free = madera_gpio_disable_free,
73862306a36Sopenharmony_ci	.gpio_set_direction = madera_gpio_set_direction,
73962306a36Sopenharmony_ci	.strict = true, /* GPIO and other functions are exclusive */
74062306a36Sopenharmony_ci};
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_cistatic int madera_pin_conf_get(struct pinctrl_dev *pctldev, unsigned int pin,
74362306a36Sopenharmony_ci			       unsigned long *config)
74462306a36Sopenharmony_ci{
74562306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
74662306a36Sopenharmony_ci	unsigned int param = pinconf_to_config_param(*config);
74762306a36Sopenharmony_ci	unsigned int result = 0;
74862306a36Sopenharmony_ci	unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);
74962306a36Sopenharmony_ci	unsigned int conf[2];
75062306a36Sopenharmony_ci	int ret;
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci	ret = regmap_read(priv->madera->regmap, reg, &conf[0]);
75362306a36Sopenharmony_ci	if (!ret)
75462306a36Sopenharmony_ci		ret = regmap_read(priv->madera->regmap, reg + 1, &conf[1]);
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	if (ret) {
75762306a36Sopenharmony_ci		dev_err(priv->dev, "Failed to read GP%d conf (%d)\n",
75862306a36Sopenharmony_ci			pin + 1, ret);
75962306a36Sopenharmony_ci		return ret;
76062306a36Sopenharmony_ci	}
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	switch (param) {
76362306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_BUS_HOLD:
76462306a36Sopenharmony_ci		conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
76562306a36Sopenharmony_ci		if (conf[1] == (MADERA_GP1_PU | MADERA_GP1_PD))
76662306a36Sopenharmony_ci			result = 1;
76762306a36Sopenharmony_ci		break;
76862306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_DISABLE:
76962306a36Sopenharmony_ci		conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
77062306a36Sopenharmony_ci		if (!conf[1])
77162306a36Sopenharmony_ci			result = 1;
77262306a36Sopenharmony_ci		break;
77362306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_PULL_DOWN:
77462306a36Sopenharmony_ci		conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
77562306a36Sopenharmony_ci		if (conf[1] == MADERA_GP1_PD_MASK)
77662306a36Sopenharmony_ci			result = 1;
77762306a36Sopenharmony_ci		break;
77862306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_PULL_UP:
77962306a36Sopenharmony_ci		conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
78062306a36Sopenharmony_ci		if (conf[1] == MADERA_GP1_PU_MASK)
78162306a36Sopenharmony_ci			result = 1;
78262306a36Sopenharmony_ci		break;
78362306a36Sopenharmony_ci	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
78462306a36Sopenharmony_ci		if (conf[0] & MADERA_GP1_OP_CFG_MASK)
78562306a36Sopenharmony_ci			result = 1;
78662306a36Sopenharmony_ci		break;
78762306a36Sopenharmony_ci	case PIN_CONFIG_DRIVE_PUSH_PULL:
78862306a36Sopenharmony_ci		if (!(conf[0] & MADERA_GP1_OP_CFG_MASK))
78962306a36Sopenharmony_ci			result = 1;
79062306a36Sopenharmony_ci		break;
79162306a36Sopenharmony_ci	case PIN_CONFIG_DRIVE_STRENGTH:
79262306a36Sopenharmony_ci		result = madera_pin_unmake_drv_str(priv, conf[1]);
79362306a36Sopenharmony_ci		break;
79462306a36Sopenharmony_ci	case PIN_CONFIG_INPUT_DEBOUNCE:
79562306a36Sopenharmony_ci		if (conf[0] & MADERA_GP1_DB_MASK)
79662306a36Sopenharmony_ci			result = 1;
79762306a36Sopenharmony_ci		break;
79862306a36Sopenharmony_ci	case PIN_CONFIG_INPUT_ENABLE:
79962306a36Sopenharmony_ci		if (conf[0] & MADERA_GP1_DIR_MASK)
80062306a36Sopenharmony_ci			result = 1;
80162306a36Sopenharmony_ci		break;
80262306a36Sopenharmony_ci	case PIN_CONFIG_INPUT_SCHMITT:
80362306a36Sopenharmony_ci	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
80462306a36Sopenharmony_ci		if (conf[0] & MADERA_GP1_IP_CFG_MASK)
80562306a36Sopenharmony_ci			result = 1;
80662306a36Sopenharmony_ci		break;
80762306a36Sopenharmony_ci	case PIN_CONFIG_OUTPUT:
80862306a36Sopenharmony_ci		if ((conf[1] & MADERA_GP1_DIR_MASK) &&
80962306a36Sopenharmony_ci		    (conf[0] & MADERA_GP1_LVL_MASK))
81062306a36Sopenharmony_ci			result = 1;
81162306a36Sopenharmony_ci		break;
81262306a36Sopenharmony_ci	default:
81362306a36Sopenharmony_ci		return -ENOTSUPP;
81462306a36Sopenharmony_ci	}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	*config = pinconf_to_config_packed(param, result);
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	return 0;
81962306a36Sopenharmony_ci}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_cistatic int madera_pin_conf_set(struct pinctrl_dev *pctldev, unsigned int pin,
82262306a36Sopenharmony_ci			       unsigned long *configs, unsigned int num_configs)
82362306a36Sopenharmony_ci{
82462306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
82562306a36Sopenharmony_ci	u16 conf[2] = {0, 0};
82662306a36Sopenharmony_ci	u16 mask[2] = {0, 0};
82762306a36Sopenharmony_ci	unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin);
82862306a36Sopenharmony_ci	unsigned int val;
82962306a36Sopenharmony_ci	int ret;
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_ci	while (num_configs) {
83262306a36Sopenharmony_ci		dev_dbg(priv->dev, "%s config 0x%lx\n", __func__, *configs);
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci		switch (pinconf_to_config_param(*configs)) {
83562306a36Sopenharmony_ci		case PIN_CONFIG_BIAS_BUS_HOLD:
83662306a36Sopenharmony_ci			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
83762306a36Sopenharmony_ci			conf[1] |= MADERA_GP1_PU | MADERA_GP1_PD;
83862306a36Sopenharmony_ci			break;
83962306a36Sopenharmony_ci		case PIN_CONFIG_BIAS_DISABLE:
84062306a36Sopenharmony_ci			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
84162306a36Sopenharmony_ci			conf[1] &= ~(MADERA_GP1_PU | MADERA_GP1_PD);
84262306a36Sopenharmony_ci			break;
84362306a36Sopenharmony_ci		case PIN_CONFIG_BIAS_PULL_DOWN:
84462306a36Sopenharmony_ci			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
84562306a36Sopenharmony_ci			conf[1] |= MADERA_GP1_PD;
84662306a36Sopenharmony_ci			conf[1] &= ~MADERA_GP1_PU;
84762306a36Sopenharmony_ci			break;
84862306a36Sopenharmony_ci		case PIN_CONFIG_BIAS_PULL_UP:
84962306a36Sopenharmony_ci			mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK;
85062306a36Sopenharmony_ci			conf[1] |= MADERA_GP1_PU;
85162306a36Sopenharmony_ci			conf[1] &= ~MADERA_GP1_PD;
85262306a36Sopenharmony_ci			break;
85362306a36Sopenharmony_ci		case PIN_CONFIG_DRIVE_OPEN_DRAIN:
85462306a36Sopenharmony_ci			mask[0] |= MADERA_GP1_OP_CFG_MASK;
85562306a36Sopenharmony_ci			conf[0] |= MADERA_GP1_OP_CFG;
85662306a36Sopenharmony_ci			break;
85762306a36Sopenharmony_ci		case PIN_CONFIG_DRIVE_PUSH_PULL:
85862306a36Sopenharmony_ci			mask[0] |= MADERA_GP1_OP_CFG_MASK;
85962306a36Sopenharmony_ci			conf[0] &= ~MADERA_GP1_OP_CFG;
86062306a36Sopenharmony_ci			break;
86162306a36Sopenharmony_ci		case PIN_CONFIG_DRIVE_STRENGTH:
86262306a36Sopenharmony_ci			val = pinconf_to_config_argument(*configs);
86362306a36Sopenharmony_ci			mask[1] |= MADERA_GP1_DRV_STR_MASK;
86462306a36Sopenharmony_ci			conf[1] &= ~MADERA_GP1_DRV_STR_MASK;
86562306a36Sopenharmony_ci			conf[1] |= madera_pin_make_drv_str(priv, val);
86662306a36Sopenharmony_ci			break;
86762306a36Sopenharmony_ci		case PIN_CONFIG_INPUT_DEBOUNCE:
86862306a36Sopenharmony_ci			mask[0] |= MADERA_GP1_DB_MASK;
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci			/*
87162306a36Sopenharmony_ci			 * we can't configure debounce time per-pin so value
87262306a36Sopenharmony_ci			 * is just a flag
87362306a36Sopenharmony_ci			 */
87462306a36Sopenharmony_ci			val = pinconf_to_config_argument(*configs);
87562306a36Sopenharmony_ci			if (val)
87662306a36Sopenharmony_ci				conf[0] |= MADERA_GP1_DB;
87762306a36Sopenharmony_ci			else
87862306a36Sopenharmony_ci				conf[0] &= ~MADERA_GP1_DB;
87962306a36Sopenharmony_ci			break;
88062306a36Sopenharmony_ci		case PIN_CONFIG_INPUT_ENABLE:
88162306a36Sopenharmony_ci			val = pinconf_to_config_argument(*configs);
88262306a36Sopenharmony_ci			mask[1] |= MADERA_GP1_DIR_MASK;
88362306a36Sopenharmony_ci			if (val)
88462306a36Sopenharmony_ci				conf[1] |= MADERA_GP1_DIR;
88562306a36Sopenharmony_ci			else
88662306a36Sopenharmony_ci				conf[1] &= ~MADERA_GP1_DIR;
88762306a36Sopenharmony_ci			break;
88862306a36Sopenharmony_ci		case PIN_CONFIG_INPUT_SCHMITT:
88962306a36Sopenharmony_ci			val = pinconf_to_config_argument(*configs);
89062306a36Sopenharmony_ci			mask[0] |= MADERA_GP1_IP_CFG;
89162306a36Sopenharmony_ci			if (val)
89262306a36Sopenharmony_ci				conf[0] |= MADERA_GP1_IP_CFG;
89362306a36Sopenharmony_ci			else
89462306a36Sopenharmony_ci				conf[0] &= ~MADERA_GP1_IP_CFG;
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci			mask[1] |= MADERA_GP1_DIR_MASK;
89762306a36Sopenharmony_ci			conf[1] |= MADERA_GP1_DIR;
89862306a36Sopenharmony_ci			break;
89962306a36Sopenharmony_ci		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
90062306a36Sopenharmony_ci			mask[0] |= MADERA_GP1_IP_CFG;
90162306a36Sopenharmony_ci			conf[0] |= MADERA_GP1_IP_CFG;
90262306a36Sopenharmony_ci			mask[1] |= MADERA_GP1_DIR_MASK;
90362306a36Sopenharmony_ci			conf[1] |= MADERA_GP1_DIR;
90462306a36Sopenharmony_ci			break;
90562306a36Sopenharmony_ci		case PIN_CONFIG_OUTPUT:
90662306a36Sopenharmony_ci			val = pinconf_to_config_argument(*configs);
90762306a36Sopenharmony_ci			mask[0] |= MADERA_GP1_LVL_MASK;
90862306a36Sopenharmony_ci			if (val)
90962306a36Sopenharmony_ci				conf[0] |= MADERA_GP1_LVL;
91062306a36Sopenharmony_ci			else
91162306a36Sopenharmony_ci				conf[0] &= ~MADERA_GP1_LVL;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci			mask[1] |= MADERA_GP1_DIR_MASK;
91462306a36Sopenharmony_ci			conf[1] &= ~MADERA_GP1_DIR;
91562306a36Sopenharmony_ci			break;
91662306a36Sopenharmony_ci		default:
91762306a36Sopenharmony_ci			return -ENOTSUPP;
91862306a36Sopenharmony_ci		}
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci		++configs;
92162306a36Sopenharmony_ci		--num_configs;
92262306a36Sopenharmony_ci	}
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	dev_dbg(priv->dev,
92562306a36Sopenharmony_ci		"%s gpio%d 0x%x:0x%x 0x%x:0x%x\n",
92662306a36Sopenharmony_ci		__func__, pin + 1, reg, conf[0], reg + 1, conf[1]);
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	ret = regmap_update_bits(priv->madera->regmap, reg, mask[0], conf[0]);
92962306a36Sopenharmony_ci	if (ret)
93062306a36Sopenharmony_ci		goto err;
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	++reg;
93362306a36Sopenharmony_ci	ret = regmap_update_bits(priv->madera->regmap, reg, mask[1], conf[1]);
93462306a36Sopenharmony_ci	if (ret)
93562306a36Sopenharmony_ci		goto err;
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci	return 0;
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_cierr:
94062306a36Sopenharmony_ci	dev_err(priv->dev,
94162306a36Sopenharmony_ci		"Failed to write GPIO%d conf (%d) reg 0x%x\n",
94262306a36Sopenharmony_ci		pin + 1, ret, reg);
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	return ret;
94562306a36Sopenharmony_ci}
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_cistatic int madera_pin_conf_group_set(struct pinctrl_dev *pctldev,
94862306a36Sopenharmony_ci				     unsigned int selector,
94962306a36Sopenharmony_ci				     unsigned long *configs,
95062306a36Sopenharmony_ci				     unsigned int num_configs)
95162306a36Sopenharmony_ci{
95262306a36Sopenharmony_ci	struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev);
95362306a36Sopenharmony_ci	const struct madera_pin_groups *pin_group;
95462306a36Sopenharmony_ci	unsigned int n_groups = priv->chip->n_pin_groups;
95562306a36Sopenharmony_ci	int i, ret;
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	dev_dbg(priv->dev, "%s setting group %s\n", __func__,
95862306a36Sopenharmony_ci		madera_get_group_name(pctldev, selector));
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	if (selector >= n_groups) {
96162306a36Sopenharmony_ci		/* group is a single pin, convert to pin number and set */
96262306a36Sopenharmony_ci		return madera_pin_conf_set(pctldev,
96362306a36Sopenharmony_ci					   selector - n_groups,
96462306a36Sopenharmony_ci					   configs,
96562306a36Sopenharmony_ci					   num_configs);
96662306a36Sopenharmony_ci	} else {
96762306a36Sopenharmony_ci		pin_group = &priv->chip->pin_groups[selector];
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci		for (i = 0; i < pin_group->n_pins; ++i) {
97062306a36Sopenharmony_ci			ret = madera_pin_conf_set(pctldev,
97162306a36Sopenharmony_ci						  pin_group->pins[i],
97262306a36Sopenharmony_ci						  configs,
97362306a36Sopenharmony_ci						  num_configs);
97462306a36Sopenharmony_ci			if (ret)
97562306a36Sopenharmony_ci				return ret;
97662306a36Sopenharmony_ci		}
97762306a36Sopenharmony_ci	}
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	return 0;
98062306a36Sopenharmony_ci}
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_cistatic const struct pinconf_ops madera_pin_conf_ops = {
98362306a36Sopenharmony_ci	.is_generic = true,
98462306a36Sopenharmony_ci	.pin_config_get = madera_pin_conf_get,
98562306a36Sopenharmony_ci	.pin_config_set = madera_pin_conf_set,
98662306a36Sopenharmony_ci	.pin_config_group_set = madera_pin_conf_group_set,
98762306a36Sopenharmony_ci};
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_cistatic struct pinctrl_desc madera_pin_desc = {
99062306a36Sopenharmony_ci	.name = "madera-pinctrl",
99162306a36Sopenharmony_ci	.pins = madera_pins,
99262306a36Sopenharmony_ci	.pctlops = &madera_pin_group_ops,
99362306a36Sopenharmony_ci	.pmxops = &madera_pin_mux_ops,
99462306a36Sopenharmony_ci	.confops = &madera_pin_conf_ops,
99562306a36Sopenharmony_ci	.owner = THIS_MODULE,
99662306a36Sopenharmony_ci};
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_cistatic int madera_pin_probe(struct platform_device *pdev)
99962306a36Sopenharmony_ci{
100062306a36Sopenharmony_ci	struct madera *madera = dev_get_drvdata(pdev->dev.parent);
100162306a36Sopenharmony_ci	const struct madera_pdata *pdata = &madera->pdata;
100262306a36Sopenharmony_ci	struct madera_pin_private *priv;
100362306a36Sopenharmony_ci	int ret;
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci	BUILD_BUG_ON(ARRAY_SIZE(madera_pin_single_group_names) !=
100662306a36Sopenharmony_ci		     ARRAY_SIZE(madera_pin_single_group_pins));
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	dev_dbg(&pdev->dev, "%s\n", __func__);
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent));
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
101362306a36Sopenharmony_ci	if (!priv)
101462306a36Sopenharmony_ci		return -ENOMEM;
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	priv->dev = &pdev->dev;
101762306a36Sopenharmony_ci	priv->madera = madera;
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	switch (madera->type) {
102062306a36Sopenharmony_ci	case CS47L15:
102162306a36Sopenharmony_ci		if (IS_ENABLED(CONFIG_PINCTRL_CS47L15))
102262306a36Sopenharmony_ci			priv->chip = &cs47l15_pin_chip;
102362306a36Sopenharmony_ci		break;
102462306a36Sopenharmony_ci	case CS47L35:
102562306a36Sopenharmony_ci		if (IS_ENABLED(CONFIG_PINCTRL_CS47L35))
102662306a36Sopenharmony_ci			priv->chip = &cs47l35_pin_chip;
102762306a36Sopenharmony_ci		break;
102862306a36Sopenharmony_ci	case CS47L85:
102962306a36Sopenharmony_ci	case WM1840:
103062306a36Sopenharmony_ci		if (IS_ENABLED(CONFIG_PINCTRL_CS47L85))
103162306a36Sopenharmony_ci			priv->chip = &cs47l85_pin_chip;
103262306a36Sopenharmony_ci		break;
103362306a36Sopenharmony_ci	case CS47L90:
103462306a36Sopenharmony_ci	case CS47L91:
103562306a36Sopenharmony_ci		if (IS_ENABLED(CONFIG_PINCTRL_CS47L90))
103662306a36Sopenharmony_ci			priv->chip = &cs47l90_pin_chip;
103762306a36Sopenharmony_ci		break;
103862306a36Sopenharmony_ci	case CS42L92:
103962306a36Sopenharmony_ci	case CS47L92:
104062306a36Sopenharmony_ci	case CS47L93:
104162306a36Sopenharmony_ci		if (IS_ENABLED(CONFIG_PINCTRL_CS47L92))
104262306a36Sopenharmony_ci			priv->chip = &cs47l92_pin_chip;
104362306a36Sopenharmony_ci		break;
104462306a36Sopenharmony_ci	default:
104562306a36Sopenharmony_ci		break;
104662306a36Sopenharmony_ci	}
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	if (!priv->chip)
104962306a36Sopenharmony_ci		return -ENODEV;
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci	madera_pin_desc.npins = priv->chip->n_pins;
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	ret = devm_pinctrl_register_and_init(&pdev->dev,
105462306a36Sopenharmony_ci					     &madera_pin_desc,
105562306a36Sopenharmony_ci					     priv,
105662306a36Sopenharmony_ci					     &priv->pctl);
105762306a36Sopenharmony_ci	if (ret) {
105862306a36Sopenharmony_ci		dev_err(priv->dev, "Failed pinctrl register (%d)\n", ret);
105962306a36Sopenharmony_ci		return ret;
106062306a36Sopenharmony_ci	}
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	/* if the configuration is provided through pdata, apply it */
106362306a36Sopenharmony_ci	if (pdata->gpio_configs) {
106462306a36Sopenharmony_ci		ret = pinctrl_register_mappings(pdata->gpio_configs,
106562306a36Sopenharmony_ci						pdata->n_gpio_configs);
106662306a36Sopenharmony_ci		if (ret) {
106762306a36Sopenharmony_ci			dev_err(priv->dev,
106862306a36Sopenharmony_ci				"Failed to register pdata mappings (%d)\n",
106962306a36Sopenharmony_ci				ret);
107062306a36Sopenharmony_ci			return ret;
107162306a36Sopenharmony_ci		}
107262306a36Sopenharmony_ci	}
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci	ret = pinctrl_enable(priv->pctl);
107562306a36Sopenharmony_ci	if (ret) {
107662306a36Sopenharmony_ci		dev_err(priv->dev, "Failed to enable pinctrl (%d)\n", ret);
107762306a36Sopenharmony_ci		return ret;
107862306a36Sopenharmony_ci	}
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	platform_set_drvdata(pdev, priv);
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ci	dev_dbg(priv->dev, "pinctrl probed ok\n");
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	return 0;
108562306a36Sopenharmony_ci}
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_cistatic int madera_pin_remove(struct platform_device *pdev)
108862306a36Sopenharmony_ci{
108962306a36Sopenharmony_ci	struct madera_pin_private *priv = platform_get_drvdata(pdev);
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_ci	if (priv->madera->pdata.gpio_configs)
109262306a36Sopenharmony_ci		pinctrl_unregister_mappings(priv->madera->pdata.gpio_configs);
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_ci	return 0;
109562306a36Sopenharmony_ci}
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_cistatic struct platform_driver madera_pin_driver = {
109862306a36Sopenharmony_ci	.probe = madera_pin_probe,
109962306a36Sopenharmony_ci	.remove = madera_pin_remove,
110062306a36Sopenharmony_ci	.driver = {
110162306a36Sopenharmony_ci		.name = "madera-pinctrl",
110262306a36Sopenharmony_ci	},
110362306a36Sopenharmony_ci};
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_cimodule_platform_driver(madera_pin_driver);
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ciMODULE_DESCRIPTION("Madera pinctrl driver");
110862306a36Sopenharmony_ciMODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
110962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
1110