mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
Changes queued in gpio/next for the start of the 3.3 merge window
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJPBSJSAAoJEEFnBt12D9kBDmIP/R6PWxg+NrJaGDmxRWBBkOch iI4Et7GT3Sk5hYqPz0kehiSz1F4bqpYK3JmdfqotJIhQCM2znXM+BaDLzgFnMsRf g4t70PIZQMpk3pj4gtIkMpZCkRdA9VFriIf1cEdHcLiRdNVsXlTE6CcQT4fbE1P/ JTAGBrVDwbchuoPsf7Mbu8SYT+cQdWLKpgzC4fAzI++QoYyYBtfvuCHTE4VvasNS jMDOfT+u0Gwp6LW34v0gKk7MXEQzeq07r1VZxMyuaWbRQoiLr5d1fy97+Fh5+4dU Rb9C6zGIoBzRdiJLlfNYrls/FueDHwPyIwXuapMp5QbaGN5fkhVpIVIhYICOLdHW IXH2V3saK1s6QbD7nErNT2lCWZQSCUKq/PR9W40dj3PYAI0oxbRBSoPdfGuW1Bl7 fYqClUza1Bln8bEmmsvAOnIDdfs6zpkWmfouwx4AGaHTfzIAg4VRdoxdUpS8h+/d sNEYi99IuYfl3KWCwQbWJMgCOvoBdOGZSCsTrXnjLf1HJCsQOt/Md69Ff6DLn1VR gDp0EeqgDH5oXJmQTW1WjXaJJair2j8pY8mlmGxl1AqA4aY8C3dxIfHxlBPzdxii I6KTPaIUSXZaOo6e7XDjjjTzabL4q0aQGT5ahpKj928Rnx00QZNXoTy4FmYkL+0k j7QZfM/p6+vfxekKUR17 =9ugo -----END PGP SIGNATURE----- Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux-2.6 Changes queued in gpio/next for the start of the 3.3 merge window * tag 'gpio-for-linus-20120104' of git://git.secretlab.ca/git/linux-2.6: gpio: Add decode of WM8994 GPIO configuration gpio: Convert GPIO drivers to module_platform_driver gpio: Fix typo in comment in Samsung driver gpio: Explicitly index samsung_gpio_cfgs gpio: Add Linus Walleij as gpio co-maintainer of: Add device tree selftests of: create of_phandle_args to simplify return of phandle parsing data gpio/powerpc: Eliminate duplication of of_get_named_gpio_flags() gpio/microblaze: Eliminate duplication of of_get_named_gpio_flags() gpiolib: output basic details and consolidate gpio device drivers pch_gpio: Change company name OKI SEMICONDUCTOR to LAPIS Semiconductor pch_gpio: Support new device LAPIS Semiconductor ML7831 IOH spi/pl022: make the chip deselect handling thread safe spi/pl022: add support for pm_runtime autosuspend spi/pl022: disable the PL022 block when unused spi/pl022: move device disable to workqueue thread spi/pl022: skip default configuration before suspending spi/pl022: fix build warnings spi/pl022: only enable RX interrupts when TX is complete
This commit is contained in:
commit
fbce1c234f
37 changed files with 530 additions and 402 deletions
|
|
@ -15,6 +15,15 @@ config PROC_DEVICETREE
|
|||
an image of the device tree that the kernel copies from Open
|
||||
Firmware or other boot firmware. If unsure, say Y here.
|
||||
|
||||
config OF_SELFTEST
|
||||
bool "Device Tree Runtime self tests"
|
||||
help
|
||||
This option builds in test cases for the device tree infrastructure
|
||||
that are executed one at boot time, and the results dumped to the
|
||||
console.
|
||||
|
||||
If unsure, say N here, but this option is safe to enable.
|
||||
|
||||
config OF_FLATTREE
|
||||
bool
|
||||
select DTC
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ obj-$(CONFIG_OF_GPIO) += gpio.o
|
|||
obj-$(CONFIG_OF_I2C) += of_i2c.o
|
||||
obj-$(CONFIG_OF_NET) += of_net.o
|
||||
obj-$(CONFIG_OF_SPI) += of_spi.o
|
||||
obj-$(CONFIG_OF_SELFTEST) += selftest.o
|
||||
obj-$(CONFIG_OF_MDIO) += of_mdio.o
|
||||
obj-$(CONFIG_OF_PCI) += of_pci.o
|
||||
obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
|
||||
|
|
|
|||
|
|
@ -824,17 +824,19 @@ of_parse_phandle(struct device_node *np, const char *phandle_name, int index)
|
|||
EXPORT_SYMBOL(of_parse_phandle);
|
||||
|
||||
/**
|
||||
* of_parse_phandles_with_args - Find a node pointed by phandle in a list
|
||||
* of_parse_phandle_with_args() - Find a node pointed by phandle in a list
|
||||
* @np: pointer to a device tree node containing a list
|
||||
* @list_name: property name that contains a list
|
||||
* @cells_name: property name that specifies phandles' arguments count
|
||||
* @index: index of a phandle to parse out
|
||||
* @out_node: optional pointer to device_node struct pointer (will be filled)
|
||||
* @out_args: optional pointer to arguments pointer (will be filled)
|
||||
* @out_args: optional pointer to output arguments structure (will be filled)
|
||||
*
|
||||
* This function is useful to parse lists of phandles and their arguments.
|
||||
* Returns 0 on success and fills out_node and out_args, on error returns
|
||||
* appropriate errno value.
|
||||
* Returns 0 on success and fills out_args, on error returns appropriate
|
||||
* errno value.
|
||||
*
|
||||
* Caller is responsible to call of_node_put() on the returned out_args->node
|
||||
* pointer.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
|
|
@ -851,94 +853,96 @@ EXPORT_SYMBOL(of_parse_phandle);
|
|||
* }
|
||||
*
|
||||
* To get a device_node of the `node2' node you may call this:
|
||||
* of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args);
|
||||
* of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
|
||||
*/
|
||||
int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
|
||||
int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
|
||||
const char *cells_name, int index,
|
||||
struct device_node **out_node,
|
||||
const void **out_args)
|
||||
struct of_phandle_args *out_args)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
const __be32 *list;
|
||||
const __be32 *list_end;
|
||||
int size;
|
||||
int cur_index = 0;
|
||||
const __be32 *list, *list_end;
|
||||
int size, cur_index = 0;
|
||||
uint32_t count = 0;
|
||||
struct device_node *node = NULL;
|
||||
const void *args = NULL;
|
||||
phandle phandle;
|
||||
|
||||
/* Retrieve the phandle list property */
|
||||
list = of_get_property(np, list_name, &size);
|
||||
if (!list) {
|
||||
ret = -ENOENT;
|
||||
goto err0;
|
||||
}
|
||||
if (!list)
|
||||
return -EINVAL;
|
||||
list_end = list + size / sizeof(*list);
|
||||
|
||||
/* Loop over the phandles until all the requested entry is found */
|
||||
while (list < list_end) {
|
||||
const __be32 *cells;
|
||||
phandle phandle;
|
||||
count = 0;
|
||||
|
||||
/*
|
||||
* If phandle is 0, then it is an empty entry with no
|
||||
* arguments. Skip forward to the next entry.
|
||||
*/
|
||||
phandle = be32_to_cpup(list++);
|
||||
args = list;
|
||||
if (phandle) {
|
||||
/*
|
||||
* Find the provider node and parse the #*-cells
|
||||
* property to determine the argument length
|
||||
*/
|
||||
node = of_find_node_by_phandle(phandle);
|
||||
if (!node) {
|
||||
pr_err("%s: could not find phandle\n",
|
||||
np->full_name);
|
||||
break;
|
||||
}
|
||||
if (of_property_read_u32(node, cells_name, &count)) {
|
||||
pr_err("%s: could not get %s for %s\n",
|
||||
np->full_name, cells_name,
|
||||
node->full_name);
|
||||
break;
|
||||
}
|
||||
|
||||
/* one cell hole in the list = <>; */
|
||||
if (!phandle)
|
||||
goto next;
|
||||
|
||||
node = of_find_node_by_phandle(phandle);
|
||||
if (!node) {
|
||||
pr_debug("%s: could not find phandle\n",
|
||||
np->full_name);
|
||||
goto err0;
|
||||
/*
|
||||
* Make sure that the arguments actually fit in the
|
||||
* remaining property data length
|
||||
*/
|
||||
if (list + count > list_end) {
|
||||
pr_err("%s: arguments longer than property\n",
|
||||
np->full_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cells = of_get_property(node, cells_name, &size);
|
||||
if (!cells || size != sizeof(*cells)) {
|
||||
pr_debug("%s: could not get %s for %s\n",
|
||||
np->full_name, cells_name, node->full_name);
|
||||
goto err1;
|
||||
}
|
||||
/*
|
||||
* All of the error cases above bail out of the loop, so at
|
||||
* this point, the parsing is successful. If the requested
|
||||
* index matches, then fill the out_args structure and return,
|
||||
* or return -ENOENT for an empty entry.
|
||||
*/
|
||||
if (cur_index == index) {
|
||||
if (!phandle)
|
||||
return -ENOENT;
|
||||
|
||||
list += be32_to_cpup(cells);
|
||||
if (list > list_end) {
|
||||
pr_debug("%s: insufficient arguments length\n",
|
||||
np->full_name);
|
||||
goto err1;
|
||||
if (out_args) {
|
||||
int i;
|
||||
if (WARN_ON(count > MAX_PHANDLE_ARGS))
|
||||
count = MAX_PHANDLE_ARGS;
|
||||
out_args->np = node;
|
||||
out_args->args_count = count;
|
||||
for (i = 0; i < count; i++)
|
||||
out_args->args[i] = be32_to_cpup(list++);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
next:
|
||||
if (cur_index == index)
|
||||
break;
|
||||
|
||||
of_node_put(node);
|
||||
node = NULL;
|
||||
args = NULL;
|
||||
list += count;
|
||||
cur_index++;
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
/*
|
||||
* args w/o node indicates that the loop above has stopped at
|
||||
* the 'hole' cell. Report this differently.
|
||||
*/
|
||||
if (args)
|
||||
ret = -EEXIST;
|
||||
else
|
||||
ret = -ENOENT;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (out_node)
|
||||
*out_node = node;
|
||||
if (out_args)
|
||||
*out_args = args;
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
of_node_put(node);
|
||||
err0:
|
||||
pr_debug("%s failed with status %d\n", __func__, ret);
|
||||
return ret;
|
||||
/* Loop exited without finding a valid entry; return an error */
|
||||
if (node)
|
||||
of_node_put(node);
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(of_parse_phandles_with_args);
|
||||
EXPORT_SYMBOL(of_parse_phandle_with_args);
|
||||
|
||||
/**
|
||||
* prom_add_property - Add a property to a node
|
||||
|
|
|
|||
|
|
@ -35,32 +35,27 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
|
|||
int index, enum of_gpio_flags *flags)
|
||||
{
|
||||
int ret;
|
||||
struct device_node *gpio_np;
|
||||
struct gpio_chip *gc;
|
||||
int size;
|
||||
const void *gpio_spec;
|
||||
const __be32 *gpio_cells;
|
||||
struct of_phandle_args gpiospec;
|
||||
|
||||
ret = of_parse_phandles_with_args(np, propname, "#gpio-cells", index,
|
||||
&gpio_np, &gpio_spec);
|
||||
ret = of_parse_phandle_with_args(np, propname, "#gpio-cells", index,
|
||||
&gpiospec);
|
||||
if (ret) {
|
||||
pr_debug("%s: can't parse gpios property\n", __func__);
|
||||
goto err0;
|
||||
}
|
||||
|
||||
gc = of_node_to_gpiochip(gpio_np);
|
||||
gc = of_node_to_gpiochip(gpiospec.np);
|
||||
if (!gc) {
|
||||
pr_debug("%s: gpio controller %s isn't registered\n",
|
||||
np->full_name, gpio_np->full_name);
|
||||
np->full_name, gpiospec.np->full_name);
|
||||
ret = -ENODEV;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
gpio_cells = of_get_property(gpio_np, "#gpio-cells", &size);
|
||||
if (!gpio_cells || size != sizeof(*gpio_cells) ||
|
||||
be32_to_cpup(gpio_cells) != gc->of_gpio_n_cells) {
|
||||
if (gpiospec.args_count != gc->of_gpio_n_cells) {
|
||||
pr_debug("%s: wrong #gpio-cells for %s\n",
|
||||
np->full_name, gpio_np->full_name);
|
||||
np->full_name, gpiospec.np->full_name);
|
||||
ret = -EINVAL;
|
||||
goto err1;
|
||||
}
|
||||
|
|
@ -69,13 +64,13 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
|
|||
if (flags)
|
||||
*flags = 0;
|
||||
|
||||
ret = gc->of_xlate(gc, np, gpio_spec, flags);
|
||||
ret = gc->of_xlate(gc, &gpiospec, flags);
|
||||
if (ret < 0)
|
||||
goto err1;
|
||||
|
||||
ret += gc->base;
|
||||
err1:
|
||||
of_node_put(gpio_np);
|
||||
of_node_put(gpiospec.np);
|
||||
err0:
|
||||
pr_debug("%s exited with status %d\n", __func__, ret);
|
||||
return ret;
|
||||
|
|
@ -105,8 +100,8 @@ unsigned int of_gpio_count(struct device_node *np)
|
|||
do {
|
||||
int ret;
|
||||
|
||||
ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells",
|
||||
cnt, NULL, NULL);
|
||||
ret = of_parse_phandle_with_args(np, "gpios", "#gpio-cells",
|
||||
cnt, NULL);
|
||||
/* A hole in the gpios = <> counts anyway. */
|
||||
if (ret < 0 && ret != -EEXIST)
|
||||
break;
|
||||
|
|
@ -127,12 +122,9 @@ EXPORT_SYMBOL(of_gpio_count);
|
|||
* gpio chips. This function performs only one sanity check: whether gpio
|
||||
* is less than ngpios (that is specified in the gpio_chip).
|
||||
*/
|
||||
int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
|
||||
const void *gpio_spec, u32 *flags)
|
||||
int of_gpio_simple_xlate(struct gpio_chip *gc,
|
||||
const struct of_phandle_args *gpiospec, u32 *flags)
|
||||
{
|
||||
const __be32 *gpio = gpio_spec;
|
||||
const u32 n = be32_to_cpup(gpio);
|
||||
|
||||
/*
|
||||
* We're discouraging gpio_cells < 2, since that way you'll have to
|
||||
* write your own xlate function (that will have to retrive the GPIO
|
||||
|
|
@ -144,13 +136,16 @@ int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (n > gc->ngpio)
|
||||
if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
|
||||
return -EINVAL;
|
||||
|
||||
if (gpiospec->args[0] > gc->ngpio)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags)
|
||||
*flags = be32_to_cpu(gpio[1]);
|
||||
*flags = gpiospec->args[1];
|
||||
|
||||
return n;
|
||||
return gpiospec->args[0];
|
||||
}
|
||||
EXPORT_SYMBOL(of_gpio_simple_xlate);
|
||||
|
||||
|
|
@ -198,8 +193,6 @@ int of_mm_gpiochip_add(struct device_node *np,
|
|||
if (ret)
|
||||
goto err2;
|
||||
|
||||
pr_debug("%s: registered as generic GPIO chip, base is %d\n",
|
||||
np->full_name, gc->base);
|
||||
return 0;
|
||||
err2:
|
||||
iounmap(mm_gc->regs);
|
||||
|
|
|
|||
139
drivers/of/selftest.c
Normal file
139
drivers/of/selftest.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Self tests for device tree subsystem
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "### %s(): " fmt, __func__
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
static bool selftest_passed = true;
|
||||
#define selftest(result, fmt, ...) { \
|
||||
selftest_passed &= (result); \
|
||||
if (!(result)) \
|
||||
pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
|
||||
}
|
||||
|
||||
static void __init of_selftest_parse_phandle_with_args(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct of_phandle_args args;
|
||||
int rc, i;
|
||||
bool passed_all = true;
|
||||
|
||||
pr_info("start\n");
|
||||
np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
|
||||
if (!np) {
|
||||
pr_err("missing testcase data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
bool passed = true;
|
||||
rc = of_parse_phandle_with_args(np, "phandle-list",
|
||||
"#phandle-cells", i, &args);
|
||||
|
||||
/* Test the values from tests-phandle.dtsi */
|
||||
switch (i) {
|
||||
case 0:
|
||||
passed &= !rc;
|
||||
passed &= (args.args_count == 1);
|
||||
passed &= (args.args[0] == (i + 1));
|
||||
break;
|
||||
case 1:
|
||||
passed &= !rc;
|
||||
passed &= (args.args_count == 2);
|
||||
passed &= (args.args[0] == (i + 1));
|
||||
passed &= (args.args[1] == 0);
|
||||
break;
|
||||
case 2:
|
||||
passed &= (rc == -ENOENT);
|
||||
break;
|
||||
case 3:
|
||||
passed &= !rc;
|
||||
passed &= (args.args_count == 3);
|
||||
passed &= (args.args[0] == (i + 1));
|
||||
passed &= (args.args[1] == 4);
|
||||
passed &= (args.args[2] == 3);
|
||||
break;
|
||||
case 4:
|
||||
passed &= !rc;
|
||||
passed &= (args.args_count == 2);
|
||||
passed &= (args.args[0] == (i + 1));
|
||||
passed &= (args.args[1] == 100);
|
||||
break;
|
||||
case 5:
|
||||
passed &= !rc;
|
||||
passed &= (args.args_count == 0);
|
||||
break;
|
||||
case 6:
|
||||
passed &= !rc;
|
||||
passed &= (args.args_count == 1);
|
||||
passed &= (args.args[0] == (i + 1));
|
||||
break;
|
||||
case 7:
|
||||
passed &= (rc == -EINVAL);
|
||||
break;
|
||||
default:
|
||||
passed = false;
|
||||
}
|
||||
|
||||
if (!passed) {
|
||||
int j;
|
||||
pr_err("index %i - data error on node %s rc=%i regs=[",
|
||||
i, args.np->full_name, rc);
|
||||
for (j = 0; j < args.args_count; j++)
|
||||
printk(" %i", args.args[j]);
|
||||
printk(" ]\n");
|
||||
|
||||
passed_all = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for missing list property */
|
||||
rc = of_parse_phandle_with_args(np, "phandle-list-missing",
|
||||
"#phandle-cells", 0, &args);
|
||||
passed_all &= (rc == -EINVAL);
|
||||
|
||||
/* Check for missing cells property */
|
||||
rc = of_parse_phandle_with_args(np, "phandle-list",
|
||||
"#phandle-cells-missing", 0, &args);
|
||||
passed_all &= (rc == -EINVAL);
|
||||
|
||||
/* Check for bad phandle in list */
|
||||
rc = of_parse_phandle_with_args(np, "phandle-list-bad-phandle",
|
||||
"#phandle-cells", 0, &args);
|
||||
passed_all &= (rc == -EINVAL);
|
||||
|
||||
/* Check for incorrectly formed argument list */
|
||||
rc = of_parse_phandle_with_args(np, "phandle-list-bad-args",
|
||||
"#phandle-cells", 1, &args);
|
||||
passed_all &= (rc == -EINVAL);
|
||||
|
||||
pr_info("end - %s\n", passed_all ? "PASS" : "FAIL");
|
||||
}
|
||||
|
||||
static int __init of_selftest(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
|
||||
if (!np) {
|
||||
pr_info("No testcase data in device tree; not running tests\n");
|
||||
return 0;
|
||||
}
|
||||
of_node_put(np);
|
||||
|
||||
pr_info("start of selftest - you will see error messages\n");
|
||||
of_selftest_parse_phandle_with_args();
|
||||
pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
|
||||
return 0;
|
||||
}
|
||||
late_initcall(of_selftest);
|
||||
Loading…
Reference in a new issue