Commit 0d2d96c4 authored by Alejandro Mery's avatar Alejandro Mery
Browse files

pio: add `pio print < PIO` to turn a PIO dump into human readable

parent 3affc3bd
fexc
bin2fex
fex2bin
bootinfo
fel
pio
*.o
*.swp
......@@ -2,7 +2,7 @@ CC = gcc
CFLAGS = -g -O0 -Wall -Wextra
CFLAGS += -std=c99 -D_POSIX_C_SOURCE=200112L
TOOLS = fexc bin2fex fex2bin bootinfo fel
TOOLS = fexc bin2fex fex2bin bootinfo fel pio
MISC_TOOLS = phoenix_info
......
/* needs _BSD_SOURCE for htole and letoh */
#define _BSD_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <endian.h>
#define PIO_REG_SIZE 0x228 /*0x300*/
#define PIO_PORT_SIZE 0x24
#define errf(...) fprintf(stderr, __VA_ARGS__)
static inline int _read(int fd, char *buf, size_t l)
{
ssize_t rc = 0;
while (l > 0) {
rc = read(fd, buf, l);
if (rc >= 0)
break;
else if (rc < 0 && errno != EINTR) {
errf("read: %s\n", strerror(errno));
break;
}
}
return rc;
}
static int read_fixed_stdin(char *buf, size_t wanted)
{
ssize_t rc;
char eof;
while (wanted > 0) {
rc = _read(0, buf, wanted);
if (rc > 0) {
wanted -= rc;
buf += rc;
} else if (rc == 0) {
errf("read: input too small\n");
goto fail;
} else if (rc < 0) {
goto fail;
}
}
if (_read(0, &eof, 1) == 0)
return 1;
errf("read: input too large\n");
fail:
return 0;
}
struct pio_status {
int mul_sel;
int pull;
int drv_level;
int data;
};
#define PIO_REG_CFG(B, N, I) ((B) + (N)*0x24 + ((I)<<2) + 0x00)
#define PIO_REG_DLEVEL(B, N, I) ((B) + (N)*0x24 + ((I)<<2) + 0x14)
#define PIO_REG_PULL(B, N, I) ((B) + (N)*0x24 + ((I)<<2) + 0x1C)
#define PIO_REG_DATA(B, N) ((B) + (N)*0x24 + 0x10)
#define LE32TOH(X) le32toh(*((uint32_t*)(X)))
static int pio_get(const char *buf, uint32_t port, uint32_t port_num, struct pio_status *pio)
{
uint32_t val;
uint32_t port_num_func, port_num_pull;
uint32_t offset_func, offset_pull;
port_num_func = port_num >> 3;
offset_func = ((port_num - (port_num_func << 3)) << 2);
port_num_pull = port_num >> 4;
offset_pull = ((port_num - (port_num_pull << 4)) << 1);
/* func */
val = LE32TOH(PIO_REG_CFG(buf, port, port_num_func));
pio->mul_sel = (val>>offset_func) & 0x07;
/* pull */
val = LE32TOH(PIO_REG_PULL(buf, port, port_num_pull));
pio->pull = (val>>offset_pull) & 0x03;
/* dlevel */
val = LE32TOH(PIO_REG_DLEVEL(buf, port, port_num_pull));
pio->drv_level = (val>>offset_pull) & 0x03;
/* i/o data */
if (pio->mul_sel > 1)
pio->data = -1;
else {
val = LE32TOH(PIO_REG_CFG(buf, port, port_num_func));
pio->data = (val >> port_num) & 0x01;
}
return 1;
}
static void print(const char *buf)
{
int port, i;
struct pio_status pio;
for (port=0; port < 10 /*PIO_REG_SIZE/0x24*/; port++) {
for (i=0; i<28; i++) {
if (pio_get(buf, port, i, &pio)) {
printf("P%c%d", 'A'+port, i+1);
printf("<%x>", pio.mul_sel);
printf("<%x>", pio.pull);
printf("<%x>", pio.drv_level);
if (pio.data >= 0)
printf("<%x>", pio.data);
fputc('\n', stdout);
}
}
}
}
static int read_and_print(void)
{
char buf[PIO_REG_SIZE];
if (read_fixed_stdin(buf, PIO_REG_SIZE)) {
print(buf);
return 0;
}
return -1;
}
static inline int usage(const char *argv0)
{
fprintf(stderr, "usage: %s print < PIO\n", argv0);
return 1;
}
int main(int argc, char **argv)
{
if (argc == 2 && (strncmp("print", argv[1], 5) == 0))
return read_and_print();
else
return usage(argv[0]);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment