1f73f88acSzhanghongchen // SPDX-License-Identifier: GPL-2.0+
2f73f88acSzhanghongchen /*
3f73f88acSzhanghongchen  * Author: zhanghongchen <zhanghongchen@loongson.cn>
4f73f88acSzhanghongchen  *         Yinbo Zhu <zhuyinbo@loongson.cn>
5f73f88acSzhanghongchen  * Copyright (C) 2022-2023 Loongson Technology Corporation Limited
6f73f88acSzhanghongchen  */
7f73f88acSzhanghongchen 
8f73f88acSzhanghongchen #include <linux/init.h>
9f73f88acSzhanghongchen #include <linux/module.h>
10f73f88acSzhanghongchen #include <linux/platform_device.h>
11f73f88acSzhanghongchen #include <linux/mod_devicetable.h>
12f73f88acSzhanghongchen #include <linux/pinctrl/pinmux.h>
13f73f88acSzhanghongchen #include <linux/pinctrl/pinconf-generic.h>
14f73f88acSzhanghongchen #include <linux/pinctrl/pinctrl.h>
15f73f88acSzhanghongchen #include <linux/bitops.h>
16f73f88acSzhanghongchen #include <linux/io.h>
17f73f88acSzhanghongchen #include <linux/seq_file.h>
18f73f88acSzhanghongchen 
19f73f88acSzhanghongchen #include "core.h"
20f73f88acSzhanghongchen #include "pinctrl-utils.h"
21f73f88acSzhanghongchen 
22f73f88acSzhanghongchen #define PMX_GROUP(name, offset, bitv)					\
23f73f88acSzhanghongchen 	{								\
24f73f88acSzhanghongchen 		.grp = PINCTRL_PINGROUP((#name), (name ## _pins),	\
25f73f88acSzhanghongchen 				ARRAY_SIZE((name ## _pins))),		\
26f73f88acSzhanghongchen 		.reg = offset,						\
27f73f88acSzhanghongchen 		.bit = bitv,						\
28f73f88acSzhanghongchen 	}
29f73f88acSzhanghongchen 
30f73f88acSzhanghongchen #define SPECIFIC_GROUP(group)						\
31f73f88acSzhanghongchen 	static const char * const group##_groups[] = {			\
32f73f88acSzhanghongchen 		#group							\
33f73f88acSzhanghongchen 	}
34f73f88acSzhanghongchen 
35f73f88acSzhanghongchen #define FUNCTION(fn)							\
36f73f88acSzhanghongchen 	{								\
37f73f88acSzhanghongchen 		.name = #fn,						\
38f73f88acSzhanghongchen 		.groups = fn ## _groups,				\
39f73f88acSzhanghongchen 		.num_groups = ARRAY_SIZE(fn ## _groups),		\
40f73f88acSzhanghongchen 	}
41f73f88acSzhanghongchen 
42f73f88acSzhanghongchen struct loongson2_pinctrl {
43f73f88acSzhanghongchen 	struct device *dev;
44f73f88acSzhanghongchen 	struct pinctrl_dev *pcdev;
45f73f88acSzhanghongchen 	struct pinctrl_desc desc;
46f73f88acSzhanghongchen 	struct device_node *of_node;
47f73f88acSzhanghongchen 	spinlock_t lock;
48*7ebfe10eSLinus Walleij 	void __iomem *reg_base;
49f73f88acSzhanghongchen };
50f73f88acSzhanghongchen 
51f73f88acSzhanghongchen struct loongson2_pmx_group {
52f73f88acSzhanghongchen 	struct pingroup grp;
53f73f88acSzhanghongchen 	unsigned int reg;
54f73f88acSzhanghongchen 	unsigned int bit;
55f73f88acSzhanghongchen };
56f73f88acSzhanghongchen 
57f73f88acSzhanghongchen struct loongson2_pmx_func {
58f73f88acSzhanghongchen 	const char *name;
59f73f88acSzhanghongchen 	const char * const *groups;
60f73f88acSzhanghongchen 	unsigned int num_groups;
61f73f88acSzhanghongchen };
62f73f88acSzhanghongchen 
63f73f88acSzhanghongchen #define LOONGSON2_PIN(x) PINCTRL_PIN(x, "gpio"#x)
64f73f88acSzhanghongchen static const struct pinctrl_pin_desc loongson2_pctrl_pins[] = {
65f73f88acSzhanghongchen 	LOONGSON2_PIN(0),  LOONGSON2_PIN(1),  LOONGSON2_PIN(2),  LOONGSON2_PIN(3),
66f73f88acSzhanghongchen 	LOONGSON2_PIN(4),  LOONGSON2_PIN(5),  LOONGSON2_PIN(6),  LOONGSON2_PIN(7),
67f73f88acSzhanghongchen 	LOONGSON2_PIN(8),  LOONGSON2_PIN(9),  LOONGSON2_PIN(10), LOONGSON2_PIN(11),
68f73f88acSzhanghongchen 	LOONGSON2_PIN(12), LOONGSON2_PIN(13), LOONGSON2_PIN(14),
69f73f88acSzhanghongchen 	LOONGSON2_PIN(16), LOONGSON2_PIN(17), LOONGSON2_PIN(18), LOONGSON2_PIN(19),
70f73f88acSzhanghongchen 	LOONGSON2_PIN(20), LOONGSON2_PIN(21), LOONGSON2_PIN(22), LOONGSON2_PIN(23),
71f73f88acSzhanghongchen 	LOONGSON2_PIN(24), LOONGSON2_PIN(25), LOONGSON2_PIN(26), LOONGSON2_PIN(27),
72f73f88acSzhanghongchen 	LOONGSON2_PIN(28), LOONGSON2_PIN(29), LOONGSON2_PIN(30),
73f73f88acSzhanghongchen 	LOONGSON2_PIN(32), LOONGSON2_PIN(33), LOONGSON2_PIN(34), LOONGSON2_PIN(35),
74f73f88acSzhanghongchen 	LOONGSON2_PIN(36), LOONGSON2_PIN(37), LOONGSON2_PIN(38), LOONGSON2_PIN(39),
75f73f88acSzhanghongchen 	LOONGSON2_PIN(40), LOONGSON2_PIN(41),
76f73f88acSzhanghongchen 	LOONGSON2_PIN(44), LOONGSON2_PIN(45), LOONGSON2_PIN(46), LOONGSON2_PIN(47),
77f73f88acSzhanghongchen 	LOONGSON2_PIN(48), LOONGSON2_PIN(49), LOONGSON2_PIN(50), LOONGSON2_PIN(51),
78f73f88acSzhanghongchen 	LOONGSON2_PIN(52), LOONGSON2_PIN(53), LOONGSON2_PIN(54), LOONGSON2_PIN(55),
79f73f88acSzhanghongchen 	LOONGSON2_PIN(56), LOONGSON2_PIN(57), LOONGSON2_PIN(58), LOONGSON2_PIN(59),
80f73f88acSzhanghongchen 	LOONGSON2_PIN(60), LOONGSON2_PIN(61), LOONGSON2_PIN(62), LOONGSON2_PIN(63),
81f73f88acSzhanghongchen };
82f73f88acSzhanghongchen 
83f73f88acSzhanghongchen static const unsigned int gpio_pins[] = {0, 1, 2, 3, 4, 5, 6, 7,
84f73f88acSzhanghongchen 					 8, 9, 10, 11, 12, 13, 14,
85f73f88acSzhanghongchen 					 16, 17, 18, 19, 20, 21, 22, 23,
86f73f88acSzhanghongchen 					 24, 25, 26, 27, 28, 29, 30,
87f73f88acSzhanghongchen 					 32, 33, 34, 35, 36, 37, 38, 39,
88f73f88acSzhanghongchen 					 40,         43, 44, 45, 46, 47,
89f73f88acSzhanghongchen 					 48, 49, 50, 51, 52, 53, 46, 55,
90f73f88acSzhanghongchen 					 56, 57, 58, 59, 60, 61, 62, 63};
91f73f88acSzhanghongchen static const unsigned int sdio_pins[] = {36, 37, 38, 39, 40, 41};
92f73f88acSzhanghongchen static const unsigned int can1_pins[] = {34, 35};
93f73f88acSzhanghongchen static const unsigned int can0_pins[] = {32, 33};
94f73f88acSzhanghongchen static const unsigned int pwm3_pins[] = {23};
95f73f88acSzhanghongchen static const unsigned int pwm2_pins[] = {22};
96f73f88acSzhanghongchen static const unsigned int pwm1_pins[] = {21};
97f73f88acSzhanghongchen static const unsigned int pwm0_pins[] = {20};
98f73f88acSzhanghongchen static const unsigned int i2c1_pins[] = {18, 19};
99f73f88acSzhanghongchen static const unsigned int i2c0_pins[] = {16, 17};
100f73f88acSzhanghongchen static const unsigned int nand_pins[] = {44, 45, 46, 47, 48, 49, 50, 51,
101f73f88acSzhanghongchen 					 52, 53, 54, 55, 56, 57, 58, 59, 60,
102f73f88acSzhanghongchen 					 61, 62, 63};
103f73f88acSzhanghongchen static const unsigned int sata_led_pins[] = {14};
104f73f88acSzhanghongchen static const unsigned int i2s_pins[]    = {24, 25, 26, 27, 28};
105f73f88acSzhanghongchen static const unsigned int hda_pins[]    = {24, 25, 26, 27, 28, 29, 30};
106f73f88acSzhanghongchen 
107f73f88acSzhanghongchen static struct loongson2_pmx_group loongson2_pmx_groups[] = {
108f73f88acSzhanghongchen 	PMX_GROUP(gpio, 0x0, 64),
109f73f88acSzhanghongchen 	PMX_GROUP(sdio, 0x0, 20),
110f73f88acSzhanghongchen 	PMX_GROUP(can1, 0x0, 17),
111f73f88acSzhanghongchen 	PMX_GROUP(can0, 0x0, 16),
112f73f88acSzhanghongchen 	PMX_GROUP(pwm3, 0x0, 15),
113f73f88acSzhanghongchen 	PMX_GROUP(pwm2, 0x0, 14),
114f73f88acSzhanghongchen 	PMX_GROUP(pwm1, 0x0, 13),
115f73f88acSzhanghongchen 	PMX_GROUP(pwm0, 0x0, 12),
116f73f88acSzhanghongchen 	PMX_GROUP(i2c1, 0x0, 11),
117f73f88acSzhanghongchen 	PMX_GROUP(i2c0, 0x0, 10),
118f73f88acSzhanghongchen 	PMX_GROUP(nand, 0x0, 9),
119f73f88acSzhanghongchen 	PMX_GROUP(sata_led, 0x0, 8),
120f73f88acSzhanghongchen 	PMX_GROUP(i2s, 0x0, 6),
121f73f88acSzhanghongchen 	PMX_GROUP(hda, 0x0, 4),
122f73f88acSzhanghongchen };
123f73f88acSzhanghongchen 
124f73f88acSzhanghongchen SPECIFIC_GROUP(sdio);
125f73f88acSzhanghongchen SPECIFIC_GROUP(can1);
126f73f88acSzhanghongchen SPECIFIC_GROUP(can0);
127f73f88acSzhanghongchen SPECIFIC_GROUP(pwm3);
128f73f88acSzhanghongchen SPECIFIC_GROUP(pwm2);
129f73f88acSzhanghongchen SPECIFIC_GROUP(pwm1);
130f73f88acSzhanghongchen SPECIFIC_GROUP(pwm0);
131f73f88acSzhanghongchen SPECIFIC_GROUP(i2c1);
132f73f88acSzhanghongchen SPECIFIC_GROUP(i2c0);
133f73f88acSzhanghongchen SPECIFIC_GROUP(nand);
134f73f88acSzhanghongchen SPECIFIC_GROUP(sata_led);
135f73f88acSzhanghongchen SPECIFIC_GROUP(i2s);
136f73f88acSzhanghongchen SPECIFIC_GROUP(hda);
137f73f88acSzhanghongchen 
138f73f88acSzhanghongchen static const char * const gpio_groups[] = {
139f73f88acSzhanghongchen 	"sdio",
140f73f88acSzhanghongchen 	"can1", "can0",
141f73f88acSzhanghongchen 	"pwm3", "pwm2", "pwm1", "pwm0",
142f73f88acSzhanghongchen 	"i2c1", "i2c0",
143f73f88acSzhanghongchen 	"nand",
144f73f88acSzhanghongchen 	"sata_led",
145f73f88acSzhanghongchen 	"i2s",
146f73f88acSzhanghongchen 	"hda",
147f73f88acSzhanghongchen };
148f73f88acSzhanghongchen 
149f73f88acSzhanghongchen static const struct loongson2_pmx_func loongson2_pmx_functions[] = {
150f73f88acSzhanghongchen 	FUNCTION(gpio),
151f73f88acSzhanghongchen 	FUNCTION(sdio),
152f73f88acSzhanghongchen 	FUNCTION(can1),
153f73f88acSzhanghongchen 	FUNCTION(can0),
154f73f88acSzhanghongchen 	FUNCTION(pwm3),
155f73f88acSzhanghongchen 	FUNCTION(pwm2),
156f73f88acSzhanghongchen 	FUNCTION(pwm1),
157f73f88acSzhanghongchen 	FUNCTION(pwm0),
158f73f88acSzhanghongchen 	FUNCTION(i2c1),
159f73f88acSzhanghongchen 	FUNCTION(i2c0),
160f73f88acSzhanghongchen 	FUNCTION(nand),
161f73f88acSzhanghongchen 	FUNCTION(sata_led),
162f73f88acSzhanghongchen 	FUNCTION(i2s),
163f73f88acSzhanghongchen 	FUNCTION(hda),
164f73f88acSzhanghongchen };
165f73f88acSzhanghongchen 
loongson2_get_groups_count(struct pinctrl_dev * pcdev)166f73f88acSzhanghongchen static int loongson2_get_groups_count(struct pinctrl_dev *pcdev)
167f73f88acSzhanghongchen {
168f73f88acSzhanghongchen 	return ARRAY_SIZE(loongson2_pmx_groups);
169f73f88acSzhanghongchen }
170f73f88acSzhanghongchen 
loongson2_get_group_name(struct pinctrl_dev * pcdev,unsigned int selector)171f73f88acSzhanghongchen static const char *loongson2_get_group_name(struct pinctrl_dev *pcdev,
172f73f88acSzhanghongchen 					unsigned int selector)
173f73f88acSzhanghongchen {
174f73f88acSzhanghongchen 	return loongson2_pmx_groups[selector].grp.name;
175f73f88acSzhanghongchen }
176f73f88acSzhanghongchen 
loongson2_get_group_pins(struct pinctrl_dev * pcdev,unsigned int selector,const unsigned int ** pins,unsigned int * num_pins)177f73f88acSzhanghongchen static int loongson2_get_group_pins(struct pinctrl_dev *pcdev, unsigned int selector,
178f73f88acSzhanghongchen 			const unsigned int **pins, unsigned int *num_pins)
179f73f88acSzhanghongchen {
180f73f88acSzhanghongchen 	*pins = loongson2_pmx_groups[selector].grp.pins;
181f73f88acSzhanghongchen 	*num_pins = loongson2_pmx_groups[selector].grp.npins;
182f73f88acSzhanghongchen 
183f73f88acSzhanghongchen 	return 0;
184f73f88acSzhanghongchen }
185f73f88acSzhanghongchen 
loongson2_pin_dbg_show(struct pinctrl_dev * pcdev,struct seq_file * s,unsigned int offset)186f73f88acSzhanghongchen static void loongson2_pin_dbg_show(struct pinctrl_dev *pcdev, struct seq_file *s,
187f73f88acSzhanghongchen 			       unsigned int offset)
188f73f88acSzhanghongchen {
189f73f88acSzhanghongchen 	seq_printf(s, " %s", dev_name(pcdev->dev));
190f73f88acSzhanghongchen }
191f73f88acSzhanghongchen 
192f73f88acSzhanghongchen static const struct pinctrl_ops loongson2_pctrl_ops = {
193f73f88acSzhanghongchen 	.get_groups_count	= loongson2_get_groups_count,
194f73f88acSzhanghongchen 	.get_group_name		= loongson2_get_group_name,
195f73f88acSzhanghongchen 	.get_group_pins		= loongson2_get_group_pins,
196f73f88acSzhanghongchen 	.dt_node_to_map		= pinconf_generic_dt_node_to_map_all,
197f73f88acSzhanghongchen 	.dt_free_map		= pinctrl_utils_free_map,
198f73f88acSzhanghongchen 	.pin_dbg_show		= loongson2_pin_dbg_show,
199f73f88acSzhanghongchen };
200f73f88acSzhanghongchen 
loongson2_pmx_set_mux(struct pinctrl_dev * pcdev,unsigned int func_num,unsigned int group_num)201f73f88acSzhanghongchen static int loongson2_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned int func_num,
202f73f88acSzhanghongchen 			      unsigned int group_num)
203f73f88acSzhanghongchen {
204f73f88acSzhanghongchen 	struct loongson2_pinctrl *pctrl = pinctrl_dev_get_drvdata(pcdev);
205*7ebfe10eSLinus Walleij 	void __iomem *reg = pctrl->reg_base +
206f73f88acSzhanghongchen 				loongson2_pmx_groups[group_num].reg;
207f73f88acSzhanghongchen 	unsigned int mux_bit = loongson2_pmx_groups[group_num].bit;
208f73f88acSzhanghongchen 	unsigned int val;
209f73f88acSzhanghongchen 	unsigned long flags;
210f73f88acSzhanghongchen 
211f73f88acSzhanghongchen 	spin_lock_irqsave(&pctrl->lock, flags);
212f73f88acSzhanghongchen 	val = readl(reg);
213f73f88acSzhanghongchen 	if (func_num == 0)
214f73f88acSzhanghongchen 		val &= ~BIT(mux_bit);
215f73f88acSzhanghongchen 	else
216f73f88acSzhanghongchen 		val |= BIT(mux_bit);
217f73f88acSzhanghongchen 	writel(val, reg);
218f73f88acSzhanghongchen 	spin_unlock_irqrestore(&pctrl->lock, flags);
219f73f88acSzhanghongchen 
220f73f88acSzhanghongchen 	return 0;
221f73f88acSzhanghongchen }
222f73f88acSzhanghongchen 
loongson2_pmx_get_funcs_count(struct pinctrl_dev * pcdev)223f73f88acSzhanghongchen static int loongson2_pmx_get_funcs_count(struct pinctrl_dev *pcdev)
224f73f88acSzhanghongchen {
225f73f88acSzhanghongchen 	return ARRAY_SIZE(loongson2_pmx_functions);
226f73f88acSzhanghongchen }
227f73f88acSzhanghongchen 
loongson2_pmx_get_func_name(struct pinctrl_dev * pcdev,unsigned int selector)228f73f88acSzhanghongchen static const char *loongson2_pmx_get_func_name(struct pinctrl_dev *pcdev,
229f73f88acSzhanghongchen 				    unsigned int selector)
230f73f88acSzhanghongchen {
231f73f88acSzhanghongchen 	return loongson2_pmx_functions[selector].name;
232f73f88acSzhanghongchen }
233f73f88acSzhanghongchen 
loongson2_pmx_get_groups(struct pinctrl_dev * pcdev,unsigned int selector,const char * const ** groups,unsigned int * const num_groups)234f73f88acSzhanghongchen static int loongson2_pmx_get_groups(struct pinctrl_dev *pcdev,
235f73f88acSzhanghongchen 			 unsigned int selector,
236f73f88acSzhanghongchen 			 const char * const **groups,
237f73f88acSzhanghongchen 			 unsigned int * const num_groups)
238f73f88acSzhanghongchen {
239f73f88acSzhanghongchen 	*groups = loongson2_pmx_functions[selector].groups;
240f73f88acSzhanghongchen 	*num_groups = loongson2_pmx_functions[selector].num_groups;
241f73f88acSzhanghongchen 
242f73f88acSzhanghongchen 	return 0;
243f73f88acSzhanghongchen }
244f73f88acSzhanghongchen 
245f73f88acSzhanghongchen static const struct pinmux_ops loongson2_pmx_ops = {
246f73f88acSzhanghongchen 	.set_mux = loongson2_pmx_set_mux,
247f73f88acSzhanghongchen 	.get_functions_count = loongson2_pmx_get_funcs_count,
248f73f88acSzhanghongchen 	.get_function_name = loongson2_pmx_get_func_name,
249f73f88acSzhanghongchen 	.get_function_groups = loongson2_pmx_get_groups,
250f73f88acSzhanghongchen };
251f73f88acSzhanghongchen 
loongson2_pinctrl_probe(struct platform_device * pdev)252f73f88acSzhanghongchen static int loongson2_pinctrl_probe(struct platform_device *pdev)
253f73f88acSzhanghongchen {
254f73f88acSzhanghongchen 	struct device *dev = &pdev->dev;
255f73f88acSzhanghongchen 	struct loongson2_pinctrl *pctrl;
256f73f88acSzhanghongchen 
257f73f88acSzhanghongchen 	pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
258f73f88acSzhanghongchen 	if (!pctrl)
259f73f88acSzhanghongchen 		return -ENOMEM;
260f73f88acSzhanghongchen 
261f73f88acSzhanghongchen 	pctrl->reg_base = devm_platform_ioremap_resource(pdev, 0);
262f73f88acSzhanghongchen 	if (IS_ERR(pctrl->reg_base))
263f73f88acSzhanghongchen 		return PTR_ERR(pctrl->reg_base);
264f73f88acSzhanghongchen 
265f73f88acSzhanghongchen 	spin_lock_init(&pctrl->lock);
266f73f88acSzhanghongchen 
267f73f88acSzhanghongchen 	pctrl->dev = dev;
268f73f88acSzhanghongchen 	pctrl->desc.name	= "pinctrl-loongson2";
269f73f88acSzhanghongchen 	pctrl->desc.owner	= THIS_MODULE;
270f73f88acSzhanghongchen 	pctrl->desc.pctlops	= &loongson2_pctrl_ops;
271f73f88acSzhanghongchen 	pctrl->desc.pmxops	= &loongson2_pmx_ops;
272f73f88acSzhanghongchen 	pctrl->desc.pins	= loongson2_pctrl_pins;
273f73f88acSzhanghongchen 	pctrl->desc.npins	= ARRAY_SIZE(loongson2_pctrl_pins);
274f73f88acSzhanghongchen 
275f73f88acSzhanghongchen 	pctrl->pcdev = devm_pinctrl_register(pctrl->dev, &pctrl->desc, pctrl);
276f73f88acSzhanghongchen 	if (IS_ERR(pctrl->pcdev))
277f73f88acSzhanghongchen 		return dev_err_probe(pctrl->dev, PTR_ERR(pctrl->pcdev),
278f73f88acSzhanghongchen 				     "can't register pinctrl device");
279f73f88acSzhanghongchen 
280f73f88acSzhanghongchen 	return 0;
281f73f88acSzhanghongchen }
282f73f88acSzhanghongchen 
283f73f88acSzhanghongchen static const struct of_device_id loongson2_pinctrl_dt_match[] = {
284f73f88acSzhanghongchen 	{
285f73f88acSzhanghongchen 		.compatible = "loongson,ls2k-pinctrl",
286f73f88acSzhanghongchen 	},
287f73f88acSzhanghongchen 	{ }
288f73f88acSzhanghongchen };
289f73f88acSzhanghongchen 
290f73f88acSzhanghongchen static struct platform_driver loongson2_pinctrl_driver = {
291f73f88acSzhanghongchen 	.probe		= loongson2_pinctrl_probe,
292f73f88acSzhanghongchen 	.driver = {
293f73f88acSzhanghongchen 		.name	= "loongson2-pinctrl",
294f73f88acSzhanghongchen 		.of_match_table = loongson2_pinctrl_dt_match,
295f73f88acSzhanghongchen 	},
296f73f88acSzhanghongchen };
297f73f88acSzhanghongchen 
loongson2_pinctrl_init(void)298f73f88acSzhanghongchen static int __init loongson2_pinctrl_init(void)
299f73f88acSzhanghongchen {
300f73f88acSzhanghongchen 	return platform_driver_register(&loongson2_pinctrl_driver);
301f73f88acSzhanghongchen }
302f73f88acSzhanghongchen arch_initcall(loongson2_pinctrl_init);
303f73f88acSzhanghongchen 
loongson2_pinctrl_exit(void)304f73f88acSzhanghongchen static void __exit loongson2_pinctrl_exit(void)
305f73f88acSzhanghongchen {
306f73f88acSzhanghongchen 	platform_driver_unregister(&loongson2_pinctrl_driver);
307f73f88acSzhanghongchen }
308f73f88acSzhanghongchen module_exit(loongson2_pinctrl_exit);
309f73f88acSzhanghongchen 
310f73f88acSzhanghongchen MODULE_DESCRIPTION("Loongson2 Pinctrl driver");
311f73f88acSzhanghongchen MODULE_LICENSE("GPL");
312