jtag-mpsse

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit a156bc18e08a648a7c073008af3fa8b4aeb0ef3b
parent 9e242746d88f3bc1a0d1a549811f2619a4acfbd4
Author: Brian Swetland <swetland@frotz.net>
Date:   Mon, 28 Apr 2014 16:52:09 -0700

more i2c tools

- i2c_core.c provides a higher level API
- rdi2c/wri2c use that to read/write 16bit addr+data registers

Diffstat:
MMakefile | 12++++++++++--
Mi2c.c | 33++++++++++++++++++++++-----------
Ai2c.h | 8++++++++
Ai2c_core.c | 151++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ardi2c.c | 41+++++++++++++++++++++++++++++++++++++++++
Awri2c.c | 41+++++++++++++++++++++++++++++++++++++++++
6 files changed, 273 insertions(+), 13 deletions(-)

diff --git a/Makefile b/Makefile @@ -2,7 +2,7 @@ CFLAGS := -g -Wall -O2 LIBS := -lusb-1.0 -all: jtag i2c +all: jtag i2c wri2c rdi2c jtag.c: jtag.h jtag-mpsse.c: jtag.h @@ -14,5 +14,13 @@ jtag: $(JTAG2232_OBJS) i2c: i2c.o jtag-mpsse.o $(CC) -o i2c i2c.o jtag-mpsse.o $(LIBS) +WRI2C_OBJS := wri2c.o i2c_core.o jtag-mpsse.o +wri2c: $(WRI2C_OBJS) + $(CC) -o wri2c $(WRI2C_OBJS) $(LIBS) + +RDI2C_OBJS := rdi2c.o i2c_core.o jtag-mpsse.o +rdi2c: $(RDI2C_OBJS) + $(CC) -o rdi2c $(RDI2C_OBJS) $(LIBS) + clean:: - rm -f jtag *.o + rm -f jtag *.o i2c wri2c rdi2c diff --git a/i2c.c b/i2c.c @@ -53,25 +53,29 @@ u32 jwr(u32 n) { return (u32) u; } -#define STA 0x0100 -#define STP 0x0200 -#define WR 0x0400 -#define RD 0x0800 -#define TIP 0x1000 -#define ACK 0x2000 -#define LOST 0x4000 -#define BUSY 0x8000 +// 0x00XX // wo - data to write +// 0x00XX // ro - last data read +#define STA 0x0100 // rw - issue start on next rd or wr +#define STP 0x0200 // rw - issue stop +#define WR 0x0400 // rw - issue write +#define RD 0x0800 // rw - issue read +#define RACK 0x1000 // wo - master ACK/NAK state for reads +#define TIP 0x1000 // ro - transaction in progress +#define ACK 0x2000 // ro - slave ACK/NAK received on write +#define LOST 0x4000 // ro - arbitration lost +#define BUSY 0x8000 // ro - I2C bus busy /* example: ./i2c sw:a0 w:fa sw:a1 r r r r r r p */ int main(int argc, char **argv) { - jconnect(); unsigned n,x; unsigned c; argc--; argv++; + jconnect(); + while (argc > 0) { char *cmd = argv[0]; n = 0; @@ -81,6 +85,7 @@ int main(int argc, char **argv) { case 'p': case 'P': n |= STP; break; case 'w': case 'W': n |= WR; break; case 'r': case 'R': n |= RD; break; + case 'z': case 'Z': n |= RACK; break; case ':': cmd++; n |= (strtoul(cmd, 0, 16) & 0xFF); @@ -94,13 +99,19 @@ int main(int argc, char **argv) { done: jwr(n); c = 1; - while ((x = jrd()) & TIP) c++; + while ((x = jrd()) & TIP) { + c++; + if (c == 100000) { + fprintf(stderr,"timeout\n"); + return -1; + } + } fprintf(stderr, "%c%c%c%c %02x -> %02x %c%c%c (%d)\n", (n&RD)?'R':'-', (n&WR)?'W':'-', (n&STP)?'P':'-', (n&STA)?'S':'-', n & 0xFF, x & 0xFF, - (x&ACK)?'A':'N', (x&LOST)?'L':'-', + (x&ACK)?'N':'A', (x&LOST)?'L':'-', (x&BUSY)?'B':'-', c); argc--; argv++; diff --git a/i2c.h b/i2c.h @@ -0,0 +1,8 @@ +#ifndef _I2C_H_ +#define _I2C_H_ + +void i2c_init(void); +int i2c_wr16(unsigned saddr, unsigned addr, unsigned val); +int i2c_rd16(unsigned saddr, unsigned addr, unsigned *val); + +#endif diff --git a/i2c_core.c b/i2c_core.c @@ -0,0 +1,151 @@ +/* Copyright 2014 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "jtag.h" +#include "zynq.h" + +#include "i2c.h" + +#define TRACE_TXN 0 + +static JTAG *jtag; + +void jconnect(void) { + if (!(jtag = jtag_open())) { + fprintf(stderr, "jconnect: cannot open usb jtag ifc\n"); + exit(-1); + } + if (jtag_enumerate(jtag) <= 0) { + fprintf(stderr, "jconnect: cannot enumerate jtag devices\n"); + exit(-1); + } + if (jtag_select(jtag, 0x13722093)) { + fprintf(stderr, "jconnect: cannot connect to ZYNQ\n"); + exit(-1); + } + + jtag_ir_wr(jtag, XIL_USER4); +} + +u32 jrd(void) { + u64 u; + jtag_dr_io(jtag, 32, 0, &u); + return (u32) u; +} + +u32 jwr(u32 n) { + u64 u; + u = n; + u |= 0x100000000ULL; + jtag_dr_io(jtag, 33, u, &u); + return (u32) u; +} + +// 0x00XX // wo - data to write +// 0x00XX // ro - last data read +#define STA 0x0100 // rw - issue start on next rd or wr +#define STP 0x0200 // rw - issue stop +#define WR 0x0400 // rw - issue write +#define RD 0x0800 // rw - issue read +#define RACK 0x1000 // wo - master ACK/NAK state for reads +#define TIP 0x1000 // ro - transaction in progress +#define ACK 0x2000 // ro - slave ACK/NAK received on write +#define LOST 0x4000 // ro - arbitration lost +#define BUSY 0x8000 // ro - I2C bus busy + +static int i2c_txn(unsigned cmd, unsigned *_status) { + unsigned timeout = 0; + unsigned status; + jwr(cmd); + while ((status = jrd()) & TIP) { + timeout++; + if (timeout == 10000) { +#if TRACE_TXN + fprintf(stderr,"txn: %04x XXXX\n",cmd); +#endif + fprintf(stderr, "i2c: txn timeout\n"); + return -1; + } + } +#if TRACE_TXN + fprintf(stderr,"txn: %04x %04x\n",cmd, status); +#endif + *_status = status; + return 0; +} + +static int i2c_start(unsigned saddr) { + unsigned status; + if (i2c_txn((saddr & 0xFF) | STA | WR, &status)) + return -1; + if (status & ACK) { + fprintf(stderr, "i2c: slave NAK'd\n"); + return -1; + } + return 0; +} + +static int i2c_stop(void) { + unsigned status; + return i2c_txn(STP, &status); +} + +static int i2c_write(unsigned data) { + unsigned status; + if (i2c_txn((data & 0xFF) | WR, &status)) + return -1; + if (status & ACK) { + fprintf(stderr, "i2c: slave NAK'd\n"); + return -1; + } + return 0; +} + +static int i2c_read(unsigned *data, unsigned send_nak) { + unsigned status; + if (i2c_txn(RD | (send_nak ? RACK : 0), &status)) + return -1; + *data = status & 0xFF; + return 0; +} + +int i2c_wr16(unsigned saddr, unsigned addr, unsigned val) { + if (i2c_start(saddr)) return -1; + if (i2c_write(addr >> 8)) return -1; + if (i2c_write(addr)) return -1; + if (i2c_write(val >> 8)) return -1; + if (i2c_write(val)) return -1; + return i2c_stop(); +} + +int i2c_rd16(unsigned saddr, unsigned addr, unsigned *val) { + unsigned a, b; + if (i2c_start(saddr)) return -1; + if (i2c_write(addr >> 8)) return -1; + if (i2c_write(addr)) return -1; + if (i2c_start(saddr | 1)) return -1; + if (i2c_read(&a, 0)) return -1; + if (i2c_read(&b, 1)) return -1; + *val = (a << 8) | b; + return i2c_stop(); +} + +void i2c_init(void) { + jconnect(); +} diff --git a/rdi2c.c b/rdi2c.c @@ -0,0 +1,41 @@ +/* Copyright 2014 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "i2c.h" + +int main(int argc, char **argv) { + unsigned saddr, addr, val; + + if (argc != 3) { + fprintf(stderr, "usage: rdi2c <saddr> <addr>\n"); + return -1; + } + + i2c_init(); + + saddr = strtoul(argv[1], 0, 16); + addr = strtoul(argv[2], 0, 16); + + if (i2c_rd16(saddr, addr, &val)) { + fprintf(stderr, "error\n"); + return -1; + } + printf("%04x\n", val); + return 0; +} diff --git a/wri2c.c b/wri2c.c @@ -0,0 +1,41 @@ +/* Copyright 2014 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "i2c.h" + +int main(int argc, char **argv) { + unsigned saddr, addr, val; + + if (argc != 4) { + fprintf(stderr, "usage: wri2c <saddr> <addr> <value>\n"); + return -1; + } + + i2c_init(); + + saddr = strtoul(argv[1], 0, 16); + addr = strtoul(argv[2], 0, 16); + val = strtoul(argv[3], 0, 16); + + if (i2c_wr16(saddr, addr, val)) { + fprintf(stderr, "error\n"); + return -1; + } + return 0; +}