* [PATCH RFC 4/6 v3] gpio-max730x: Add block GPIO API
From: Roland Stigge @ 2012-10-12 19:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350069085-13283-1-git-send-email-stigge@antcom.de>
This patch adds block GPIO API support to the MAX730x driver.
Due to hardware constraints in this chip, simultaneous access to GPIO lines can
only be done in groups of 8: GPIOs 0-7, 8-15, 16-23, 24-27. However, setting
and clearing will be done at once.
Signed-off-by: Roland Stigge <stigge@antcom.de>
---
drivers/gpio/gpio-max730x.c | 60 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
--- linux-2.6.orig/drivers/gpio/gpio-max730x.c
+++ linux-2.6/drivers/gpio/gpio-max730x.c
@@ -146,6 +146,43 @@ static int max7301_get(struct gpio_chip
return level;
}
+static unsigned max7301_get_block(struct gpio_chip *chip, unsigned mask)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+ int i, j;
+ unsigned result = 0;
+
+ for (i = 0; i < 4; i++) {
+ if ((mask >> (i * 8)) & 0xFF) { /* i/o only if necessary */
+ u8 in_level = ts->read(ts->dev, 0x44 + i * 8);
+ u8 in_mask = 0;
+ u8 out_level = (ts->out_level >> (i * 8 + 4)) & 0xFF;
+ u8 out_mask = 0;
+
+ for (j = 0; j < 8; j++) {
+ int offset = 4 + i * 8 + j;
+ int config = (ts->port_config[offset >> 2] >>
+ ((offset & 3) << 1)) &
+ PIN_CONFIG_MASK;
+
+ switch (config) {
+ case PIN_CONFIG_OUT:
+ out_mask |= BIT(j);
+ break;
+ case PIN_CONFIG_IN_WO_PULLUP:
+ case PIN_CONFIG_IN_PULLUP:
+ in_mask |= BIT(j);
+ }
+ }
+
+ result |= ((unsigned)(in_level & in_mask) |
+ (out_level & out_mask)) << (i * 8);
+ }
+ }
+
+ return result & mask;
+}
+
static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct max7301 *ts = container_of(chip, struct max7301, chip);
@@ -160,6 +197,27 @@ static void max7301_set(struct gpio_chip
mutex_unlock(&ts->lock);
}
+static
+void max7301_set_block(struct gpio_chip *chip, unsigned mask, unsigned values)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+ unsigned changes;
+ int i;
+
+ mutex_lock(&ts->lock);
+
+ changes = (ts->out_level ^ (values << 4)) & (mask << 4);
+ ts->out_level ^= changes;
+
+ for (i = 0; i < 4; i++) {
+ if ((changes >> (i * 8 + 4)) & 0xFF) /* i/o only on change */
+ ts->write(ts->dev, 0x44 + i * 8,
+ (ts->out_level >> (i * 8 + 4)) & 0xFF);
+ }
+
+ mutex_unlock(&ts->lock);
+}
+
int __devinit __max730x_probe(struct max7301 *ts)
{
struct device *dev = ts->dev;
@@ -183,8 +241,10 @@ int __devinit __max730x_probe(struct max
ts->chip.direction_input = max7301_direction_input;
ts->chip.get = max7301_get;
+ ts->chip.get_block = max7301_get_block;
ts->chip.direction_output = max7301_direction_output;
ts->chip.set = max7301_set;
+ ts->chip.set_block = max7301_set_block;
ts->chip.base = pdata->base;
ts->chip.ngpio = PIN_NUMBER;
^ permalink raw reply
* [PATCH RFC 3/6 v3] gpio: Add device tree support to block GPIO API
From: Roland Stigge @ 2012-10-12 19:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350069085-13283-1-git-send-email-stigge@antcom.de>
This patch adds device tree support to the block GPIO API.
Signed-off-by: Roland Stigge <stigge@antcom.de>
---
Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 +++++++
drivers/gpio/Makefile | 1
drivers/gpio/gpioblock-of.c | 84 ++++++++++++++++++
3 files changed, 121 insertions(+)
--- /dev/null
+++ linux-2.6/Documentation/devicetree/bindings/gpio/gpio-block.txt
@@ -0,0 +1,36 @@
+Block GPIO definition
+=====================
+
+This binding specifies arbitrary blocks of gpios, combining gpios from one or
+more GPIO controllers together, to form a word for r/w access.
+
+Required property:
+- compatible: must be "linux,gpio-block"
+
+Required subnodes:
+- the name will be the registered name of the block
+- property "gpios" is a list of gpios for the respective block
+
+Example:
+
+ blockgpio {
+ compatible = "linux,gpio-block";
+
+ block0 {
+ gpios = <&gpio 3 0 0>,
+ <&gpio 3 1 0>;
+ };
+ block1 {
+ gpios = <&gpio 4 1 0>,
+ <&gpio 4 3 0>,
+ <&gpio 4 2 0>,
+ <&gpio 4 4 0>,
+ <&gpio 4 5 0>,
+ <&gpio 4 6 0>,
+ <&gpio 4 7 0>,
+ <&gpio 4 8 0>,
+ <&gpio 4 9 0>,
+ <&gpio 4 10 0>,
+ <&gpio 4 19 0>;
+ };
+ };
--- linux-2.6.orig/drivers/gpio/Makefile
+++ linux-2.6/drivers/gpio/Makefile
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o
obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
+obj-$(CONFIG_OF_GPIO) += gpioblock-of.o
# Device drivers. Generally keep list sorted alphabetically
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
--- /dev/null
+++ linux-2.6/drivers/gpio/gpioblock-of.c
@@ -0,0 +1,84 @@
+/*
+ * OF implementation for Block GPIO
+ *
+ * Copyright (C) 2012 Roland Stigge <stigge@antcom.de>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+static int __devinit gpioblock_of_probe(struct platform_device *pdev)
+{
+ struct device_node *block;
+ unsigned *gpios;
+ int ngpio;
+ int ret;
+ struct gpio_block *gb;
+
+ for_each_available_child_of_node(pdev->dev.of_node, block) {
+ int i;
+
+ ngpio = of_gpio_count(block);
+ gpios = kzalloc(ngpio * sizeof(*gpios), GFP_KERNEL);
+ if (!gpios)
+ return -ENOMEM;
+ for (i = 0; i < ngpio; i++) {
+ ret = of_get_gpio(block, i);
+ if (ret < 0)
+ return ret; /* expect -EPROBE_DEFER */
+ gpios[i] = ret;
+ }
+ gb = gpio_block_create(gpios, ngpio, block->name);
+ if (IS_ERR(gb)) {
+ dev_err(&pdev->dev,
+ "Error creating GPIO block from device tree\n");
+ return PTR_ERR(gb);
+ }
+ ret = gpio_block_register(gb);
+ if (ret < 0) {
+ gpio_block_free(gb);
+ return ret;
+ }
+ kfree(gpios);
+ dev_info(&pdev->dev, "Registered gpio block %s: %d gpios\n",
+ block->name, ngpio);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id gpioblock_of_match[] __devinitdata = {
+ { .compatible = "linux,gpio-block", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, gpioblock_of_match);
+#endif
+
+static struct platform_driver gpioblock_of_driver = {
+ .driver = {
+ .name = "gpio-block",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(gpioblock_of_match),
+
+ },
+ .probe = gpioblock_of_probe,
+};
+
+module_platform_driver(gpioblock_of_driver);
+
+MODULE_DESCRIPTION("GPIO Block driver");
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpioblock-of");
^ permalink raw reply
* [PATCH RFC 2/6 v3] gpio: Add sysfs support to block GPIO API
From: Roland Stigge @ 2012-10-12 19:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350069085-13283-1-git-send-email-stigge@antcom.de>
This patch adds sysfs support to the block GPIO API.
Signed-off-by: Roland Stigge <stigge@antcom.de>
---
Documentation/ABI/testing/sysfs-gpio | 6
drivers/gpio/gpiolib.c | 226 ++++++++++++++++++++++++++++++++++-
include/asm-generic/gpio.h | 11 +
include/linux/gpio.h | 13 ++
4 files changed, 254 insertions(+), 2 deletions(-)
--- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio
+++ linux-2.6/Documentation/ABI/testing/sysfs-gpio
@@ -24,4 +24,8 @@ Description:
/base ... (r/o) same as N
/label ... (r/o) descriptive, not necessarily unique
/ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1)
-
+ /blockN ... for each GPIO block #N
+ /ngpio ... (r/o) number of GPIOs in this group
+ /exported ... sysfs export state of this group (0, 1)
+ /value ... current value as 32 or 64 bit integer in decimal
+ (only available if /exported is 1)
--- linux-2.6.orig/drivers/gpio/gpiolib.c
+++ linux-2.6/drivers/gpio/gpiolib.c
@@ -974,6 +974,218 @@ static void gpiochip_unexport(struct gpi
chip->label, status);
}
+static ssize_t gpio_block_ngpio_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_block *block = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", block->ngpio);
+}
+static struct device_attribute
+dev_attr_block_ngpio = __ATTR(ngpio, 0444, gpio_block_ngpio_show, NULL);
+
+static ssize_t gpio_block_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ const struct gpio_block *block = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", gpio_block_get(block));
+}
+
+static bool gpio_block_is_output(struct gpio_block *block)
+{
+ int i;
+
+ for (i = 0; i < block->ngpio; i++)
+ if (!test_bit(FLAG_IS_OUT, &gpio_desc[block->gpio[i]].flags))
+ return false;
+ return true;
+}
+
+static ssize_t gpio_block_value_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ ssize_t status;
+ struct gpio_block *block = dev_get_drvdata(dev);
+ unsigned long value;
+
+ mutex_lock(&sysfs_lock);
+
+ status = kstrtoul(buf, 0, &value);
+ if (status == 0) {
+ if (gpio_block_is_output(block)) {
+ gpio_block_set(block, value);
+ status = size;
+ } else {
+ status = -EPERM;
+ }
+ }
+
+ mutex_unlock(&sysfs_lock);
+ return status;
+}
+
+static struct device_attribute
+dev_attr_block_value = __ATTR(value, 0644, gpio_block_value_show,
+ gpio_block_value_store);
+
+static int gpio_block_value_is_exported(struct gpio_block *block)
+{
+ struct device *dev;
+ struct sysfs_dirent *sd = NULL;
+
+ mutex_lock(&sysfs_lock);
+ dev = class_find_device(&gpio_class, NULL, block, match_export);
+ if (!dev)
+ goto out;
+
+ sd = sysfs_get_dirent(dev->kobj.sd, NULL, "value");
+
+out:
+ mutex_unlock(&sysfs_lock);
+ return sd ? 1 : 0;
+}
+
+static ssize_t gpio_block_exported_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct gpio_block *block = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", gpio_block_value_is_exported(block));
+}
+
+static int gpio_block_value_export(struct gpio_block *block)
+{
+ struct device *dev;
+ int status;
+ int i;
+
+ mutex_lock(&sysfs_lock);
+
+ for (i = 0; i < block->ngpio; i++) {
+ status = gpio_request(block->gpio[i], "sysfs");
+ if (status)
+ goto out;
+ }
+
+ dev = class_find_device(&gpio_class, NULL, block, match_export);
+ if (!dev) {
+ status = -ENODEV;
+ goto out;
+ }
+
+ status = device_create_file(dev, &dev_attr_block_value);
+ if (status)
+ goto out;
+
+ mutex_unlock(&sysfs_lock);
+ return 0;
+
+out:
+ while (i > 0) {
+ i--;
+ gpio_free(block->gpio[i]);
+ }
+
+ mutex_unlock(&sysfs_lock);
+ return status;
+}
+
+static int gpio_block_value_unexport(struct gpio_block *block)
+{
+ struct device *dev;
+ int i;
+
+ dev = class_find_device(&gpio_class, NULL, block, match_export);
+ if (!dev)
+ return -ENODEV;
+
+ for (i = 0; i < block->ngpio; i++)
+ gpio_free(block->gpio[i]);
+
+ device_remove_file(dev, &dev_attr_block_value);
+
+ return 0;
+}
+
+static ssize_t gpio_block_exported_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ long value;
+ int status;
+ struct gpio_block *block = dev_get_drvdata(dev);
+ int exported = gpio_block_value_is_exported(block);
+
+ status = kstrtoul(buf, 0, &value);
+ if (status < 0)
+ goto err;
+
+ if (value != exported) {
+ if (value)
+ status = gpio_block_value_export(block);
+ else
+ status = gpio_block_value_unexport(block);
+ if (!status)
+ status = size;
+ } else {
+ status = size;
+ }
+err:
+ return status;
+}
+
+static DEVICE_ATTR(exported, 0644, gpio_block_exported_show,
+ gpio_block_exported_store);
+
+static const struct attribute *gpio_block_attrs[] = {
+ &dev_attr_block_ngpio.attr,
+ &dev_attr_exported.attr,
+ NULL,
+};
+
+static const struct attribute_group gpio_block_attr_group = {
+ .attrs = (struct attribute **) gpio_block_attrs,
+};
+
+int gpio_block_export(struct gpio_block *block)
+{
+ int status;
+ struct device *dev;
+
+ /* can't export until sysfs is available ... */
+ if (!gpio_class.p) {
+ pr_debug("%s: called too early!\n", __func__);
+ return -ENOENT;
+ }
+
+ mutex_lock(&sysfs_lock);
+ dev = device_create(&gpio_class, NULL, MKDEV(0, 0), block,
+ block->name);
+ if (!IS_ERR(dev))
+ status = sysfs_create_group(&dev->kobj, &gpio_block_attr_group);
+ else
+ status = PTR_ERR(dev);
+ mutex_unlock(&sysfs_lock);
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(gpio_block_export);
+
+void gpio_block_unexport(struct gpio_block *block)
+{
+ struct device *dev;
+
+ mutex_lock(&sysfs_lock);
+ dev = class_find_device(&gpio_class, NULL, block, match_export);
+ if (dev)
+ device_unregister(dev);
+ mutex_unlock(&sysfs_lock);
+}
+EXPORT_SYMBOL_GPL(gpio_block_unexport);
+
static int __init gpiolib_sysfs_init(void)
{
int status;
@@ -1882,7 +2094,14 @@ int gpio_block_register(struct gpio_bloc
break;
}
}
- return i == NR_GPIO_BLOCKS ? -EBUSY : 0;
+ if (i == NR_GPIO_BLOCKS)
+ goto err;
+
+ gpio_block_export(block);
+
+ return 0;
+err:
+ return -EBUSY;
}
EXPORT_SYMBOL_GPL(gpio_block_register);
@@ -1896,6 +2115,11 @@ void gpio_block_unregister(struct gpio_b
break;
}
}
+
+ if (i == NR_GPIO_BLOCKS)
+ return;
+
+ gpio_block_unexport(block);
}
EXPORT_SYMBOL_GPL(gpio_block_unregister);
--- linux-2.6.orig/include/asm-generic/gpio.h
+++ linux-2.6/include/asm-generic/gpio.h
@@ -210,6 +210,8 @@ extern int gpio_export_link(struct devic
unsigned gpio);
extern int gpio_sysfs_set_active_low(unsigned gpio, int value);
extern void gpio_unexport(unsigned gpio);
+extern int gpio_block_export(struct gpio_block *block);
+extern void gpio_block_unexport(struct gpio_block *block);
#endif /* CONFIG_GPIO_SYSFS */
@@ -269,6 +271,15 @@ static inline int gpio_sysfs_set_active_
static inline void gpio_unexport(unsigned gpio)
{
}
+
+static inline int gpio_block_export(struct gpio_block *block)
+{
+ return -ENOSYS;
+}
+
+static inline void gpio_block_unexport(struct gpio_block *block)
+{
+}
#endif /* CONFIG_GPIO_SYSFS */
#endif /* _ASM_GENERIC_GPIO_H */
--- linux-2.6.orig/include/linux/gpio.h
+++ linux-2.6/include/linux/gpio.h
@@ -278,6 +278,19 @@ static inline void gpio_unexport(unsigne
WARN_ON(1);
}
+static inline int gpio_block_export(struct gpio_block *block)
+{
+ /* GPIO block can never have been requested or set as {in,out}put */
+ WARN_ON(1);
+ return -EINVAL;
+}
+
+static inline void gpio_block_unexport(struct gpio_block *block)
+{
+ /* GPIO block can never have been exported */
+ WARN_ON(1);
+}
+
static inline int gpio_to_irq(unsigned gpio)
{
/* GPIO can never have been requested or set as input */
^ permalink raw reply
* [PATCH RFC 1/6 v3] gpio: Add a block GPIO API to gpiolib
From: Roland Stigge @ 2012-10-12 19:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350069085-13283-1-git-send-email-stigge@antcom.de>
The recurring task of providing simultaneous access to GPIO lines (especially
for bit banging protocols) needs an appropriate API.
This patch adds a kernel internal "Block GPIO" API that enables simultaneous
access to several GPIOs. This is done by abstracting GPIOs to an n-bit word:
Once requested, it provides access to a group of GPIOs which can range over
multiple GPIO chips.
Signed-off-by: Roland Stigge <stigge@antcom.de>
---
Documentation/gpio.txt | 45 +++++++++
drivers/gpio/gpiolib.c | 223 +++++++++++++++++++++++++++++++++++++++++++++
include/asm-generic/gpio.h | 14 ++
include/linux/gpio.h | 61 ++++++++++++
4 files changed, 343 insertions(+)
--- linux-2.6.orig/Documentation/gpio.txt
+++ linux-2.6/Documentation/gpio.txt
@@ -439,6 +439,51 @@ slower clock delays the rising edge of S
signaling rate accordingly.
+Block GPIO
+----------
+
+The above described interface concentrates on handling single GPIOs. However,
+in applications where it is critical to set several GPIOs at once, this
+interface doesn't work well, e.g. bit-banging protocols via grouped GPIO lines.
+Consider a GPIO controller that is connected via a slow I2C line. When
+switching two or more GPIOs one after another, there can be considerable time
+between those events. This is solved by an interface called Block GPIO:
+
+struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size);
+
+This creates a new block of GPIOs as a list of GPIO numbers with the specified
+size which are accessible via the returned struct gpio_block and the accessor
+functions described below. Please note that you need to request the GPIOs
+separately via gpio_request(). An arbitrary list of globally valid GPIOs can be
+specified, even ranging over several gpio_chips. Actual handling of I/O
+operations will be done on a best effort base, i.e. simultaneous I/O only where
+possible by hardware and implemented in the respective GPIO driver. The number
+of GPIOs in one block is limited to 32 on a 32 bit system, and 64 on a 64 bit
+system. However, several blocks can be defined at once.
+
+unsigned gpio_block_get(struct gpio_block *block);
+void gpio_block_set(struct gpio_block *block, unsigned value);
+
+With those accessor functions, setting and getting the GPIO values is possible,
+analogous to gpio_get_value() and gpio_set_value(). Each bit in the return
+value of gpio_block_get() and in the value argument of gpio_block_set()
+corresponds to a bit specified on gpio_block_create(). Block operations in
+hardware are only possible where the respective GPIO driver implements it,
+falling back to using single GPIO operations where the driver only implements
+single GPIO access.
+
+void gpio_block_free(struct gpio_block *block);
+
+After the GPIO block isn't used anymore, it should be free'd via
+gpio_block_free().
+
+int gpio_block_register(struct gpio_block *block);
+void gpio_block_unregister(struct gpio_block *block);
+
+These functions can be used to register a GPIO block. Blocks registered this
+way will be available via sysfs.
+
+
What do these conventions omit?
===============================
One of the biggest things these conventions omit is pin multiplexing, since
--- linux-2.6.orig/drivers/gpio/gpiolib.c
+++ linux-2.6/drivers/gpio/gpiolib.c
@@ -83,6 +83,10 @@ static inline void desc_set_label(struct
#endif
}
+#define NR_GPIO_BLOCKS 16
+
+static struct gpio_block *gpio_block[NR_GPIO_BLOCKS];
+
/* Warn when drivers omit gpio_request() calls -- legal but ill-advised
* when setting direction, and otherwise illegal. Until board setup code
* and drivers use explicit requests everywhere (which won't happen when
@@ -1676,6 +1680,225 @@ void __gpio_set_value(unsigned gpio, int
}
EXPORT_SYMBOL_GPL(__gpio_set_value);
+static inline
+int gpio_block_chip_index(struct gpio_block *block, struct gpio_chip *gc)
+{
+ int i;
+
+ for (i = 0; i < block->nchip; i++) {
+ if (block->gbc[i].gc == gc)
+ return i;
+ }
+ return -1;
+}
+
+struct gpio_block *gpio_block_create(unsigned *gpios, size_t size,
+ const char *name)
+{
+ struct gpio_block *block;
+ struct gpio_block_chip *gbc;
+ struct gpio_remap *remap;
+ int i;
+
+ if (size < 1 || size > sizeof(unsigned) * 8)
+ return ERR_PTR(-EINVAL);
+
+ block = kzalloc(sizeof(struct gpio_block), GFP_KERNEL);
+ if (!block)
+ return ERR_PTR(-ENOMEM);
+
+ block->name = name;
+ block->ngpio = size;
+ block->gpio = kzalloc(sizeof(*block->gpio) * size, GFP_KERNEL);
+ if (!block->gpio)
+ goto err1;
+
+ memcpy(block->gpio, gpios, sizeof(*block->gpio) * size);
+
+ for (i = 0; i < size; i++)
+ if (!gpio_is_valid(gpios[i]))
+ goto err2;
+
+ for (i = 0; i < size; i++) {
+ struct gpio_chip *gc = gpio_to_chip(gpios[i]);
+ int bit = gpios[i] - gc->base;
+ int index = gpio_block_chip_index(block, gc);
+
+ if (index < 0) {
+ block->nchip++;
+ block->gbc = krealloc(block->gbc,
+ sizeof(struct gpio_block_chip) *
+ block->nchip, GFP_KERNEL);
+ if (!block->gbc)
+ goto err2;
+ gbc = &block->gbc[block->nchip - 1];
+ gbc->gc = gc;
+ gbc->remap = NULL;
+ gbc->nremap = 0;
+ gbc->mask = 0;
+ } else {
+ gbc = &block->gbc[index];
+ }
+ /* represents the mask necessary on calls to the driver's
+ * .get_block() and .set_block()
+ */
+ gbc->mask |= BIT(bit);
+
+ /* collect gpios that are specified together, represented by
+ * neighboring bits
+ */
+ remap = &gbc->remap[gbc->nremap - 1];
+ if (!gbc->nremap || (bit - i != remap->offset)) {
+ gbc->nremap++;
+ gbc->remap = krealloc(gbc->remap,
+ sizeof(struct gpio_remap) *
+ gbc->nremap, GFP_KERNEL);
+ if (!gbc->remap)
+ goto err3;
+ remap = &gbc->remap[gbc->nremap - 1];
+ remap->offset = bit - i;
+ remap->mask = 0;
+ }
+
+ /* represents the mask necessary for bit reordering between
+ * gpio_block (i.e. as specified on gpio_block_get() and
+ * gpio_block_set()) and gpio_chip domain (i.e. as specified on
+ * the driver's .set_block() and .get_block())
+ */
+ remap->mask |= BIT(i);
+ }
+
+ return block;
+err3:
+ for (i = 0; i < block->nchip - 1; i++)
+ kfree(block->gbc[i].remap);
+ kfree(block->gbc);
+err2:
+ kfree(block->gpio);
+err1:
+ kfree(block);
+ return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL_GPL(gpio_block_create);
+
+void gpio_block_free(struct gpio_block *block)
+{
+ int i;
+
+ for (i = 0; i < block->nchip; i++)
+ kfree(block->gbc[i].remap);
+ kfree(block->gpio);
+ kfree(block->gbc);
+ kfree(block);
+}
+EXPORT_SYMBOL_GPL(gpio_block_free);
+
+unsigned gpio_block_get(const struct gpio_block *block)
+{
+ struct gpio_block_chip *gbc;
+ int i, j;
+ unsigned values = 0;
+
+ for (i = 0; i < block->nchip; i++) {
+ unsigned remapped = 0;
+
+ gbc = &block->gbc[i];
+
+ if (gbc->gc->get_block) {
+ remapped = gbc->gc->get_block(gbc->gc, gbc->mask);
+ } else { /* emulate */
+ unsigned bit = 1;
+
+ for (j = 0; j < sizeof(unsigned) * 8; j++, bit <<= 1) {
+ if (gbc->mask & bit)
+ remapped |= gbc->gc->get(gbc->gc,
+ gbc->gc->base + j) << j;
+ }
+ }
+
+ for (j = 0; j < gbc->nremap; j++) {
+ struct gpio_remap *gr = &gbc->remap[j];
+
+ values |= (remapped >> gr->offset) & gr->mask;
+ }
+ }
+
+ return values;
+}
+EXPORT_SYMBOL_GPL(gpio_block_get);
+
+void gpio_block_set(struct gpio_block *block, unsigned values)
+{
+ struct gpio_block_chip *gbc;
+ int i, j;
+
+ for (i = 0; i < block->nchip; i++) {
+ unsigned remapped = 0;
+
+ gbc = &block->gbc[i];
+
+ for (j = 0; j < gbc->nremap; j++) {
+ struct gpio_remap *gr = &gbc->remap[j];
+
+ remapped |= (values & gr->mask) << gr->offset;
+ }
+ if (gbc->gc->set_block) {
+ gbc->gc->set_block(gbc->gc, gbc->mask, remapped);
+ } else { /* emulate */
+ unsigned bit = 1;
+
+ for (j = 0; j < sizeof(unsigned) * 8; j++, bit <<= 1) {
+ if (gbc->mask & bit)
+ gbc->gc->set(gbc->gc, gbc->gc->base + j,
+ (remapped >> j) & 1);
+ }
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(gpio_block_set);
+
+struct gpio_block *gpio_block_find_by_name(const char *name)
+{
+ int i;
+
+ for (i = 0; i < NR_GPIO_BLOCKS; i++) {
+ if (gpio_block[i] && !strcmp(gpio_block[i]->name, name))
+ return gpio_block[i];
+ }
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gpio_block_find_by_name);
+
+int gpio_block_register(struct gpio_block *block)
+{
+ int i;
+
+ if (gpio_block_find_by_name(block->name))
+ return -EBUSY;
+
+ for (i = 0; i < NR_GPIO_BLOCKS; i++) {
+ if (!gpio_block[i]) {
+ gpio_block[i] = block;
+ break;
+ }
+ }
+ return i == NR_GPIO_BLOCKS ? -EBUSY : 0;
+}
+EXPORT_SYMBOL_GPL(gpio_block_register);
+
+void gpio_block_unregister(struct gpio_block *block)
+{
+ int i;
+
+ for (i = 0; i < NR_GPIO_BLOCKS; i++) {
+ if (gpio_block[i] == block) {
+ gpio_block[i] = NULL;
+ break;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(gpio_block_unregister);
+
/**
* __gpio_cansleep() - report whether gpio value access will sleep
* @gpio: gpio in question
--- linux-2.6.orig/include/asm-generic/gpio.h
+++ linux-2.6/include/asm-generic/gpio.h
@@ -43,6 +43,7 @@ static inline bool gpio_is_valid(int num
struct device;
struct gpio;
+struct gpio_block;
struct seq_file;
struct module;
struct device_node;
@@ -105,6 +106,8 @@ struct gpio_chip {
unsigned offset);
int (*get)(struct gpio_chip *chip,
unsigned offset);
+ unsigned (*get_block)(struct gpio_chip *chip,
+ unsigned mask);
int (*direction_output)(struct gpio_chip *chip,
unsigned offset, int value);
int (*set_debounce)(struct gpio_chip *chip,
@@ -112,6 +115,8 @@ struct gpio_chip {
void (*set)(struct gpio_chip *chip,
unsigned offset, int value);
+ void (*set_block)(struct gpio_chip *chip,
+ unsigned mask, unsigned values);
int (*to_irq)(struct gpio_chip *chip,
unsigned offset);
@@ -171,6 +176,15 @@ extern void gpio_set_value_cansleep(unsi
extern int __gpio_get_value(unsigned gpio);
extern void __gpio_set_value(unsigned gpio, int value);
+extern struct gpio_block *gpio_block_create(unsigned *gpio, size_t size,
+ const char *name);
+extern void gpio_block_free(struct gpio_block *block);
+extern unsigned gpio_block_get(const struct gpio_block *block);
+extern void gpio_block_set(struct gpio_block *block, unsigned values);
+extern struct gpio_block *gpio_block_find_by_name(const char *name);
+extern int gpio_block_register(struct gpio_block *block);
+extern void gpio_block_unregister(struct gpio_block *block);
+
extern int __gpio_cansleep(unsigned gpio);
extern int __gpio_to_irq(unsigned gpio);
--- linux-2.6.orig/include/linux/gpio.h
+++ linux-2.6/include/linux/gpio.h
@@ -2,6 +2,7 @@
#define __LINUX_GPIO_H
#include <linux/errno.h>
+#include <linux/types.h>
/* see Documentation/gpio.txt */
@@ -39,6 +40,31 @@ struct gpio {
const char *label;
};
+struct gpio_remap {
+ int mask;
+ int offset;
+};
+
+struct gpio_block_chip {
+ struct gpio_chip *gc;
+ struct gpio_remap *remap;
+ int nremap;
+ unsigned mask;
+};
+
+/**
+ * struct gpio_block - a structure describing a list of GPIOs for simultaneous
+ * operations
+ */
+struct gpio_block {
+ struct gpio_block_chip *gbc;
+ size_t nchip;
+ const char *name;
+
+ int ngpio;
+ unsigned *gpio;
+};
+
#ifdef CONFIG_GENERIC_GPIO
#ifdef CONFIG_ARCH_HAVE_CUSTOM_GPIO_H
@@ -169,6 +195,41 @@ static inline void gpio_set_value(unsign
WARN_ON(1);
}
+static inline
+struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size,
+ const char *name)
+{
+ WARN_ON(1);
+ return NULL;
+}
+
+static inline void gpio_block_free(struct gpio_block *block)
+{
+ WARN_ON(1);
+}
+
+static inline unsigned gpio_block_get(const struct gpio_block *block)
+{
+ WARN_ON(1);
+ return 0;
+}
+
+static inline void gpio_block_set(struct gpio_block *block, unsigned value)
+{
+ WARN_ON(1);
+}
+
+static inline int gpio_block_register(struct gpio_block *block)
+{
+ WARN_ON(1);
+ return 0;
+}
+
+static inline void gpio_block_unregister(struct gpio_block *block)
+{
+ WARN_ON(1);
+}
+
static inline int gpio_cansleep(unsigned gpio)
{
/* GPIO can never have been requested or set as {in,out}put */
^ permalink raw reply
* [PATCH RFC 0/6 v3] gpio: Add block GPIO
From: Roland Stigge @ 2012-10-12 19:11 UTC (permalink / raw)
To: linux-arm-kernel
This set of patches adds:
* Block GPIO API to gpiolib
* Sysfs support for GPIO API, to provide userland access
* Devicetree support to instantiate GPIO blocks via DT
* Example implementations in several gpio drivers since they need
special accessor functions for block wise GPIO access
Signed-off-by: Roland Stigge <stigge@antcom.de>
--
Changes since v2:
* Added sysfs support
* Added devicetree support
* Added support for lpc32xx, generic
* Added functions for GPIO block registration
* Added more error checking
* Bit remapping bugfix
Roland Stigge (6):
gpio: Add a block GPIO API to gpiolib
gpio: Add sysfs support to block GPIO API
gpio: Add device tree support to block GPIO API
gpio-max730x: Add block GPIO API
gpio-lpc32xx: Add block GPIO API
gpio-generic: Add block GPIO API
Documentation/ABI/testing/sysfs-gpio | 6
Documentation/devicetree/bindings/gpio/gpio-block.txt | 36
Documentation/gpio.txt | 45 +
drivers/gpio/Makefile | 1
drivers/gpio/gpio-generic.c | 56 +
drivers/gpio/gpio-lpc32xx.c | 78 +
drivers/gpio/gpio-max730x.c | 60 +
drivers/gpio/gpioblock-of.c | 83 +
drivers/gpio/gpiolib.c | 449 +++++++++-
include/asm-generic/gpio.h | 25
include/linux/gpio.h | 74 +
11 files changed, 911 insertions(+), 2 deletions(-)
^ permalink raw reply
* [RFT/PATCH] serial: omap: prevent resume if device is not suspended.
From: Russell King - ARM Linux @ 2012-10-12 18:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <877gqv4lmt.fsf@deeprootsystems.com>
On Fri, Oct 12, 2012 at 10:59:22AM -0700, Kevin Hilman wrote:
> Russell King - ARM Linux <linux@arm.linux.org.uk> writes:
>
> > On Fri, Oct 12, 2012 at 09:35:54AM -0700, Kevin Hilman wrote:
> >> Sourav <sourav.poddar@ti.com> writes:
> >> > diff --git a/drivers/tty/serial/omap-serial.c
> >> > b/drivers/tty/serial/omap-serial.c
> >> > index 6ede6fd..3fbc7f7 100644
> >> > --- a/drivers/tty/serial/omap-serial.c
> >> > +++ b/drivers/tty/serial/omap-serial.c
> >> > @@ -1414,6 +1414,7 @@ static int __devinit serial_omap_probe(struct
> >> > platform_device *pdev)
> >> > INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
> >> >
> >> > platform_set_drvdata(pdev, up);
> >> > + pm_runtime_set_active(&pdev->dev);
> >>
> >> NAK.
> >>
> >> This will obviously break platforms where the UARTs are not active
> >> before driver loads.
> >
> > I thought I had proposed a solution for this issue, which was this
> > sequence:
> >
> > omap_device_enable(dev);
> > pm_runtime_set_active(dev);
> > pm_runtime_enable(dev);
> >
> > Yes, I can understand people not liking the omap_device_enable()
> > there, but I also notice that the email suggesting that never got a
> > reply either - not even a "I tried this and it doesn't work" or "it
> > does work".
>
> Yes, that solution would work (though I didn't actually try it.)
>
> However, we can't use omap_device_enable() in the driver. We're trying
> to clean all the drivers of OMAP-specific APIs. That being said,
> something similar could be done in the device/board init code to ensure
> the UART HW is in the state that the driver is expecting it, but again,
> that would just mask the real problem which is that a (re)init of the
> console UART on 2420/n800 is causing output to disappear.
See my more expansive suggestion just posted.
Whatever way, this discrepancy between runtime PM state and actual device
state is what is biting you, and it is that which needs fixing. It's
fairly easy to fix given the right design, one which several other bus
types are already using.
Given the route that OMAP went down when adopting runtime PM, it's going
to be a big change across many drivers, because there's no way to gradually
transition them, but that's unfortunately one of the results of ignoring
requirements of the layers being used. Sooner or later the oversights
come back to haunt. Just make sure it's not the ghost of Jaws.
^ permalink raw reply
* [RFT/PATCH] serial: omap: prevent resume if device is not suspended.
From: Russell King - ARM Linux @ 2012-10-12 18:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <FEB1293C1A07484EA4E9721B32981131CC2362@DBDE01.ent.ti.com>
On Fri, Oct 12, 2012 at 05:29:55PM +0000, Poddar, Sourav wrote:
> Hi Russell,
> ________________________________________
> From: Russell King - ARM Linux [linux at arm.linux.org.uk]
> Sent: Friday, October 12, 2012 10:12 PM
> To: Kevin Hilman
> Cc: Poddar, Sourav; Paul Walmsley; Balbi, Felipe; gregkh at linuxfoundation.org; tony at atomide.com; linux-kernel at vger.kernel.org; Shilimkar, Santosh; linux-serial at vger.kernel.org; linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org; alan at linux.intel.com
> Subject: Re: [RFT/PATCH] serial: omap: prevent resume if device is not suspended.
>
> On Fri, Oct 12, 2012 at 09:35:54AM -0700, Kevin Hilman wrote:
> > Sourav <sourav.poddar@ti.com> writes:
> > > diff --git a/drivers/tty/serial/omap-serial.c
> > > b/drivers/tty/serial/omap-serial.c
> > > index 6ede6fd..3fbc7f7 100644
> > > --- a/drivers/tty/serial/omap-serial.c
> > > +++ b/drivers/tty/serial/omap-serial.c
> > > @@ -1414,6 +1414,7 @@ static int __devinit serial_omap_probe(struct
> > > platform_device *pdev)
> > > INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
> > >
> > > platform_set_drvdata(pdev, up);
> > > + pm_runtime_set_active(&pdev->dev);
> >
> > NAK.
> >
> > This will obviously break platforms where the UARTs are not active
> > before driver loads.
>
> I thought I had proposed a solution for this issue, which was this
> sequence:
>
> omap_device_enable(dev);
> pm_runtime_set_active(dev);
> pm_runtime_enable(dev);
>
> Yes, I can understand people not liking the omap_device_enable()
> there, but I also notice that the email suggesting that never got a
> reply either - not even a "I tried this and it doesn't work" or "it
> does work".
>
> Sorry for the late reply on this. I tried this sequence and it worked perfectly fine on
> panda and beagle.
>
> As such, it seems this issue isn't making any progress as we had
> already established that merely doing a "pm_runtime_set_active()"
> before "pm_runtime_enable()" was going to break other platforms.
>
> I was trying to analyse your explanations on this and since
> omap_device_enable is not generally recommended, I was trying to see
> if anything else can be done to get around this.
Right, so what you need is explanation about why I believe the above
sequence to be necessary.
What is happening is that we're starting from a device in unknown state.
We don't know whether it is enabled or disabled. We don't know the
state of the clocks or the power domain.
PM runtime state is initialized at device creation in the "device is
suspended" state. If we merely enable PM runtime from that state, we
are telling the PM runtime subsystem that the device is _indeed_
suspended (disabled) at boot time.
So, that causes the first pm_runtime_get() call to resume the device.
Due to the OMAP runtime PM hooks at the bus layer, this causes
_od_runtime_resume() to be called.
_od_runtime_resume() does two things. It calls omap_device_enable()
to ensure that the device is woken up (such as, ensuring that the
power domain is on, and turning on the clocks etc.) It then goes on
to call the device PM layers to call the driver specific runtime PM
resume hook.
So, in summary, what this sequence does is:
pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev,
omap_up_info->autosuspend_timeout);
pm_runtime_irq_safe(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
is, at the last call, it calls:
_od_runtime_resume()
omap_device_enable()
serial_omap_runtime_resume()
Your original patch at the head of this thread says that the driver
specific runtime resume call causes a problem for N800 - because the
device is already enabled and setup.
Okay, so the initial device state does not match the runtime PM state.
So, what happens if we _do_ make it match your state - as required by
the runtime PM documentation - by adding a call before the sequence:
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev,
omap_up_info->autosuspend_timeout);
pm_runtime_irq_safe(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
Right, now runtime PM knows that the device is enabled and alive prior
to that pm_runtime_get_sync() call, and it will _not_ call the runtime
resume hooks.
However, this breaks beaglebone, because the device is disabled when
this driver probes. So, we have exactly the opposite problem here -
the device is disabled, but runtime PM thinks it is enabled.
The _two_ problems are precisely the same problem: the runtime PM state
does not accurately reflect the actual hardware state - again, as required
by the runtime PM documentation. The only sane solution to this is to
ensure that the hardware _is_ in a known state prior to enabling runtime
PM.
How do we do that? Well, the clue is in the bus layer runtime resume
handler - that's what is missing from the beaglebone situation.
Calling this before calling pm_runtime_set_active() gets the hardware
into a known state (enabled), and we then tell the runtime PM code
that the harware _is_ enabled. Now, runtime PM can be sure what the
initial state is, and everything works.
What's the longer term answer?
Well, I _bet_ all OMAP drivers are doing something along the lines of:
pm_runtime_enable(dev);
pm_runtime_get(dev);
in their probe functions.
PCI already solved this problem - partly because it has far too many drivers
to convert. I took that solution over to the AMBA bus layer, because I
didn't want to have a flag day for all the drivers to convert over in one
massive patch. What is this solution?
You get the bus layer to handle the initial setup of runtime PM state like
this - in OMAP's case:
omap_device_enable(pdev);
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
You do this prior to calling the device probe function. If the device
probe fails, then you can undo those actions. You also need to undo them
when the device is unbound from the driver:
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
(It is probably dangerous to call omap_device_disable() here for certain
devices...)
This gets rid of all that driver specific runtime PM initialization, with
questionable starting state. It also means that your devices all get
runtime PM support in so far as if they're bound to a driver, they will
be runtime PM resumed, and when unbound, they will be runtime PM suspended.
However, it means that the driver has to do something to make runtime PM
work. In the probe function, just before it returns success, it has to
'put' that pm_runtime_get_noresume() reference to allow the device to
enter runtime PM states. And more importantly, on a remove call, it
_must_ balance that 'put' in the probe with an appropriate 'get' - no
exceptions to that.
And that is how we get to a sane state over runtime PM here, which will
work in every situation on every device, without throwing calls to
omap_device_enable() into every OMAP device driver.
This also has another advantage - by doing that, the OMAP specific
omap_device_enable() call ends up being in bus layer code, not driver
layer, which is the right place for it to be - after all, it's the
bus layer which is already handling that stuff in its runtime PM support
code.
^ permalink raw reply
* [PATCH 1/2] ARM: config: sort select statements alphanumerically
From: Linus Walleij @ 2012-10-12 18:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121012144832.GN28061@n2100.arm.linux.org.uk>
On Fri, Oct 12, 2012 at 4:48 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> Instead, here's the updated script:
Works like a charm, the result compiles and boots nicely.
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 1/3] i2c: omap: Do not enable the irq always
From: Shubhrajyoti Datta @ 2012-10-12 18:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87txtz7on9.fsf@deeprootsystems.com>
On Fri, Oct 12, 2012 at 7:56 PM, Kevin Hilman
<khilman@deeprootsystems.com> wrote:
> +Kalle, Grygorii, Huzefa
>
> Shubhrajyoti D <shubhrajyoti@ti.com> writes:
>
>> Enable the irq in the transfer and disable it after the
>> transfer is done.
>>
>> Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com>
>> ---
>> drivers/i2c/busses/i2c-omap.c | 3 +++
>> 1 files changed, 3 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
>> index b6c6b95..ce41596 100644
>> --- a/drivers/i2c/busses/i2c-omap.c
>> +++ b/drivers/i2c/busses/i2c-omap.c
>> @@ -625,6 +625,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
>> if (IS_ERR_VALUE(r))
>> goto out;
>>
>> + enable_irq(dev->irq);
>> r = omap_i2c_wait_for_bb(dev);
>> if (r < 0)
>> goto out;
>> @@ -654,6 +655,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
>>
>> omap_i2c_wait_for_bb(dev);
>> out:
>> + disable_irq(dev->irq);
>
> When using runtime PM with auto-suspend timeouts, why would you disable
> the IRQ before the runtime suspend handlers have run?
>
> If you really want to do this, you probably should have these in the
> runtime PM callbacks.
OK.
> But I'll wait until you add a more descriptive
> changelog before I can really tell why this is being done. Based on the
> discussion in the patch from Kalle, I'm assuming this is to prevent
> interrups when I2C is being used by co-processors. If so, plese
> describe in the changelog.
OK.
>
> That being said, doesn't the runtime suspend callback already disable
> IRQs at the device level instead of the INTC level?
My idea is that the device may get reconfigured by the other processor.
I felt intc is the only way. do you agree?
>
> Kevin
>
>> pm_runtime_mark_last_busy(dev->dev);
>> pm_runtime_put_autosuspend(dev->dev);
>> return r;
>> @@ -1179,6 +1181,7 @@ omap_i2c_probe(struct platform_device *pdev)
>> goto err_unuse_clocks;
>> }
>>
>> + disable_irq(dev->irq);
>> adap = &dev->adapter;
>> i2c_set_adapdata(adap, dev);
>> adap->owner = THIS_MODULE;
> --
> To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [RFT/PATCH] serial: omap: prevent resume if device is not suspended.
From: Kevin Hilman @ 2012-10-12 17:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121012164202.GQ28061@n2100.arm.linux.org.uk>
Russell King - ARM Linux <linux@arm.linux.org.uk> writes:
> On Fri, Oct 12, 2012 at 09:35:54AM -0700, Kevin Hilman wrote:
>> Sourav <sourav.poddar@ti.com> writes:
>> > diff --git a/drivers/tty/serial/omap-serial.c
>> > b/drivers/tty/serial/omap-serial.c
>> > index 6ede6fd..3fbc7f7 100644
>> > --- a/drivers/tty/serial/omap-serial.c
>> > +++ b/drivers/tty/serial/omap-serial.c
>> > @@ -1414,6 +1414,7 @@ static int __devinit serial_omap_probe(struct
>> > platform_device *pdev)
>> > INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
>> >
>> > platform_set_drvdata(pdev, up);
>> > + pm_runtime_set_active(&pdev->dev);
>>
>> NAK.
>>
>> This will obviously break platforms where the UARTs are not active
>> before driver loads.
>
> I thought I had proposed a solution for this issue, which was this
> sequence:
>
> omap_device_enable(dev);
> pm_runtime_set_active(dev);
> pm_runtime_enable(dev);
>
> Yes, I can understand people not liking the omap_device_enable()
> there, but I also notice that the email suggesting that never got a
> reply either - not even a "I tried this and it doesn't work" or "it
> does work".
Yes, that solution would work (though I didn't actually try it.)
However, we can't use omap_device_enable() in the driver. We're trying
to clean all the drivers of OMAP-specific APIs. That being said,
something similar could be done in the device/board init code to ensure
the UART HW is in the state that the driver is expecting it, but again,
that would just mask the real problem which is that a (re)init of the
console UART on 2420/n800 is causing output to disappear.
As I detailed in an earlier response, I still think it's the fact that
the pinmux is not setup correctly for the console UART pins in the board
file, so when the UART is initialized, its mux settings are changed from
the bootloader defaults, causing output to disappear.
> As such, it seems this issue isn't making any progress as we had
> already established that merely doing a "pm_runtime_set_active()"
> before "pm_runtime_enable()" was going to break other platforms.
Agreed.
Kevin
^ permalink raw reply
* [PATCH 2/6] ARM: OMAP3/4: iommu: adapt to runtime pm
From: Omar Ramirez Luna @ 2012-10-12 17:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAMP44s2LTGPnXQuetVLV1tA8w90gUtoJ5coucBUZsbqb3vFnng@mail.gmail.com>
On 12 October 2012 02:48, Felipe Contreras <felipe.contreras@gmail.com> wrote:
> I already made most of these comments, but here they go again.
I replied to all, but here it goes again:
>> @@ -142,11 +142,10 @@ static int iommu_enable(struct omap_iommu *obj)
>> }
>> }
>>
>> - clk_enable(obj->clk);
>> + pm_runtime_get_sync(obj->dev);
>>
>> err = arch_iommu->enable(obj);
>>
>> - clk_disable(obj->clk);
>
> The device will never go to sleep, until iommu_disable is called.
> clk_enable -> pm_runtime_get_sync, clk_disable pm_runtime_put.
Which is what you want... why would you want your iommu to be disabled
if the client of that iommu could request a translation?
Remember that these iommus, sit along of other processors not on the
main processor side. So, this code should enable it for the other
processor to use, and there is no point where the processor can say
"I'm not using it, shut it down" or "I'm using it, turn it on" in the
middle of execution, other than suspend/resume and if supported,
autosuspend.
>> @@ -288,7 +285,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
>> if (!obj || !obj->nr_tlb_entries || !e)
>> return -EINVAL;
>>
>> - clk_enable(obj->clk);
>> + pm_runtime_get_sync(obj->dev);
>>
>> iotlb_lock_get(obj, &l);
>> if (l.base == obj->nr_tlb_entries) {
>> @@ -318,7 +315,7 @@ static int load_iotlb_entry(struct omap_iommu *obj, struct iotlb_entry *e)
>>
>> cr = iotlb_alloc_cr(obj, e);
>> if (IS_ERR(cr)) {
>> - clk_disable(obj->clk);
>> + pm_runtime_put_sync(obj->dev);
>> return PTR_ERR(cr);
>> }
>
> If I'm correct, the above pm_runtime_get/put are redundant, because
> the count can't possibly reach 0 because of the reason I explained
> before.
>
> The same for all the cases below.
You can access this paths through debugfs, some of them doesn't work
if the module is not enabled first, but in future if you just want to
idle the iommu withouth freeing, these are needed to debug.
BTW, the next patch in the series: ARM: OMAP: iommu: pm runtime save
and restore context, let's you do a pm_runtime_[enable|put] through
save/restore ctx functions, which is just for compatibility on how isp
code uses the save and restore code.
>> @@ -1009,7 +1001,8 @@ static int __devexit omap_iommu_remove(struct platform_device *pdev)
>> release_mem_region(res->start, resource_size(res));
>> iounmap(obj->regbase);
>>
>> - clk_put(obj->clk);
>> + pm_runtime_disable(obj->dev);
>
> This will turn on the device unnecessarily, wasting power, and there's
> no need for that, kfree will take care of that without resuming.
Left aside the aesthetics of having balanced calls, the device will be
enabled if there was a pending resume to be executed, otherwise it
won't, kfree won't increment the disable_depth counter and I don't
think that freeing the pointer is enough reason to ignore
pm_runtime_disable.
> Also, I still think that something like this is needed:
...
> +static struct clk cam_fck = {
> + .name = "cam_fck",
> + .ops = &clkops_omap2_iclk_dflt,
> + .parent = &l3_ick,
> + .enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
a cam_fck name to enable the ick?
Cheers,
Omar
^ permalink raw reply
* [PATCH v2] i2c: change the id to let the i2c-gpio work
From: Joachim Eastwood @ 2012-10-12 17:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1350034971-1050-1-git-send-email-voice.shen@atmel.com>
Hi Bo Shen,
On Fri, Oct 12, 2012 at 11:42 AM, Bo Shen <voice.shen@atmel.com> wrote:
> The i2c-gpio driver will turn the platform device ID to busnum.
> When using platfrom device ID as -1, it means dynamically assigned
> the busnum. When writing code, we need to make sure the busnum,
> and call i2c_register_board_info(int busnum, ...) to register device
> if using -1, we do not know the value of busnum.
>
> In order to solve this issue, set the platform device ID as a fix number
> Here using 0 to match the busnum used in i2c_regsiter_board_info().
I have been bitten by this myself on RM9200.
> Signed-off-by: Bo Shen <voice.shen@atmel.com>
> ---
> Change since v1
> Make the commit message more clear
> ---
> arch/arm/mach-at91/at91sam9260_devices.c | 2 +-
This pattern exist in at91rm9200_devices.c, at91sam9261_devices.c,
at91sam9263_devices.c and at91sam9rl_devices.c you might want to fix
them as well.
I assume we have the same problem if CONFIG_I2C_AT91 is set?
See further down in at91sam9260_devices.c we have another: ".id = -1,"
regards
Joachim Eastwood
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
> index 0f24cfb..805ef95 100644
> --- a/arch/arm/mach-at91/at91sam9260_devices.c
> +++ b/arch/arm/mach-at91/at91sam9260_devices.c
> @@ -389,7 +389,7 @@ static struct i2c_gpio_platform_data pdata = {
>
> static struct platform_device at91sam9260_twi_device = {
> .name = "i2c-gpio",
> - .id = -1,
> + .id = 0,
> .dev.platform_data = &pdata,
> };
>
> --
> 1.7.9.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [RFT/PATCH] serial: omap: prevent resume if device is not suspended.
From: Poddar, Sourav @ 2012-10-12 17:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121012164202.GQ28061@n2100.arm.linux.org.uk>
Hi Russell,
________________________________________
From: Russell King - ARM Linux [linux at arm.linux.org.uk]
Sent: Friday, October 12, 2012 10:12 PM
To: Kevin Hilman
Cc: Poddar, Sourav; Paul Walmsley; Balbi, Felipe; gregkh at linuxfoundation.org; tony at atomide.com; linux-kernel at vger.kernel.org; Shilimkar, Santosh; linux-serial at vger.kernel.org; linux-omap at vger.kernel.org; linux-arm-kernel at lists.infradead.org; alan at linux.intel.com
Subject: Re: [RFT/PATCH] serial: omap: prevent resume if device is not suspended.
On Fri, Oct 12, 2012 at 09:35:54AM -0700, Kevin Hilman wrote:
> Sourav <sourav.poddar@ti.com> writes:
> > diff --git a/drivers/tty/serial/omap-serial.c
> > b/drivers/tty/serial/omap-serial.c
> > index 6ede6fd..3fbc7f7 100644
> > --- a/drivers/tty/serial/omap-serial.c
> > +++ b/drivers/tty/serial/omap-serial.c
> > @@ -1414,6 +1414,7 @@ static int __devinit serial_omap_probe(struct
> > platform_device *pdev)
> > INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
> >
> > platform_set_drvdata(pdev, up);
> > + pm_runtime_set_active(&pdev->dev);
>
> NAK.
>
> This will obviously break platforms where the UARTs are not active
> before driver loads.
I thought I had proposed a solution for this issue, which was this
sequence:
omap_device_enable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
Yes, I can understand people not liking the omap_device_enable()
there, but I also notice that the email suggesting that never got a
reply either - not even a "I tried this and it doesn't work" or "it
does work".
Sorry for the late reply on this. I tried this sequence and it worked perfectly fine on
panda and beagle.
As such, it seems this issue isn't making any progress as we had
already established that merely doing a "pm_runtime_set_active()"
before "pm_runtime_enable()" was going to break other platforms.
I was trying to analyse your explanations on this and since omap_device_enable is not generally
recommended, I was trying to see if anything else can be done to get around this.
I send this patch for N800 testing so as to see how it behaves. (We are suspecting that there might be
mux setting issue also with N800).
~Sourav
^ permalink raw reply
* [PATCH V2 2/3] dmaengine: dw_dmac: Enhance device tree support
From: Viresh Kumar @ 2012-10-12 17:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121012162057.GG12801@game.jcrosoft.org>
On 12 October 2012 21:50, Jean-Christophe PLAGNIOL-VILLARD
<plagnioj@jcrosoft.com> wrote:
>> >> - pass platform data via DT, non-DT way still takes precedence if both are used.
>> > why keep it all platform are DT
>>
>> I would love to remove that, but not sure if somebody want's the non-DT
>> way too.
>>
>> I didn't wanted to get into fixing user SoCs of this driver.
> no drop it at the mailine if do not need it
But what's the harm in keeping it until we are sure, all users of it have
moved into DT? It is not adding any overhead for DT case. And this
is what most of the drivers today are doing, because not every platform
is DT compatible.
This driver is used in multiple architectures, not only ARM.
--
viresh
^ permalink raw reply
* [PATCH V2 3/3] ARM: SPEAr13xx: Pass DW DMAC platform data from DT
From: Viresh Kumar @ 2012-10-12 17:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121012162148.GH12801@game.jcrosoft.org>
On 12 October 2012 21:51, Jean-Christophe PLAGNIOL-VILLARD
<plagnioj@jcrosoft.com> wrote:
>> >> + OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, "cf"),
>> > ?/
>>
>> Sorry. can't get it :(
> what is the "cf" as paltfrom data
This is dma bus_id string, which matches with what is passed from dtb.
^ permalink raw reply
* Booting vanilla kernel on the beaglebone
From: Richard Cochran @ 2012-10-12 17:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <EB1619762EAF8B4E97A227FB77B7E0293E9F451D@DBDE01.ent.ti.com>
On Thu, Oct 11, 2012 at 09:20:24PM +0000, N, Mugunthan V wrote:
>
> I have a working branch for CPSW which is based on 3.5.0-rc6 in the following git repo
> Repo: https://github.com/hvaibhav/am335x-linux.git
> Branch: am335x-linux-next-master-cpsw
It looks like the last five commits in that branch are relevant:
86116a8 ARM: OMAP2+: omap2plus_defconfig: Enable CPSW support
020c28d arm/dts: am33xx: Add cpsw and mdio module nodes for AM33XX
e36f449 net: cpsw: Add parent<->child relation support between cpsw and mdio
011d593 net: davinci_mdio: Fix type mistake in calling runtime-pm api
7179021 ARM: OMAP3+: hwmod: Add AM33XX HWMOD data for davinci_mdio
Are there any others buried deeper in there?
Are you submitting the needed patches for 3.7-rc1?
Thanks,
Richard
^ permalink raw reply
* [PATCH 3/4] ARM: AT91: Add AT91RM9200 support to DT board
From: Joachim Eastwood @ 2012-10-12 17:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121012162706.GI12801@game.jcrosoft.org>
On Fri, Oct 12, 2012 at 6:27 PM, Jean-Christophe PLAGNIOL-VILLARD
<plagnioj@jcrosoft.com> wrote:
> On 17:28 Fri 12 Oct , ludovic.desroches wrote:
>> Le 10/12/2012 04:22 PM, Jean-Christophe PLAGNIOL-VILLARD a ?crit :
>> >On 00:05 Fri 12 Oct , Joachim Eastwood wrote:
>> >>Signed-off-by: Joachim Eastwood <manabian@gmail.com>
>> >>---
>> >>
>> >>Hi,
>> >>
>> >>This patch has some potential issues.
>> >>Before this patch board-dt would fail building when only AT91RM9200 was enabled because at91sam926x_timer symbol would be missing. This patch uses the at91rm9200_timer which
>> >>will fail if AT91RM9200 is not enabled.
>> >this need work with ot wtihout rm9200
btw, to solve the build issue with board-dt in mainline now we need to
add a select CONFIG_SOC_AT91SAM9 to config MACH_AT91SAM_DT.
>> >>
>> >>Any thoughts on solving this? As mention above this bug exists in mainline now.
>> >duplicate the board-dt with one for rm9200 only
>> >as rm9200 ans sam9 are 2 distict familly
>>
>> Why not adding a new machine descriptor for rm9200 in order to
>> prevent file duplication?
> because the soc are different and can only be compile if the timer is enable
> and I do not want to enable the rm9200 timer on sam9 so instead of a ifdef i
> the board-dt create a new board is better as we have a 50 lines file
>
> with different board_compat and different machine descriptor
I am okey with either approach, but I would like to hear what Nicolas
Ferre has to say since he is the on the one that added board-dt. It
would be nice to have everything in one board DT file, but I
understand your concern with the RM9200 timer.
We will also bump into this again on AT91X40 I guess.
regards
Joachim Eastwood
^ permalink raw reply
* [PATCH] ARM: OMAP4: Fix twd_local_timer_register regression
From: Tony Lindgren @ 2012-10-12 16:51 UTC (permalink / raw)
To: linux-arm-kernel
Commit 7d7e1eba (ARM: OMAP2+: Prepare for irqs.h removal)
changed the interrupts to allow enabling sparse IRQ, but
accidentally added the omap3 INTC base to the local IRQ.
This causes the following:
twd: can't register interrupt 45 (-22)
twd_local_timer_register failed -22
The right fix is to not add any base, as it is a local
timer. For the OMAP44XX_IRQ_LOCALWDT we had defined earlier
there are no users, so no need to fix that.
Reported-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Tony Lindgren <tony@atomide.com>
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -467,7 +467,7 @@ OMAP_SYS_TIMER(3_am33xx)
#ifdef CONFIG_ARCH_OMAP4
#ifdef CONFIG_LOCAL_TIMERS
static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
- OMAP44XX_LOCAL_TWD_BASE, 29 + OMAP_INTC_START);
+ OMAP44XX_LOCAL_TWD_BASE, 29);
#endif
static void __init omap4_timer_init(void)
^ permalink raw reply
* [PATCH] Boottime: A tool for automatic measurement of kernel/bootloader boot time
From: Lee Jones @ 2012-10-12 16:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50784729.4030302@ti.com>
On Fri, 12 Oct 2012, Dan Murphy wrote:
>
> On 10/12/2012 09:01 AM, Lee Jones wrote:
> >On Fri, 12 Oct 2012, Arnd Bergmann wrote:
> >
> >>On Friday 12 October 2012, Russell King - ARM Linux wrote:
> >>>>root at ME:/ cat /sys/kernel/debug/boottime/bootgraph
> >>>>[ 0.185254] calling splash+0x0/0x0
> >>>>[ 2.984335] initcall splash+0x0/0x0 returned 0 after 2799 msecs.
> >>>>[ 2.984335] calling autoboot_delay+0x0/0x0
> >>>>[ 4.089513] initcall autoboot_delay+0x0/0x0 returned 0 after 1105 msecs.
> >>>>[ 4.089513] calling load_kernel+0x0/0x0
> >>>>[ 4.239174] initcall load_kernel+0x0/0x0 returned 0 after 149 msecs.
> >>>>[ 4.239174] calling boot_kernel+0x0/0x0
> >>>>[ 4.276260] initcall boot_kernel+0x0/0x0 returned 0 after 37 msecs.
> >>>>[ 4.276260] calling uncompress_ll_init+0x0/0x0
> >>>>[ 4.276260] initcall uncompress_ll_init+0x0/0x0 returned 0 after 0 msecs.
> >>>>[ 4.276260] Freeing init memory: 0K
> >>>Umm, what happened to sysfs not becoming procfs v2? I thought we had
> >>>a fairly strict requirement for "one value per file and not nicely
> >>>formatted" for sysfs?
> >>>
> >>I was thinking the same thing at first, but then I noticed it's actually
> >>debugfs, which has no such rules.
> >Right. :)
> >
> OK I don't see when boottime_activate is called.
>
> Where would this call actually be made from?
>
> I see the call to deactivate but no call to activate.
Here perhaps (Jonas, alerted me to the missing patch):
commit 4c49a18bcfd2d041cbad7f41c6e6b39d90008382 (HEAD, refs/heads/dt-snowball-pre-rc1)
Author: Jonas Aaberg <jonas.aberg@stericsson.com>
Date: Wed Sep 14 09:29:20 2011 +0200
drivers: clocksource: dbx500-prcmu: Add boottime support
Change-Id: I9b5e3d050131c08c08786ae84cb76619c0525049
Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32055
diff --git a/drivers/clocksource/clksrc-dbx500-prcmu.c b/drivers/clocksource/clksrc-dbx500-prcmu.c
index c26c369..0069cd9 100644
--- a/drivers/clocksource/clksrc-dbx500-prcmu.c
+++ b/drivers/clocksource/clksrc-dbx500-prcmu.c
@@ -14,6 +14,7 @@
*/
#include <linux/clockchips.h>
#include <linux/clksrc-dbx500-prcmu.h>
+#include <linux/boottime.h>
#include <asm/sched_clock.h>
@@ -68,6 +69,23 @@ static u32 notrace dbx500_prcmu_sched_clock_read(void)
#endif
+#ifdef CONFIG_BOOTTIME
+static unsigned long __init boottime_get_time(void)
+{
+ return div_s64(clocksource_cyc2ns(clocksource_dbx500_prcmu.read(
+ &clocksource_dbx500_prcmu),
+ clocksource_dbx500_prcmu.mult,
+ clocksource_dbx500_prcmu.shift),
+ 1000);
+}
+
+static struct boottime_timer __initdata boottime_timer = {
+ .init = NULL,
+ .get_time = boottime_get_time,
+ .finalize = NULL,
+};
+#endif
+
void __init clksrc_dbx500_prcmu_init(void __iomem *base)
{
clksrc_dbx500_timer_base = base;
@@ -90,4 +108,6 @@ void __init clksrc_dbx500_prcmu_init(void __iomem *base)
32, RATE_32K);
#endif
clocksource_register_hz(&clocksource_dbx500_prcmu, RATE_32K);
+
+ boottime_activate(&boottime_timer);
}
--
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply related
* [RFT/PATCH] serial: omap: prevent resume if device is not suspended.
From: Russell King - ARM Linux @ 2012-10-12 16:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <877gqv7imt.fsf@deeprootsystems.com>
On Fri, Oct 12, 2012 at 09:35:54AM -0700, Kevin Hilman wrote:
> Sourav <sourav.poddar@ti.com> writes:
> > diff --git a/drivers/tty/serial/omap-serial.c
> > b/drivers/tty/serial/omap-serial.c
> > index 6ede6fd..3fbc7f7 100644
> > --- a/drivers/tty/serial/omap-serial.c
> > +++ b/drivers/tty/serial/omap-serial.c
> > @@ -1414,6 +1414,7 @@ static int __devinit serial_omap_probe(struct
> > platform_device *pdev)
> > INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
> >
> > platform_set_drvdata(pdev, up);
> > + pm_runtime_set_active(&pdev->dev);
>
> NAK.
>
> This will obviously break platforms where the UARTs are not active
> before driver loads.
I thought I had proposed a solution for this issue, which was this
sequence:
omap_device_enable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
Yes, I can understand people not liking the omap_device_enable()
there, but I also notice that the email suggesting that never got a
reply either - not even a "I tried this and it doesn't work" or "it
does work".
As such, it seems this issue isn't making any progress as we had
already established that merely doing a "pm_runtime_set_active()"
before "pm_runtime_enable()" was going to break other platforms.
^ permalink raw reply
* [PATCH] Boottime: A tool for automatic measurement of kernel/bootloader boot time
From: Dan Murphy @ 2012-10-12 16:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121012140149.GJ12567@gmail.com>
On 10/12/2012 09:01 AM, Lee Jones wrote:
> On Fri, 12 Oct 2012, Arnd Bergmann wrote:
>
>> On Friday 12 October 2012, Russell King - ARM Linux wrote:
>>>> root at ME:/ cat /sys/kernel/debug/boottime/bootgraph
>>>> [ 0.185254] calling splash+0x0/0x0
>>>> [ 2.984335] initcall splash+0x0/0x0 returned 0 after 2799 msecs.
>>>> [ 2.984335] calling autoboot_delay+0x0/0x0
>>>> [ 4.089513] initcall autoboot_delay+0x0/0x0 returned 0 after 1105 msecs.
>>>> [ 4.089513] calling load_kernel+0x0/0x0
>>>> [ 4.239174] initcall load_kernel+0x0/0x0 returned 0 after 149 msecs.
>>>> [ 4.239174] calling boot_kernel+0x0/0x0
>>>> [ 4.276260] initcall boot_kernel+0x0/0x0 returned 0 after 37 msecs.
>>>> [ 4.276260] calling uncompress_ll_init+0x0/0x0
>>>> [ 4.276260] initcall uncompress_ll_init+0x0/0x0 returned 0 after 0 msecs.
>>>> [ 4.276260] Freeing init memory: 0K
>>> Umm, what happened to sysfs not becoming procfs v2? I thought we had
>>> a fairly strict requirement for "one value per file and not nicely
>>> formatted" for sysfs?
>>>
>> I was thinking the same thing at first, but then I noticed it's actually
>> debugfs, which has no such rules.
> Right. :)
>
OK I don't see when boottime_activate is called.
Where would this call actually be made from?
I see the call to deactivate but no call to activate.
Dan
^ permalink raw reply
* [RFT/PATCH] serial: omap: prevent resume if device is not suspended.
From: Kevin Hilman @ 2012-10-12 16:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50784458.9080806@ti.com>
Sourav <sourav.poddar@ti.com> writes:
> Hi Paul,
>
> There are
> On Thursday 11 October 2012 11:58 PM, Paul Walmsley wrote:
>> Hi Sourav, Felipe,
>>
>> any progress on fixing the N800 problem? Would be good to keep it booting
>> since we use it as our primary 2420 test platform.
>>
>>
>> - Paul
> The patch sent inlined below might help us to get rid of the serial
> init issue.
> Unfortunately, I dont have a N800 board with me to test it and will require
> your help to do so.
> -----------
> From: Sourav Poddar <sourav.poddar@ti.com>
> Date: Wed, 1 Aug 2012 15:44:12 +0530
> Subject: [RFT/PATCH] serial: omap: Fix N800 serial init issue.
>
>
> This patch might solve the N800 serial init issue.
>
> This patch will also give pointers if there is any mux settings issue
> with N800 OR
> a mismatch between the initial harware state, runtime PM state and
> omap hwmod state.
> I don't have a N800 schematics to check about the mux settings getting used.
>
> The observation on beagle board XM with this patch on different boards
> looks flaky,
> so your feedback on beagle board will also be very helpful.
>
> Cc: Felipe Balbi <balbi@ti.com>
> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
> ---
> drivers/tty/serial/omap-serial.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/tty/serial/omap-serial.c
> b/drivers/tty/serial/omap-serial.c
> index 6ede6fd..3fbc7f7 100644
> --- a/drivers/tty/serial/omap-serial.c
> +++ b/drivers/tty/serial/omap-serial.c
> @@ -1414,6 +1414,7 @@ static int __devinit serial_omap_probe(struct
> platform_device *pdev)
> INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
>
> platform_set_drvdata(pdev, up);
> + pm_runtime_set_active(&pdev->dev);
NAK.
This will obviously break platforms where the UARTs are not active
before driver loads.
Kevin
> pm_runtime_enable(&pdev->dev);
> pm_runtime_use_autosuspend(&pdev->dev);
> pm_runtime_set_autosuspend_delay(&pdev->dev,
^ permalink raw reply
* [PATCH 3/4] ARM: AT91: Add AT91RM9200 support to DT board
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-12 16:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50783714.2000702@atmel.com>
On 17:28 Fri 12 Oct , ludovic.desroches wrote:
> Le 10/12/2012 04:22 PM, Jean-Christophe PLAGNIOL-VILLARD a ?crit :
> >On 00:05 Fri 12 Oct , Joachim Eastwood wrote:
> >>Signed-off-by: Joachim Eastwood <manabian@gmail.com>
> >>---
> >>
> >>Hi,
> >>
> >>This patch has some potential issues.
> >>Before this patch board-dt would fail building when only AT91RM9200 was enabled because at91sam926x_timer symbol would be missing. This patch uses the at91rm9200_timer which
> >>will fail if AT91RM9200 is not enabled.
> >this need work with ot wtihout rm9200
> >>
> >>Any thoughts on solving this? As mention above this bug exists in mainline now.
> >duplicate the board-dt with one for rm9200 only
> >as rm9200 ans sam9 are 2 distict familly
>
> Why not adding a new machine descriptor for rm9200 in order to
> prevent file duplication?
because the soc are different and can only be compile if the timer is enable
and I do not want to enable the rm9200 timer on sam9 so instead of a ifdef i
the board-dt create a new board is better as we have a 50 lines file
with different board_compat and different machine descriptor
Best Regards,
J.
>
> Regards
>
> Ludovic
>
> >>
> >>I had to create a new at91rm9200_dt_initialize since at91_dt_initialize will panic when it tries to add rstc and shdwc.
> >>Is it okay to add at91rm9200_dt_initialize or should we fix at91_dt_rstc and at91_dt_shdwc to not panic when DT nodes are not found?
> >it's ok
> >>
> >
> >can you add a board too rm9200ek will be good
> >
> >Best Regards,
> >J.
> >>regards
> >>Joachim Eastwood
> >>
> >> arch/arm/mach-at91/board-dt.c | 15 +++++++++++++++
> >> arch/arm/mach-at91/generic.h | 1 +
> >> arch/arm/mach-at91/setup.c | 14 ++++++++++++++
> >> 3 files changed, 30 insertions(+)
> >>
> >>diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
> >>index e8f45c4..0e73317 100644
> >>--- a/arch/arm/mach-at91/board-dt.c
> >>+++ b/arch/arm/mach-at91/board-dt.c
> >>@@ -45,11 +45,26 @@ static void __init at91_dt_device_init(void)
> >> of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
> >> }
> >>
> >>+static const char *at91rm9200_dt_board_compat[] __initdata = {
> >>+ "atmel,at91rm9200",
> >>+ NULL
> >>+};
> >>+
> >> static const char *at91_dt_board_compat[] __initdata = {
> >> "atmel,at91sam9",
> >> NULL
> >> };
> >>
> >>+DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
> >>+ .timer = &at91rm9200_timer,
> >>+ .map_io = at91_map_io,
> >>+ .handle_irq = at91_aic_handle_irq,
> >>+ .init_early = at91rm9200_dt_initialize,
> >>+ .init_irq = at91_dt_init_irq,
> >>+ .init_machine = at91_dt_device_init,
> >>+ .dt_compat = at91rm9200_dt_board_compat,
> >>+MACHINE_END
> >>+
> >> DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
> >> /* Maintainer: Atmel */
> >> .timer = &at91sam926x_timer,
> >>diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
> >>index f496506..9bb5ce5 100644
> >>--- a/arch/arm/mach-at91/generic.h
> >>+++ b/arch/arm/mach-at91/generic.h
> >>@@ -20,6 +20,7 @@ extern void __init at91_init_sram(int bank, unsigned long base,
> >> extern void __init at91rm9200_set_type(int type);
> >> extern void __init at91_initialize(unsigned long main_clock);
> >> extern void __init at91x40_initialize(unsigned long main_clock);
> >>+extern void __init at91rm9200_dt_initialize(void);
> >> extern void __init at91_dt_initialize(void);
> >>
> >> /* Interrupts */
> >>diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
> >>index da9881b..2c1fdd4 100644
> >>--- a/arch/arm/mach-at91/setup.c
> >>+++ b/arch/arm/mach-at91/setup.c
> >>@@ -338,6 +338,7 @@ static void at91_dt_rstc(void)
> >> }
> >>
> >> static struct of_device_id ramc_ids[] = {
> >>+ { .compatible = "atmel,at91rm9200-sdramc" },
> >> { .compatible = "atmel,at91sam9260-sdramc" },
> >> { .compatible = "atmel,at91sam9g45-ddramc" },
> >> { /*sentinel*/ }
> >>@@ -436,6 +437,19 @@ end:
> >> of_node_put(np);
> >> }
> >>
> >>+void __init at91rm9200_dt_initialize(void)
> >>+{
> >>+ at91_dt_ramc();
> >>+
> >>+ /* Init clock subsystem */
> >>+ at91_dt_clock_init();
> >>+
> >>+ /* Register the processor-specific clocks */
> >>+ at91_boot_soc.register_clocks();
> >>+
> >>+ at91_boot_soc.init();
> >>+}
> >>+
> >> void __init at91_dt_initialize(void)
> >> {
> >> at91_dt_rstc();
> >>--
> >>1.7.12.2
> >>
> >
> >_______________________________________________
> >linux-arm-kernel mailing list
> >linux-arm-kernel at lists.infradead.org
> >http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> >
> >
>
^ permalink raw reply
* [RFT/PATCH] serial: omap: prevent resume if device is not suspended.
From: Sourav @ 2012-10-12 16:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1210111748010.5736@utopia.booyaka.com>
Hi Paul,
There are
On Thursday 11 October 2012 11:58 PM, Paul Walmsley wrote:
> Hi Sourav, Felipe,
>
> any progress on fixing the N800 problem? Would be good to keep it booting
> since we use it as our primary 2420 test platform.
>
>
> - Paul
The patch sent inlined below might help us to get rid of the serial init
issue.
Unfortunately, I dont have a N800 board with me to test it and will require
your help to do so.
-----------
From: Sourav Poddar <sourav.poddar@ti.com>
Date: Wed, 1 Aug 2012 15:44:12 +0530
Subject: [RFT/PATCH] serial: omap: Fix N800 serial init issue.
This patch might solve the N800 serial init issue.
This patch will also give pointers if there is any mux settings issue
with N800 OR
a mismatch between the initial harware state, runtime PM state and omap
hwmod state.
I don't have a N800 schematics to check about the mux settings getting used.
The observation on beagle board XM with this patch on different boards
looks flaky,
so your feedback on beagle board will also be very helpful.
Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
---
drivers/tty/serial/omap-serial.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/tty/serial/omap-serial.c
b/drivers/tty/serial/omap-serial.c
index 6ede6fd..3fbc7f7 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1414,6 +1414,7 @@ static int __devinit serial_omap_probe(struct
platform_device *pdev)
INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
platform_set_drvdata(pdev, up);
+ pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev,
--
1.7.1
^ permalink raw reply related
* [PATCH V2 3/3] ARM: SPEAr13xx: Pass DW DMAC platform data from DT
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-12 16:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKohpo=vMchmiz70evBB5bPqt4O4DWUocd5M1o9gc8fsY_Fkiw@mail.gmail.com>
On 20:22 Fri 12 Oct , Viresh Kumar wrote:
> On 12 October 2012 20:18, Jean-Christophe PLAGNIOL-VILLARD
> <plagnioj@jcrosoft.com> wrote:
> >> static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
> >> - OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
> >> - OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
> >> - OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
> >> + OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, "cf"),
> > ?/
>
> Sorry. can't get it :(
what is the "cf" as paltfrom data
Best Regards,
J.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox