r4932 - trunk/src/target/gpio
werner at docs.openmoko.org
werner at docs.openmoko.org
Wed Feb 25 11:39:16 CET 2009
Author: werner
Date: 2009-02-25 11:39:15 +0100 (Wed, 25 Feb 2009)
New Revision: 4932
Added:
trunk/src/target/gpio/gpio-s3c6410.c
Modified:
trunk/src/target/gpio/Makefile
Log:
gpio-s3c6410.c: same as "gpio", but for the S3C6410
Modified: trunk/src/target/gpio/Makefile
===================================================================
--- trunk/src/target/gpio/Makefile 2009-02-25 06:21:13 UTC (rev 4931)
+++ trunk/src/target/gpio/Makefile 2009-02-25 10:39:15 UTC (rev 4932)
@@ -2,4 +2,4 @@
CFLAGS=-Wall -g
-all: gpio gpio-glamo
+all: gpio gpio-glamo gpio-s3c6410
Added: trunk/src/target/gpio/gpio-s3c6410.c
===================================================================
--- trunk/src/target/gpio/gpio-s3c6410.c (rev 0)
+++ trunk/src/target/gpio/gpio-s3c6410.c 2009-02-25 10:39:15 UTC (rev 4932)
@@ -0,0 +1,407 @@
+/*
+ * gpio-s3c6410.c - Read and set GPIO pins (of the Samsung S3C6410 MCU)
+ *
+ * Copyright (C) 2008, 2009 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ * All Rights Reserved
+ *
+ * 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 <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+
+#define BASE 0x7f008000
+
+
+static volatile void *mem;
+
+
+#define CON_IN 0
+#define CON_OUT 1
+#define CON_F1 2
+#define CON_F2 3
+#define CON_F3 4
+#define CON_F4 5
+#define CON_F5 6
+#define CON_INT 7
+
+#define R_Z 0
+#define R_DOWN 1
+#define R_UP 2
+
+
+/* 6410 port assignment */
+
+static struct port {
+ const char *name;
+ int offset;
+ int last;
+ enum { pt_a, pt_f, pt_h } type;
+} ports[] = {
+ { "A", 0x000, 8, pt_a },
+ { "B", 0x020, 7, pt_a },
+ { "C", 0x040, 8, pt_a },
+ { "D", 0x060, 5, pt_a },
+ { "E", 0x080, 5, pt_a },
+ { "F", 0x0a0, 16, pt_f },
+ { "G", 0x0c0, 7, pt_a },
+ { "H", 0x0e0, 10, pt_h },
+ { "I", 0x100, 16, pt_f },
+ { "J", 0x120, 12, pt_f },
+ { "K", 0x800, 16, pt_h },
+ { "L", 0x810, 15, pt_h },
+ { "M", 0x820, 6, pt_a },
+ { "N", 0x830, 16, pt_f },
+ { "O", 0x140, 16, pt_f },
+ { "P", 0x160, 15, pt_f },
+ { "Q", 0x180, 9, pt_f },
+ { NULL, }
+};
+
+
+static void print_n(const char *name, int last)
+{
+ int i;
+
+ printf("%s ", name);
+ for (i = 0; i <= last; i++)
+ printf("%2d ", i);
+ putchar('\n');
+}
+
+
+/* ----- Read a pin -------------------------------------------------------- */
+
+
+static const char *pin_a(int con, int dat, int pud)
+{
+ static char res[4];
+
+ res[0] = " >ABCDEIXXXXXXXX"[con];
+ res[1] = dat ? '1' : '0';
+ res[2] = " DUX"[pud];
+ return res;
+}
+
+
+static const char *pin_f(int con, int dat, int pud)
+{
+ static char res[4];
+
+ res[0] = " >FI"[con];
+ res[1] = dat ? '1' : '0';
+ res[2] = " DUX"[pud];
+ return res;
+}
+
+
+static const char *pin(const struct port *p, int num)
+{
+ uint32_t con, con1, dat, pud;
+
+ con = *(uint32_t *) (mem+p->offset);
+ if (p->type != pt_h) {
+ dat = *(uint32_t *) (mem+p->offset+4);
+ pud = *(uint32_t *) (mem+p->offset+8);
+ } else {
+ con1 = *(uint32_t *) (mem+p->offset+4);
+ dat = *(uint32_t *) (mem+p->offset+8);
+ pud = *(uint32_t *) (mem+p->offset+12);
+ }
+
+ switch (p->type) {
+ case pt_a:
+ return pin_a(
+ (con >> (num*4)) & 15,
+ (dat >> num) & 1,
+ (pud >> (num*2)) & 3);
+ case pt_f:
+ return pin_f(
+ (con >> (num*2)) & 3,
+ (dat >> num) & 1,
+ (pud >> (num*2)) & 3);
+ case pt_h:
+ return pin_a(
+ num < 8 ? (con >> (num*4)) & 15 : (con1 >> (num*4-32)) & 15,
+ (dat >> num) & 1,
+ (pud >> (num*2)) & 3);
+ default:
+ abort();
+ }
+}
+
+
+/* ----- Set a pin --------------------------------------------------------- */
+
+
+static void set_a(const struct port *p, int num, int c, int d, int r)
+{
+ uint32_t con, dat, pud;
+
+ con = *(uint32_t *) (mem+p->offset);
+ con = (con & ~(15 << (num*4))) | (c << (num*4));
+ *(uint32_t *) (mem+p->offset) = con;
+
+ if (d != -1) {
+ dat = *(uint32_t *) (mem+p->offset+4);
+ dat = (dat & ~(1 << num)) | (d << num);
+ *(uint32_t *) (mem+p->offset+4) = dat;
+ }
+
+ pud = *(uint32_t *) (mem+p->offset+8);
+ pud = (pud & ~(15 << (num*2))) | (r << (num*2));
+ *(uint32_t *) (mem+p->offset+8) = pud;
+}
+
+
+static void set_f(const struct port *p, int num, int c, int d, int r)
+{
+ uint32_t con, dat, pud;
+
+ con = *(uint32_t *) (mem+p->offset);
+ con = (con & ~(3 << (num*2))) | (c << (num*2));
+ *(uint32_t *) (mem+p->offset) = con;
+
+ if (d != -1) {
+ dat = *(uint32_t *) (mem+p->offset+4);
+ dat = (dat & ~(1 << num)) | (d << num);
+ *(uint32_t *) (mem+p->offset+4) = dat;
+ }
+
+ pud = *(uint32_t *) (mem+p->offset+8);
+ pud = (pud & ~(3 << (num*2))) | (r << (num*2));
+ *(uint32_t *) (mem+p->offset+8) = pud;
+}
+
+
+static void set_h(const struct port *p, int num, int c, int d, int r)
+{
+ uint32_t con, dat, pud;
+
+ if (num < 8) {
+ con = *(uint32_t *) (mem+p->offset);
+ con = (con & ~(15 << (num*4))) | (c << (num*4));
+ *(uint32_t *) (mem+p->offset) = con;
+ } else {
+ con = *(uint32_t *) (mem+p->offset+4);
+ con = (con & ~(15 << (num*4-32))) | (c << (num*4-32));
+ *(uint32_t *) (mem+p->offset+4) = con;
+ }
+
+ if (d != -1) {
+ dat = *(uint32_t *) (mem+p->offset+4);
+ dat = (dat & ~(1 << num)) | (d << num);
+ *(uint32_t *) (mem+p->offset+4) = dat;
+ }
+
+ pud = *(uint32_t *) (mem+p->offset+8);
+ pud = (pud & ~(15 << (num*4))) | (r << (num*4));
+ *(uint32_t *) (mem+p->offset+8) = pud;
+}
+
+
+static void set_pin(const struct port *p, int num, int c, int d, int r)
+{
+ if (num > p->last) {
+ fprintf(stderr, "invalid pin %s%d\n", p->name, num);
+ exit(1);
+ }
+ switch (p->type) {
+ case pt_a:
+ set_a(p, num, c, d, r);
+ break;
+ case pt_f:
+ if (c > 3) {
+ fprintf(stderr, "pin %s%d is F-type\n", p->name, num);
+ exit(1);
+ }
+ set_f(p, num, c, d, r);
+ break;
+ case pt_h:
+ set_h(p, num, c, d, r);
+ break;
+ default:
+ abort();
+ }
+}
+
+
+/* ----- Dump all ports ---------------------------------------------------- */
+
+
+static void dump_all(void)
+{
+fprintf(stderr, "not yet implemented\n");
+exit(1);
+#if 0
+ const struct port *p;
+ uint32_t con, dat, pud;
+ int i;
+
+ for (p = ports; p->name; p++) {
+ con = *(uint32_t *) (mem+p->offset);
+ dat = *(uint32_t *) (mem+p->offset+4);
+ if (p->type == pt_a) {
+ print_n(p->name, p->last);
+ printf("%*s ", strlen(p->name), "");
+ for (i = 0; i <= p->last; i++)
+ printf("%s ",
+ pin_a((con >> i) & 1, (dat >> i) & 1));
+ putchar('\n');
+ }
+ else {
+ pud = *(uint32_t *) (mem+p->offset+8);
+ print_n(p->name, p->last);
+ printf("%*s ", strlen(p->name), "");
+ for (i = 0; i <= p->last; i++)
+ printf("%s",
+ pin_a((con >> (i*2)) & 3, (dat >> i) & 1,
+ (pud >> i) & 1));
+ putchar('\n');
+ }
+ }
+#endif
+}
+
+
+/* ----- Command-line parsing ---------------------------------------------- */
+
+
+static void __attribute__((noreturn)) usage(const char *name)
+{
+ fprintf(stderr,
+"usage: %s [pin[=value] ...]\n\n"
+" pin = <letter><number>, e.g., A5, b10\n"
+" value = <control><pull-down>, with\n"
+" <control> = 0 (output 0), 1 (output 1), Z (input), A or F (primary\n"
+" function), B, C, ... E (additional function), I (interrupt)\n"
+" <pull-down> = D (pull-down), U (pull-up), or nothing\n\n"
+" Examples: A5=ZR, b10=0\n",
+ name);
+ exit(1);
+}
+
+
+static void port_op(const char *name, const char *op)
+{
+ const char *eq, *s;
+ const struct port *p;
+ int num, c, d = -1, r = R_Z;
+ char *end;
+
+ eq = strchr(op, '=');
+ if (!eq)
+ eq = strchr(op, 0);
+ num = strcspn(op, "0123456789");
+ if (!num || op+num >= eq)
+ usage(name);
+ for (p = ports; p->name; p++)
+ if (strlen(p->name) == num && !strncasecmp(p->name, op, num))
+ break;
+ if (!p->name) {
+ fprintf(stderr, "invalid port \"%.*s\"\n", num, op);
+ exit(1);
+ }
+ num = strtoul(op+num, &end, 10);
+ if (end != eq)
+ usage(name);
+ if (!*eq) {
+ s = pin(p, num);
+ if (*s == ' ')
+ s++;
+ printf("%s\n", s);
+ return;
+ }
+ switch (eq[1]) {
+ case '0':
+ d = 0;
+ c = CON_OUT;
+ break;
+ case '1':
+ d = 1;
+ c = CON_OUT;
+ break;
+ case 'Z':
+ case 'z':
+ c = CON_IN;
+ break;
+ case 'F':
+ case 'f':
+ case 'A':
+ case 'a':
+ c = CON_F1;
+ break;
+ case 'B':
+ case 'b':
+ c = CON_F2;
+ break;
+ case 'C':
+ case 'c':
+ c = CON_F3;
+ break;
+ case 'D':
+ case 'd':
+ c = CON_F4;
+ break;
+ case 'E':
+ case 'e':
+ c = CON_F5;
+ break;
+ case 'I':
+ case 'i':
+ c = CON_INT;
+ break;
+ default:
+ usage(name);
+ }
+ if (eq[2]) {
+ switch (eq[2]) {
+ case 'D':
+ case 'd':
+ r = R_DOWN;
+ break;
+ case 'U':
+ case 'u':
+ r = R_UP;
+ break;
+ default:
+ usage(name);
+ }
+ if (eq[3])
+ usage(name);
+ }
+ set_pin(p, num, c, d, r);
+}
+
+
+int main(int argc, char **argv)
+{
+ int fd, i;
+
+ fd = open("/dev/mem", O_RDWR);
+ if (fd < 0) {
+ perror("/dev/mem");
+ exit(1);
+ }
+ mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE);
+ if (mem == MAP_FAILED) {
+ perror("mmap");
+ exit(1);
+ }
+ if (argc == 1)
+ dump_all();
+ else
+ for (i = 1; i != argc; i++)
+ port_op(*argv, argv[i]);
+ return 0;
+}
More information about the commitlog
mailing list