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

« back to all changes in this revision

Viewing changes to roms/u-boot/arch/powerpc/cpu/mpc824x/drivers/i2c/i2c.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 2003
 
3
 * Gleb Natapov <gnatapov@mrv.com>
 
4
 * Some bits are taken from linux driver writen by adrian@humboldt.co.uk
 
5
 *
 
6
 * Hardware I2C driver for MPC107 PCI bridge.
 
7
 *
 
8
 * SPDX-License-Identifier:     GPL-2.0+
 
9
 */
 
10
 
 
11
#include <common.h>
 
12
 
 
13
#undef I2CDBG
 
14
 
 
15
#ifdef CONFIG_HARD_I2C
 
16
#include <i2c.h>
 
17
 
 
18
#define TIMEOUT (CONFIG_SYS_HZ/4)
 
19
 
 
20
#define I2C_Addr ((unsigned *)(CONFIG_SYS_EUMB_ADDR + 0x3000))
 
21
 
 
22
#define I2CADR &I2C_Addr[0]
 
23
#define I2CFDR  &I2C_Addr[1]
 
24
#define I2CCCR  &I2C_Addr[2]
 
25
#define I2CCSR  &I2C_Addr[3]
 
26
#define I2CCDR  &I2C_Addr[4]
 
27
 
 
28
#define MPC107_CCR_MEN  0x80
 
29
#define MPC107_CCR_MIEN 0x40
 
30
#define MPC107_CCR_MSTA 0x20
 
31
#define MPC107_CCR_MTX  0x10
 
32
#define MPC107_CCR_TXAK 0x08
 
33
#define MPC107_CCR_RSTA 0x04
 
34
 
 
35
#define MPC107_CSR_MCF  0x80
 
36
#define MPC107_CSR_MAAS 0x40
 
37
#define MPC107_CSR_MBB  0x20
 
38
#define MPC107_CSR_MAL  0x10
 
39
#define MPC107_CSR_SRW  0x04
 
40
#define MPC107_CSR_MIF  0x02
 
41
#define MPC107_CSR_RXAK 0x01
 
42
 
 
43
#define I2C_READ  1
 
44
#define I2C_WRITE 0
 
45
 
 
46
/* taken from linux include/asm-ppc/io.h */
 
47
inline unsigned in_le32 (volatile unsigned *addr)
 
48
{
 
49
        unsigned ret;
 
50
 
 
51
        __asm__ __volatile__ ("lwbrx %0,0,%1;\n"
 
52
                              "twi 0,%0,0;\n"
 
53
                              "isync":"=r" (ret): "r" (addr), "m" (*addr));
 
54
        return ret;
 
55
}
 
56
 
 
57
inline void out_le32 (volatile unsigned *addr, int val)
 
58
{
 
59
        __asm__ __volatile__ ("stwbrx %1,0,%2; eieio":"=m" (*addr):"r" (val),
 
60
                              "r" (addr));
 
61
}
 
62
 
 
63
#define writel(val, addr) out_le32(addr, val)
 
64
#define readl(addr) in_le32(addr)
 
65
 
 
66
void i2c_init (int speed, int slaveadd)
 
67
{
 
68
        /* stop I2C controller */
 
69
        writel (0x0, I2CCCR);
 
70
        /* set clock */
 
71
        writel (0x1020, I2CFDR);
 
72
        /* write slave address */
 
73
        writel (slaveadd, I2CADR);
 
74
        /* clear status register */
 
75
        writel (0x0, I2CCSR);
 
76
        /* start I2C controller */
 
77
        writel (MPC107_CCR_MEN, I2CCCR);
 
78
 
 
79
        return;
 
80
}
 
81
 
 
82
static __inline__ int i2c_wait4bus (void)
 
83
{
 
84
        ulong timeval = get_timer (0);
 
85
 
 
86
        while (readl (I2CCSR) & MPC107_CSR_MBB)
 
87
                if (get_timer (timeval) > TIMEOUT)
 
88
                        return -1;
 
89
 
 
90
        return 0;
 
91
}
 
92
 
 
93
static __inline__ int i2c_wait (int write)
 
94
{
 
95
        u32 csr;
 
96
        ulong timeval = get_timer (0);
 
97
 
 
98
        do {
 
99
                csr = readl (I2CCSR);
 
100
 
 
101
                if (!(csr & MPC107_CSR_MIF))
 
102
                        continue;
 
103
 
 
104
                writel (0x0, I2CCSR);
 
105
 
 
106
                if (csr & MPC107_CSR_MAL) {
 
107
#ifdef I2CDBG
 
108
                        printf ("i2c_wait: MAL\n");
 
109
#endif
 
110
                        return -1;
 
111
                }
 
112
 
 
113
                if (!(csr & MPC107_CSR_MCF)) {
 
114
#ifdef I2CDBG
 
115
                        printf ("i2c_wait: unfinished\n");
 
116
#endif
 
117
                        return -1;
 
118
                }
 
119
 
 
120
                if (write == I2C_WRITE && (csr & MPC107_CSR_RXAK)) {
 
121
#ifdef I2CDBG
 
122
                        printf ("i2c_wait: No RXACK\n");
 
123
#endif
 
124
                        return -1;
 
125
                }
 
126
 
 
127
                return 0;
 
128
        } while (get_timer (timeval) < TIMEOUT);
 
129
 
 
130
#ifdef I2CDBG
 
131
        printf ("i2c_wait: timed out\n");
 
132
#endif
 
133
        return -1;
 
134
}
 
