dect
/
linux-2.6
Archived
13
0
Fork 0

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:
Linus Torvalds 2012-01-07 12:15:36 -08:00
commit fbce1c234f
37 changed files with 529 additions and 401 deletions

View File

@ -2912,6 +2912,7 @@ F: include/linux/gigaset_dev.h
GPIO SUBSYSTEM
M: Grant Likely <grant.likely@secretlab.ca>
M: Linus Walleij <linus.walleij@stericsson.com>
S: Maintained
T: git git://git.secretlab.ca/git/linux-2.6.git
F: Documentation/gpio.txt

View File

@ -0,0 +1,37 @@
/ {
testcase-data {
phandle-tests {
provider0: provider0 {
#phandle-cells = <0>;
};
provider1: provider1 {
#phandle-cells = <1>;
};
provider2: provider2 {
#phandle-cells = <2>;
};
provider3: provider3 {
#phandle-cells = <3>;
};
consumer-a {
phandle-list = <&provider1 1>,
<&provider2 2 0>,
<0>,
<&provider3 4 4 3>,
<&provider2 5 100>,
<&provider0>,
<&provider1 7>;
phandle-list-names = "first", "second", "third";
phandle-list-bad-phandle = <12345678 0 0>;
phandle-list-bad-args = <&provider2 1 0>,
<&provider3 0>;
};
};
};
};

View File

@ -0,0 +1 @@
/include/ "tests-phandle.dtsi"

View File

@ -46,3 +46,5 @@
};
};
};
/include/ "testcases/tests.dtsi"

View File

