~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/drivers/misc/fsl_iim.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (C) Copyright 2009-2013 ADVANSEE
 
3
 * Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
 
4
 *
 
5
 * Based on the mpc512x iim code:
 
6
 * Copyright 2008 Silicon Turnkey Express, Inc.
 
7
 * Martha Marx <mmarx@silicontkx.com>
 
8
 *
 
9
 * SPDX-License-Identifier:     GPL-2.0+
 
10
 */
 
11
 
 
12
#include <common.h>
 
13
#include <fuse.h>
 
14
#include <asm/errno.h>
 
15
#include <asm/io.h>
 
16
#ifndef CONFIG_MPC512X
 
17
#include <asm/arch/imx-regs.h>
 
18
#endif
 
19
#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
 
20
#include <asm/arch/clock.h>
 
21
#endif
 
22
 
 
23
/* FSL IIM-specific constants */
 
24
#define STAT_BUSY               0x80
 
25
#define STAT_PRGD               0x02
 
26
#define STAT_SNSD               0x01
 
27
 
 
28
#define STATM_PRGD_M            0x02
 
29
#define STATM_SNSD_M            0x01
 
30
 
 
31
#define ERR_PRGE                0x80
 
32
#define ERR_WPE                 0x40
 
33
#define ERR_OPE                 0x20
 
34
#define ERR_RPE                 0x10
 
35
#define ERR_WLRE                0x08
 
36
#define ERR_SNSE                0x04
 
37
#define ERR_PARITYE             0x02
 
38
 
 
39
#define EMASK_PRGE_M            0x80
 
40
#define EMASK_WPE_M             0x40
 
41
#define EMASK_OPE_M             0x20
 
42
#define EMASK_RPE_M             0x10
 
43
#define EMASK_WLRE_M            0x08
 
44
#define EMASK_SNSE_M            0x04
 
45
#define EMASK_PARITYE_M         0x02
 
46
 
 
47
#define FCTL_DPC                0x80
 
48
#define FCTL_PRG_LENGTH_MASK    0x70
 
49
#define FCTL_ESNS_N             0x08
 
50
#define FCTL_ESNS_0             0x04
 
51
#define FCTL_ESNS_1             0x02
 
52
#define FCTL_PRG                0x01
 
53
 
 
54
#define UA_A_BANK_MASK          0x38
 
55
#define UA_A_ROWH_MASK          0x07
 
56
 
 
57
#define LA_A_ROWL_MASK          0xf8
 
58
#define LA_A_BIT_MASK           0x07
 
59
 
 
60
#define PREV_PROD_REV_MASK      0xf8
 
61
#define PREV_PROD_VT_MASK       0x07
 
62
 
 
63
/* Select the correct accessors depending on endianness */
 
64
#if __BYTE_ORDER == __LITTLE_ENDIAN
 
65
#define iim_read32              in_le32
 
66
#define iim_write32             out_le32
 
67
#define iim_clrsetbits32        clrsetbits_le32
 
68
#define iim_clrbits32           clrbits_le32
 
69
#define iim_setbits32           setbits_le32
 
70
#elif __BYTE_ORDER == __BIG_ENDIAN
 
71
#define iim_read32              in_be32
 
72
#define iim_write32             out_be32
 
73
#define iim_clrsetbits32        clrsetbits_be32
 
74
#define iim_clrbits32           clrbits_be32
 
75
#define iim_setbits32           setbits_be32
 
76
#else
 
77
#error Endianess is not defined: please fix to continue
 
78
#endif
 
79
 
 
80
/* IIM control registers */
 
81
struct fsl_iim {
 
82
        u32 stat;
 
83
        u32 statm;
 
84
        u32 err;
 
85
        u32 emask;
 
86
        u32 fctl;
 
87
        u32 ua;
 
88
        u32 la;
 
89
        u32 sdat;
 
90
        u32 prev;
 
91
        u32 srev;
 
92
        u32 prg_p;
 
93
        u32 scs[0x1f5];
 
94
        struct {
 
95
                u32 word[0x100];
 
96
        } bank[8];
 
97
};
 
98
 
 
99
#if !defined(CONFIG_MX51) && !defined(CONFIG_MX53)
 
100
#define enable_efuse_prog_supply(enable)
 
101
#endif
 
102
 
 
103
static int prepare_access(struct fsl_iim **regs, u32 bank, u32 word, int assert,
 
104
                                const char *caller)
 
105
{
 
106
        *regs = (struct fsl_iim *)IIM_BASE_ADDR;
 
107
 
 
108
        if (bank >= ARRAY_SIZE((*regs)->bank) ||
 
109
                        word >= ARRAY_SIZE((*regs)->bank[0].word) ||
 
110
                        !assert) {
 
111
                printf("fsl_iim %s(): Invalid argument\n", caller);
 
112
                return -EINVAL;
 
113
        }
 
114
 
 
115
        return 0;
 
116
}
 
117
 
 
118
static void clear_status(struct fsl_iim *regs)
 
119
{
 
120
        iim_setbits32(&regs->stat, 0);
 
121
        iim_setbits32(&regs->err, 0);
 
122
}
 
123
 
 
124
static void finish_access(struct fsl_iim *regs, u32 *stat, u32 *err)
 
125
{
 
126
        *stat = iim_read32(&regs->stat);
 
127
        *err = iim_read32(&regs->err);
 
128
        clear_status(regs);
 
129
}
 
130
 
 
131
static int prepare_read(struct fsl_iim **regs, u32 bank, u32 word, u32 *val,
 
132
                        const char *caller)
 
