1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2020 Rockchip Electronics Co. Ltd.
4 *
5 * Author: Algea Cao <algea.cao@rock-chips.com>
6 */
7
8 #include <linux/i2c.h>
9 #include <linux/init.h>
10 #include <linux/interrupt.h>
11 #include <linux/module.h>
12 #include <linux/regmap.h>
13 #include <linux/gpio/consumer.h>
14 #include <linux/mfd/rk630.h>
15
rk630_macphy_enable(struct rk630 * rk630)16 static int rk630_macphy_enable(struct rk630 *rk630)
17 {
18 u32 val;
19 int ret;
20
21 /* IOMUX */
22 val = 0xfffc5554;
23 ret = regmap_write(rk630->grf, GRF_REG(0x8), val);
24 if (ret != 0) {
25 dev_err(rk630->dev, "Could not write to GRF: %d\n", ret);
26 return ret;
27 }
28
29 /* IOMUX */
30 val = 0x00330021;
31 ret = regmap_write(rk630->grf, GRF_REG(0x10), val);
32 if (ret != 0) {
33 dev_err(rk630->dev, "Could not write to GRF: %d\n", ret);
34 return ret;
35 }
36
37 /* reset */
38 val = BIT(12 + 16) | BIT(12);
39 ret = regmap_write(rk630->cru, CRU_REG(0x50), val);
40 if (ret != 0) {
41 dev_err(rk630->dev, "Could not write to CRU: %d\n", ret);
42 return ret;
43 }
44 udelay(20);
45
46 val = BIT(12 + 16);
47 ret = regmap_write(rk630->cru, CRU_REG(0x50), val);
48 if (ret != 0) {
49 dev_err(rk630->dev, "Could not write to CRU: %d\n", ret);
50 return ret;
51 }
52 udelay(20);
53
54 /* power up && led*/
55 val = BIT(1 + 16) | BIT(1) | BIT(2 + 16);
56 ret = regmap_write(rk630->grf, GRF_REG(0x408), val);
57 if (ret != 0) {
58 dev_err(rk630->dev, "Could not write to GRF: %d\n", ret);
59 return ret;
60 }
61 usleep_range(20000, 50000);
62
63 /* mdio_sel: mdio */
64 val = BIT(8 + 16) | BIT(8);
65 ret = regmap_write(rk630->grf, GRF_REG(0x400), val);
66 if (ret != 0) {
67 dev_err(rk630->dev, "Could not write to GRF: %d\n", ret);
68 return ret;
69 }
70
71 /* mode sel: RMII && clock sel: 24M && BGS value: OTP && id */
72 val = (2 << 14) | (0 << 12) | (0x1 << 8) | (6 << 5) | 1;
73 ret = regmap_write(rk630->grf, GRF_REG(0x404), val | 0xffff0000);
74 if (ret != 0) {
75 dev_err(rk630->dev, "Could not write to GRF: %d\n", ret);
76 return ret;
77 }
78 usleep_range(100, 150);
79
80 return 0;
81 }
82
rk630_macphy_disable(struct rk630 * rk630)83 static int rk630_macphy_disable(struct rk630 *rk630)
84 {
85 u32 val;
86 int ret;
87
88 /* GRF_SOC_CON2_CFG */
89 val = BIT(2) | BIT(16 + 2);
90 ret = regmap_write(rk630->grf, GRF_REG(0x408), val);
91 if (ret != 0) {
92 dev_err(rk630->dev, "Could not write to GRF: %d\n", ret);
93 return ret;
94 }
95
96 return 0;
97 }
98
99 static const struct mfd_cell rk630_devs[] = {
100 {
101 .name = "rk630-tve",
102 .of_compatible = "rockchip,rk630-tve",
103 },
104 {
105 .name = "rk630-macphy",
106 .of_compatible = "rockchip,rk630-macphy",
107 },
108 };
109
110 static const struct regmap_range rk630_grf_readable_ranges[] = {
111 regmap_reg_range(PLUMAGE_GRF_GPIO0A_IOMUX, PLUMAGE_GRF_GPIO0A_IOMUX),
112 regmap_reg_range(PLUMAGE_GRF_GPIO0B_IOMUX, PLUMAGE_GRF_GPIO0B_IOMUX),
113 regmap_reg_range(PLUMAGE_GRF_GPIO0C_IOMUX, PLUMAGE_GRF_GPIO0C_IOMUX),
114 regmap_reg_range(PLUMAGE_GRF_GPIO0D_IOMUX, PLUMAGE_GRF_GPIO0D_IOMUX),
115 regmap_reg_range(PLUMAGE_GRF_GPIO1A_IOMUX, PLUMAGE_GRF_GPIO1A_IOMUX),
116 regmap_reg_range(PLUMAGE_GRF_GPIO1B_IOMUX, PLUMAGE_GRF_GPIO1B_IOMUX),
117 regmap_reg_range(PLUMAGE_GRF_GPIO0A_P, PLUMAGE_GRF_GPIO1B_P),
118 regmap_reg_range(PLUMAGE_GRF_GPIO1B_SR, PLUMAGE_GRF_GPIO1B_SR),
119 regmap_reg_range(PLUMAGE_GRF_GPIO1B_E, PLUMAGE_GRF_GPIO1B_E),
120 regmap_reg_range(PLUMAGE_GRF_SOC_CON0, PLUMAGE_GRF_SOC_CON4),
121 regmap_reg_range(PLUMAGE_GRF_SOC_STATUS, PLUMAGE_GRF_SOC_STATUS),
122 regmap_reg_range(PLUMAGE_GRF_GPIO0_REN0, PLUMAGE_GRF_GPIO1_REN0),
123 };
124
125 static const struct regmap_access_table rk630_grf_readable_table = {
126 .yes_ranges = rk630_grf_readable_ranges,
127 .n_yes_ranges = ARRAY_SIZE(rk630_grf_readable_ranges),
128 };
129
130 const struct regmap_config rk630_grf_regmap_config = {
131 .name = "grf",
132 .reg_bits = 32,
133 .val_bits = 32,
134 .reg_stride = 4,
135 .max_register = GRF_MAX_REGISTER,
136 .reg_format_endian = REGMAP_ENDIAN_NATIVE,
137 .val_format_endian = REGMAP_ENDIAN_NATIVE,
138 .rd_table = &rk630_grf_readable_table,
139 };
140 EXPORT_SYMBOL_GPL(rk630_grf_regmap_config);
141
142 static const struct regmap_range rk630_cru_readable_ranges[] = {
143 regmap_reg_range(CRU_SPLL_CON0, CRU_SPLL_CON2),
144 regmap_reg_range(CRU_MODE_CON, CRU_MODE_CON),
145 regmap_reg_range(CRU_CLKSEL_CON0, CRU_CLKSEL_CON3),
146 regmap_reg_range(CRU_GATE_CON0, CRU_GATE_CON0),
147 regmap_reg_range(CRU_SOFTRST_CON0, CRU_SOFTRST_CON0),
148 };
149
150 static const struct regmap_access_table rk630_cru_readable_table = {
151 .yes_ranges = rk630_cru_readable_ranges,
152 .n_yes_ranges = ARRAY_SIZE(rk630_cru_readable_ranges),
153 };
154
155 const struct regmap_config rk630_cru_regmap_config = {
156 .name = "cru",
157 .reg_bits = 32,
158 .val_bits = 32,
159 .reg_stride = 4,
160 .max_register = CRU_MAX_REGISTER,
161 .reg_format_endian = REGMAP_ENDIAN_NATIVE,
162 .val_format_endian = REGMAP_ENDIAN_NATIVE,
163 .rd_table = &rk630_cru_readable_table,
164 };
165 EXPORT_SYMBOL_GPL(rk630_cru_regmap_config);
166
rk630_core_probe(struct rk630 * rk630)167 int rk630_core_probe(struct rk630 *rk630)
168 {
169 bool macphy_enabled = false;
170 struct device_node *np;
171 int ret;
172
173 rk630->reset_gpio = devm_gpiod_get(rk630->dev, "reset", 0);
174 if (IS_ERR(rk630->reset_gpio)) {
175 ret = PTR_ERR(rk630->reset_gpio);
176 dev_err(rk630->dev, "failed to request reset GPIO: %d\n", ret);
177 return ret;
178 }
179
180 gpiod_direction_output(rk630->reset_gpio, 0);
181 usleep_range(2000, 4000);
182 gpiod_direction_output(rk630->reset_gpio, 1);
183 usleep_range(50000, 60000);
184 gpiod_direction_output(rk630->reset_gpio, 0);
185
186 ret = devm_mfd_add_devices(rk630->dev, PLATFORM_DEVID_NONE,
187 rk630_devs, ARRAY_SIZE(rk630_devs),
188 NULL, 0, NULL);
189 if (ret) {
190 dev_err(rk630->dev, "failed to add MFD children: %d\n", ret);
191 return ret;
192 }
193
194 for_each_child_of_node(rk630->dev->of_node, np) {
195 if (!of_device_is_compatible(np, "rockchip,rk630-macphy"))
196 continue;
197
198 if (!of_device_is_available(np)) {
199 continue;
200 } else {
201 macphy_enabled = true;
202 break;
203 }
204 }
205
206 if (macphy_enabled)
207 rk630_macphy_enable(rk630);
208 else
209 rk630_macphy_disable(rk630);
210
211 return 0;
212 }
213 EXPORT_SYMBOL_GPL(rk630_core_probe);
214
215 MODULE_AUTHOR("Algea Cao <Algea.cao@rock-chips.com>");
216 MODULE_DESCRIPTION("Rockchip rk630 MFD Core driver");
217 MODULE_LICENSE("GPL v2");
218