2 * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards
4 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
14 #include "ar71xx_regs.h"
16 #define READREG(r) *(volatile unsigned int *)(r)
17 #define WRITEREG(r,v) *(volatile unsigned int *)(r) = v
19 #define KSEG1ADDR(_x) (((_x) & 0x1fffffff) | 0xa0000000)
21 #define UART_BASE 0xb8020000
26 #define UART_LSR_THRE 0x20
28 #define UART_READ(r) READREG(UART_BASE + 4 * (r))
29 #define UART_WRITE(r,v) WRITEREG(UART_BASE + 4 * (r), (v))
31 void board_putc(int ch
)
33 while (((UART_READ(UART_LSR
)) & UART_LSR_THRE
) == 0);
34 UART_WRITE(UART_TX
, ch
);
35 while (((UART_READ(UART_LSR
)) & UART_LSR_THRE
) == 0);
38 #ifdef CONFIG_BOARD_TL_WR1043ND_V1
39 static void tlwr1043nd_init(void)
41 unsigned int reg
= KSEG1ADDR(AR71XX_RESET_BASE
);
44 t
= READREG(reg
+ AR913X_RESET_REG_RESET_MODULE
);
45 t
|= AR71XX_RESET_GE0_PHY
;
46 WRITEREG(reg
+ AR913X_RESET_REG_RESET_MODULE
, t
);
48 t
= READREG(reg
+ AR913X_RESET_REG_RESET_MODULE
);
51 static inline void tlwr1043nd_init(void) {}
54 #ifdef CONFIG_BOARD_MERAKI_MR18
56 static int mr18_extract_sgmii_res_cal(void)
59 unsigned int reversed_sgmii_value
;
61 unsigned int otp_value
, otp_per_val
, rbias_per
, read_data
;
62 unsigned int rbias_pos_or_neg
;
63 unsigned int sgmii_res_cal_value
;
66 base
= KSEG1ADDR(QCA955X_OTP_BASE
);
68 WRITEREG(base
+ QCA955X_OTP_REG_INTF2
, 0x7d);
69 WRITEREG(base
+ QCA955X_OTP_REG_LDO_CTRL
, 0x00);
71 while (READREG(base
+ QCA955X_OTP_REG_LDO_STATUS
) &
72 QCA955X_OTP_LDO_STATUS_POWER_ON
);
74 READREG(base
+ QCA955X_OTP_REG_MEM_0
+ 4);
76 while (!(READREG(base
+ QCA955X_OTP_REG_STATUS0
) &
77 QCA955X_OTP_STATUS0_EFUSE_VALID
));
79 read_data
= READREG(base
+ QCA955X_OTP_REG_STATUS1
);
81 if (!(read_data
& 0x1fff))
84 if (read_data
& 0x00001000)
85 otp_value
= (read_data
& 0xfc0) >> 6;
87 otp_value
= read_data
& 0x3f;
90 otp_per_val
= 63 - otp_value
;
93 otp_per_val
= otp_value
;
97 rbias_per
= otp_per_val
* 15;
99 if (rbias_pos_or_neg
== 1)
100 res_cal_val
= (rbias_per
+ 34) / 21;
101 else if (rbias_per
> 34)
102 res_cal_val
= -((rbias_per
- 34) / 21);
104 res_cal_val
= (34 - rbias_per
) / 21;
106 sgmii_res_cal_value
= (8 + res_cal_val
) & 0xf;
108 reversed_sgmii_value
= (sgmii_res_cal_value
& 8) >> 3;
109 reversed_sgmii_value
|= (sgmii_res_cal_value
& 4) >> 1;
110 reversed_sgmii_value
|= (sgmii_res_cal_value
& 2) << 1;
111 reversed_sgmii_value
|= (sgmii_res_cal_value
& 1) << 3;
112 printf("SGMII cal value = 0x%x\n", reversed_sgmii_value
);
113 return reversed_sgmii_value
;
116 #define QCA955X_SGMII_SERDES_RES_CALIBRATION BIT(23)
117 #define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf
118 #define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23
119 #define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15)
120 #define QCA955X_PLL_ETH_SGMII_SERDES_LOCK_DETECT BIT(2)
121 #define QCA955X_PLL_ETH_SGMII_SERDES_PLL_REFCLK BIT(1)
122 #define QCA955X_PLL_ETH_SGMII_SERDES_EN_PLL BIT(0)
123 #define QCA955X_PLL_CLK_CTRL_REG 0x08
124 #define QCA955X_PLL_ETH_XMII_CONTROL_REG 0x28
125 #define QCA955X_PLL_ETH_SGMII_CONTROL_REG 0x48
126 #define QCA955X_PLL_ETH_SGMII_SERDES_REG 0x4c
128 static void qca955x_device_reset_clear(unsigned int mask
)
132 reg
= KSEG1ADDR(AR71XX_RESET_BASE
+
133 QCA955X_RESET_REG_RESET_MODULE
);
136 WRITEREG(reg
, t
& ~mask
);
139 static void mr18_setup_qca955x_eth_serdes_cal(unsigned int sgmii_value
)
141 unsigned int ethbase
, pllbase
, t
;
143 ethbase
= KSEG1ADDR(QCA955X_GMAC_BASE
);
144 pllbase
= KSEG1ADDR(AR71XX_PLL_BASE
);
146 /* To Check the locking of the SGMII PLL */
147 t
= READREG(ethbase
+ QCA955X_GMAC_REG_SGMII_SERDES
);
148 t
&= ~(QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK
<<
149 QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT
);
150 t
|= (sgmii_value
& QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK
) <<
151 QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT
;
152 WRITEREG(ethbase
+ QCA955X_GMAC_REG_SGMII_SERDES
, t
);
154 WRITEREG(pllbase
+ QCA955X_PLL_ETH_SGMII_SERDES_REG
,
155 QCA955X_PLL_ETH_SGMII_SERDES_LOCK_DETECT
|
156 QCA955X_PLL_ETH_SGMII_SERDES_PLL_REFCLK
|
157 QCA955X_PLL_ETH_SGMII_SERDES_EN_PLL
);
159 qca955x_device_reset_clear(QCA955X_RESET_SGMII_ANALOG
);
160 qca955x_device_reset_clear(QCA955X_RESET_SGMII
);
162 while (!(READREG(ethbase
+ QCA955X_GMAC_REG_SGMII_SERDES
) &
163 QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS
));
166 static inline void mr18_init(void)
170 printf("Meraki MR18\n");
172 res
= mr18_extract_sgmii_res_cal();
174 mr18_setup_qca955x_eth_serdes_cal(res
);
178 static inline void mr18_init(void) { }
181 void board_init(void)