Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 362965
b: refs/heads/master
c: a1a277e
h: refs/heads/master
i:
  362963: b6e9b51
v: v3
  • Loading branch information
Haojian Zhuang authored and Linus Walleij committed Mar 7, 2013
1 parent ae666a7 commit 3963090
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 39b70ee05199f9bea50641df104aee4dbd913d1d
refs/heads/master: a1a277eb76b3507df7c41774048a644aa4dfd096
73 changes: 71 additions & 2 deletions trunk/drivers/pinctrl/pinctrl-single.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ struct pcs_function {
struct list_head node;
};

/**
* struct pcs_gpiofunc_range - pin ranges with same mux value of gpio function
* @offset: offset base of pins
* @npins: number pins with the same mux value of gpio function
* @gpiofunc: mux value of gpio function
* @node: list node
*/
struct pcs_gpiofunc_range {
unsigned offset;
unsigned npins;
unsigned gpiofunc;
struct list_head node;
};

/**
* struct pcs_data - wrapper for data needed by pinctrl framework
* @pa: pindesc array
Expand Down Expand Up @@ -123,6 +137,7 @@ struct pcs_name {
* @ftree: function index radix tree
* @pingroups: list of pingroups
* @functions: list of functions
* @gpiofuncs: list of gpio functions
* @ngroups: number of pingroups
* @nfuncs: number of functions
* @desc: pin controller descriptor
Expand All @@ -148,6 +163,7 @@ struct pcs_device {
struct radix_tree_root ftree;
struct list_head pingroups;
struct list_head functions;
struct list_head gpiofuncs;
unsigned ngroups;
unsigned nfuncs;
struct pinctrl_desc desc;
Expand Down Expand Up @@ -403,9 +419,26 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
}

static int pcs_request_gpio(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset)
struct pinctrl_gpio_range *range, unsigned pin)
{
return -ENOTSUPP;
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
struct pcs_gpiofunc_range *frange = NULL;
struct list_head *pos, *tmp;
int mux_bytes = 0;
unsigned data;

list_for_each_safe(pos, tmp, &pcs->gpiofuncs) {
frange = list_entry(pos, struct pcs_gpiofunc_range, node);
if (pin >= frange->offset + frange->npins
|| pin < frange->offset)
continue;
mux_bytes = pcs->width / BITS_PER_BYTE;
data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask;
data |= frange->gpiofunc;
pcs->write(data, pcs->base + pin * mux_bytes);
break;
}
return 0;
}

static const struct pinmux_ops pcs_pinmux_ops = {
Expand Down Expand Up @@ -879,6 +912,37 @@ static void pcs_free_resources(struct pcs_device *pcs)

static struct of_device_id pcs_of_match[];

static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
{
const char *propname = "pinctrl-single,gpio-range";
const char *cellname = "#pinctrl-single,gpio-range-cells";
struct of_phandle_args gpiospec;
struct pcs_gpiofunc_range *range;
int ret, i;

for (i = 0; ; i++) {
ret = of_parse_phandle_with_args(node, propname, cellname,
i, &gpiospec);
/* Do not treat it as error. Only treat it as end condition. */
if (ret) {
ret = 0;
break;
}
range = devm_kzalloc(pcs->dev, sizeof(*range), GFP_KERNEL);
if (!range) {
ret = -ENOMEM;
break;
}
range->offset = gpiospec.args[0];
range->npins = gpiospec.args[1];
range->gpiofunc = gpiospec.args[2];
mutex_lock(&pcs->mutex);
list_add_tail(&range->node, &pcs->gpiofuncs);
mutex_unlock(&pcs->mutex);
}
return ret;
}

static int pcs_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
Expand All @@ -900,6 +964,7 @@ static int pcs_probe(struct platform_device *pdev)
mutex_init(&pcs->mutex);
INIT_LIST_HEAD(&pcs->pingroups);
INIT_LIST_HEAD(&pcs->functions);
INIT_LIST_HEAD(&pcs->gpiofuncs);

PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
"register width not specified\n");
Expand Down Expand Up @@ -975,6 +1040,10 @@ static int pcs_probe(struct platform_device *pdev)
goto free;
}

ret = pcs_add_gpio_func(np, pcs);
if (ret < 0)
goto free;

dev_info(pcs->dev, "%i pins at pa %p size %u\n",
pcs->desc.npins, pcs->base, pcs->size);

Expand Down

0 comments on commit 3963090

Please sign in to comment.