Hello Amit/Sanjay,
Did you get a chance to look at the patch?
-- Thanks, -Meraj
On Mon, Jun 30, 2014 at 2:06 PM, Mohammad Merajul Islam Molla meraj.enigma@gmail.com wrote:
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
- Contributors:
Mohammad Merajul Islam Molla <meraj.molla@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
- Contributors:
Mohammad merajul Islam Molla <meraj.molla@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