aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl
diff options
context:
space:
mode:
authorLaurent Meunier <laurent.meunier@st.com>2013-02-06 03:09:44 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-02-10 15:11:54 -0500
commit6f9e41f4e673bf9ae6a5c0831b1524a91ea1c440 (patch)
tree9cff86fdcbbefdbca5520cc1746163d7ad9534a6 /drivers/pinctrl
parent007cd694332e6d5f57ef76431d2372c958b85a21 (diff)
pinctrl/pinconfig: add debug interface
This update adds a debugfs interface to modify a pin configuration for a given state in the pinctrl map. This allows to modify the configuration for a non-active state, typically sleep state. This configuration is not applied right away, but only when the state will be entered. This solution is mandated for us by HW validation: in order to test and verify several pin configurations during sleep without recompiling the software. Signed-off-by: Laurent Meunier <laurent.meunier@st.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
-rw-r--r--drivers/pinctrl/core.c18
-rw-r--r--drivers/pinctrl/core.h19
-rw-r--r--drivers/pinctrl/pinconf.c207
3 files changed, 227 insertions, 17 deletions
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index b0a8e9a38393..b0de6e7f1fdb 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -32,17 +32,6 @@
32#include "pinmux.h" 32#include "pinmux.h"
33#include "pinconf.h" 33#include "pinconf.h"
34 34
35/**
36 * struct pinctrl_maps - a list item containing part of the mapping table
37 * @node: mapping table list node
38 * @maps: array of mapping table entries
39 * @num_maps: the number of entries in @maps
40 */
41struct pinctrl_maps {
42 struct list_head node;
43 struct pinctrl_map const *maps;
44 unsigned num_maps;
45};
46 35
47static bool pinctrl_dummy_state; 36static bool pinctrl_dummy_state;
48 37
@@ -56,13 +45,8 @@ LIST_HEAD(pinctrldev_list);
56static LIST_HEAD(pinctrl_list); 45static LIST_HEAD(pinctrl_list);
57 46
58/* List of pinctrl maps (struct pinctrl_maps) */ 47/* List of pinctrl maps (struct pinctrl_maps) */
59static LIST_HEAD(pinctrl_maps); 48LIST_HEAD(pinctrl_maps);
60 49
61#define for_each_maps(_maps_node_, _i_, _map_) \
62 list_for_each_entry(_maps_node_, &pinctrl_maps, node) \
63 for (_i_ = 0, _map_ = &_maps_node_->maps[_i_]; \
64 _i_ < _maps_node_->num_maps; \
65 _i_++, _map_ = &_maps_node_->maps[_i_])
66 50
67/** 51/**
68 * pinctrl_provide_dummies() - indicate if pinctrl provides dummy state support 52 * pinctrl_provide_dummies() - indicate if pinctrl provides dummy state support
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index fdd350d639f6..ee72f1f6d862 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -155,6 +155,18 @@ struct pin_desc {
155#endif 155#endif
156}; 156};
157 157
158/**
159 * struct pinctrl_maps - a list item containing part of the mapping table
160 * @node: mapping table list node
161 * @maps: array of mapping table entries
162 * @num_maps: the number of entries in @maps
163 */
164struct pinctrl_maps {
165 struct list_head node;
166 struct pinctrl_map const *maps;
167 unsigned num_maps;
168};
169
158struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name); 170struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name);
159int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name); 171int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name);
160const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin); 172const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin);
@@ -176,3 +188,10 @@ extern int pinctrl_force_default(struct pinctrl_dev *pctldev);
176 188
177extern struct mutex pinctrl_mutex; 189extern struct mutex pinctrl_mutex;
178extern struct list_head pinctrldev_list; 190extern struct list_head pinctrldev_list;
191extern struct list_head pinctrl_maps;
192
193#define for_each_maps(_maps_node_, _i_, _map_) \
194 list_for_each_entry(_maps_node_, &pinctrl_maps, node) \
195 for (_i_ = 0, _map_ = &_maps_node_->maps[_i_]; \
196 _i_ < _maps_node_->num_maps; \
197 _i_++, _map_ = &_maps_node_->maps[_i_])
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index baee2cc46a17..ac8d382a79bb 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -574,6 +574,207 @@ static const struct file_operations pinconf_groups_ops = {
574 .release = single_release, 574 .release = single_release,
575}; 575};
576 576
577/* 32bit read/write ressources */
578#define MAX_NAME_LEN 16
579char dbg_pinname[MAX_NAME_LEN]; /* shared: name of the state of the pin*/
580char dbg_state_name[MAX_NAME_LEN]; /* shared: state of the pin*/
581static u32 dbg_config; /* shared: config to be read/set for the pin & state*/
582
583static int pinconf_dbg_pinname_print(struct seq_file *s, void *d)
584{
585 if (strlen(dbg_pinname))
586 seq_printf(s, "%s\n", dbg_pinname);
587 else
588 seq_printf(s, "No pin name set\n");
589 return 0;
590}
591
592static int pinconf_dbg_pinname_open(struct inode *inode, struct file *file)
593{
594 return single_open(file, pinconf_dbg_pinname_print, inode->i_private);
595}
596
597static int pinconf_dbg_pinname_write(struct file *file,
598 const char __user *user_buf, size_t count, loff_t *ppos)
599{
600 int err;
601
602 if (count > MAX_NAME_LEN)
603 return -EINVAL;
604
605 err = sscanf(user_buf, "%15s", dbg_pinname);
606
607 if (err != 1)
608 return -EINVAL;
609
610 return count;
611}
612
613static const struct file_operations pinconf_dbg_pinname_fops = {
614 .open = pinconf_dbg_pinname_open,
615 .write = pinconf_dbg_pinname_write,
616 .read = seq_read,
617 .llseek = seq_lseek,
618 .release = single_release,
619 .owner = THIS_MODULE,
620};
621
622static int pinconf_dbg_state_print(struct seq_file *s, void *d)
623{
624 if (strlen(dbg_state_name))
625 seq_printf(s, "%s\n", dbg_pinname);
626 else
627 seq_printf(s, "No pin state set\n");
628 return 0;
629}
630
631static int pinconf_dbg_state_open(struct inode *inode, struct file *file)
632{
633 return single_open(file, pinconf_dbg_state_print, inode->i_private);
634}
635
636static int pinconf_dbg_state_write(struct file *file,
637 const char __user *user_buf, size_t count, loff_t *ppos)
638{
639 int err;
640
641 if (count > MAX_NAME_LEN)
642 return -EINVAL;
643
644 err = sscanf(user_buf, "%15s", dbg_state_name);
645
646 if (err != 1)
647 return -EINVAL;
648
649 return count;
650}
651
652static const struct file_operations pinconf_dbg_pinstate_fops = {
653 .open = pinconf_dbg_state_open,
654 .write = pinconf_dbg_state_write,
655 .read = seq_read,
656 .llseek = seq_lseek,
657 .release = single_release,
658 .owner = THIS_MODULE,
659};
660
661/**
662 * pinconf_dbg_config_print() - display the pinctrl config from the pinctrl
663 * map, of a pin/state pair based on pinname and state that have been
664 * selected with the debugfs entries pinconf-name and pinconf-state
665 * @s: contains the 32bits config to be written
666 * @d: not used
667 */
668static int pinconf_dbg_config_print(struct seq_file *s, void *d)
669{
670 struct pinctrl_maps *maps_node;
671 struct pinctrl_map const *map;
672 struct pinctrl_dev *pctldev = NULL;
673 struct pinconf_ops *confops = NULL;
674 int i, j;
675 bool found = false;
676
677 mutex_lock(&pinctrl_mutex);
678
679 /* Parse the pinctrl map and look for the elected pin/state */
680 for_each_maps(maps_node, i, map) {
681 if (map->type != PIN_MAP_TYPE_CONFIGS_PIN)
682 continue;
683
684 if (strncmp(map->name, dbg_state_name, MAX_NAME_LEN) > 0)
685 continue;
686
687 for (j = 0; j < map->data.configs.num_configs; j++) {
688 if (0 == strncmp(map->data.configs.group_or_pin,
689 dbg_pinname, MAX_NAME_LEN)) {
690 /* We found the right pin / state, read the
691 * config and store the pctldev */
692 dbg_config = map->data.configs.configs[j];
693 pctldev = get_pinctrl_dev_from_devname
694 (map->ctrl_dev_name);
695 found = true;
696 break;
697 }
698 }
699 }
700
701 mutex_unlock(&pinctrl_mutex);
702
703 if (found) {
704 seq_printf(s, "Config of %s in state %s: 0x%08X\n", dbg_pinname,
705 dbg_state_name, dbg_config);
706
707 if (pctldev)
708 confops = pctldev->desc->confops;
709
710 if (confops && confops->pin_config_config_dbg_show)
711 confops->pin_config_config_dbg_show(pctldev,
712 s, dbg_config);
713 } else {
714 seq_printf(s, "No pin found for defined name/state\n");
715 }
716
717 return 0;
718}
719
720static int pinconf_dbg_config_open(struct inode *inode, struct file *file)
721{
722 return single_open(file, pinconf_dbg_config_print, inode->i_private);
723}
724
725/**
726 * pinconf_dbg_config_write() - overwrite the pinctrl config in thepinctrl
727 * map, of a pin/state pair based on pinname and state that have been
728 * selected with the debugfs entries pinconf-name and pinconf-state
729 */
730static int pinconf_dbg_config_write(struct file *file,
731 const char __user *user_buf, size_t count, loff_t *ppos)
732{
733 int err;
734 unsigned long config;
735 struct pinctrl_maps *maps_node;
736 struct pinctrl_map const *map;
737 int i, j;
738
739 err = kstrtoul_from_user(user_buf, count, 0, &config);
740
741 if (err)
742 return err;
743
744 dbg_config = config;
745
746 mutex_lock(&pinctrl_mutex);
747
748 /* Parse the pinctrl map and look for the selected pin/state */
749 for_each_maps(maps_node, i, map) {
750 if (map->type != PIN_MAP_TYPE_CONFIGS_PIN)
751 continue;
752
753 if (strncmp(map->name, dbg_state_name, MAX_NAME_LEN) > 0)
754 continue;
755
756 /* we found the right pin / state, so overwrite config */
757 for (j = 0; j < map->data.configs.num_configs; j++) {
758 if (strncmp(map->data.configs.group_or_pin, dbg_pinname,
759 MAX_NAME_LEN) == 0)
760 map->data.configs.configs[j] = dbg_config;
761 }
762 }
763
764 mutex_unlock(&pinctrl_mutex);
765
766 return count;
767}
768
769static const struct file_operations pinconf_dbg_pinconfig_fops = {
770 .open = pinconf_dbg_config_open,
771 .write = pinconf_dbg_config_write,
772 .read = seq_read,
773 .llseek = seq_lseek,
774 .release = single_release,
775 .owner = THIS_MODULE,
776};
777
577void pinconf_init_device_debugfs(struct dentry *devroot, 778void pinconf_init_device_debugfs(struct dentry *devroot,
578 struct pinctrl_dev *pctldev) 779 struct pinctrl_dev *pctldev)
579{ 780{
@@ -581,6 +782,12 @@ void pinconf_init_device_debugfs(struct dentry *devroot,
581 devroot, pctldev, &pinconf_pins_ops); 782 devroot, pctldev, &pinconf_pins_ops);
582 debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO, 783 debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO,
583 devroot, pctldev, &pinconf_groups_ops); 784 devroot, pctldev, &pinconf_groups_ops);
785 debugfs_create_file("pinconf-name", (S_IRUGO | S_IWUSR | S_IWGRP),
786 devroot, pctldev, &pinconf_dbg_pinname_fops);
787 debugfs_create_file("pinconf-state", (S_IRUGO | S_IWUSR | S_IWGRP),
788 devroot, pctldev, &pinconf_dbg_pinstate_fops);
789 debugfs_create_file("pinconf-config", (S_IRUGO | S_IWUSR | S_IWGRP),
790 devroot, pctldev, &pinconf_dbg_pinconfig_fops);
584} 791}
585 792
586#endif 793#endif