]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - sys/mips/rmi/xlr_i2c.c
Copy stable/8 to releng/8.2 in preparation for FreeBSD-8.2 release.
[FreeBSD/releng/8.2.git] / sys / mips / rmi / xlr_i2c.c
1 /*-
2  * Copyright (c) 2003-2009 RMI Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of RMI Corporation, nor the names of its contributors,
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * RMI_BSD */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 /*
35  * I2C driver for the Palm-BK3220 I2C Host adapter on the RMI XLR.
36  */
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/module.h>
42 #include <sys/bus.h>
43 #include <sys/rman.h>
44
45
46 #include <dev/iicbus/iiconf.h>
47 #include <dev/iicbus/iicbus.h>
48
49 #include <mips/rmi/iomap.h>
50 #include <mips/include/resource.h>
51
52 #include "iicbus_if.h"
53
54 #define DEVTOIICBUS(dev) ((struct iicbus_device*)device_get_ivars(dev))
55
56 #define I2C_PALM_CFG            0x00
57 #define I2C_PALM_CLKDIV         0x01
58 #define I2C_PALM_DEVADDR        0x02
59 #define I2C_PALM_ADDR           0x03
60 #define I2C_PALM_DATAOUT        0x04
61 #define I2C_PALM_DATAIN         0x05
62 #define I2C_PALM_STATUS         0x06
63 #define I2C_PALM_STARTXFR       0x07
64 #define I2C_PALM_BYTECNT        0x08
65 #define I2C_PALM_HDSTATIM       0x09
66
67 /* TEST Values!! Change as required */
68 #define I2C_PALM_CFG_DEF        0x000000F8      /* 8-Bit Addr + POR Values */
69 #define I2C_PALM_CLKDIV_DEF     0x14A //0x00000052
70 #define I2C_PALM_HDSTATIM_DEF       0x107 //0x00000000
71
72 #define I2C_PALM_STARTXFR_RD        0x00000001
73 #define I2C_PALM_STARTXFR_WR        0x00000000
74
75
76 #define PHOENIX_IO_I2C_0_OFFSET           0x16000
77 #define PHOENIX_IO_I2C_1_OFFSET           0x17000
78
79 #define ARIZONA_I2c_BUS 1
80
81 int bus = 1;
82
83
84 uint8_t current_slave;
85 uint8_t read_address;
86 static xlr_reg_t *iobase_i2c_regs;
87
88 static devclass_t xlr_i2c_devclass;
89
90 /*
91  * Device methods
92  */
93 static int xlr_i2c_probe(device_t);
94 static int xlr_i2c_attach(device_t);
95 static int xlr_i2c_detach(device_t);
96
97 static int xlr_i2c_start(device_t dev, u_char slave, int timeout);
98 static int xlr_i2c_stop(device_t dev);
99 static int xlr_i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay);
100 static int xlr_i2c_write(device_t dev, char *buf, int len, int *sent, int timeout);
101
102
103 struct xlr_i2c_softc {
104         device_t dev;           /* Myself */
105         struct resource *mem_res;       /* Memory resource */
106         volatile int flags;
107 #define RXRDY       4
108 #define TXRDY       0x10
109         int sc_started;
110         int twi_addr;
111         device_t iicbus;
112 };
113
114
115 #define MDELAY(a){ \
116     unsigned long  local_loop = 0xfffff; \
117     while(local_loop--); \
118 }\
119
120 static void 
121 get_i2c_base(void)
122 {
123         if (bus == 0)
124                 iobase_i2c_regs = xlr_io_mmio(PHOENIX_IO_I2C_0_OFFSET);
125         else
126                 iobase_i2c_regs = xlr_io_mmio(PHOENIX_IO_I2C_1_OFFSET);
127         return;
128 }
129
130 static void 
131 palm_write(int reg, int value)
132 {
133         get_i2c_base();
134         xlr_write_reg(iobase_i2c_regs, reg, value);
135         return;
136 }
137
138
139 static int 
140 palm_read(int reg)
141 {
142         uint32_t val;
143
144         get_i2c_base();
145         val = xlr_read_reg(iobase_i2c_regs, reg);
146         return ((int)val);
147 }
148
149 static int 
150 palm_addr_only(uint8_t addr, uint8_t offset)
151 {
152         volatile uint32_t regVal = 0x00;
153
154         palm_write(I2C_PALM_ADDR, offset);
155         palm_write(I2C_PALM_DEVADDR, addr);
156         palm_write(I2C_PALM_CFG, 0xfa);
157         palm_write(I2C_PALM_STARTXFR, 0x02);
158         regVal = palm_read(I2C_PALM_STATUS);
159         if (regVal & 0x0008) {
160                 printf("palm_addr_only: ACKERR. Aborting...\n");
161                 return -1;
162         }
163         return 0;
164 }
165
166
167 static int 
168 palm_rx(uint8_t addr, uint8_t offset, uint8_t len,
169     uint8_t * buf)
170 {
171         volatile uint32_t regVal = 0x00, ctr = 0x00;
172         int timeOut, numBytes = 0x00;
173
174         palm_write(I2C_PALM_CFG, 0xfa);
175         palm_write(I2C_PALM_BYTECNT, len);
176         palm_write(I2C_PALM_DEVADDR, addr);
177         //DEVADDR = 0x4c, 0x68
178             MDELAY(1);
179
180         for (numBytes = 0x00; numBytes < len; numBytes++) {
181                 palm_write(I2C_PALM_ADDR, offset + numBytes);
182 //I2C_PALM_ADDR:offset
183                     MDELAY(1);
184                 if (!ctr) {
185                         /* Trigger a READ Transaction */
186                         palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_RD);
187                         ctr++;
188                 }
189                 /* Error Conditions [Begin] */
190                 regVal = palm_read(I2C_PALM_STATUS);
191                 MDELAY(1);
192                 if (regVal & 0x0008) {
193                         printf("palm_rx: ACKERR. Aborting...\n");
194                         return -1;
195                 }
196                 timeOut = 10;
197                 while ((regVal & 0x0030) && timeOut--) {
198                         palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_RD);
199                         regVal = palm_read(I2C_PALM_STATUS);
200                 }
201                 if (timeOut == 0x00) {
202                         printf("palm_rx: TimedOut on Valid STARTXFR/Arbitration\n");
203                         return -1;
204                 }
205                 timeOut = 10;
206                 /* Do we have valid data from the device yet..? */
207                 regVal &= 0x0004;
208                 while (!regVal && timeOut--) {
209                         regVal = palm_read(I2C_PALM_STATUS) & 0x0004;
210                 }
211                 if (timeOut == 0x00) {
212                         printf("palm_rx: TimedOut Waiting for Valid Data\n");
213                         return -1;
214                 }
215                 /* Error Conditions [End] */
216                 /* Read the data */
217                 buf[numBytes] = (uint8_t) palm_read(I2C_PALM_DATAIN);
218         }
219         return 0;
220 }
221
222
223
224 static int 
225 wait_for_idle(void)
226 {
227         int timeOut = 0x1000;
228         volatile uint32_t regVal = 0x00;
229
230         regVal = palm_read(I2C_PALM_STATUS) & 0x0001;
231         while (regVal && timeOut--) {
232                 regVal = palm_read(I2C_PALM_STATUS) & 0x0001;
233         }
234         if (timeOut == 0x00)
235                 return -1;      /* Timed Out */
236         else
237                 return 0;
238 }
239
240
241 static int 
242 palm_tx(uint8_t addr, uint8_t offset, uint8_t * buf, uint8_t len)
243 {
244         volatile uint32_t regVal = 0x00;
245         int timeOut, ctr = 0x00, numBytes = len;
246
247         for (ctr = 0x00; ctr < len; ctr++) {
248                 if (wait_for_idle() < 0) {
249                         printf("TimedOut on Waiting for I2C Bus Idle.\n");
250                         return -EIO;
251                 }
252                 palm_write(I2C_PALM_CFG, 0xF8);
253                 palm_write(I2C_PALM_BYTECNT, 0x00);
254                 palm_write(I2C_PALM_DEVADDR, addr);
255                 //0x4c, 0x68
256                     palm_write(I2C_PALM_ADDR, offset + numBytes - 1);
257                 //offset
258                     palm_write(I2C_PALM_DATAOUT, buf[ctr]);
259                 palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_WR);
260                 MDELAY(1);
261
262                 regVal = palm_read(I2C_PALM_STATUS);
263                 MDELAY(1);
264                 if (regVal & 0x0008) {
265                         printf("palm_tx: ACKERR. Aborting...\n");
266                         return -1;
267                 }
268                 timeOut = 0x1000;
269                 while (!(regVal & 0x0002) && timeOut) {
270                         regVal = palm_read(I2C_PALM_STATUS);
271                         timeOut--;
272                 }
273                 if (timeOut == 0x00) {
274                         printf("palm_tx: [TimeOut] SDOEMPTY Not Set\n");
275                         return -1;
276                 }
277                 timeOut = 1000;
278                 while ((regVal & 0x0030) && timeOut) {
279                         palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_WR);
280                         regVal = palm_read(I2C_PALM_STATUS);
281                         timeOut--;
282                 }
283                 if (timeOut == 0x00) {
284                         printf("palm_rx: TimedOut on Valid STARTXFR/Arbitration\n");
285                         return -1;
286                 }
287                 numBytes--;
288         }
289         return 0;
290 }
291
292
293
294
295
296 static int
297 xlr_i2c_probe(device_t dev)
298 {
299         device_set_desc(dev, "I2C bus controller");
300
301         return (0);
302 }
303
304
305 /*
306  * We add all the devices which we know about.
307  * The generic attach routine will attach them if they are alive.
308  */
309 static int
310 xlr_i2c_attach(device_t dev)
311 {
312         struct xlr_i2c_softc *sc;
313         int rid;
314
315         sc = device_get_softc(dev);
316         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
317             RF_ACTIVE);
318         if (sc->mem_res == NULL) {
319                 printf("not able to allocate the bus resource\n");
320         }
321         if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL)
322                 printf("could not allocate iicbus instance\n");
323
324         bus_generic_attach(dev);
325
326         return (0);
327 }
328
329 static int
330 xlr_i2c_detach(device_t dev)
331 {
332         bus_generic_detach(dev);
333
334         return (0);
335 }
336
337 /*
338 static int
339 xlr_i2c_add_child(device_t dev, int order, const char *name, int unit)
340 {
341     printf("********* %s ********  \n", __FUNCTION__);
342         device_add_child_ordered(dev, order, name, unit);
343
344         bus_generic_attach(dev);
345
346         return (0);
347 }
348 */
349
350 static int 
351 xlr_i2c_start(device_t dev, u_char slave, int timeout)
352 {
353         int error = 0;
354         struct xlr_i2c_softc *sc;
355
356         sc = device_get_softc(dev);
357         sc->sc_started = 1;
358
359         current_slave = (slave >> 1);
360         return error;
361
362 }
363
364 static int 
365 xlr_i2c_stop(device_t dev)
366 {
367         int error = 0;
368
369         return error;
370
371 }
372
373 static int 
374 xlr_i2c_read(device_t dev, char *buf, int len, int *read, int last,
375     int delay)
376 {
377         int error = 0;
378
379         if (palm_addr_only(current_slave, read_address) == -1) {
380                 printf("I2C ADDRONLY Phase Fail.\n");
381                 return -1;
382         }
383         if (palm_rx(current_slave, read_address, len, buf) == -1) {
384                 printf("I2C Read Fail.\n");
385                 return -1;
386         }
387         *read = len;
388         return error;
389
390 }
391
392
393 static int 
394 xlr_i2c_write(device_t dev, char *buf, int len, int *sent, int timeout /* us */ )
395 {
396
397         int error = 0;
398         uint8_t write_address;
399
400         if (len == 1) {
401                 /* address for the next read */
402                 read_address = buf[0];
403                 return error;
404         }
405         if (len < 2)
406                 return (-1);
407
408         write_address = buf[0];
409
410         /*
411          * for write operation, buf[0] contains the register offset and
412          * buf[1] onwards contains the value
413          */
414         palm_tx(current_slave, write_address, &buf[1], len - 1);
415
416         return error;
417
418 }
419
420 static int
421 xlr_i2c_callback(device_t dev, int index, caddr_t *data)
422 {
423         return 0;
424 }
425
426 static int
427 xlr_i2c_repeated_start(device_t dev, u_char slave, int timeout)
428 {
429         return 0;
430 }
431
432
433 static device_method_t xlr_i2c_methods[] = {
434         /* device interface */
435         DEVMETHOD(device_probe, xlr_i2c_probe),
436         DEVMETHOD(device_attach, xlr_i2c_attach),
437         DEVMETHOD(device_detach, xlr_i2c_detach),
438
439         /* iicbus interface */
440         DEVMETHOD(iicbus_callback, xlr_i2c_callback),
441         DEVMETHOD(iicbus_repeated_start, xlr_i2c_repeated_start),
442         DEVMETHOD(iicbus_start, xlr_i2c_start),
443         DEVMETHOD(iicbus_stop, xlr_i2c_stop),
444         DEVMETHOD(iicbus_write, xlr_i2c_write),
445         DEVMETHOD(iicbus_read, xlr_i2c_read),
446         {0, 0}
447 };
448
449 static driver_t xlr_i2c_driver = {
450         "xlr_i2c",
451         xlr_i2c_methods,
452         sizeof(struct xlr_i2c_softc),
453 };
454
455 DRIVER_MODULE(xlr_i2c, iodi, xlr_i2c_driver, xlr_i2c_devclass, 0, 0);