@ -19,50 +19,11 @@
static int handle; /* reset pin handle */
static unsigned int reset_val;
static int of_reset_gpio_handle(void)
{
int ret; /* variable which stored handle reset gpio pin */
struct device_node *root; /* root node */
struct device_node *gpio; /* gpio node */
struct gpio_chip *gc;
u32 flags;
const void *gpio_spec;
/* find out root node */
root = of_find_node_by_path("/");
/* give me handle for gpio node to be possible allocate pin */
ret = of_parse_phandles_with_args(root, "hard-reset-gpios",
"#gpio-cells", 0, &gpio, &gpio_spec);
if (ret) {
pr_debug("%s: can't parse gpios property\n", __func__);
goto err0;
}
gc = of_node_to_gpiochip(gpio);
if (!gc) {
pr_debug("%s: gpio controller %s isn't registered\n",
root->full_name, gpio->full_name);
ret = -ENODEV;
goto err1;
}
ret = gc->of_xlate(gc, root, gpio_spec, &flags);
if (ret < 0)
goto err1;
ret += gc->base;
err1:
of_node_put(gpio);
err0:
pr_debug("%s exited with status %d\n", __func__, ret);
return ret;
}
void of_platform_reset_gpio_probe(void)
{
int ret;
handle = of_reset_gpio_handle();
handle = of_get_named_gpio(of_find_node_by_path("/"),
"hard-reset-gpios", 0);
if (!gpio_is_valid(handle)) {
printk(KERN_INFO "Skipping unavailable RESET gpio %d (%s)\n",

View File

@ -139,14 +139,10 @@ struct qe_pin {
struct qe_pin *qe_pin_request(struct device_node *np, int index)
{
struct qe_pin *qe_pin;
struct device_node *gpio_np;
struct gpio_chip *gc;
struct of_mm_gpio_chip *mm_gc;
struct qe_gpio_chip *qe_gc;
int err;
int size;
const void *gpio_spec;
const u32 *gpio_cells;
unsigned long flags;
qe_pin = kzalloc(sizeof(*qe_pin), GFP_KERNEL);
@ -155,45 +151,25 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index)
return ERR_PTR(-ENOMEM);
}
err = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
&gpio_np, &gpio_spec);
if (err) {
pr_debug("%s: can't parse gpios property\n", __func__);
err = of_get_gpio(np, index);
if (err < 0)
goto err0;
gc = gpio_to_chip(err);
if (WARN_ON(!gc))
goto err0;
}
if (!of_device_is_compatible(gpio_np, "fsl,mpc8323-qe-pario-bank")) {
if (!of_device_is_compatible(gc->of_node, "fsl,mpc8323-qe-pario-bank")) {
pr_debug("%s: tried to get a non-qe pin\n", __func__);
err = -EINVAL;
goto err1;
goto err0;
}
gc = of_node_to_gpiochip(gpio_np);
if (!gc) {
pr_debug("%s: gpio controller %s isn't registered\n",
np->full_name, gpio_np->full_name);
err = -ENODEV;
goto err1;
}
gpio_cells = of_get_property(gpio_np, "#gpio-cells", &size);
if (!gpio_cells || size != sizeof(*gpio_cells) ||
*gpio_cells != gc->of_gpio_n_cells) {
pr_debug("%s: wrong #gpio-cells for %s\n",
np->full_name, gpio_np->full_name);
err = -EINVAL;
goto err1;
}
err = gc->of_xlate(gc, np, gpio_spec, NULL);
if (err < 0)
goto err1;
mm_gc = to_of_mm_gpio_chip(gc);
qe_gc = to_qe_gpio_chip(mm_gc);
spin_lock_irqsave(&qe_gc->lock, flags);
err -= gc->base;
if (test_and_set_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[err]) == 0) {
qe_pin->controller = qe_gc;
qe_pin->num = err;
@ -206,8 +182,6 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index)
if (!err)
return qe_pin;
err1:
of_node_put(gpio_np);
err0:
kfree(qe_pin);
pr_debug("%s failed with status %d\n", __func__, err);

View File

@ -387,7 +387,7 @@ config GPIO_LANGWELL
Say Y here to support Intel Langwell/Penwell GPIO.
config GPIO_PCH
tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO"
depends on PCI && X86
select GENERIC_IRQ_CHIP
help
@ -395,11 +395,12 @@ config GPIO_PCH
which is an IOH(Input/Output Hub) for x86 embedded processor.
This driver can access PCH GPIO device.
This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
Output Hub), ML7223.
This driver also can be used for LAPIS Semiconductor IOH(Input/
Output Hub), ML7223 and ML7831.
ML7223 IOH is for MP(Media Phone) use.
ML7223 is companion chip for Intel Atom E6xx series.
ML7223 is completely compatible for Intel EG20T PCH.
ML7831 IOH is for general purpose use.
ML7223/ML7831 is companion chip for Intel Atom E6xx series.
ML7223/ML7831 is completely compatible for Intel EG20T PCH.
config GPIO_ML_IOH
tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"

View File

@ -193,17 +193,7 @@ static struct platform_driver adp5520_gpio_driver = {
.remove = __devexit_p(adp5520_gpio_remove),
};
static int __init adp5520_gpio_init(void)
{
return platform_driver_register(&adp5520_gpio_driver);
}
module_init(adp5520_gpio_init);
static void __exit adp5520_gpio_exit(void)
{
platform_driver_unregister(&adp5520_gpio_driver);
}
module_exit(adp5520_gpio_exit);
module_platform_driver(adp5520_gpio_driver);
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("GPIO ADP5520 Driver");

View File

@ -418,9 +418,8 @@ static int __devinit adp5588_gpio_probe(struct i2c_client *client,
if (ret)
goto err_irq;
dev_info(&client->dev, "gpios %d..%d (IRQ Base %d) on a %s Rev. %d\n",
gc->base, gc->base + gc->ngpio - 1,
pdata->irq_base, client->name, revid);
dev_info(&client->dev, "IRQ Base: %d Rev.: %d\n",
pdata->irq_base, revid);
if (pdata->setup) {
ret = pdata->setup(client, gc->base, gc->ngpio, pdata->context);

View File

@ -223,9 +223,6 @@ static int bt8xxgpio_probe(struct pci_dev *dev,
goto err_release_mem;
}
printk(KERN_INFO "bt8xxgpio: Abusing BT8xx card for GPIOs %d to %d\n",
bg->gpio.base, bg->gpio.base + BT8XXGPIO_NR_GPIOS - 1);
return 0;
err_release_mem:

View File

@ -347,7 +347,6 @@ static int __devinit cs5535_gpio_probe(struct platform_device *pdev)
if (err)
goto release_region;
dev_info(&pdev->dev, "GPIO support successfully loaded.\n");
return 0;
release_region:
@ -382,18 +381,7 @@ static struct platform_driver cs5535_gpio_driver = {
.remove = __devexit_p(cs5535_gpio_remove),
};
static int __init cs5535_gpio_init(void)
{
return platform_driver_register(&cs5535_gpio_driver);
}
static void __exit cs5535_gpio_exit(void)
{
platform_driver_unregister(&cs5535_gpio_driver);
}
module_init(cs5535_gpio_init);
module_exit(cs5535_gpio_exit);
module_platform_driver(cs5535_gpio_driver);
MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");

View File

@ -254,17 +254,7 @@ static struct platform_driver da9052_gpio_driver = {
},
};
static int __init da9052_gpio_init(void)
{
return platform_driver_register(&da9052_gpio_driver);
}
module_init(da9052_gpio_init);
static void __exit da9052_gpio_exit(void)
{
return platform_driver_unregister(&da9052_gpio_driver);
}
module_exit(da9052_gpio_exit);
module_platform_driver(da9052_gpio_driver);
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
MODULE_DESCRIPTION("DA9052 GPIO Device Driver");

View File

@ -524,17 +524,7 @@ static struct platform_driver bgpio_driver = {
.remove = __devexit_p(bgpio_pdev_remove),
};
static int __init bgpio_platform_init(void)
{
return platform_driver_register(&bgpio_driver);
}
module_init(bgpio_platform_init);
static void __exit bgpio_platform_exit(void)
{
platform_driver_unregister(&bgpio_driver);
}
module_exit(bgpio_platform_exit);
module_platform_driver(bgpio_driver);
#endif /* CONFIG_GPIO_GENERIC_PLATFORM */

View File

@ -201,8 +201,6 @@ static int __devinit ttl_probe(struct platform_device *pdev)
goto out_iounmap_regs;
}
dev_info(&pdev->dev, "module %d: registered GPIO device\n",
pdata->modno);
return 0;
out_iounmap_regs:
@ -239,20 +237,9 @@ static struct platform_driver ttl_driver = {
.remove = __devexit_p(ttl_remove),
};
static int __init ttl_init(void)
{
return platform_driver_register(&ttl_driver);
}
static void __exit ttl_exit(void)
{
platform_driver_unregister(&ttl_driver);
}
module_platform_driver(ttl_driver);
MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:janz-ttl");
module_init(ttl_init);
module_exit(ttl_exit);

View File

@ -1150,8 +1150,8 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
nmk_gpio_init_irq(nmk_chip);
dev_info(&dev->dev, "Bits %i-%i at address %p\n",
nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr);
dev_info(&dev->dev, "at address %p\n",
nmk_chip->addr);
return 0;
out_free:

View File

@ -290,10 +290,7 @@ static int pcf857x_probe(struct i2c_client *client,
* methods can't be called from sleeping contexts.
*/
dev_info(&client->dev, "gpios %d..%d on a %s%s\n",
gpio->chip.base,
gpio->chip.base + gpio->chip.ngpio - 1,
client->name,
dev_info(&client->dev, "%s\n",
client->irq ? " (irq ignored)" : "");
/* Let platform code set up the GPIOs and their users.

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
* Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -49,8 +49,8 @@ struct pch_regs {
enum pch_type_t {
INTEL_EG20T_PCH,
OKISEMI_ML7223m_IOH, /* OKISEMI ML7223 IOH PCIe Bus-m */
OKISEMI_ML7223n_IOH /* OKISEMI ML7223 IOH PCIe Bus-n */
OKISEMI_ML7223m_IOH, /* LAPIS Semiconductor ML7223 IOH PCIe Bus-m */
OKISEMI_ML7223n_IOH /* LAPIS Semiconductor ML7223 IOH PCIe Bus-n */
};
/* Specifies number of GPIO PINS */
@ -524,6 +524,7 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8043) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8803) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);

