mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
rockchip: kernel add efuse support
Signed-off-by: 陈亮 <cl@rock-chips.com>
This commit is contained in:
@@ -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
|
||||
|
||||
135
arch/arm/mach-rockchip/efuse.c
Normal file
135
arch/arm/mach-rockchip/efuse.c
Normal 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);
|
||||
25
arch/arm/mach-rockchip/efuse.h
Normal file
25
arch/arm/mach-rockchip/efuse.h
Normal 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
|
||||
Reference in New Issue
Block a user