523-MIPS-ath79-OTP-support.patch 4.5 KB

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