xref: /freebsd-13-stable/sys/mips/atheros/ar71xx_chip.c (revision 3bc80996974a61a4223eae4c1ccd47b6ee32a48a)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2010 Adrian Chadd
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 #include "opt_ddb.h"
31 
32 #include <sys/param.h>
33 #include <sys/conf.h>
34 #include <sys/kernel.h>
35 #include <sys/systm.h>
36 #include <sys/bus.h>
37 #include <sys/cons.h>
38 #include <sys/kdb.h>
39 #include <sys/reboot.h>
40 
41 #include <vm/vm.h>
42 #include <vm/vm_page.h>
43 
44 #include <net/ethernet.h>
45 
46 #include <machine/clock.h>
47 #include <machine/cpu.h>
48 #include <machine/cpuregs.h>
49 #include <machine/hwfunc.h>
50 #include <machine/md_var.h>
51 #include <machine/trap.h>
52 #include <machine/vmparam.h>
53 
54 #include <mips/atheros/ar71xxreg.h>
55 #include <mips/atheros/ar71xx_chip.h>
56 #include <mips/atheros/ar71xx_cpudef.h>
57 
58 /* XXX these should replace the current definitions in ar71xxreg.h */
59 /* XXX perhaps an ar71xx_chip.h header file? */
60 #define AR71XX_PLL_REG_CPU_CONFIG       AR71XX_PLL_CPU_BASE + 0x00
61 #define AR71XX_PLL_REG_SEC_CONFIG       AR71XX_PLL_CPU_BASE + 0x04
62 #define AR71XX_PLL_REG_ETH0_INT_CLOCK   AR71XX_PLL_CPU_BASE + 0x10
63 #define AR71XX_PLL_REG_ETH1_INT_CLOCK   AR71XX_PLL_CPU_BASE + 0x14
64 
65 #define AR71XX_PLL_DIV_SHIFT            3
66 #define AR71XX_PLL_DIV_MASK             0x1f
67 #define AR71XX_CPU_DIV_SHIFT            16
68 #define AR71XX_CPU_DIV_MASK             0x3
69 #define AR71XX_DDR_DIV_SHIFT            18
70 #define AR71XX_DDR_DIV_MASK             0x3
71 #define AR71XX_AHB_DIV_SHIFT            20
72 #define AR71XX_AHB_DIV_MASK             0x7
73 
74 /* XXX these shouldn't be in here - this file is a per-chip file */
75 /* XXX these should be in the top-level ar71xx type, not ar71xx -chip */
76 uint32_t u_ar71xx_cpu_freq;
77 uint32_t u_ar71xx_ahb_freq;
78 uint32_t u_ar71xx_ddr_freq;
79 uint32_t u_ar71xx_uart_freq;
80 uint32_t u_ar71xx_wdt_freq;
81 uint32_t u_ar71xx_refclk;
82 uint32_t u_ar71xx_mdio_freq;
83 
84 static void
ar71xx_chip_detect_mem_size(void)85 ar71xx_chip_detect_mem_size(void)
86 {
87 }
88 
89 static void
ar71xx_chip_detect_sys_frequency(void)90 ar71xx_chip_detect_sys_frequency(void)
91 {
92 	uint32_t pll;
93 	uint32_t freq;
94 	uint32_t div;
95 
96 	u_ar71xx_mdio_freq = u_ar71xx_refclk = AR71XX_BASE_FREQ;
97 
98 	pll = ATH_READ_REG(AR71XX_PLL_REG_CPU_CONFIG);
99 
100 	div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
101 	freq = div * AR71XX_BASE_FREQ;
102 
103 	div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
104 	u_ar71xx_cpu_freq = freq / div;
105 
106 	div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
107 	u_ar71xx_ddr_freq = freq / div;
108 
109 	div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
110 	u_ar71xx_ahb_freq = u_ar71xx_cpu_freq / div;
111 	u_ar71xx_wdt_freq = u_ar71xx_cpu_freq / div;
112 	u_ar71xx_uart_freq = u_ar71xx_cpu_freq / div;
113 }
114 
115 /*
116  * This does not lock the CPU whilst doing the work!
117  */
118 static void
ar71xx_chip_device_stop(uint32_t mask)119 ar71xx_chip_device_stop(uint32_t mask)
120 {
121 	uint32_t reg;
122 
123 	reg = ATH_READ_REG(AR71XX_RST_RESET);
124 	ATH_WRITE_REG(AR71XX_RST_RESET, reg | mask);
125 }
126 
127 static void
ar71xx_chip_device_start(uint32_t mask)128 ar71xx_chip_device_start(uint32_t mask)
129 {
130 	uint32_t reg;
131 
132 	reg = ATH_READ_REG(AR71XX_RST_RESET);
133 	ATH_WRITE_REG(AR71XX_RST_RESET, reg & ~mask);
134 }
135 
136 static int
ar71xx_chip_device_stopped(uint32_t mask)137 ar71xx_chip_device_stopped(uint32_t mask)
138 {
139 	uint32_t reg;
140 
141 	reg = ATH_READ_REG(AR71XX_RST_RESET);
142 	return ((reg & mask) == mask);
143 }
144 
145 void
ar71xx_chip_set_mii_speed(uint32_t unit,uint32_t speed)146 ar71xx_chip_set_mii_speed(uint32_t unit, uint32_t speed)
147 {
148 	uint32_t val, reg, ctrl;
149 
150 	switch (unit) {
151 	case 0:
152 		reg = AR71XX_MII0_CTRL;
153 		break;
154 	case 1:
155 		reg = AR71XX_MII1_CTRL;
156 		break;
157 	default:
158 		printf("%s: invalid MII unit set for arge unit: %d\n",
159 		    __func__, unit);
160 		return;
161 	}
162 
163 	switch (speed) {
164 	case 10:
165 		ctrl = MII_CTRL_SPEED_10;
166 		break;
167 	case 100:
168 		ctrl = MII_CTRL_SPEED_100;
169 		break;
170 	case 1000:
171 		ctrl = MII_CTRL_SPEED_1000;
172 		break;
173 	default:
174 		printf("%s: invalid MII speed (%d) set for arge unit: %d\n",
175 		    __func__, speed, unit);
176 		return;
177 	}
178 
179 	val = ATH_READ_REG(reg);
180 	val &= ~(MII_CTRL_SPEED_MASK << MII_CTRL_SPEED_SHIFT);
181 	val |= (ctrl & MII_CTRL_SPEED_MASK) << MII_CTRL_SPEED_SHIFT;
182 	ATH_WRITE_REG(reg, val);
183 }
184 
185 void
ar71xx_chip_set_mii_if(uint32_t unit,uint32_t mii_mode)186 ar71xx_chip_set_mii_if(uint32_t unit, uint32_t mii_mode)
187 {
188 	uint32_t val, reg, mii_if;
189 
190 	switch (unit) {
191 	case 0:
192 		reg = AR71XX_MII0_CTRL;
193 		if (mii_mode == AR71XX_MII_MODE_GMII)
194 			mii_if = MII0_CTRL_IF_GMII;
195 		else if (mii_mode == AR71XX_MII_MODE_MII)
196 			mii_if = MII0_CTRL_IF_MII;
197 		else if (mii_mode == AR71XX_MII_MODE_RGMII)
198 			mii_if = MII0_CTRL_IF_RGMII;
199 		else if (mii_mode == AR71XX_MII_MODE_RMII)
200 			mii_if = MII0_CTRL_IF_RMII;
201 		else {
202 			printf("%s: invalid MII mode (%d) for unit %d\n",
203 			    __func__, mii_mode, unit);
204 			return;
205 		}
206 		break;
207 	case 1:
208 		reg = AR71XX_MII1_CTRL;
209 		if (mii_mode == AR71XX_MII_MODE_RGMII)
210 			mii_if = MII1_CTRL_IF_RGMII;
211 		else if (mii_mode == AR71XX_MII_MODE_RMII)
212 			mii_if = MII1_CTRL_IF_RMII;
213 		else {
214 			printf("%s: invalid MII mode (%d) for unit %d\n",
215 			    __func__, mii_mode, unit);
216 			return;
217 		}
218 		break;
219 	default:
220 		printf("%s: invalid MII unit set for arge unit: %d\n",
221 		    __func__, unit);
222 		return;
223 	}
224 
225 	val = ATH_READ_REG(reg);
226 	val &= ~(MII_CTRL_IF_MASK << MII_CTRL_IF_SHIFT);
227 	val |= (mii_if & MII_CTRL_IF_MASK) << MII_CTRL_IF_SHIFT;
228 	ATH_WRITE_REG(reg, val);
229 }
230 
231 /* Speed is either 10, 100 or 1000 */
232 static void
ar71xx_chip_set_pll_ge(int unit,int speed,uint32_t pll)233 ar71xx_chip_set_pll_ge(int unit, int speed, uint32_t pll)
234 {
235 
236 	switch (unit) {
237 	case 0:
238 		ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG,
239 		    AR71XX_PLL_ETH_INT0_CLK, pll,
240 		    AR71XX_PLL_ETH0_SHIFT);
241 		break;
242 	case 1:
243 		ar71xx_write_pll(AR71XX_PLL_SEC_CONFIG,
244 		    AR71XX_PLL_ETH_INT1_CLK, pll,
245 		    AR71XX_PLL_ETH1_SHIFT);
246 		break;
247 	default:
248 		printf("%s: invalid PLL set for arge unit: %d\n",
249 		    __func__, unit);
250 		return;
251 	}
252 }
253 
254 static void
ar71xx_chip_ddr_flush(ar71xx_flush_ddr_id_t id)255 ar71xx_chip_ddr_flush(ar71xx_flush_ddr_id_t id)
256 {
257 
258 	switch (id) {
259 	case AR71XX_CPU_DDR_FLUSH_GE0:
260 		ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE0);
261 		break;
262 	case AR71XX_CPU_DDR_FLUSH_GE1:
263 		ar71xx_ddr_flush(AR71XX_WB_FLUSH_GE1);
264 		break;
265 	case AR71XX_CPU_DDR_FLUSH_USB:
266 		ar71xx_ddr_flush(AR71XX_WB_FLUSH_USB);
267 		break;
268 	case AR71XX_CPU_DDR_FLUSH_PCIE:
269 		ar71xx_ddr_flush(AR71XX_WB_FLUSH_PCI);
270 		break;
271 	default:
272 		printf("%s: invalid DDR flush id (%d)\n", __func__, id);
273 		break;
274 	}
275 }
276 
277 static uint32_t
ar71xx_chip_get_eth_pll(unsigned int mac,int speed)278 ar71xx_chip_get_eth_pll(unsigned int mac, int speed)
279 {
280 	uint32_t pll;
281 
282 	switch (speed) {
283 	case 10:
284 		pll = PLL_ETH_INT_CLK_10;
285 		break;
286 	case 100:
287 		pll = PLL_ETH_INT_CLK_100;
288 		break;
289 	case 1000:
290 		pll = PLL_ETH_INT_CLK_1000;
291 		break;
292 	default:
293 		printf("%s%d: invalid speed %d\n", __func__, mac, speed);
294 		pll = 0;
295 	}
296 
297 	return (pll);
298 }
299 
300 static void
ar71xx_chip_init_usb_peripheral(void)301 ar71xx_chip_init_usb_peripheral(void)
302 {
303 
304 	ar71xx_device_stop(RST_RESET_USB_OHCI_DLL |
305 	    RST_RESET_USB_HOST | RST_RESET_USB_PHY);
306 	DELAY(1000);
307 
308 	ar71xx_device_start(RST_RESET_USB_OHCI_DLL |
309 	    RST_RESET_USB_HOST | RST_RESET_USB_PHY);
310 	DELAY(1000);
311 
312 	ATH_WRITE_REG(AR71XX_USB_CTRL_CONFIG,
313 	    USB_CTRL_CONFIG_OHCI_DES_SWAP |
314 	    USB_CTRL_CONFIG_OHCI_BUF_SWAP |
315 	    USB_CTRL_CONFIG_EHCI_DES_SWAP |
316 	    USB_CTRL_CONFIG_EHCI_BUF_SWAP);
317 
318 	ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ,
319 	    (32 << USB_CTRL_FLADJ_HOST_SHIFT) |
320 	    (3 << USB_CTRL_FLADJ_A5_SHIFT));
321 
322 	DELAY(1000);
323 }
324 
325 struct ar71xx_cpu_def ar71xx_chip_def = {
326 	&ar71xx_chip_detect_mem_size,
327 	&ar71xx_chip_detect_sys_frequency,
328 	&ar71xx_chip_device_stop,
329 	&ar71xx_chip_device_start,
330 	&ar71xx_chip_device_stopped,
331 	&ar71xx_chip_set_pll_ge,
332 	&ar71xx_chip_set_mii_speed,
333 	&ar71xx_chip_set_mii_if,
334 	&ar71xx_chip_get_eth_pll,
335 	&ar71xx_chip_ddr_flush,
336 	&ar71xx_chip_init_usb_peripheral,
337 };
338