133
{
 
134
        int ret;
 
135
 
 
136
        ret = prepare_access(regs, bank, word, val != NULL, caller);
 
137
        if (ret)
 
138
                return ret;
 
139
 
 
140
        clear_status(*regs);
 
141
 
 
142
        return 0;
 
143
}
 
144
 
 
145
int fuse_read(u32 bank, u32 word, u32 *val)
 
146
{
 
147
        struct fsl_iim *regs;
 
148
        u32 stat, err;
 
149
        int ret;
 
150
 
 
151
        ret = prepare_read(&regs, bank, word, val, __func__);
 
152
        if (ret)
 
153
                return ret;
 
154
 
 
155
        *val = iim_read32(&regs->bank[bank].word[word]);
 
156
        finish_access(regs, &stat, &err);
 
157
 
 
158
        if (err & ERR_RPE) {
 
159
                puts("fsl_iim fuse_read(): Read protect error\n");
 
160
                return -EIO;
 
161
        }
 
162
 
 
163
        return 0;
 
164
}
 
165
 
 
166
static void direct_access(struct fsl_iim *regs, u32 bank, u32 word, u32 bit,
 
167
                                u32 fctl, u32 *stat, u32 *err)
 
168
{
 
169
        iim_write32(&regs->ua, bank << 3 | word >> 5);
 
170
        iim_write32(&regs->la, (word << 3 | bit) & 0xff);
 
171
        if (fctl == FCTL_PRG)
 
172
                iim_write32(&regs->prg_p, 0xaa);
 
173
        iim_setbits32(&regs->fctl, fctl);
 
174
        while (iim_read32(&regs->stat) & STAT_BUSY)
 
175
                udelay(20);
 
176
        finish_access(regs, stat, err);
 
177
}
 
178
 
 
179
int fuse_sense(u32 bank, u32 word, u32 *val)
 
180
{
 
181
        struct fsl_iim *regs;
 
182
        u32 stat, err;
 
183
        int ret;
 
184
 
 
185
        ret = prepare_read(&regs, bank, word, val, __func__);
 
186
        if (ret)
 
187
                return ret;
 
188
 
 
189
        direct_access(regs, bank, word, 0, FCTL_ESNS_N, &stat, &err);
 
190
 
 
191
        if (err & ERR_SNSE) {
 
192
                puts("fsl_iim fuse_sense(): Explicit sense cycle error\n");
 
193
                return -EIO;
 
194
        }
 
195
 
 
196
        if (!(stat & STAT_SNSD)) {
 
197
                puts("fsl_iim fuse_sense(): Explicit sense cycle did not complete\n");
 
198
                return -EIO;
 
199
        }
 
200
 
 
201
        *val = iim_read32(&regs->sdat);
 
202
        return 0;
 
203
}
 
204
 
 
205
static int prog_bit(struct fsl_iim *regs, u32 bank, u32 word, u32 bit)
 
206
{
 
207
        u32 stat, err;
 
208
 
 
209
        clear_status(regs);
 
210
        direct_access(regs, bank, word, bit, FCTL_PRG, &stat, &err);
 
211
        iim_write32(&regs->prg_p, 0x00);
 
212
 
 
213
        if (err & ERR_PRGE) {
 
214
                puts("fsl_iim fuse_prog(): Program error\n");
 
215
                return -EIO;
 
216
        }
 
217
 
 
218
        if (err & ERR_WPE) {
 
219
                puts("fsl_iim fuse_prog(): Write protect error\n");
 
220
                return -EIO;
 
221
        }
 
222
 
 
223
        if (!(stat & STAT_PRGD)) {
 
224
                puts("fsl_iim fuse_prog(): Program did not complete\n");
 
225
                return -EIO;
 
226
        }
 
227
 
 
228
        return 0;
 
229
}
 
230
 
 
231
static int prepare_write(struct fsl_iim **regs, u32 bank, u32 word, u32 val,
 
232
                                const char *caller)
 
233
{
 
234
        return prepare_access(regs, bank, word, !(val & ~0xff), caller);
 
235
}
 
236
 
 
237
int fuse_prog(u32 bank, u32 word, u32 val)
 
238
{
 
239
        struct fsl_iim *regs;
 
240
        u32 bit;
 
241
        int ret;
 
242
 
 
243
        ret = prepare_write(&regs, bank, word, val, __func__);
 
244
        if (ret)
 
245
                return ret;
 
246
 
 
247
        enable_efuse_prog_supply(1);
 
248
        for (bit = 0; val; bit++, val >>= 1)
 
249
                if (val & 0x01) {
 
250
                        ret = prog_bit(regs, bank, word, bit);
 
251
                        if (ret) {
 
252
                                enable_efuse_prog_supply(0);
 
253
                                return ret;
 
254
                        }
 
255
                }
 
256
        enable_efuse_prog_supply(0);
 
257
 
 
258
        return 0;
 
259
}
 
260
 
 
261
int fuse_override(u32 bank, u32 word, u32 val)
 
262
{
 
263
        struct fsl_iim *regs;
 
264
        u32 stat, err;
 
265
        int ret;
 
266
 
 
267
        ret = prepare_write(&regs, bank, word, val, __func__);
 
268
        if (ret)
 
269
                return ret;
 
270
 
 
271
        clear_status(regs);
 
272
        iim_write32(&regs->bank[bank].word[word], val);
 
273
        finish_access(regs, &stat, &err);
 
274
 
 
275
        if (err & ERR_OPE) {
 
276
                puts("fsl_iim fuse_override(): Override protect error\n");
 
277
                return -EIO;
 
278
        }
 
279
 
 
280
        return 0;
 
281
}