View File

@ -227,18 +227,7 @@ static struct platform_driver rdc321x_gpio_driver = {
.remove = __devexit_p(rdc321x_gpio_remove),
};
static int __init rdc321x_gpio_init(void)
{
return platform_driver_register(&rdc321x_gpio_driver);
}
static void __exit rdc321x_gpio_exit(void)
{
platform_driver_unregister(&rdc321x_gpio_driver);
}
module_init(rdc321x_gpio_init);
module_exit(rdc321x_gpio_exit);
module_platform_driver(rdc321x_gpio_driver);
MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
MODULE_DESCRIPTION("RDC321x GPIO driver");

View File

@ -230,7 +230,7 @@ static int samsung_gpio_setcfg_2bit(struct samsung_gpio_chip *chip,
* @chip: The gpio chip that is being configured.
* @off: The offset for the GPIO being configured.
*
* The reverse of samsung_gpio_setcfg_2bit(). Will return a value whicg
* The reverse of samsung_gpio_setcfg_2bit(). Will return a value which
* could be directly passed back to samsung_gpio_setcfg_2bit(), from the
* S3C_GPIO_SPECIAL() macro.
*/
@ -467,33 +467,42 @@ static struct samsung_gpio_cfg s5p64x0_gpio_cfg_rbank = {
#endif
static struct samsung_gpio_cfg samsung_gpio_cfgs[] = {
{
[0] = {
.cfg_eint = 0x0,
}, {
},
[1] = {
.cfg_eint = 0x3,
}, {
},
[2] = {
.cfg_eint = 0x7,
}, {
},
[3] = {
.cfg_eint = 0xF,
}, {
},
[4] = {
.cfg_eint = 0x0,
.set_config = samsung_gpio_setcfg_2bit,
.get_config = samsung_gpio_getcfg_2bit,
}, {
},
[5] = {
.cfg_eint = 0x2,
.set_config = samsung_gpio_setcfg_2bit,
.get_config = samsung_gpio_getcfg_2bit,
}, {
},
[6] = {
.cfg_eint = 0x3,
.set_config = samsung_gpio_setcfg_2bit,
.get_config = samsung_gpio_getcfg_2bit,
}, {
},
[7] = {
.set_config = samsung_gpio_setcfg_2bit,
.get_config = samsung_gpio_getcfg_2bit,
}, {
},
[8] = {
.set_pull = exynos4_gpio_setpull,
.get_pull = exynos4_gpio_getpull,
}, {
},
[9] = {
.cfg_eint = 0x3,
.set_pull = exynos4_gpio_setpull,
.get_pull = exynos4_gpio_getpull,

View File

@ -297,18 +297,7 @@ static struct platform_driver sch_gpio_driver = {
.remove = __devexit_p(sch_gpio_remove),
};
static int __init sch_gpio_init(void)
{
return platform_driver_register(&sch_gpio_driver);
}
static void __exit sch_gpio_exit(void)
{
platform_driver_unregister(&sch_gpio_driver);
}
module_init(sch_gpio_init);
module_exit(sch_gpio_exit);
module_platform_driver(sch_gpio_driver);
MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH");

View File

@ -359,18 +359,7 @@ static struct platform_driver timbgpio_platform_driver = {
/*--------------------------------------------------------------------------*/
static int __init timbgpio_init(void)
{
return platform_driver_register(&timbgpio_platform_driver);
}
static void __exit timbgpio_exit(void)
{
platform_driver_unregister(&timbgpio_platform_driver);
}
module_init(timbgpio_init);
module_exit(timbgpio_exit);
module_platform_driver(timbgpio_platform_driver);
MODULE_DESCRIPTION("Timberdale GPIO driver");
MODULE_LICENSE("GPL v2");

View File

@ -103,23 +103,12 @@ static struct platform_driver ucb1400_gpio_driver = {
},
};
static int __init ucb1400_gpio_init(void)
{
return platform_driver_register(&ucb1400_gpio_driver);
}
static void __exit ucb1400_gpio_exit(void)
{
platform_driver_unregister(&ucb1400_gpio_driver);
}
void __init ucb1400_gpio_set_data(struct ucb1400_gpio_data *data)
{
ucbdata = data;
}
module_init(ucb1400_gpio_init);
module_exit(ucb1400_gpio_exit);
module_platform_driver(ucb1400_gpio_driver);
MODULE_DESCRIPTION("Philips UCB1400 GPIO driver");
MODULE_LICENSE("GPL");

View File

@ -571,15 +571,4 @@ static struct platform_driver giu_device_driver = {
},
};
static int __init vr41xx_giu_init(void)
{
return platform_driver_register(&giu_device_driver);
}
static void __exit vr41xx_giu_exit(void)
{
platform_driver_unregister(&giu_device_driver);
}
module_init(vr41xx_giu_init);
module_exit(vr41xx_giu_exit);
module_platform_driver(giu_device_driver);

View File

@ -315,17 +315,7 @@ static struct platform_driver vx855gpio_driver = {
.remove = __devexit_p(vx855gpio_remove),
};
static int vx855gpio_init(void)
{
return platform_driver_register(&vx855gpio_driver);
}
module_init(vx855gpio_init);
static void vx855gpio_exit(void)
{
platform_driver_unregister(&vx855gpio_driver);
}
module_exit(vx855gpio_exit);
module_platform_driver(vx855gpio_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>");

View File

@ -117,6 +117,60 @@ static int wm8994_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
#ifdef CONFIG_DEBUG_FS
static const char *wm8994_gpio_fn(u16 fn)
{
switch (fn) {
case WM8994_GP_FN_PIN_SPECIFIC:
return "pin-specific";
case WM8994_GP_FN_GPIO:
return "GPIO";
case WM8994_GP_FN_SDOUT:
return "SDOUT";
case WM8994_GP_FN_IRQ:
return "IRQ";
case WM8994_GP_FN_TEMPERATURE:
return "Temperature";
case WM8994_GP_FN_MICBIAS1_DET:
return "MICBIAS1 detect";
case WM8994_GP_FN_MICBIAS1_SHORT:
return "MICBIAS1 short";
case WM8994_GP_FN_MICBIAS2_DET:
return "MICBIAS2 detect";
case WM8994_GP_FN_MICBIAS2_SHORT:
return "MICBIAS2 short";
case WM8994_GP_FN_FLL1_LOCK:
return "FLL1 lock";
case WM8994_GP_FN_FLL2_LOCK:
return "FLL2 lock";
case WM8994_GP_FN_SRC1_LOCK:
return "SRC1 lock";
case WM8994_GP_FN_SRC2_LOCK:
return "SRC2 lock";
case WM8994_GP_FN_DRC1_ACT:
return "DRC1 activity";
case WM8994_GP_FN_DRC2_ACT:
return "DRC2 activity";
case WM8994_GP_FN_DRC3_ACT:
return "DRC3 activity";
case WM8994_GP_FN_WSEQ_STATUS:
return "Write sequencer";
case WM8994_GP_FN_FIFO_ERROR:
return "FIFO error";
case WM8994_GP_FN_OPCLK:
return "OPCLK";
case WM8994_GP_FN_THW:
return "Thermal warning";
case WM8994_GP_FN_DCS_DONE:
return "DC servo";
case WM8994_GP_FN_FLL1_OUT:
return "FLL1 output";
case WM8994_GP_FN_FLL2_OUT:
return "FLL1 output";
default:
return "Unknown";
}
}
static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
@ -148,8 +202,29 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
continue;
}
/* No decode yet; note that GPIO2 is special */
seq_printf(s, "(%x)\n", reg);
if (reg & WM8994_GPN_DIR)
seq_printf(s, "in ");
else
seq_printf(s, "out ");
if (reg & WM8994_GPN_PU)
seq_printf(s, "pull up ");
if (reg & WM8994_GPN_PD)
seq_printf(s, "pull down ");
if (reg & WM8994_GPN_POL)
seq_printf(s, "inverted ");
else
seq_printf(s, "noninverted ");
if (reg & WM8994_GPN_OP_CFG)
seq_printf(s, "open drain ");
else
seq_printf(s, "CMOS ");
seq_printf(s, "%s (%x)\n",
wm8994_gpio_fn(reg & WM8994_GPN_FN_MASK), reg);
}
}
#else

View File

@ -206,7 +206,6 @@ static int __devinit xgpio_of_probe(struct device_node *np)
np->full_name, status);
return status;
}
pr_info("XGpio: %s: registered\n", np->full_name);
return 0;
}

