Add support for pinctrl in powerdebug. Both dump and display
modes supported. Tested only on Samsung Arndale board.

Sample output in display mode on Arndale Board -

Pin   Name       MUX Owner       GPIO Owner      HOG   Function
Group
0     gpa0-0     MUX UNCLAIMED   GPIO UNCLAIMED
1     gpa0-1     MUX UNCLAIMED   GPIO UNCLAIMED
2     gpa0-2     MUX UNCLAIMED   GPIO UNCLAIMED
3     gpa0-3     MUX UNCLAIMED   GPIO UNCLAIMED
4     gpa0-4     MUX UNCLAIMED   GPIO UNCLAIMED
5     gpa0-5     MUX UNCLAIMED   GPIO UNCLAIMED
6     gpa0-6     12c80000.i2c    GPIO UNCLAIMED        i2c2-bus-mux
i2c2-bus-grp
7     gpa0-7     12c80000.i2c    GPIO UNCLAIMED        i2c2-bus-mux
i2c2-bus-grp
8     gpa1-0     MUX UNCLAIMED   GPIO UNCLAIMED
9     gpa1-1     MUX UNCLAIMED   GPIO UNCLAIMED
10    gpa1-2     12c90000.i2c    GPIO UNCLAIMED        i2c3-bus-mux
i2c3-bus-grp
11    gpa1-3     12c90000.i2c    GPIO UNCLAIMED        i2c3-bus-mux
i2c3-bus-grp



---
 Android.mk   |   2 +-
 Makefile     |   2 +-
 README       |   4 +-
 display.c    |   3 +-
 display.h    |   2 +-
 pinctrl.c    | 329 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 pinctrl.h    |  19 ++++
 powerdebug.c |  35 +++++--
 8 files changed, 381 insertions(+), 15 deletions(-)
 create mode 100644 pinctrl.c
 create mode 100644 pinctrl.h

diff --git a/Android.mk b/Android.mk
index 36c73cd..19d00ca 100644
--- a/Android.mk
+++ b/Android.mk
@@ -29,6 +29,6 @@ LOCAL_C_INCLUDES += external/stlport/stlport/ \

 LOCAL_SRC_FILES += \
        powerdebug.c sensor.c clocks.c regulator.c \
-       display.c tree.c utils.c mainloop.c gpio.c
+       display.c tree.c utils.c mainloop.c gpio.c pinctrl.c

 include $(BUILD_EXECUTABLE)
diff --git a/Makefile b/Makefile
index 2da9d67..f002438 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ CFLAGS?=-O1 -g -Wall -Wshadow
 CC?=gcc

 OBJS = powerdebug.o sensor.o clocks.o regulator.o gpio.o \
-       display.o tree.o utils.o mainloop.o
+       display.o tree.o utils.o mainloop.o pinctrl.o

 default: powerdebug

diff --git a/README b/README
index 1479db1..b24dd98 100644
--- a/README
+++ b/README
@@ -1,8 +1,8 @@
 powerdebug
 ----------

-This is a new tool which displays regulator, sensor and clock tree
-information.
+This is a new tool which displays regulator, sensor, clock tree, gpio and
+pinctrl information.

 Current version only displays regulator information and clock tree from
 debugfs. Support will be added for sensors later.
diff --git a/display.c b/display.c
index 0000ee9..fb899c0 100644
--- a/display.c
+++ b/display.c
@@ -63,7 +63,8 @@ struct windata windata[] = {
        [CLOCK]     = { .name = "Clocks"     },
        [REGULATOR] = { .name = "Regulators" },
        [SENSOR]    = { .name = "Sensors"    },
-       [GPIO]      = { .name = "Gpio"    },
+       [GPIO]      = { .name = "Gpio"       },
+       [PINCTRL]   = { .name = "Pins"       },
 };

 static void display_fini(void)
diff --git a/display.h b/display.h
index e3a1529..4496f30 100644
--- a/display.h
+++ b/display.h
@@ -13,7 +13,7 @@
  *       - initial API and implementation
  
*******************************************************************************/

