rockchip: kernel add efuse support

Signed-off-by: 陈亮 <cl@rock-chips.com>
This commit is contained in:
陈亮
2014-07-28 04:51:31 -07:00
parent d38e801e1d
commit 1304b6022d
3 changed files with 161 additions and 0 deletions

View File

@@ -3,6 +3,7 @@ obj-y += cpu.o
obj-y += rk3188.o
obj-y += rk3288.o
obj-y += ddr_freq.o
obj-y += efuse.o
obj-y += rk_system_status.o
obj-$(CONFIG_PM) += rockchip_pm.o sleep.o
obj-$(CONFIG_RK_FPGA) += fpga.o

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2013 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
* published by the Free Software Foundation.
*/
#include <linux/delay.h>
#include <linux/spinlock.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 int 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);
efuse_writel(EFUSE_CSB, REG_EFUSE_CTRL);
efuse_writel(EFUSE_LOAD | EFUSE_PGENB, REG_EFUSE_CTRL);
udelay(2);
do {
efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
(~(EFUSE_A_MASK << EFUSE_A_SHIFT)), REG_EFUSE_CTRL);
efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
((addr & EFUSE_A_MASK) << EFUSE_A_SHIFT),
REG_EFUSE_CTRL);
udelay(2);
efuse_writel(efuse_readl(REG_EFUSE_CTRL) |
EFUSE_STROBE, REG_EFUSE_CTRL);
udelay(2);
*buf = efuse_readl(REG_EFUSE_DOUT);
efuse_writel(efuse_readl(REG_EFUSE_CTRL) &
(~EFUSE_STROBE), REG_EFUSE_CTRL);
udelay(2);
buf++;
addr++;
} while (--length);
udelay(2);
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)
{
int ret = efuse_buf[4] & (~(0x1 << 3));
return ret;
}
int rockchip_get_leakage(int ch)
{
if ((ch < 0) || (ch > 2))
return 0;
return efuse_buf[23+ch];
}
static int efuse_init(void)
{
efuse_readregs(0, 32, efuse_buf);
return 0;
}
core_initcall(efuse_init);

View File

@@ -0,0 +1,25 @@
#ifndef _EFUSE_H_
#define _EFUSE_H_
#include <asm/types.h>
/* eFuse controller register */
#define EFUSE_A_SHIFT (6)
#define EFUSE_A_MASK (0x3FF)
//#define EFUSE_PD (1 << 5)
//#define EFUSE_PS (1 << 4)
#define EFUSE_PGENB (1 << 3) //active low
#define EFUSE_LOAD (1 << 2)
#define EFUSE_STROBE (1 << 1)
#define EFUSE_CSB (1 << 0) //active low
#define REG_EFUSE_CTRL (0x0000)
#define REG_EFUSE_DOUT (0x0004)
#define ARM_LEAKAGE_CH 0
#define GPU_LEAKAGE_CH 1
#define LOG_LEAKAGE_CH 2
int rockchip_efuse_version(void);
int rockchip_get_leakage(int ch);
#endif