View File

@ -114,7 +114,7 @@ static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset)
}
/* caller holds gpio_lock *OR* gpio is marked as requested */
static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
struct gpio_chip *gpio_to_chip(unsigned gpio)
{
return gpio_desc[gpio].chip;
}
@ -1089,6 +1089,10 @@ unlock:
if (status)
goto fail;
pr_info("gpiochip_add: registered GPIOs %d to %d on device: %s\n",
chip->base, chip->base + chip->ngpio - 1,
chip->label ? : "generic");
return 0;
fail:
/* failures here can mean systems won't boot... */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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);

View File

@ -340,6 +340,10 @@ struct vendor_data {
* @cur_msg: Pointer to current spi_message being processed
* @cur_transfer: Pointer to current spi_transfer
* @cur_chip: pointer to current clients chip(assigned from controller_state)
* @next_msg_cs_active: the next message in the queue has been examined
* and it was found that it uses the same chip select as the previous
* message, so we left it active after the previous transfer, and it's
* active already.
* @tx: current position in TX buffer to be read
* @tx_end: end position in TX buffer to be read
* @rx: current position in RX buffer to be written
@ -373,6 +377,7 @@ struct pl022 {
struct spi_message *cur_msg;
struct spi_transfer *cur_transfer;
struct chip_data *cur_chip;
bool next_msg_cs_active;
void *tx;
void *tx_end;
void *rx;
@ -445,23 +450,9 @@ static void giveback(struct pl022 *pl022)
struct spi_transfer *last_transfer;
unsigned long flags;
struct spi_message *msg;
void (*curr_cs_control) (u32 command);
pl022->next_msg_cs_active = false;
/*
* This local reference to the chip select function
* is needed because we set curr_chip to NULL
* as a step toward termininating the message.
*/
curr_cs_control = pl022->cur_chip->cs_control;
spin_lock_irqsave(&pl022->queue_lock, flags);
msg = pl022->cur_msg;
pl022->cur_msg = NULL;
pl022->cur_transfer = NULL;
pl022->cur_chip = NULL;
queue_work(pl022->workqueue, &pl022->pump_messages);
spin_unlock_irqrestore(&pl022->queue_lock, flags);
last_transfer = list_entry(msg->transfers.prev,
last_transfer = list_entry(pl022->cur_msg->transfers.prev,
struct spi_transfer,
transfer_list);
@ -473,18 +464,13 @@ static void giveback(struct pl022 *pl022)
*/
udelay(last_transfer->delay_usecs);
/*
* Drop chip select UNLESS cs_change is true or we are returning
* a message with an error, or next message is for another chip
*/
if (!last_transfer->cs_change)
curr_cs_control(SSP_CHIP_DESELECT);
else {
if (!last_transfer->cs_change) {
struct spi_message *next_msg;
/* Holding of cs was hinted, but we need to make sure
* the next message is for the same chip. Don't waste
* time with the following tests unless this was hinted.
/*
* cs_change was not set. We can keep the chip select
* enabled if there is message in the queue and it is
* for the same spi device.
*
* We cannot postpone this until pump_messages, because
* after calling msg->complete (below) the driver that
@ -501,19 +487,29 @@ static void giveback(struct pl022 *pl022)
struct spi_message, queue);
spin_unlock_irqrestore(&pl022->queue_lock, flags);
/* see if the next and current messages point
* to the same chip
/*
* see if the next and current messages point
* to the same spi device.
*/
if (next_msg && next_msg->spi != msg->spi)
if (next_msg && next_msg->spi != pl022->cur_msg->spi)
next_msg = NULL;
if (!next_msg || msg->state == STATE_ERROR)
curr_cs_control(SSP_CHIP_DESELECT);
if (!next_msg || pl022->cur_msg->state == STATE_ERROR)
pl022->cur_chip->cs_control(SSP_CHIP_DESELECT);
else
pl022->next_msg_cs_active = true;
}
spin_lock_irqsave(&pl022->queue_lock, flags);
msg = pl022->cur_msg;
pl022->cur_msg = NULL;
pl022->cur_transfer = NULL;
pl022->cur_chip = NULL;
queue_work(pl022->workqueue, &pl022->pump_messages);
spin_unlock_irqrestore(&pl022->queue_lock, flags);
msg->state = NULL;
if (msg->complete)
msg->complete(msg->context);
/* This message is completed, so let's turn off the clocks & power */
pm_runtime_put(&pl022->adev->dev);
}
/**
@ -1244,9 +1240,9 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
if ((pl022->tx == pl022->tx_end) && (flag == 0)) {
flag = 1;
/* Disable Transmit interrupt */
writew(readw(SSP_IMSC(pl022->virtbase)) &
(~SSP_IMSC_MASK_TXIM),
/* Disable Transmit interrupt, enable receive interrupt */
writew((readw(SSP_IMSC(pl022->virtbase)) &
~SSP_IMSC_MASK_TXIM) | SSP_IMSC_MASK_RXIM,
SSP_IMSC(pl022->virtbase));
}
@ -1352,7 +1348,7 @@ static void pump_transfers(unsigned long data)
*/
udelay(previous->delay_usecs);
/* Drop chip select only if cs_change is requested */
/* Reselect chip select only if cs_change was requested */
if (previous->cs_change)
pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
} else {
@ -1379,15 +1375,22 @@ static void pump_transfers(unsigned long data)
}
err_config_dma:
writew(ENABLE_ALL_INTERRUPTS, SSP_IMSC(pl022->virtbase));
/* enable all interrupts except RX */
writew(ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM, SSP_IMSC(pl022->virtbase));
}
static void do_interrupt_dma_transfer(struct pl022 *pl022)
{
u32 irqflags = ENABLE_ALL_INTERRUPTS;
/*
* Default is to enable all interrupts except RX -
* this will be enabled once TX is complete
*/
u32 irqflags = ENABLE_ALL_INTERRUPTS & ~SSP_IMSC_MASK_RXIM;
/* Enable target chip, if not already active */
if (!pl022->next_msg_cs_active)
pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
/* Enable target chip */
pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
if (set_up_next_transfer(pl022, pl022->cur_transfer)) {
/* Error path */
pl022->cur_msg->state = STATE_ERROR;
@ -1442,7 +1445,8 @@ static void do_polling_transfer(struct pl022 *pl022)
} else {
/* STATE_START */
message->state = STATE_RUNNING;
pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
if (!pl022->next_msg_cs_active)
pl022->cur_chip->cs_control(SSP_CHIP_SELECT);
}
/* Configuration Changing Per Transfer */
@ -1504,14 +1508,28 @@ static void pump_messages(struct work_struct *work)
struct pl022 *pl022 =
container_of(work, struct pl022, pump_messages);
unsigned long flags;
bool was_busy = false;
/* Lock queue and check for queue work */
spin_lock_irqsave(&pl022->queue_lock, flags);
if (list_empty(&pl022->queue) || !pl022->running) {
if (pl022->busy) {
/* nothing more to do - disable spi/ssp and power off */
writew((readw(SSP_CR1(pl022->virtbase)) &
(~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
if (pl022->master_info->autosuspend_delay > 0) {
pm_runtime_mark_last_busy(&pl022->adev->dev);
pm_runtime_put_autosuspend(&pl022->adev->dev);
} else {
pm_runtime_put(&pl022->adev->dev);
}
}
pl022->busy = false;
spin_unlock_irqrestore(&pl022->queue_lock, flags);
return;
}
/* Make sure we are not already running a message */
if (pl022->cur_msg) {
spin_unlock_irqrestore(&pl022->queue_lock, flags);
@ -1522,7 +1540,10 @@ static void pump_messages(struct work_struct *work)
list_entry(pl022->queue.next, struct spi_message, queue);
list_del_init(&pl022->cur_msg->queue);
pl022->busy = true;
if (pl022->busy)
was_busy = true;
else
pl022->busy = true;
spin_unlock_irqrestore(&pl022->queue_lock, flags);
/* Initial message state */
@ -1532,12 +1553,14 @@ static void pump_messages(struct work_struct *work)
/* Setup the SPI using the per chip configuration */
pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
/*
* We enable the core voltage and clocks here, then the clocks
* and core will be disabled when giveback() is called in each method
* (poll/interrupt/DMA)
*/
pm_runtime_get_sync(&pl022->adev->dev);
if (!was_busy)
/*
* We enable the core voltage and clocks here, then the clocks
* and core will be disabled when this workqueue is run again
* and there is no more work to be done.
*/
pm_runtime_get_sync(&pl022->adev->dev);
restore_state(pl022);
flush(pl022);
@ -1582,6 +1605,7 @@ static int start_queue(struct pl022 *pl022)
pl022->cur_msg = NULL;
pl022->cur_transfer = NULL;
pl022->cur_chip = NULL;
pl022->next_msg_cs_active = false;
spin_unlock_irqrestore(&pl022->queue_lock, flags);
queue_work(pl022->workqueue, &pl022->pump_messages);
@ -1881,7 +1905,7 @@ static int pl022_setup(struct spi_device *spi)
{
struct pl022_config_chip const *chip_info;
struct chip_data *chip;
struct ssp_clock_params clk_freq = {0, };
struct ssp_clock_params clk_freq = { .cpsdvsr = 0, .scr = 0};
int status = 0;
struct pl022 *pl022 = spi_master_get_devdata(spi->master);
unsigned int bits = spi->bits_per_word;
@ -2231,7 +2255,17 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
dev_dbg(dev, "probe succeeded\n");
/* let runtime pm put suspend */
pm_runtime_put(dev);
if (platform_info->autosuspend_delay > 0) {
dev_info(&adev->dev,
"will use autosuspend for runtime pm, delay %dms\n",
platform_info->autosuspend_delay);
pm_runtime_set_autosuspend_delay(dev,
platform_info->autosuspend_delay);
pm_runtime_use_autosuspend(dev);
pm_runtime_put_autosuspend(dev);
} else {
pm_runtime_put(dev);
}
return 0;
err_spi_register:
@ -2305,11 +2339,6 @@ static int pl022_suspend(struct device *dev)
return status;
}
amba_vcore_enable(pl022->adev);
amba_pclk_enable(pl022->adev);
load_ssp_default_config(pl022);
amba_pclk_disable(pl022->adev);
amba_vcore_disable(pl022->adev);
dev_dbg(dev, "suspended\n");
return 0;
}

View File

@ -4,6 +4,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/of.h>
#ifdef CONFIG_GPIOLIB
@ -128,13 +129,14 @@ struct gpio_chip {
*/
struct device_node *of_node;
int of_gpio_n_cells;
int (*of_xlate)(struct gpio_chip *gc, struct device_node *np,
const void *gpio_spec, u32 *flags);
int (*of_xlate)(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags);
#endif
};
extern const char *gpiochip_is_requested(struct gpio_chip *chip,
unsigned offset);
extern struct gpio_chip *gpio_to_chip(unsigned gpio);
extern int __must_check gpiochip_reserve(int start, int ngpio);
/* add/remove chips */

View File

@ -238,6 +238,9 @@ struct dma_chan;
* @enable_dma: if true enables DMA driven transfers.
* @dma_rx_param: parameter to locate an RX DMA channel.
* @dma_tx_param: parameter to locate a TX DMA channel.
* @autosuspend_delay: delay in ms following transfer completion before the
* runtime power management system suspends the device. A setting of 0
* indicates no delay and the device will be suspended immediately.
*/
struct pl022_ssp_controller {
u16 bus_id;
@ -246,6 +249,7 @@ struct pl022_ssp_controller {
bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
void *dma_rx_param;
void *dma_tx_param;
int autosuspend_delay;
};
/**

View File

@ -65,6 +65,13 @@ struct device_node {
#endif
};
#define MAX_PHANDLE_ARGS 8
struct of_phandle_args {
struct device_node *np;
int args_count;
uint32_t args[MAX_PHANDLE_ARGS];
};
#ifdef CONFIG_OF
/* Pointer for first entry in chain of all nodes. */
@ -230,9 +237,9 @@ extern int of_modalias_node(struct device_node *node, char *modalias, int len);
extern struct device_node *of_parse_phandle(struct device_node *np,
const char *phandle_name,
int index);
extern int of_parse_phandles_with_args(struct device_node *np,
extern 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);
extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
extern int of_alias_get_id(struct device_node *np, const char *stem);

View File

@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/of.h>
struct device_node;
@ -57,8 +58,9 @@ extern int of_mm_gpiochip_add(struct device_node *np,
extern void of_gpiochip_add(struct gpio_chip *gc);
extern void of_gpiochip_remove(struct gpio_chip *gc);
extern struct gpio_chip *of_node_to_gpiochip(struct device_node *np);
extern int of_gpio_simple_xlate(struct gpio_chip *gc, struct device_node *np,
const void *gpio_spec, u32 *flags);
extern int of_gpio_simple_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec,
u32 *flags);
#else /* CONFIG_OF_GPIO */
@ -75,8 +77,8 @@ static inline unsigned int of_gpio_count(struct device_node *np)
}
static inline int of_gpio_simple_xlate(struct gpio_chip *gc,
struct device_node *np,
const void *gpio_spec, u32 *flags)
const struct of_phandle_args *gpiospec,
u32 *flags)
{
return -ENOSYS;
}