jtag-mpsse

JTAG tools for FTDI MPSSE transports
git clone http://frotz.net/git/jtag-mpsse.git
Log | Files | Refs

i2c_core.c (3575B)


      1 /* Copyright 2014 Brian Swetland <swetland@frotz.net>
      2  *
      3  * Licensed under the Apache License, Version 2.0 (the "License");
      4  * you may not use this file except in compliance with the License.
      5  * You may obtain a copy of the License at
      6  *
      7  *     http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software
     10  * distributed under the License is distributed on an "AS IS" BASIS,
     11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12  * See the License for the specific language governing permissions and
     13  * limitations under the License.
     14  */
     15 
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 #include <unistd.h>
     19 
     20 #include "jtag.h"
     21 #include "zynq.h"
     22 
     23 #include "i2c.h"
     24 
     25 #define TRACE_TXN 0
     26 
     27 static JTAG *jtag;
     28 
     29 void jconnect(void) {
     30 	if (!(jtag = jtag_open())) {
     31 		fprintf(stderr, "jconnect: cannot open usb jtag ifc\n");
     32 		exit(-1);
     33 	}
     34 	if (jtag_enumerate(jtag) <= 0) {
     35 		fprintf(stderr, "jconnect: cannot enumerate jtag devices\n");
     36 		exit(-1);
     37 	}
     38 	if (jtag_select(jtag, 0x13722093)) {
     39 		fprintf(stderr, "jconnect: cannot connect to ZYNQ\n");
     40 		exit(-1);
     41 	}
     42 
     43 	jtag_ir_wr(jtag, XIL_USER4);
     44 }
     45 
     46 u32 jrd(void) {
     47 	u64 u;
     48 	jtag_dr_io(jtag, 32, 0, &u);
     49 	return (u32) u;
     50 }
     51 
     52 u32 jwr(u32 n) {
     53 	u64 u;
     54 	u = n;
     55 	u |= 0x100000000ULL;
     56 	jtag_dr_io(jtag, 33, u, &u);
     57 	return (u32) u;
     58 }
     59 
     60 //              0x00XX // wo - data to write
     61 //              0x00XX // ro - last data read
     62 #define STA	0x0100 // rw - issue start on next rd or wr
     63 #define STP	0x0200 // rw - issue stop
     64 #define WR	0x0400 // rw - issue write
     65 #define RD	0x0800 // rw - issue read
     66 #define RACK    0x1000 // wo - master ACK/NAK state for reads
     67 #define TIP	0x1000 // ro - transaction in progress
     68 #define ACK     0x2000 // ro - slave ACK/NAK received on write
     69 #define LOST    0x4000 // ro - arbitration lost
     70 #define BUSY    0x8000 // ro - I2C bus busy
     71 
     72 static int i2c_txn(unsigned cmd, unsigned *_status) {
     73 	unsigned timeout = 0;
     74 	unsigned status;
     75 	jwr(cmd);
     76 	while ((status = jrd()) & TIP) {
     77 		timeout++;
     78 		if (timeout == 10000) {
     79 #if TRACE_TXN
     80 			fprintf(stderr,"txn: %04x XXXX\n",cmd); 
     81 #endif
     82 			fprintf(stderr, "i2c: txn timeout\n");
     83 			return -1;
     84 		}
     85 	}
     86 #if TRACE_TXN
     87 	fprintf(stderr,"txn: %04x %04x\n",cmd, status); 
     88 #endif
     89 	*_status = status;
     90 	return 0;	
     91 }
     92 
     93 static int i2c_start(unsigned saddr) {
     94 	unsigned status;
     95 	if (i2c_txn((saddr & 0xFF) | STA | WR, &status))
     96 		return -1;
     97 	if (status & ACK) {
     98 		fprintf(stderr, "i2c: slave NAK'd\n");
     99 		return -1;
    100 	}
    101 	return 0;
    102 }
    103 
    104 static int i2c_stop(void) {
    105 	unsigned status;
    106 	return i2c_txn(STP, &status);
    107 }
    108 
    109 static int i2c_write(unsigned data) {
    110 	unsigned status;
    111 	if (i2c_txn((data & 0xFF) | WR, &status))
    112 		return -1;
    113 	if (status & ACK) {
    114 		fprintf(stderr, "i2c: slave NAK'd\n");
    115 		return -1;
    116 	}
    117 	return 0;
    118 }
    119 
    120 static int i2c_read(unsigned *data, unsigned send_nak) {
    121 	unsigned status;
    122 	if (i2c_txn(RD | (send_nak ? RACK : 0), &status))
    123 		return -1;
    124 	*data = status & 0xFF;
    125 	return 0;
    126 }
    127 
    128 int i2c_wr16(unsigned saddr, unsigned addr, unsigned val) {
    129 	if (i2c_start(saddr)) return -1;
    130 	if (i2c_write(addr >> 8)) return -1;
    131 	if (i2c_write(addr)) return -1;
    132 	if (i2c_write(val >> 8)) return -1;
    133 	if (i2c_write(val)) return -1;
    134 	return i2c_stop();
    135 }
    136 
    137 int i2c_rd16(unsigned saddr, unsigned addr, unsigned *val) {
    138 	unsigned a, b;
    139 	if (i2c_start(saddr)) return -1;
    140 	if (i2c_write(addr >> 8)) return -1;
    141 	if (i2c_write(addr)) return -1;
    142 	if (i2c_start(saddr | 1)) return -1;
    143 	if (i2c_read(&a, 0)) return -1;
    144 	if (i2c_read(&b, 1)) return -1;
    145 	*val = (a << 8) | b;
    146 	return i2c_stop();
    147 }
    148 
    149 void i2c_init(void) {
    150 	jconnect();
    151 }