135
 
 
136
static __inline__ int i2c_write_addr (u8 dev, u8 dir, int rsta)
 
137
{
 
138
        writel (MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_MTX |
 
139
                (rsta ? MPC107_CCR_RSTA : 0), I2CCCR);
 
140
 
 
141
        writel ((dev << 1) | dir, I2CCDR);
 
142
 
 
143
        if (i2c_wait (I2C_WRITE) < 0)
 
144
                return 0;
 
145
 
 
146
        return 1;
 
147
}
 
148
 
 
149
static __inline__ int __i2c_write (u8 * data, int length)
 
150
{
 
151
        int i;
 
152
 
 
153
        writel (MPC107_CCR_MEN | MPC107_CCR_MSTA | MPC107_CCR_MTX, I2CCCR);
 
154
 
 
155
        for (i = 0; i < length; i++) {
 
156
                writel (data[i], I2CCDR);
 
157
 
 
158
                if (i2c_wait (I2C_WRITE) < 0)
 
159
                        break;
 
160
        }
 
161
 
 
162
        return i;
 
163
}
 
164
 
 
165
static __inline__ int __i2c_read (u8 * data, int length)
 
166
{
 
167
        int i;
 
168
 
 
169
        writel (MPC107_CCR_MEN | MPC107_CCR_MSTA |
 
170
                ((length == 1) ? MPC107_CCR_TXAK : 0), I2CCCR);
 
171
 
 
172
        /* dummy read */
 
173
        readl (I2CCDR);
 
174
 
 
175
        for (i = 0; i < length; i++) {
 
176
                if (i2c_wait (I2C_READ) < 0)
 
177
                        break;
 
178
 
 
179
                /* Generate ack on last next to last byte */
 
180
                if (i == length - 2)
 
181
                        writel (MPC107_CCR_MEN | MPC107_CCR_MSTA |
 
182
                                MPC107_CCR_TXAK, I2CCCR);
 
183
 
 
184
                /* Generate stop on last byte */
 
185
                if (i == length - 1)
 
186
                        writel (MPC107_CCR_MEN | MPC107_CCR_TXAK, I2CCCR);
 
187
 
 
188
                data[i] = readl (I2CCDR);
 
189
        }
 
190
 
 
191
        return i;
 
192
}
 
193
 
 
194
int i2c_read (u8 dev, uint addr, int alen, u8 * data, int length)
 
195
{
 
196
        int i = 0;
 
197
        u8 *a = (u8 *) & addr;
 
198
 
 
199
        if (i2c_wait4bus () < 0)
 
200
                goto exit;
 
201
 
 
202
        if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
 
203
                goto exit;
 
204
 
 
205
        if (__i2c_write (&a[4 - alen], alen) != alen)
 
206
                goto exit;
 
207
 
 
208
        if (i2c_write_addr (dev, I2C_READ, 1) == 0)
 
209
                goto exit;
 
210
 
 
211
        i = __i2c_read (data, length);
 
212
 
 
213
exit:
 
214
        writel (MPC107_CCR_MEN, I2CCCR);
 
215
 
 
216
        return !(i == length);
 
217
}
 
218
 
 
219
int i2c_write (u8 dev, uint addr, int alen, u8 * data, int length)
 
220
{
 
221
        int i = 0;
 
222
        u8 *a = (u8 *) & addr;
 
223
 
 
224
        if (i2c_wait4bus () < 0)
 
225
                goto exit;
 
226
 
 
227
        if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
 
228
                goto exit;
 
229
 
 
230
        if (__i2c_write (&a[4 - alen], alen) != alen)
 
231
                goto exit;
 
232
 
 
233
        i = __i2c_write (data, length);
 
234
 
 
235
exit:
 
236
        writel (MPC107_CCR_MEN, I2CCCR);
 
237
 
 
238
        return !(i == length);
 
239
}
 
240
 
 
241
int i2c_probe (uchar chip)
 
242
{
 
243
        int tmp;
 
244
 
 
245
        /*
 
246
         * Try to read the first location of the chip.  The underlying
 
247
         * driver doesn't appear to support sending just the chip address
 
248
         * and looking for an <ACK> back.
 
249
         */
 
250
        udelay (10000);
 
251
        return i2c_read (chip, 0, 1, (uchar *) &tmp, 1);
 
252
}
 
253
 
 
254
#endif /* CONFIG_HARD_I2C */