2 * Copyright (C) 2014 Spreadtrum Communications Inc.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
21 #include <linux/types.h>
22 #include <linux/err.h>
24 //#include <asm/arch/hardware.h>
25 #include <asm/arch/sprd_reg.h>
26 #include <asm/arch/sci.h>
27 #include <asm/arch/adi.h>
28 #include <asm/arch/__regs_efuse.h>
29 #include <asm/arch/__regs_ana_efuse.h>
31 #define pr_debug(args...) printf(args)
34 u32 SCI_GetTickCount(void);
35 #define jiffies (SCI_GetTickCount()) /* return msec count */
36 #define msecs_to_jiffies(a) (a)
37 #define time_after(a,b) ((int)(b) - (int)(a) < 0)
40 #define SPRD_ADISLAVE_BASE (SPRD_ADI_PHYS + 0x8000)
42 #define ANA_REGS_EFUSE_BASE ( SPRD_ADISLAVE_BASE + 0x200 )
44 #define EFUSE_BLOCK_MAX ( 32 )
45 #define EFUSE_BLOCK_WIDTH ( 8 ) /* bit counts */
47 static u8 dummy_cached_otp[EFUSE_BLOCK_MAX] = {
48 0x9f, 0xdf, 0xef, 0x37, 0x91, 0x27, 0xfc, 0xfd,
49 0x7f, 0x7f, 0x7f, 0x7f, 0xff, 0xfe, 0x7d, 0xbf,
50 0x7f, 0xff, 0x6c, 0x00, 0xe7, 0x71, 0x5f, 0xb7,
51 0x81, 0x5b, 0xe7, 0x3c, 0xa1, 0x27, 0x8a, 0xa1,
54 void adie_efuse_workaround(void)
56 #define REG_ADI_GSSI_CFG0 (SPRD_ADI_PHYS + 0x1C)
57 /** BIT_RF_GSSI_SCK_ALL_IN
61 #define BIT_RF_GSSI_SCK_ALL_IN BIT(30)
62 sci_glb_write(REG_ADI_GSSI_CFG0,
63 BIT_RF_GSSI_SCK_ALL_IN, BIT_RF_GSSI_SCK_ALL_IN);
66 void adie_efuse_lookat(void)
68 volatile u32 *reg = (volatile u32 *)ANA_REGS_EFUSE_BASE;
71 printf("[%p] = %08x\n", reg, sci_adi_read((u32) reg));
77 static void adie_efuse_lock(void)
81 static void adie_efuse_unlock(void)
85 static void adie_efuse_reset(void)
89 static void __adie_efuse_power_on(void)
91 sci_adi_set(ANA_REG_GLB_ARM_MODULE_EN, BIT_ANA_EFS_EN);
92 /* FIXME: rtc_efs only for prog
93 sci_adi_set(ANA_REG_GLB_RTC_CLK_EN, BIT_RTC_EFS_EN);
96 /* FIXME: sclk always on or not ? */
97 /* adie_efuse_workaround(); */
100 static void __adie_efuse_power_off(void)
102 /* FIXME: rtc_efs only for prog
103 sci_adi_clr(ANA_REG_GLB_RTC_CLK_EN, BIT_RTC_EFS_EN);
105 sci_adi_clr(ANA_REG_GLB_ARM_MODULE_EN, BIT_ANA_EFS_EN);
108 static __inline int __adie_efuse_wait_clear(u32 bits)
111 unsigned long timeout;
113 pr_debug("wait %x\n", sci_adi_read(ANA_REG_EFUSE_STATUS));
115 /* wait for maximum of 3000 msec */
116 timeout = jiffies + msecs_to_jiffies(3000);
117 while (sci_adi_read(ANA_REG_EFUSE_STATUS) & bits) {
118 if (time_after(jiffies, timeout)) {
128 static u32 adie_efuse_read(int blk_index)
132 pr_debug("adie efuse read %d\n", blk_index);
134 __adie_efuse_power_on();
135 /* enable adie_efuse module clk and power before */
137 /* adie_efuse_lookat(); */
139 /* FIXME: set read timing, why 0x20 (default value)
140 sci_adi_raw_write(ANA_REG_EFUSE_RD_TIMING_CTRL,
141 BITS_EFUSE_RD_TIMING(0x20));
144 sci_adi_raw_write(ANA_REG_EFUSE_BLOCK_INDEX,
145 BITS_READ_WRITE_INDEX(blk_index));
146 sci_adi_raw_write(ANA_REG_EFUSE_MODE_CTRL, BIT_RD_START);
148 if (IS_ERR_VALUE(__adie_efuse_wait_clear(BIT_READ_BUSY)))
151 val = sci_adi_read(ANA_REG_EFUSE_DATA_RD);
153 /* FIXME: reverse the otp value */
154 val = BITS_EFUSE_DATA_RD(~val);
157 __adie_efuse_power_off();
162 u32 __adie_efuse_read(int blk_index)
164 return adie_efuse_read(blk_index);
167 //EXPORT_SYMBOL_GPL(__adie_efuse_read);
169 u32 __adie_efuse_read_bits(int bit_index, int length)
171 int i, blk_index = (int)bit_index / EFUSE_BLOCK_WIDTH;
172 int blk_max = DIV_ROUND_UP(bit_index + length, EFUSE_BLOCK_WIDTH);
174 pr_debug("otp read blk %d - %d\n", blk_index, blk_max);
175 /* FIXME: length should not bigger than 8 */
176 for (i = blk_index; i < blk_max; i++) {
177 val |= __adie_efuse_read(i)
178 << ((i - blk_index) * EFUSE_BLOCK_WIDTH);
180 //pr_debug("val=%08x\n", val);
181 val >>= (bit_index & (EFUSE_BLOCK_WIDTH - 1));
182 val &= BIT(length) - 1;
183 pr_debug("otp read bits %d ++ %d 0x%08x\n\n", bit_index, length, val);
187 void __adie_efuse_block_dump(void)
190 printf("adie efuse blocks dump:\n");
191 printf("-- 7 6 5 4 3 2 1 0");
192 for (idx = 0; idx < EFUSE_BLOCK_MAX; idx++) {
195 val = __adie_efuse_read(idx);
196 dummy_cached_otp[idx] = (u8) val;
197 printf("%02d ", idx);
198 for (i = EFUSE_BLOCK_WIDTH - 1; i >= 0; --i)
199 printf("%s ", (val & BIT(i)) ? "1" : "0");