1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) ASPEED Technology Inc.
4  */
5 
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <asm/io.h>
10 #include <linux/bitops.h>
11 #include <asm/arch/pinctrl.h>
12 #include <asm/arch/scu_ast2600.h>
13 #include <dm/pinctrl.h>
14 
15 /*
16  * This driver works with very simple configuration that has the same name
17  * for group and function. This way it is compatible with the Linux Kernel
18  * driver.
19  */
20 
21 struct ast2600_pinctrl_priv {
22 	struct ast2600_scu *scu;
23 };
24 
25 static int ast2600_pinctrl_probe(struct udevice *dev)
26 {
27 	struct ast2600_pinctrl_priv *priv = dev_get_priv(dev);
28 
29 	priv->scu = ast_get_scu();
30 
31 	return 0;
32 }
33 
34 struct aspeed_sig_desc {
35 	u32 offset;
36 	u32 reg_set;
37 };
38 
39 struct ast2600_group_config {
40 	char *group_name;
41 	int ndescs;
42 	const struct aspeed_sig_desc *descs;
43 };
44 
45 static struct aspeed_sig_desc mac1_link[] = {
46 	{ 0x410, BIT(4)	},
47 };
48 
49 static struct aspeed_sig_desc mac2_link[] = {
50 	{ 0x410, BIT(5)	},
51 };
52 
53 static struct aspeed_sig_desc mac3_link[] = {
54 	{ 0x410, BIT(6)	},
55 };
56 
57 static struct aspeed_sig_desc mac4_link[] = {
58 	{ 0x410, BIT(7)	},
59 };
60 
61 static struct aspeed_sig_desc mdio1_link[] = {
62 	{ 0x430, BIT(17)	},
63 };
64 
65 static struct aspeed_sig_desc mdio2_link[] = {
66 	{ 0x410, BIT(14) | BIT(13)	},
67 };
68 
69 static struct aspeed_sig_desc mdio3_link[] = {
70 	{ 0x410, BIT(1) | BIT(0)	},
71 };
72 
73 static struct aspeed_sig_desc mdio4_link[] = {
74 	{ 0x410, BIT(3) | BIT(2)	},
75 };
76 
77 //8bit mode offset 0x414 (21~18) 0x450 bit0: sd0 bit1: sd1,  bit3: sd0 8bits
78 	//sdio1 414 (23~16) = 0, 4b4 (23~16) = 1, 450 bit1 = 1
79 
80 static struct aspeed_sig_desc sdio2_link[] = {
81 	{ 0x4B4, GENMASK(23, 16)	},
82 	{ 0x450, BIT(1)		},
83 	{ 0x414, GENMASK(23, 16)	},
84 };
85 
86 static struct aspeed_sig_desc sdio1_link[] = {
87 	{ 0x414, GENMASK(15, 8)	},
88 	{ 0x450, BIT(0)	},
89 };
90 
91 static struct aspeed_sig_desc emmc_link[] = {
92 	{ 0x400, GENMASK(31, 24) },
93 	{ 0x404, GENMASK(3, 0) },
94 };
95 
96 static const struct ast2600_group_config ast2600_groups[] = {
97 	{ "MAC1LINK", 1, mac1_link },
98 	{ "MAC2LINK", 1, mac2_link },
99 	{ "MAC3LINK", 1, mac3_link },
100 	{ "MAC4LINK", 1, mac4_link },
101 	{ "MDIO1LINK", 1, mdio1_link },
102 	{ "MDIO2LINK", 1, mdio2_link },
103 	{ "MDIO3LINK", 1, mdio3_link },
104 	{ "MDIO4LINK", 1, mdio4_link },
105 	{ "SDIO1", ARRAY_SIZE(sdio2_link), sdio2_link },
106 	{ "SDIO0", ARRAY_SIZE(sdio1_link), sdio1_link },
107 	{ "EMMC", ARRAY_SIZE(emmc_link), emmc_link },
108 };
109 
110 static int ast2600_pinctrl_get_groups_count(struct udevice *dev)
111 {
112 	printf("PINCTRL: get_(functions/groups)_count\n");
113 
114 	return ARRAY_SIZE(ast2600_groups);
115 }
116 
117 static const char *ast2600_pinctrl_get_group_name(struct udevice *dev,
118 						  unsigned selector)
119 {
120 	printf("PINCTRL: get_(function/group)_name %u\n", selector);
121 
122 	return ast2600_groups[selector].group_name;
123 }
124 
125 static int ast2600_pinctrl_group_set(struct udevice *dev, unsigned selector,
126 				     unsigned func_selector)
127 {
128 	struct ast2600_pinctrl_priv *priv = dev_get_priv(dev);
129 	const struct ast2600_group_config *config;
130 	const struct aspeed_sig_desc *descs;
131 	u32 ctrl_reg = (u32)&priv->scu;
132 
133 	printf("PINCTRL: group_set <%u, %u>\n", selector, func_selector);
134 	if (selector >= ARRAY_SIZE(ast2600_groups))
135 		return -EINVAL;
136 
137 	config = &ast2600_groups[selector];
138 	descs = config->descs;
139 
140 	setbits_le32(ctrl_reg + descs->offset, descs->reg_set);
141 
142 	return 0;
143 }
144 
145 static struct pinctrl_ops ast2600_pinctrl_ops = {
146 	.set_state = pinctrl_generic_set_state,
147 	.get_groups_count = ast2600_pinctrl_get_groups_count,
148 	.get_group_name = ast2600_pinctrl_get_group_name,
149 	.get_functions_count = ast2600_pinctrl_get_groups_count,
150 	.get_function_name = ast2600_pinctrl_get_group_name,
151 	.pinmux_group_set = ast2600_pinctrl_group_set,
152 };
153 
154 static const struct udevice_id ast2600_pinctrl_ids[] = {
155 	{ .compatible = "aspeed,g6-pinctrl" },
156 	{ }
157 };
158 
159 U_BOOT_DRIVER(pinctrl_aspeed) = {
160 	.name = "aspeed_ast2600_pinctrl",
161 	.id = UCLASS_PINCTRL,
162 	.of_match = ast2600_pinctrl_ids,
163 	.priv_auto_alloc_size = sizeof(struct ast2600_pinctrl_priv),
164 	.ops = &ast2600_pinctrl_ops,
165 	.probe = ast2600_pinctrl_probe,
166 };
167