ar71xx: Add kernel 4.9 support
[openwrt/openwrt.git] / target / linux / ar71xx / patches-4.9 / 523-MIPS-ath79-OTP-support.patch
1 --- a/arch/mips/ath79/dev-wmac.c
2 +++ b/arch/mips/ath79/dev-wmac.c
3 @@ -166,6 +166,149 @@ static void qca955x_wmac_setup(void)
4 ath79_wmac_data.is_clk_25mhz = true;
5 }
6
7 +#define AR93XX_WMAC_SIZE \
8 + (soc_is_ar934x() ? AR934X_WMAC_SIZE : AR933X_WMAC_SIZE)
9 +#define AR93XX_WMAC_BASE \
10 + (soc_is_ar934x() ? AR934X_WMAC_BASE : AR933X_WMAC_BASE)
11 +
12 +#define AR93XX_OTP_BASE \
13 + (soc_is_ar934x() ? AR934X_OTP_BASE : AR9300_OTP_BASE)
14 +#define AR93XX_OTP_STATUS \
15 + (soc_is_ar934x() ? AR934X_OTP_STATUS : AR9300_OTP_STATUS)
16 +#define AR93XX_OTP_READ_DATA \
17 + (soc_is_ar934x() ? AR934X_OTP_READ_DATA : AR9300_OTP_READ_DATA)
18 +
19 +static bool __init
20 +ar93xx_wmac_otp_read_word(void __iomem *base, int addr, u32 *data)
21 +{
22 + int timeout = 1000;
23 + u32 val;
24 +
25 + __raw_readl(base + AR93XX_OTP_BASE + (4 * addr));
26 + while (timeout--) {
27 + val = __raw_readl(base + AR93XX_OTP_STATUS);
28 + if ((val & AR9300_OTP_STATUS_TYPE) == AR9300_OTP_STATUS_VALID)
29 + break;
30 +
31 + udelay(10);
32 + }
33 +
34 + if (!timeout)
35 + return false;
36 +
37 + *data = __raw_readl(base + AR93XX_OTP_READ_DATA);
38 + return true;
39 +}
40 +
41 +static bool __init
42 +ar93xx_wmac_otp_read(void __iomem *base, int addr, u8 *dest, int len)
43 +{
44 + u32 data;
45 + int i;
46 +
47 + for (i = 0; i < len; i++) {
48 + int offset = 8 * ((addr - i) % 4);
49 +
50 + if (!ar93xx_wmac_otp_read_word(base, (addr - i) / 4, &data))
51 + return false;
52 +
53 + dest[i] = (data >> offset) & 0xff;
54 + }
55 +
56 + return true;
57 +}
58 +
59 +static bool __init
60 +ar93xx_wmac_otp_uncompress(void __iomem *base, int addr, int len, u8 *dest,
61 + int dest_start, int dest_len)
62 +{
63 + int dest_bytes = 0;
64 + int offset = 0;
65 + int end = addr - len;
66 + u8 hdr[2];
67 +
68 + while (addr > end) {
69 + if (!ar93xx_wmac_otp_read(base, addr, hdr, 2))
70 + return false;
71 +
72 + addr -= 2;
73 + offset += hdr[0];
74 +
75 + if (offset <= dest_start + dest_len &&
76 + offset + len >= dest_start) {
77 + int data_offset = 0;
78 + int dest_offset = 0;
79 + int copy_len;
80 +
81 + if (offset < dest_start)
82 + data_offset = dest_start - offset;
83 + else
84 + dest_offset = offset - dest_start;
85 +
86 + copy_len = len - data_offset;
87 + if (copy_len > dest_len - dest_offset)
88 + copy_len = dest_len - dest_offset;
89 +
90 + ar93xx_wmac_otp_read(base, addr - data_offset,
91 + dest + dest_offset,
92 + copy_len);
93 +
94 + dest_bytes += copy_len;
95 + }
96 + addr -= hdr[1];
97 + }
98 + return !!dest_bytes;
99 +}
100 +
101 +bool __init ar93xx_wmac_read_mac_address(u8 *dest)
102 +{
103 + void __iomem *base;
104 + bool ret = false;
105 + int addr = 0x1ff;
106 + unsigned int len;
107 + u32 hdr_u32;
108 + u8 *hdr = (u8 *) &hdr_u32;
109 + u8 mac[6] = { 0x00, 0x02, 0x03, 0x04, 0x05, 0x06 };
110 + int mac_start = 2, mac_end = 8;
111 +
112 + BUG_ON(!soc_is_ar933x() && !soc_is_ar934x());
113 + base = ioremap_nocache(AR93XX_WMAC_BASE, AR93XX_WMAC_SIZE);
114 + while (addr > sizeof(hdr_u32)) {
115 + if (!ar93xx_wmac_otp_read(base, addr, hdr, sizeof(hdr_u32)))
116 + break;
117 +
118 + if (hdr_u32 == 0 || hdr_u32 == ~0)
119 + break;
120 +
121 + len = (hdr[1] << 4) | (hdr[2] >> 4);
122 + addr -= 4;
123 +
124 + switch (hdr[0] >> 5) {
125 + case 0:
126 + if (len < mac_end)
127 + break;
128 +
129 + ar93xx_wmac_otp_read(base, addr - mac_start, mac, 6);
130 + ret = true;
131 + break;
132 + case 3:
133 + ret |= ar93xx_wmac_otp_uncompress(base, addr, len, mac,
134 + mac_start, 6);
135 + break;
136 + default:
137 + break;
138 + }
139 +
140 + addr -= len + 2;
141 + }
142 +
143 + iounmap(base);
144 + if (ret)
145 + memcpy(dest, mac, 6);
146 +
147 + return ret;
148 +}
149 +
150 void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr)
151 {
152 if (soc_is_ar913x())
153 --- a/arch/mips/ath79/dev-wmac.h
154 +++ b/arch/mips/ath79/dev-wmac.h
155 @@ -14,5 +14,6 @@
156
157 void ath79_register_wmac(u8 *cal_data, u8 *mac_addr);
158 void ath79_register_wmac_simple(void);
159 +bool ar93xx_wmac_read_mac_address(u8 *dest);
160
161 #endif /* _ATH79_DEV_WMAC_H */
162 --- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
163 +++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
164 @@ -112,6 +112,14 @@
165 #define QCA955X_EHCI1_BASE 0x1b400000
166 #define QCA955X_EHCI_SIZE 0x1000
167
168 +#define AR9300_OTP_BASE 0x14000
169 +#define AR9300_OTP_STATUS 0x15f18
170 +#define AR9300_OTP_STATUS_TYPE 0x7
171 +#define AR9300_OTP_STATUS_VALID 0x4
172 +#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2
173 +#define AR9300_OTP_STATUS_SM_BUSY 0x1
174 +#define AR9300_OTP_READ_DATA 0x15f1c
175 +
176 /*
177 * DDR_CTRL block
178 */
179 @@ -149,6 +157,13 @@
180 #define AR934X_DDR_REG_FLUSH_PCIE 0xa8
181 #define AR934X_DDR_REG_FLUSH_WMAC 0xac
182
183 +#define AR934X_OTP_BASE 0x30000
184 +#define AR934X_OTP_STATUS 0x31018
185 +#define AR934X_OTP_READ_DATA 0x3101c
186 +#define AR934X_OTP_INTF2_ADDRESS 0x31008
187 +#define AR934X_OTP_INTF3_ADDRESS 0x3100c
188 +#define AR934X_OTP_PGENB_SETUP_HOLD_TIME_ADDRESS 0x31034
189 +
190 /*
191 * PLL block
192 */