ARM: rockchip: rk3288 better support eFuse init
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-rockchip / efuse.c
index 89d3d6cb7708b91ed429ad762241e7148d308693..18eeaa423a07970737d0d27eb13d7a5e79ccc878 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 ROCKCHIP, Inc.
+ * Copyright (C) 2013-2014 ROCKCHIP, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -7,29 +7,30 @@
  */
 
 #include <linux/delay.h>
-#include <linux/spinlock.h>
+#include <linux/rockchip/cpu.h>
 #include <linux/rockchip/iomap.h>
-#include <linux/kobject.h>
 #include "efuse.h"
 
 #define efuse_readl(offset) readl_relaxed(RK_EFUSE_VIRT + offset)
 #define efuse_writel(val, offset) writel_relaxed(val, RK_EFUSE_VIRT + offset)
 
-static u8 efuse_buf[32 + 1] = {0, 0};
+static u8 efuse_buf[32] = {};
 
-static int efuse_readregs(u32 addr, u32 length, u8 *buf)
+struct rockchip_efuse {
+       int (*get_leakage)(int ch);
+       int efuse_version;
+};
+
+static struct rockchip_efuse efuse;
+
+static int __init rk3288_efuse_readregs(u32 addr, u32 length, u8 *buf)
 {
-#ifndef efuse_readl
-       return 0;
-#else
-       unsigned long flags;
-       static DEFINE_SPINLOCK(efuse_lock);
        int ret = length;
 
        if (!length)
                return 0;
-
-       spin_lock_irqsave(&efuse_lock, flags);
+       if (!buf)
+               return 0;
 
        efuse_writel(EFUSE_CSB, REG_EFUSE_CTRL);
        efuse_writel(EFUSE_LOAD | EFUSE_PGENB, REG_EFUSE_CTRL);
@@ -55,69 +56,16 @@ static int efuse_readregs(u32 addr, u32 length, u8 *buf)
        efuse_writel(efuse_readl(REG_EFUSE_CTRL) | EFUSE_CSB, REG_EFUSE_CTRL);
        udelay(1);
 
-       spin_unlock_irqrestore(&efuse_lock, flags);
        return ret;
-#endif
 }
 
-/*
-static int efuse_writeregs(u32 addr, u32 length, u8 *buf)
-{
-       u32 j=0;
-       unsigned long flags;
-       static DEFINE_SPINLOCK(efuse_lock);
-       spin_lock_irqsave(&efuse_lock, flags);
-
-       efuse_writel(EFUSE_CSB|EFUSE_LOAD|EFUSE_PGENB,REG_EFUSE_CTRL);
-       udelay(10);
-       efuse_writel((~EFUSE_PGENB)&(efuse_readl(REG_EFUSE_CTRL)),
-               REG_EFUSE_CTRL);
-       udelay(10);
-       efuse_writel((~(EFUSE_LOAD | EFUSE_CSB))&(efuse_readl(REG_EFUSE_CTRL)),
-               REG_EFUSE_CTRL);
-       udelay(1);
-
-       do {
-               for(j=0; j<8; j++){
-                       if(*buf & (1<<j)){
-                               efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
-                                       (~(EFUSE_A_MASK << EFUSE_A_SHIFT)),
-                                       REG_EFUSE_CTRL);
-                               efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
-                                       (((addr + (j<<5))&EFUSE_A_MASK) << EFUSE_A_SHIFT),
-                                       REG_EFUSE_CTRL);
-                               udelay(1);
-                               efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
-                               EFUSE_STROBE, REG_EFUSE_CTRL);
-                               udelay(10);
-                               efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
-                               (~EFUSE_STROBE), REG_EFUSE_CTRL);
-                               udelay(1);
-                       }
-               }
-               buf++;
-               addr++;
-       } while (--length);
-
-       udelay(1);
-       efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
-               EFUSE_CSB | EFUSE_LOAD, REG_EFUSE_CTRL);
-       udelay(1);
-       efuse_writel(efuse_readl(REG_EFUSE_CTRL)|EFUSE_PGENB, REG_EFUSE_CTRL);
-       udelay(1);
-
-       spin_unlock_irqrestore(&efuse_lock, flags);
-       return 0;
-}
-*/
-
-int rockchip_efuse_version(void)
+static int __init rk3288_get_efuse_version(void)
 {
        int ret = efuse_buf[4] & (~(0x1 << 3));
        return ret;
 }
 
-int rockchip_get_leakage(int ch)
+static int rk3288_get_leakage(int ch)
 {
        if ((ch < 0) || (ch > 2))
                return 0;
@@ -125,11 +73,30 @@ int rockchip_get_leakage(int ch)
        return efuse_buf[23+ch];
 }
 
-static int efuse_init(void)
+int rockchip_efuse_version(void)
 {
-       efuse_readregs(0, 32, efuse_buf);
+       return efuse.efuse_version;
+}
 
+int rockchip_get_leakage(int ch)
+{
+       if (efuse.get_leakage)
+               return efuse.get_leakage(ch);
        return 0;
 }
 
-core_initcall(efuse_init);
+void __init rockchip_efuse_init(void)
+{
+       int ret;
+
+       if (cpu_is_rk3288()) {
+               ret = rk3288_efuse_readregs(0, 32, efuse_buf);
+               if (ret == 32) {
+                       efuse.get_leakage = rk3288_get_leakage;
+                       efuse.efuse_version = rk3288_get_efuse_version();
+                       rockchip_set_cpu_version((efuse_buf[6] >> 4) & 3);
+               } else {
+                       pr_err("failed to read eFuse, return %d\n", ret);
+               }
+       }
+}