aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/pinctrl-single.c
diff options
context:
space:
mode:
authorHaojian Zhuang <haojian.zhuang@linaro.org>2013-02-17 06:42:52 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-03-06 23:27:30 -0500
commita1a277eb76b3507df7c41774048a644aa4dfd096 (patch)
tree8f48089478f87dff9a37284af6a1c68ca7911a26 /drivers/pinctrl/pinctrl-single.c
parent39b70ee05199f9bea50641df104aee4dbd913d1d (diff)
pinctrl: single: create new gpio function range
Since gpio driver could create gpio range in DTS, it could invoke pinctrl_request_gpio(). In the pinctrl-single driver, it needs to configure pins with gpio function mode. A new gpio function range should be created in DTS file in below. pinctrl-single,gpio-range = <phandle pin_offset nr_pins gpio_func>; range: gpio-range { #pinctrl-single,gpio-range-cells = <3>; }; The gpio-ranges property is used in gpio driver and the pinctrl-single,gpio-range property is used in pinctrl-single driver. 1. gpio-ranges is used for gpio driver in below. gpio-ranges = <phandle gpio_offset_in_chip pin_offset nr_pins> gpio-ranges = < &pmx0 0 89 1 &pmx0 1 89 1 &pmx0 2 90 1 &pmx0 3 90 1 &pmx0 4 91 1 &pmx0 5 92 1>; 2. gpio driver could get pin offset from gpio-ranges property. pinctrl-single driver could get gpio function mode from gpio_func that is stored in @gpiofuncs list in struct pcs_device. This new pinctrl-single,gpio-range is used as complement for gpio-ranges property in gpio driver. Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinctrl-single.c')
-rw-r--r--drivers/pinctrl/pinctrl-single.c73
1 files changed, 71 insertions, 2 deletions
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 0c0e2da9d880..f4bc602cdb08 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -77,6 +77,20 @@ struct pcs_function {
77}; 77};
78 78
79/** 79/**
80 * struct pcs_gpiofunc_range - pin ranges with same mux value of gpio function
81 * @offset: offset base of pins
82 * @npins: number pins with the same mux value of gpio function
83 * @gpiofunc: mux value of gpio function
84 * @node: list node
85 */
86struct pcs_gpiofunc_range {
87 unsigned offset;
88 unsigned npins;
89 unsigned gpiofunc;
90 struct list_head node;
91};
92
93/**
80 * struct pcs_data - wrapper for data needed by pinctrl framework 94 * struct pcs_data - wrapper for data needed by pinctrl framework
81 * @pa: pindesc array 95 * @pa: pindesc array
82 * @cur: index to current element 96 * @cur: index to current element
@@ -123,6 +137,7 @@ struct pcs_name {
123 * @ftree: function index radix tree 137 * @ftree: function index radix tree
124 * @pingroups: list of pingroups 138 * @pingroups: list of pingroups
125 * @functions: list of functions 139 * @functions: list of functions
140 * @gpiofuncs: list of gpio functions
126 * @ngroups: number of pingroups 141 * @ngroups: number of pingroups
127 * @nfuncs: number of functions 142 * @nfuncs: number of functions
128 * @desc: pin controller descriptor 143 * @desc: pin controller descriptor
@@ -148,6 +163,7 @@ struct pcs_device {
148 struct radix_tree_root ftree; 163 struct radix_tree_root ftree;
149 struct list_head pingroups; 164 struct list_head pingroups;
150 struct list_head functions; 165 struct list_head functions;
166 struct list_head gpiofuncs;
151 unsigned ngroups; 167 unsigned ngroups;
152 unsigned nfuncs; 168 unsigned nfuncs;
153 struct pinctrl_desc desc; 169 struct pinctrl_desc desc;
@@ -403,9 +419,26 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
403} 419}
404 420
405static int pcs_request_gpio(struct pinctrl_dev *pctldev, 421static int pcs_request_gpio(struct pinctrl_dev *pctldev,
406 struct pinctrl_gpio_range *range, unsigned offset) 422 struct pinctrl_gpio_range *range, unsigned pin)
407{ 423{
408 return -ENOTSUPP; 424 struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
425 struct pcs_gpiofunc_range *frange = NULL;
426 struct list_head *pos, *tmp;
427 int mux_bytes = 0;
428 unsigned data;
429
430 list_for_each_safe(pos, tmp, &pcs->gpiofuncs) {
431 frange = list_entry(pos, struct pcs_gpiofunc_range, node);
432 if (pin >= frange->offset + frange->npins
433 || pin < frange->offset)
434 continue;
435 mux_bytes = pcs->width / BITS_PER_BYTE;
436 data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask;
437 data |= frange->gpiofunc;
438 pcs->write(data, pcs->base + pin * mux_bytes);
439 break;
440 }
441 return 0;
409} 442}
410 443
411static const struct pinmux_ops pcs_pinmux_ops = { 444static const struct pinmux_ops pcs_pinmux_ops = {
@@ -879,6 +912,37 @@ static void pcs_free_resources(struct pcs_device *pcs)
879 912
880static struct of_device_id pcs_of_match[]; 913static struct of_device_id pcs_of_match[];
881 914
915static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
916{
917 const char *propname = "pinctrl-single,gpio-range";
918 const char *cellname = "#pinctrl-single,gpio-range-cells";
919 struct of_phandle_args gpiospec;
920 struct pcs_gpiofunc_range *range;
921 int ret, i;
922
923 for (i = 0; ; i++) {
924 ret = of_parse_phandle_with_args(node, propname, cellname,
925 i, &gpiospec);
926 /* Do not treat it as error. Only treat it as end condition. */
927 if (ret) {
928 ret = 0;
929 break;
930 }
931 range = devm_kzalloc(pcs->dev, sizeof(*range), GFP_KERNEL);
932 if (!range) {
933 ret = -ENOMEM;
934 break;
935 }
936 range->offset = gpiospec.args[0];
937 range->npins = gpiospec.args[1];
938 range->gpiofunc = gpiospec.args[2];
939 mutex_lock(&pcs->mutex);
940 list_add_tail(&range->node, &pcs->gpiofuncs);
941 mutex_unlock(&pcs->mutex);
942 }
943 return ret;
944}
945
882static int pcs_probe(struct platform_device *pdev) 946static int pcs_probe(struct platform_device *pdev)
883{ 947{
884 struct device_node *np = pdev->dev.of_node; 948 struct device_node *np = pdev->dev.of_node;
@@ -900,6 +964,7 @@ static int pcs_probe(struct platform_device *pdev)
900 mutex_init(&pcs->mutex); 964 mutex_init(&pcs->mutex);
901 INIT_LIST_HEAD(&pcs->pingroups); 965 INIT_LIST_HEAD(&pcs->pingroups);
902 INIT_LIST_HEAD(&pcs->functions); 966 INIT_LIST_HEAD(&pcs->functions);
967 INIT_LIST_HEAD(&pcs->gpiofuncs);
903 968
904 PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width, 969 PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
905 "register width not specified\n"); 970 "register width not specified\n");
@@ -975,6 +1040,10 @@ static int pcs_probe(struct platform_device *pdev)
975 goto free; 1040 goto free;
976 } 1041 }
977 1042
1043 ret = pcs_add_gpio_func(np, pcs);
1044 if (ret < 0)
1045 goto free;
1046
978 dev_info(pcs->dev, "%i pins at pa %p size %u\n", 1047 dev_info(pcs->dev, "%i pins at pa %p size %u\n",
979 pcs->desc.npins, pcs->base, pcs->size); 1048 pcs->desc.npins, pcs->base, pcs->size);
980 1049