mirror of
git://projects.qi-hardware.com/ben-wpan.git
synced 2024-12-24 14:53:56 +02:00
186 lines
3.4 KiB
C
186 lines
3.4 KiB
C
|
/*
|
||
|
* atrf-gpio/atben.c - ATBEN-specific GPIO driver
|
||
|
*
|
||
|
* Written 2011 by Werner Almesberger
|
||
|
* Copyright 2011 Werner Almesberger
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 2 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include <stdint.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include "at86rf230.h"
|
||
|
#include "atrf.h"
|
||
|
|
||
|
#include "atrf-gpio.h"
|
||
|
|
||
|
|
||
|
static struct pin {
|
||
|
const char *name;
|
||
|
int bit;
|
||
|
} pins[] = {
|
||
|
{ "SCLK", 11 },
|
||
|
{ "MISO", 10 },
|
||
|
{ "SLP_TR", 9 },
|
||
|
{ "MOSI", 8 },
|
||
|
{ "nSEL", 13 },
|
||
|
{ "IRQ", 12 },
|
||
|
{ NULL, 0 }
|
||
|
};
|
||
|
|
||
|
static uint32_t orig_dat, orig_pe, orig_dir;
|
||
|
static uint32_t changed = 0;
|
||
|
|
||
|
|
||
|
/* ----- Ben hardware ------------------------------------------------------ */
|
||
|
|
||
|
|
||
|
static volatile uint32_t *pdpin, *pddat, *pddats, *pddatc;
|
||
|
static volatile uint32_t *pdpe, *pdpes, *pdpec;
|
||
|
static volatile uint32_t *pddir, *pddirs, *pddirc;
|
||
|
|
||
|
|
||
|
static void ben_setup(struct atrf_dsc *dsc)
|
||
|
{
|
||
|
volatile void *base = atrf_ben_regs(dsc);
|
||
|
|
||
|
pdpin = base+0x10300;
|
||
|
pddat = base+0x10310;
|
||
|
pddats = base+0x10314;
|
||
|
pddatc = base+0x10318;
|
||
|
|
||
|
pdpe = base+0x10330;
|
||
|
pdpes = base+0x10334;
|
||
|
pdpec = base+0x10338;
|
||
|
|
||
|
pddir = base+0x10360;
|
||
|
pddirs = base+0x10364;
|
||
|
pddirc = base+0x10368;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* ----- Diagnostic dump --------------------------------------------------- */
|
||
|
|
||
|
|
||
|
static char decode_cfg(uint32_t bit)
|
||
|
{
|
||
|
if (*pddir & bit)
|
||
|
return *pddat & bit ? '1' : '0';
|
||
|
return *pdpe & bit ? 'Z' : 'P';
|
||
|
}
|
||
|
|
||
|
|
||
|
static void dump_pd(uint32_t expect, uint32_t got, uint32_t mask)
|
||
|
{
|
||
|
const struct pin *pin;
|
||
|
|
||
|
fprintf(stderr, "name\tcfg exp got\n");
|
||
|
for (pin = pins; pin->name; pin++) {
|
||
|
uint32_t bit = 1 << pin->bit;
|
||
|
|
||
|
fprintf(stderr, "%s\t%c %d %d",
|
||
|
pin->name, decode_cfg(bit),
|
||
|
!!(expect & bit), !!(got & bit));
|
||
|
if ((expect ^ got) & mask & bit)
|
||
|
fprintf(stderr, "\t***");
|
||
|
fputc('\n', stderr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static void restore_gpios(void)
|
||
|
{
|
||
|
*pddats = orig_dat & changed;
|
||
|
*pddatc = ~orig_dat & changed;
|
||
|
*pdpes = orig_pe & changed;
|
||
|
*pdpec = ~orig_pe & changed;
|
||
|
*pddirs = orig_dir & changed;
|
||
|
*pddirc = ~orig_dir & changed;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* ----- Decode and apply pattern ------------------------------------------ */
|
||
|
|
||
|
|
||
|
void do_atben(struct atrf_dsc *dsc, const char *pattern, const char *next)
|
||
|
{
|
||
|
static int first = 1;
|
||
|
uint32_t read = 0, expect = 0;
|
||
|
const struct pin *pin = pins;
|
||
|
uint32_t got;
|
||
|
const char *p;
|
||
|
|
||
|
if (first) {
|
||
|
ben_setup(dsc);
|
||
|
orig_dat = *pddat;
|
||
|
orig_pe = *pdpe;
|
||
|
orig_dir = *pddir;
|
||
|
atexit(restore_gpios);
|
||
|
|
||
|
first = 0;
|
||
|
}
|
||
|
|
||
|
for (p = pattern; *p; p++) {
|
||
|
uint32_t bit;
|
||
|
|
||
|
if (!pin->name) {
|
||
|
fprintf(stderr, "too many pins in \"%s\"\n", pattern);
|
||
|
exit(1);
|
||
|
}
|
||
|
bit = 1 << pin->bit;
|
||
|
switch (*p) {
|
||
|
case '0':
|
||
|
*pddatc = bit;
|
||
|
*pddirs = bit;
|
||
|
break;
|
||
|
case '1':
|
||
|
*pddats = bit;
|
||
|
*pddirs = bit;
|
||
|
break;
|
||
|
case 'H':
|
||
|
expect |= bit;
|
||
|
/* fall through */
|
||
|
case 'L':
|
||
|
read |= bit;
|
||
|
/* fall through */
|
||
|
case 'Z':
|
||
|
*pdpec = bit;
|
||
|
*pddirc = bit;
|
||
|
break;
|
||
|
case 'h':
|
||
|
expect |= bit;
|
||
|
/* fall through */
|
||
|
case 'l':
|
||
|
read |= bit;
|
||
|
/* fall through */
|
||
|
case 'z':
|
||
|
*pddirc = bit;
|
||
|
*pdpes = bit;
|
||
|
break;
|
||
|
case 'x':
|
||
|
pin++;
|
||
|
continue;
|
||
|
default:
|
||
|
continue;
|
||
|
}
|
||
|
changed |= bit;
|
||
|
pin++;
|
||
|
}
|
||
|
|
||
|
usleep(1000);
|
||
|
|
||
|
got = *pdpin;
|
||
|
if ((got & read) != expect) {
|
||
|
dump_pd(expect, got, read);
|
||
|
fprintf(stderr, "at \"%s\", next \"%s\"\n", pattern, next);
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|