-enum { CLOCK, REGULATOR, SENSOR, GPIO };
+enum { CLOCK, REGULATOR, SENSOR, GPIO, PINCTRL };

 struct display_ops {
        int (*display)(bool refresh);
diff --git a/pinctrl.c b/pinctrl.c
new file mode 100644
index 0000000..eef06e2
--- /dev/null
+++ b/pinctrl.c
@@ -0,0 +1,329 @@
+
+/*******************************************************************************
+ * Copyright (C) 2014, Linaro Limited.
+ *
+ * This file is part of PowerDebug.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Mohammad Merajul Islam Molla <meraj.mo...@samsung.com>
+ *                                     (Samsung R&D Institute Bangladesh)
+ *             - initial API and implementation
+ 
*******************************************************************************/
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#include <stdio.h>
+#undef _GNU_SOURCE
+#endif
+#include <string.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "pinctrl.h"
+#include "display.h"
+
+#define SIZE 64
+#define MAX_PINS 256
+
+#define PIN_fmt         "%*[^ ] %d"
+#define NAME_fmt       "%*[^(]( %s"
+#define MUX_fmt                "%*[^:]: %s"
+#define GPIO_fmt       "%*[^:]: %*[^ ] %s"
+#define GPIO_fmt1      "%*[^:]: %*[^ ] %*[^ ] %s"
+
+#define SYS_PINCTRL "/sys/kernel/debug/pinctrl"
+
+static bool pinctrl_error = false;
+
+static struct pintcrl_info {
+       int pin;
+       char name[SIZE];
+       char mux_owner[SIZE];
+       char gpio_owner[SIZE];
+       char hog[SIZE];
+       char function[SIZE];
+       char group[SIZE];
+} pins_info[MAX_PINS];
+
+static int fill_pinctrl_info();
+
+static int pinctrl_print_header(void)
+{
+       char *buf;
+       int ret;
+
+       if (asprintf(&buf, "%-5s %-10s %-15s %-15s %-5s %-20s %-20s",
+                    "Pin", "Name", "MUX Owner", "GPIO Owner", "HOG",
"Function",
+                    "Group") < 0)
+               return -1;
+
+       ret = display_column_name(buf);
+
+       free(buf);
+
+       return ret;
+}
+
+static char *pin_line(int pin)
+{
+       char *pinline = 0;
+
+       if (asprintf(&pinline,"%-5d %-10s %-15s %-15s %-5s %-20s %-20s",
+               pins_info[pin].pin, pins_info[pin].name,
+               pins_info[pin].mux_owner, pins_info[pin].gpio_owner,
+               pins_info[pin].hog, pins_info[pin].function,
+               pins_info[pin].group) < 0)
+               return NULL;
+
+       return pinline;
+}
+
+static int pinctrl_print_info()
+{
+       int i;
+       int line = 0;
+       char *buffer;
+
+       display_reset_cursor(PINCTRL);
+
+       pinctrl_print_header();
+
+       for (i = 0; i < MAX_PINS; i++) {
+               if (pins_info[i].pin == -1)
+                       continue;
+
+               buffer = pin_line(i);
+               if (!buffer)
+                       return -1;
+
+               display_print_line(PINCTRL, line, buffer, 0, NULL);
+               line++;
+
+               free(buffer);
+       }
+
+       display_refresh_pad(PINCTRL);
+
+       return 0;
+}
+
+static int dump_pinctrl_info()
+{
+       int i;
+
+       for (i = 0; i < MAX_PINS; i++) {
+               if (pins_info[i].pin == -1)
+                       continue;
+               printf("\tPin %d: (Name: %s, MUX_owner: %s,
GPIO_owner: %s, HOG: %s, Function: %s, Group: %s)\n",
+                       pins_info[i].pin, pins_info[i].name,
+                       pins_info[i].mux_owner, pins_info[i].gpio_owner,
+                       pins_info[i].hog,
+                       pins_info[i].function, pins_info[i].group);
+       }
+
+       return 0;
+}
+
+
+int pinctrl_dump()
+{
+       int ret;
+
+       if (pinctrl_error)
+               return -1;
+
+       printf("\nPin Information:\n");
+       printf("****************\n");
+       ret = dump_pinctrl_info();
+       printf("\n\n");
+
+       return ret;
+
+}
+
+static int pinctrl_display(bool refresh)
+{
+       if (pinctrl_error) {
+               display_message(PINCTRL,
+                       "error: path " SYS_PINCTRL " not found or not root");
+               return -2;
+       }
+
+       if (refresh && fill_pinctrl_info())
+               return -1;
+
+       return pinctrl_print_info();
+}
+
+static struct display_ops pinctrl_ops = {
+       .display = pinctrl_display,
+};
+
+static int read_pin_info(const char *path)
+{
+       FILE *fpinmux;
+       int pin;
+       int ret = 0;
+       char *p;
+       char buf[4096];
+
+       fpinmux = fopen(path, "r");
+       if (!fpinmux) {
+               printf("error: failed to read %s\n", path);
+               return -1;
+       }
+
+       /* first two lines are headers, ignore */
+       fgets(buf, 4096, fpinmux);
+       fgets(buf, 4096, fpinmux);
+
+       while (fgets(buf, 4096, fpinmux)) {
+               int mux_owner = 0;
+
+               /* get pin number */
+               sscanf(buf, PIN_fmt, &pin);
+
+               if (pin >= MAX_PINS) {
+                       printf("WARNING: # of pins > max pins (256),
need to increase limit\n");
+                       continue;
+               }
+
+               pins_info[pin].pin = pin;
+               sscanf(buf, NAME_fmt, pins_info[pin].name);
+               pins_info[pin].name[strlen(pins_info[pin].name) - 2] = '\0';
+
+               if (strstr(buf, "MUX UNCLAIMED"))
+                       strcpy(pins_info[pin].mux_owner, "MUX UNCLAIMED");
+               else {
+                       sscanf(buf, MUX_fmt, pins_info[pin].mux_owner);
+                       mux_owner = 1;
+               }
+
+               if (strstr(buf, "GPIO UNCLAIMED"))
+                       strcpy(pins_info[pin].gpio_owner, "GPIO UNCLAIMED");
+               else {
+                       if (mux_owner)
+                               sscanf(buf, GPIO_fmt,
pins_info[pin].gpio_owner);
+                       else
+                               sscanf(buf, GPIO_fmt1,
pins_info[pin].gpio_owner);
+               }
+
+               if (strstr(buf, "HOG"))
+                       strcpy(pins_info[pin].hog, "HOG");
+               else
+                       strcpy(pins_info[pin].hog, "");
+
+               if ((p = strstr(buf, "function"))) {
+                       p += 9;
+                       sscanf(p, "%s", pins_info[pin].function);
+               }
+               else
+                       strcpy(pins_info[pin].function, "");
+
+               if ((p = strstr(buf, "group"))) {
+                       p += 5;
+                       sscanf(p, "%s", pins_info[pin].group);
+               }
+               else
+                       strcpy(pins_info[pin].group, "");
+       }
+
+       fclose(fpinmux);
+       return ret;
+}
+
+static void init_pins_info()
+{
+       int i;
+
+       memset(pins_info, 0, sizeof(pins_info));
+
+       for (i = 0; i < MAX_PINS; i++)
+               pins_info[i].pin = -1;
+}
+
+static int fill_pinctrl_info()
+{
+       DIR *dir;
+       char *newpath, *pinmux_path;
+       struct dirent dirent, *direntp;
+       struct stat s;
+       int ret = 0;
+
+       dir = opendir(SYS_PINCTRL);
+       if (!dir) {
+               printf("error: unable to open directory " SYS_PINCTRL);
+               ret = -1;
+               goto out;
+       }
+
+       init_pins_info();
+
+       while (!readdir_r(dir, &dirent, &direntp)) {
+               ret = 0;
+
+               if (!direntp)
+                       break;
+
+               if (direntp->d_name[0] == '.')
+                       continue;
+
+               ret = asprintf(&newpath, "%s/%s", SYS_PINCTRL, direntp->d_name);
+               if (ret < 0)
+                       goto out;
+
+               ret = stat(newpath, &s);
+               if (ret)
+                       goto out_free_newpath;
+
+               if (S_ISDIR(s.st_mode)) {
+                       ret = asprintf(&pinmux_path, "%s/%s", newpath,
+                                       "pinmux-pins");
+                       if (ret < 0)
+                               goto out_free_newpath;
+
+                       if (read_pin_info(pinmux_path)) {
+                               ret = -1;
+                               goto out_free_pinmux;
+                       }
+               }
+       }
+
+out_free_pinmux:
+       free(pinmux_path);
+
+out_free_newpath:
+       free(newpath);
+
+out:
+       closedir(dir);
+       return ret;
+}
+
+int pinctrl_init(void)
+{
+       int ret = 0;
+
+       ret = display_register(PINCTRL, &pinctrl_ops);
+       if (ret)
+               printf("error: pinctrl display register failed");
+
+       if (access(SYS_PINCTRL, F_OK)) {
+               pinctrl_error = true;
+               return -1;
+       }
+
+       if (fill_pinctrl_info())
+               return -1;
+
+       return ret;
+}
diff --git a/pinctrl.h b/pinctrl.h
new file mode 100644
index 0000000..2fa4f3a
--- /dev/null
+++ b/pinctrl.h
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (C) 2014, Linaro Limited.
+ *
+ * This file is part of PowerDebug.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Mohammad merajul Islam Molla <meraj.mo...@samsung.com>
+ *                                     (Samsung R&D Institute Bangladesh)
+ *
+ *       - initial API and implementation
+ 
*******************************************************************************/
+
+extern int pinctrl_init(void);
+extern int pinctrl_dump(void);
diff --git a/powerdebug.c b/powerdebug.c
index 6cf3a1b..b4f4833 100644
--- a/powerdebug.c
+++ b/powerdebug.c
@@ -26,6 +26,7 @@
 #include "clocks.h"
 #include "sensor.h"
 #include "gpio.h"
+#include "pinctrl.h"
 #include "mainloop.h"
 #include "powerdebug.h"

@@ -35,13 +36,14 @@ void usage(void)
 {
        printf("Usage: powerdebug [OPTIONS]\n");
        printf("\n");
-       printf("powerdebug -d [ -r ] [ -s ] [ -c [ -p <clock-name> ] ] "
+       printf("powerdebug -d [ -r ] [ -s ] [ -p ][ -c [ -P <clock-name> ] ] "
                "[ -v ]\n");
-       printf("powerdebug [ -r | -s | -c ]\n");
+       printf("powerdebug [ -r | -s | -c | -p] \n");
        printf("  -r, --regulator       Show regulator information\n");
        printf("  -s, --sensor          Show sensor information\n");
        printf("  -c, --clock           Show clock information\n");
-       printf("  -p, --findparents     Show all parents for a particular"
+       printf("  -p, --pin             Show pin information\n");
+       printf("  -P, --findparents     Show all parents for a particular"
                " clock\n");
        printf("  -t, --time            Set ticktime in seconds (eg. 10.0)\n");
        printf("  -d, --dump            Dump information once (no refresh)\n");
@@ -62,7 +64,8 @@ void version()
  * -s, --sensor                : sensors
  * -c, --clock         : clocks
  * -g, --gpio           : gpios
- * -p, --findparents    : clockname whose parents have to be found
+ * -p, --pin           : pins
+ * -P, --findparents    : clockname whose parents have to be found
  * -t, --time          : ticktime
  * -d, --dump          : dump
  * -v, --verbose       : verbose
@@ -76,7 +79,8 @@ static struct option long_options[] = {
        { "sensor", 0, 0, 's' },
        { "clock",  0, 0, 'c' },
        { "gpio",  0, 0, 'g' },
-       { "findparents", 1, 0, 'p' },
+       { "pin", 0 , 0, 'p' },
+       { "findparents", 1, 0, 'P' },
        { "time", 1, 0, 't' },
        { "dump", 0, 0, 'd' },
        { "verbose", 0, 0, 'v' },
@@ -91,6 +95,7 @@ struct powerdebug_options {
        bool sensors;
        bool clocks;
        bool gpios;
+       bool pins;
        bool dump;
        unsigned int ticktime;
        int selectedwindow;
@@ -108,7 +113,7 @@ int getoptions(int argc, char *argv[], struct
powerdebug_options *options)
        while (1) {
                int optindex = 0;

-               c = getopt_long(argc, argv, "rscgp:t:dvVh",
+               c = getopt_long(argc, argv, "rscgpP:t:dvVh",
                                long_options, &optindex);
                if (c == -1)
                        break;
@@ -131,6 +136,10 @@ int getoptions(int argc, char *argv[], struct
powerdebug_options *options)
                        options->selectedwindow = GPIO;
                        break;
                case 'p':
+                       options->pins = true;
+                       options->selectedwindow = PINCTRL;
+                       break;
+               case 'P':
                        options->clkname = strdup(optarg);
                        if (!options->clkname) {
                                fprintf(stderr, "failed to allocate memory");
@@ -161,9 +170,9 @@ int getoptions(int argc, char *argv[], struct
powerdebug_options *options)

        /* No system specified to be dump, let's default to all */
        if (!options->regulators && !options->clocks &&
-           !options->sensors && !options->gpios)
-               options->regulators = options->clocks =
-                       options->sensors = options->gpios = true;
+           !options->sensors && !options->gpios && !options->pins)
+               options->regulators = options->clocks = options->sensors =
+                       options->gpios = options->pins = true;

        if (options->selectedwindow == -1)
                options->selectedwindow = CLOCK;
@@ -185,6 +194,9 @@ static int powerdebug_dump(struct
powerdebug_options *options)
        if (options->gpios)
                gpio_dump();

+       if (options->pins)
+               pinctrl_dump();
+
        return 0;
 }

@@ -266,6 +278,11 @@ int main(int argc, char **argv)
                options->gpios = false;
        }

+       if (pinctrl_init()) {
+               printf("failed to initialize pinctrl\n");
+               options->pins = false;
+       }
+
        ret = options->dump ? powerdebug_dump(options) :
                powerdebug_display(options);



--
Thanks,
-Meraj

_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to