1290910Sadrian/*-
2290910Sadrian * Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
3290910Sadrian * All rights reserved.
4290910Sadrian *
5290910Sadrian * Redistribution and use in source and binary forms, with or without
6290910Sadrian * modification, are permitted provided that the following conditions
7290910Sadrian * are met:
8290910Sadrian * 1. Redistributions of source code must retain the above copyright
9290910Sadrian *    notice, this list of conditions and the following disclaimer.
10290910Sadrian * 2. Redistributions in binary form must reproduce the above copyright
11290910Sadrian *    notice, this list of conditions and the following disclaimer in the
12290910Sadrian *    documentation and/or other materials provided with the distribution.
13290910Sadrian *
14290910Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15290910Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16290910Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17290910Sadrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18290910Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19290910Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20290910Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21290910Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22290910Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23290910Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24290910Sadrian * SUCH DAMAGE.
25290910Sadrian */
26290910Sadrian
27290910Sadrian#include <sys/cdefs.h>
28290910Sadrian__FBSDID("$FreeBSD: releng/11.0/sys/mips/atheros/qca953x_chip.c 298848 2016-04-30 14:41:18Z pfg $");
29290910Sadrian
30290910Sadrian#include "opt_ddb.h"
31290910Sadrian
32290910Sadrian#include <sys/param.h>
33290910Sadrian#include <sys/conf.h>
34290910Sadrian#include <sys/kernel.h>
35290910Sadrian#include <sys/systm.h>
36290910Sadrian#include <sys/bus.h>
37290910Sadrian#include <sys/cons.h>
38290910Sadrian#include <sys/kdb.h>
39290910Sadrian#include <sys/reboot.h>
40290910Sadrian
41290910Sadrian#include <vm/vm.h>
42290910Sadrian#include <vm/vm_page.h>
43290910Sadrian
44290910Sadrian#include <net/ethernet.h>
45290910Sadrian
46290910Sadrian#include <machine/clock.h>
47290910Sadrian#include <machine/cpu.h>
48290910Sadrian#include <machine/cpuregs.h>
49290910Sadrian#include <machine/hwfunc.h>
50290910Sadrian#include <machine/md_var.h>
51290910Sadrian#include <machine/trap.h>
52290910Sadrian#include <machine/vmparam.h>
53290910Sadrian
54290910Sadrian#include <mips/atheros/ar71xxreg.h>
55290910Sadrian#include <mips/atheros/qca953xreg.h>
56290910Sadrian
57290910Sadrian#include <mips/atheros/ar71xx_cpudef.h>
58290910Sadrian#include <mips/atheros/ar71xx_setup.h>
59290910Sadrian
60290910Sadrian#include <mips/atheros/ar71xx_chip.h>
61290910Sadrian
62290910Sadrian#include <mips/atheros/qca953x_chip.h>
63290910Sadrian
64290910Sadrianstatic void
65290910Sadrianqca953x_chip_detect_mem_size(void)
66290910Sadrian{
67290910Sadrian}
68290910Sadrian
69290910Sadrianstatic void
70290910Sadrianqca953x_chip_detect_sys_frequency(void)
71290910Sadrian{
72290910Sadrian	unsigned long ref_rate;
73290910Sadrian	unsigned long cpu_rate;
74290910Sadrian	unsigned long ddr_rate;
75290910Sadrian	unsigned long ahb_rate;
76290910Sadrian	uint32_t pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv;
77290910Sadrian	uint32_t cpu_pll, ddr_pll;
78290910Sadrian	uint32_t bootstrap;
79290910Sadrian
80290910Sadrian	bootstrap = ATH_READ_REG(QCA953X_RESET_REG_BOOTSTRAP);
81290910Sadrian	if (bootstrap &	QCA953X_BOOTSTRAP_REF_CLK_40)
82290910Sadrian		ref_rate = 40 * 1000 * 1000;
83290910Sadrian	else
84290910Sadrian		ref_rate = 25 * 1000 * 1000;
85290910Sadrian
86290910Sadrian	pll = ATH_READ_REG(QCA953X_PLL_CPU_CONFIG_REG);
87290910Sadrian	out_div = (pll >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
88290910Sadrian		  QCA953X_PLL_CPU_CONFIG_OUTDIV_MASK;
89290910Sadrian	ref_div = (pll >> QCA953X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
90290910Sadrian		  QCA953X_PLL_CPU_CONFIG_REFDIV_MASK;
91290910Sadrian	nint = (pll >> QCA953X_PLL_CPU_CONFIG_NINT_SHIFT) &
92290910Sadrian	       QCA953X_PLL_CPU_CONFIG_NINT_MASK;
93290910Sadrian	frac = (pll >> QCA953X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
94290910Sadrian	       QCA953X_PLL_CPU_CONFIG_NFRAC_MASK;
95290910Sadrian
96290910Sadrian	cpu_pll = nint * ref_rate / ref_div;
97290910Sadrian	cpu_pll += frac * (ref_rate >> 6) / ref_div;
98290910Sadrian	cpu_pll /= (1 << out_div);
99290910Sadrian
100290910Sadrian	pll = ATH_READ_REG(QCA953X_PLL_DDR_CONFIG_REG);
101290910Sadrian	out_div = (pll >> QCA953X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
102290910Sadrian		  QCA953X_PLL_DDR_CONFIG_OUTDIV_MASK;
103290910Sadrian	ref_div = (pll >> QCA953X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
104290910Sadrian		  QCA953X_PLL_DDR_CONFIG_REFDIV_MASK;
105290910Sadrian	nint = (pll >> QCA953X_PLL_DDR_CONFIG_NINT_SHIFT) &
106290910Sadrian	       QCA953X_PLL_DDR_CONFIG_NINT_MASK;
107290910Sadrian	frac = (pll >> QCA953X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
108290910Sadrian	       QCA953X_PLL_DDR_CONFIG_NFRAC_MASK;
109290910Sadrian
110290910Sadrian	ddr_pll = nint * ref_rate / ref_div;
111290910Sadrian	ddr_pll += frac * (ref_rate >> 6) / (ref_div << 4);
112290910Sadrian	ddr_pll /= (1 << out_div);
113290910Sadrian
114290910Sadrian	clk_ctrl = ATH_READ_REG(QCA953X_PLL_CLK_CTRL_REG);
115290910Sadrian
116290910Sadrian	postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
117290910Sadrian		  QCA953X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
118290910Sadrian
119290910Sadrian	if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
120290910Sadrian		cpu_rate = ref_rate;
121290910Sadrian	else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL)
122290910Sadrian		cpu_rate = cpu_pll / (postdiv + 1);
123290910Sadrian	else
124290910Sadrian		cpu_rate = ddr_pll / (postdiv + 1);
125290910Sadrian
126290910Sadrian	postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
127290910Sadrian		  QCA953X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
128290910Sadrian
129290910Sadrian	if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
130290910Sadrian		ddr_rate = ref_rate;
131290910Sadrian	else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL)
132290910Sadrian		ddr_rate = ddr_pll / (postdiv + 1);
133290910Sadrian	else
134290910Sadrian		ddr_rate = cpu_pll / (postdiv + 1);
135290910Sadrian
136290910Sadrian	postdiv = (clk_ctrl >> QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
137290910Sadrian		  QCA953X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
138290910Sadrian
139290910Sadrian	if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
140290910Sadrian		ahb_rate = ref_rate;
141290910Sadrian	else if (clk_ctrl & QCA953X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
142290910Sadrian		ahb_rate = ddr_pll / (postdiv + 1);
143290910Sadrian	else
144290910Sadrian		ahb_rate = cpu_pll / (postdiv + 1);
145290910Sadrian
146290910Sadrian	u_ar71xx_ddr_freq = ddr_rate;
147290910Sadrian	u_ar71xx_cpu_freq = cpu_rate;
148290910Sadrian	u_ar71xx_ahb_freq = ahb_rate;
149290910Sadrian
150290910Sadrian	u_ar71xx_wdt_freq = ref_rate;
151290910Sadrian	u_ar71xx_uart_freq = ref_rate;
152290910Sadrian	u_ar71xx_mdio_freq = ref_rate;
153290910Sadrian	u_ar71xx_refclk = ref_rate;
154290910Sadrian}
155290910Sadrian
156290910Sadrianstatic void
157290910Sadrianqca953x_chip_device_stop(uint32_t mask)
158290910Sadrian{
159290910Sadrian	uint32_t reg;
160290910Sadrian
161290910Sadrian	reg = ATH_READ_REG(QCA953X_RESET_REG_RESET_MODULE);
162290910Sadrian	ATH_WRITE_REG(QCA953X_RESET_REG_RESET_MODULE, reg | mask);
163290910Sadrian}
164290910Sadrian
165290910Sadrianstatic void
166290910Sadrianqca953x_chip_device_start(uint32_t mask)
167290910Sadrian{
168290910Sadrian	uint32_t reg;
169290910Sadrian
170290910Sadrian	reg = ATH_READ_REG(QCA953X_RESET_REG_RESET_MODULE);
171290910Sadrian	ATH_WRITE_REG(QCA953X_RESET_REG_RESET_MODULE, reg & ~mask);
172290910Sadrian}
173290910Sadrian
174290910Sadrianstatic int
175290910Sadrianqca953x_chip_device_stopped(uint32_t mask)
176290910Sadrian{
177290910Sadrian	uint32_t reg;
178290910Sadrian
179290910Sadrian	reg = ATH_READ_REG(QCA953X_RESET_REG_RESET_MODULE);
180290910Sadrian	return ((reg & mask) == mask);
181290910Sadrian}
182290910Sadrian
183290910Sadrianstatic void
184290910Sadrianqca953x_chip_set_mii_speed(uint32_t unit, uint32_t speed)
185290910Sadrian{
186290910Sadrian
187290910Sadrian	/* XXX TODO */
188290910Sadrian	return;
189290910Sadrian}
190290910Sadrian
191290910Sadrianstatic void
192290910Sadrianqca953x_chip_set_pll_ge(int unit, int speed, uint32_t pll)
193290910Sadrian{
194290910Sadrian	switch (unit) {
195290910Sadrian	case 0:
196290910Sadrian		ATH_WRITE_REG(QCA953X_PLL_ETH_XMII_CONTROL_REG, pll);
197290910Sadrian		break;
198290910Sadrian	case 1:
199292247Sadrian		/* nothing */
200290910Sadrian		break;
201290910Sadrian	default:
202290910Sadrian		printf("%s: invalid PLL set for arge unit: %d\n",
203290910Sadrian		    __func__, unit);
204290910Sadrian		return;
205290910Sadrian	}
206290910Sadrian}
207290910Sadrian
208290910Sadrianstatic void
209290910Sadrianqca953x_chip_ddr_flush(ar71xx_flush_ddr_id_t id)
210290910Sadrian{
211290910Sadrian
212290910Sadrian	switch (id) {
213290910Sadrian	case AR71XX_CPU_DDR_FLUSH_GE0:
214290910Sadrian		ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_GE0);
215290910Sadrian		break;
216290910Sadrian	case AR71XX_CPU_DDR_FLUSH_GE1:
217290910Sadrian		ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_GE1);
218290910Sadrian		break;
219290910Sadrian	case AR71XX_CPU_DDR_FLUSH_USB:
220290910Sadrian		ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_USB);
221290910Sadrian		break;
222290910Sadrian	case AR71XX_CPU_DDR_FLUSH_PCIE:
223290910Sadrian		ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_PCIE);
224290910Sadrian		break;
225290910Sadrian	case AR71XX_CPU_DDR_FLUSH_WMAC:
226290910Sadrian		ar71xx_ddr_flush(QCA953X_DDR_REG_FLUSH_WMAC);
227290910Sadrian		break;
228290910Sadrian	default:
229290910Sadrian		printf("%s: invalid flush (%d)\n", __func__, id);
230290910Sadrian	}
231290910Sadrian}
232290910Sadrian
233290910Sadrianstatic uint32_t
234290910Sadrianqca953x_chip_get_eth_pll(unsigned int mac, int speed)
235290910Sadrian{
236290910Sadrian	uint32_t pll;
237290910Sadrian
238290910Sadrian	switch (speed) {
239290910Sadrian	case 10:
240290910Sadrian		pll = QCA953X_PLL_VAL_10;
241290910Sadrian		break;
242290910Sadrian	case 100:
243290910Sadrian		pll = QCA953X_PLL_VAL_100;
244290910Sadrian		break;
245290910Sadrian	case 1000:
246290910Sadrian		pll = QCA953X_PLL_VAL_1000;
247290910Sadrian		break;
248290910Sadrian	default:
249290910Sadrian		printf("%s%d: invalid speed %d\n", __func__, mac, speed);
250290910Sadrian		pll = 0;
251290910Sadrian	}
252290910Sadrian	return (pll);
253290910Sadrian}
254290910Sadrian
255290910Sadrianstatic void
256290910Sadrianqca953x_chip_reset_ethernet_switch(void)
257290910Sadrian{
258290910Sadrian}
259290910Sadrian
260290910Sadrianstatic void
261290910Sadrianqca953x_configure_gmac(uint32_t gmac_cfg)
262290910Sadrian{
263290910Sadrian	uint32_t reg;
264290910Sadrian
265290910Sadrian	reg = ATH_READ_REG(QCA953X_GMAC_REG_ETH_CFG);
266290910Sadrian	printf("%s: ETH_CFG=0x%08x\n", __func__, reg);
267290910Sadrian	reg &= ~(QCA953X_ETH_CFG_SW_ONLY_MODE |
268290910Sadrian	    QCA953X_ETH_CFG_SW_PHY_SWAP |
269290910Sadrian	    QCA953X_ETH_CFG_SW_APB_ACCESS |
270290910Sadrian	    QCA953X_ETH_CFG_SW_ACC_MSB_FIRST);
271290910Sadrian
272290910Sadrian	reg |= gmac_cfg;
273290910Sadrian	ATH_WRITE_REG(QCA953X_GMAC_REG_ETH_CFG, reg);
274290910Sadrian}
275290910Sadrian
276290910Sadrianstatic void
277290910Sadrianqca953x_chip_init_usb_peripheral(void)
278290910Sadrian{
279290910Sadrian	uint32_t bootstrap;
280290910Sadrian
281290910Sadrian	bootstrap = ATH_READ_REG(QCA953X_RESET_REG_BOOTSTRAP);
282290910Sadrian
283290910Sadrian	ar71xx_device_stop(QCA953X_RESET_USBSUS_OVERRIDE);
284290910Sadrian	DELAY(1000);
285290910Sadrian
286290910Sadrian	ar71xx_device_start(QCA953X_RESET_USB_PHY);
287290910Sadrian	DELAY(1000);
288290910Sadrian
289290910Sadrian	ar71xx_device_start(QCA953X_RESET_USB_PHY_ANALOG);
290290910Sadrian	DELAY(1000);
291290910Sadrian
292290910Sadrian	ar71xx_device_start(QCA953X_RESET_USB_HOST);
293290910Sadrian	DELAY(1000);
294290910Sadrian}
295290910Sadrian
296290910Sadrianstatic void
297290910Sadrianqca953x_chip_set_mii_if(uint32_t unit, uint32_t mii_mode)
298290910Sadrian{
299290910Sadrian
300290910Sadrian	/*
301290910Sadrian	 * XXX !
302290910Sadrian	 *
303290910Sadrian	 * Nothing to see here; although gmac0 can have its
304290910Sadrian	 * MII configuration changed, the register values
305290910Sadrian	 * are slightly different.
306290910Sadrian	 */
307290910Sadrian}
308290910Sadrian
309290910Sadrian/*
310290910Sadrian * XXX TODO: fetch default MII divider configuration
311290910Sadrian */
312290910Sadrian
313290910Sadrianstatic void
314290910Sadrianqca953x_chip_reset_wmac(void)
315290910Sadrian{
316290910Sadrian
317290910Sadrian	/* XXX TODO */
318290910Sadrian}
319290910Sadrian
320290910Sadrianstatic void
321290910Sadrianqca953x_chip_init_gmac(void)
322290910Sadrian{
323290910Sadrian	long gmac_cfg;
324290910Sadrian
325290910Sadrian	if (resource_long_value("qca953x_gmac", 0, "gmac_cfg",
326290910Sadrian	    &gmac_cfg) == 0) {
327290910Sadrian		printf("%s: gmac_cfg=0x%08lx\n",
328290910Sadrian		    __func__,
329290910Sadrian		    (long) gmac_cfg);
330290910Sadrian		qca953x_configure_gmac((uint32_t) gmac_cfg);
331290910Sadrian	}
332290910Sadrian}
333290910Sadrian
334290910Sadrian/*
335290910Sadrian * Reset the NAND Flash Controller.
336290910Sadrian *
337290910Sadrian * + active=1 means "make it active".
338290910Sadrian * + active=0 means "make it inactive".
339290910Sadrian */
340290910Sadrianstatic void
341290910Sadrianqca953x_chip_reset_nfc(int active)
342290910Sadrian{
343290910Sadrian}
344290910Sadrian
345290910Sadrian/*
346290910Sadrian * Configure the GPIO output mux setup.
347290910Sadrian *
348290910Sadrian * The QCA953x has an output mux which allowed
349290910Sadrian * certain functions to be configured on any pin.
350290910Sadrian * Specifically, the switch PHY link LEDs and
351290910Sadrian * WMAC external RX LNA switches are not limited to
352290910Sadrian * a specific GPIO pin.
353290910Sadrian */
354290910Sadrianstatic void
355290910Sadrianqca953x_chip_gpio_output_configure(int gpio, uint8_t func)
356290910Sadrian{
357290910Sadrian	uint32_t reg, s;
358290910Sadrian	uint32_t t;
359290910Sadrian
360290910Sadrian	if (gpio > QCA953X_GPIO_COUNT)
361290910Sadrian		return;
362290910Sadrian
363298848Spfg	reg = QCA953X_GPIO_REG_OUT_FUNC0 + rounddown(gpio, 4);
364290910Sadrian	s = 8 * (gpio % 4);
365290910Sadrian
366290910Sadrian	/* read-modify-write */
367290910Sadrian	t = ATH_READ_REG(AR71XX_GPIO_BASE + reg);
368290910Sadrian	t &= ~(0xff << s);
369290910Sadrian	t |= func << s;
370290910Sadrian	ATH_WRITE_REG(AR71XX_GPIO_BASE + reg, t);
371290910Sadrian
372290910Sadrian	/* flush write */
373290910Sadrian	ATH_READ_REG(AR71XX_GPIO_BASE + reg);
374290910Sadrian}
375290910Sadrian
376290910Sadrianstruct ar71xx_cpu_def qca953x_chip_def = {
377290910Sadrian	&qca953x_chip_detect_mem_size,
378290910Sadrian	&qca953x_chip_detect_sys_frequency,
379290910Sadrian	&qca953x_chip_device_stop,
380290910Sadrian	&qca953x_chip_device_start,
381290910Sadrian	&qca953x_chip_device_stopped,
382290910Sadrian	&qca953x_chip_set_pll_ge,
383290910Sadrian	&qca953x_chip_set_mii_speed,
384290910Sadrian	&qca953x_chip_set_mii_if,
385290910Sadrian	&qca953x_chip_get_eth_pll,
386290910Sadrian	&qca953x_chip_ddr_flush,
387290910Sadrian	&qca953x_chip_init_usb_peripheral,
388290910Sadrian	&qca953x_chip_reset_ethernet_switch,
389290910Sadrian	&qca953x_chip_reset_wmac,
390290910Sadrian	&qca953x_chip_init_gmac,
391290910Sadrian	&qca953x_chip_reset_nfc,
392290910Sadrian	&qca953x_chip_gpio_output_configure,
393290910Sadrian};
394