mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-12-28 18:17:43 +02:00
ar71xx: add support for reading the MAC address from OTP ROM on AR933x
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@32446 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
295fa0808d
commit
bd85fd265b
166
target/linux/ar71xx/patches-3.3/620-MIPS-ath79-OTP-support.patch
Normal file
166
target/linux/ar71xx/patches-3.3/620-MIPS-ath79-OTP-support.patch
Normal file
@ -0,0 +1,166 @@
|
||||
--- a/arch/mips/ath79/dev-wmac.c
|
||||
+++ b/arch/mips/ath79/dev-wmac.c
|
||||
@@ -121,6 +121,137 @@ static void ar934x_wmac_setup(void)
|
||||
ath79_wmac_data.is_clk_25mhz = true;
|
||||
}
|
||||
|
||||
+static bool __init
|
||||
+ar93xx_wmac_otp_read_word(void __iomem *base, int addr, u32 *data)
|
||||
+{
|
||||
+ int timeout = 1000;
|
||||
+ u32 val;
|
||||
+
|
||||
+ __raw_readl(base + AR9300_OTP_BASE + (4 * addr));
|
||||
+ while (timeout--) {
|
||||
+ val = __raw_readl(base + AR9300_OTP_STATUS);
|
||||
+ if ((val & AR9300_OTP_STATUS_TYPE) == AR9300_OTP_STATUS_VALID)
|
||||
+ break;
|
||||
+
|
||||
+ udelay(10);
|
||||
+ }
|
||||
+
|
||||
+ if (!timeout)
|
||||
+ return false;
|
||||
+
|
||||
+ *data = __raw_readl(base + AR9300_OTP_READ_DATA);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool __init
|
||||
+ar93xx_wmac_otp_read(void __iomem *base, int addr, u8 *dest, int len)
|
||||
+{
|
||||
+ u32 data;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < len; i++) {
|
||||
+ int offset = 8 * ((addr - i) % 4);
|
||||
+
|
||||
+ if (!ar93xx_wmac_otp_read_word(base, (addr - i) / 4, &data))
|
||||
+ return false;
|
||||
+
|
||||
+ dest[i] = (data >> offset) & 0xff;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool __init
|
||||
+ar93xx_wmac_otp_uncompress(void __iomem *base, int addr, int len, u8 *dest,
|
||||
+ int dest_start, int dest_len)
|
||||
+{
|
||||
+ int dest_bytes = 0;
|
||||
+ int offset = 0;
|
||||
+ int end = addr - len;
|
||||
+ u8 hdr[2];
|
||||
+
|
||||
+ while (addr > end) {
|
||||
+ if (!ar93xx_wmac_otp_read(base, addr, hdr, 2))
|
||||
+ return false;
|
||||
+
|
||||
+ addr -= 2;
|
||||
+ offset += hdr[0];
|
||||
+
|
||||
+ if (offset <= dest_start + dest_len &&
|
||||
+ offset + len >= dest_start) {
|
||||
+ int data_offset = 0;
|
||||
+ int dest_offset = 0;
|
||||
+ int copy_len;
|
||||
+
|
||||
+ if (offset < dest_start)
|
||||
+ data_offset = dest_start - offset;
|
||||
+ else
|
||||
+ dest_offset = offset - dest_start;
|
||||
+
|
||||
+ copy_len = len - data_offset;
|
||||
+ if (copy_len > dest_len - dest_offset)
|
||||
+ copy_len = dest_len - dest_offset;
|
||||
+
|
||||
+ ar93xx_wmac_otp_read(base, addr - data_offset,
|
||||
+ dest + dest_offset,
|
||||
+ copy_len);
|
||||
+
|
||||
+ dest_bytes += copy_len;
|
||||
+ }
|
||||
+ addr -= hdr[1];
|
||||
+ }
|
||||
+ return !!dest_bytes;
|
||||
+}
|
||||
+
|
||||
+bool __init ar93xx_wmac_read_mac_address(u8 *dest)
|
||||
+{
|
||||
+ void __iomem *base;
|
||||
+ bool ret = false;
|
||||
+ int addr = 0x1ff;
|
||||
+ unsigned int len;
|
||||
+ u32 hdr_u32;
|
||||
+ u8 *hdr = (u8 *) &hdr_u32;
|
||||
+ u8 mac[6] = { 0x00, 0x02, 0x03, 0x04, 0x05, 0x06 };
|
||||
+ int mac_start = 2, mac_end = 8;
|
||||
+
|
||||
+ BUG_ON(!soc_is_ar933x() && !soc_is_ar934x());
|
||||
+ base = ioremap_nocache(AR933X_WMAC_BASE, AR933X_WMAC_SIZE);
|
||||
+ while (addr > sizeof(hdr)) {
|
||||
+ if (!ar93xx_wmac_otp_read(base, addr, hdr, sizeof(hdr)))
|
||||
+ break;
|
||||
+
|
||||
+ if (hdr_u32 == 0 || hdr_u32 == ~0)
|
||||
+ break;
|
||||
+
|
||||
+ len = (hdr[1] << 4) | (hdr[2] >> 4);
|
||||
+ addr -= 4;
|
||||
+
|
||||
+ switch (hdr[0] >> 5) {
|
||||
+ case 0:
|
||||
+ if (len < mac_end)
|
||||
+ break;
|
||||
+
|
||||
+ ar93xx_wmac_otp_read(base, addr - mac_start, mac, 6);
|
||||
+ ret = true;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ ret |= ar93xx_wmac_otp_uncompress(base, addr, len, mac,
|
||||
+ mac_start, 6);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ addr -= len + 2;
|
||||
+ }
|
||||
+
|
||||
+ iounmap(base);
|
||||
+ if (ret)
|
||||
+ memcpy(dest, mac, 6);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
void __init ath79_register_wmac(u8 *cal_data, u8 *mac_addr)
|
||||
{
|
||||
if (soc_is_ar913x())
|
||||
--- a/arch/mips/ath79/dev-wmac.h
|
||||
+++ b/arch/mips/ath79/dev-wmac.h
|
||||
@@ -13,5 +13,6 @@
|
||||
#define _ATH79_DEV_WMAC_H
|
||||
|
||||
void ath79_register_wmac(u8 *cal_data, u8 *mac_addr);
|
||||
+bool ar93xx_wmac_read_mac_address(u8 *dest);
|
||||
|
||||
#endif /* _ATH79_DEV_WMAC_H */
|
||||
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
|
||||
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
|
||||
@@ -78,6 +78,14 @@
|
||||
#define AR934X_EHCI_BASE 0x1b000000
|
||||
#define AR934X_EHCI_SIZE 0x1000
|
||||
|
||||
+#define AR9300_OTP_BASE 0x14000
|
||||
+#define AR9300_OTP_STATUS 0x15f18
|
||||
+#define AR9300_OTP_STATUS_TYPE 0x7
|
||||
+#define AR9300_OTP_STATUS_VALID 0x4
|
||||
+#define AR9300_OTP_STATUS_ACCESS_BUSY 0x2
|
||||
+#define AR9300_OTP_STATUS_SM_BUSY 0x1
|
||||
+#define AR9300_OTP_READ_DATA 0x15f1c
|
||||
+
|
||||
/*
|
||||
* DDR_CTRL block
|
||||
*/
|
Loading…
Reference in New Issue
Block a user