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.cinclude $(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.odefault: 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);
elsesscanf(buf, GPIO_fmt1,pins_info[pin].gpio_owner);
}if (strstr(buf, "HOG"))strcpy(pins_info[pin].hog, "HOG");elsestrcpy(pins_info[pin].hog, "");if ((p = strstr(buf, "function"))) {p += 9;sscanf(p, "%s", pins_info[pin].function);}elsestrcpy(pins_info[pin].function, "");if ((p = strstr(buf, "group"))) {p += 5;sscanf(p, "%s", pins_info[pin].group);}elsestrcpy(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