diff --git a/bbl/bbl.c b/bbl/bbl.c index 36bbaad..e54e0d4 100644 --- a/bbl/bbl.c +++ b/bbl/bbl.c @@ -19,42 +19,55 @@ #include -#define PDDATS 0x10010314 -#define PDDATC 0x10010318 -#define PDFUNC 0x10010348 -#define PDDIRS 0x10010364 -#define PDDIRC 0x10010368 +#define GPIO_BASE 0x10010000 -#define LEDS 10 +#define REG(n) (*(uint32_t *) (mem+(n)-GPIO_BASE)) -#define LED_MASK 0x3f00 -#define LED_SEL 11 +/* + * The XBurst CPUs use an interesting concept for setting GPIOs: instead of + * writing the value of a pin (0 or 1) directly to an output latch, the latch + * is set by writing a 1 to a "set" register and cleared by writing a 1 to a + * "clear" register. This way, only an atomic store but no atomic + * read-modify-write operations are necessary for changing only part of the + * bits on a port. + * + * The same set/clear mechanism is also used for the other writable registers + * affecting GPIOs, e.g., the direction (input/output) and function (GPIO or + * MMC) registers. + */ + +#define PDDATS REG(0x10010314) /* port D data set */ +#define PDDATC REG(0x10010318) /* port D data clear */ +#define PDFUNC REG(0x10010348) /* port D function clear */ +#define PDDIRS REG(0x10010364) /* port D direction set */ +#define PDDIRC REG(0x10010368) /* port D direction clear */ + +#define LEDS 10 /* number of LEDs */ + +#define GROUP_SEL 11 /* PD11, DAT1 - LED group selection */ + +#define LED_MASK 0x3f00 /* all the LED groups and GROUP_SEL */ #define DELAY_US 50000 #define PAGE_SIZE 4096 -#define GPIO_BASE 0x10010000 -#define REG(n) (*(uint32_t *) (mem+(n)-GPIO_BASE)) static volatile void *mem; -/* ----- Command-line parsing ---------------------------------------------- */ - - -static int map(int g) +static int map(int group) { - switch (g) { + switch (group) { case 0: - return 12; + return 12; /* PD12, DAT2 */ case 1: - return 13; + return 13; /* PD13, DAT3/CD */ case 2: - return 8; + return 8; /* PD08, CMD */ case 3: - return 9; + return 9; /* PD09, CLK */ case 4: - return 10; + return 10; /* PD10, DAT0 */ default: abort(); } @@ -65,18 +78,18 @@ static void set(int n) { if (n & 1) { - REG(PDDATC) = LED_MASK; - REG(PDDATS) = 1 << map(n >> 1); + PDDATC = LED_MASK; + PDDATS = 1 << map(n >> 1); } else { - REG(PDDATS) = LED_MASK; - REG(PDDATC) = 1 << map(n >> 1); + PDDATS = LED_MASK; + PDDATC = 1 << map(n >> 1); } } static void die(int sig) { - REG(PDDIRC) = LED_MASK; + PDDIRC = LED_MASK; /* make all MMC pins inputs again */ _exit(0); } @@ -99,8 +112,8 @@ int main(int argc, char **argv) signal(SIGINT, die); - REG(PDFUNC) = LED_MASK; - REG(PDDIRS) = LED_MASK; + PDFUNC = LED_MASK; /* make all MMC pins GPIOs */ + PDDIRS = LED_MASK; /* make all MMC pins outputs */ while (1) { for (i = 0; i != LEDS-1; i++) {