From a7ca13826e478f9b201eb2f9f20de0b978a82ad9 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 29 Jun 2018 14:11:19 +1000 Subject: gpio: aspeed: Add interfaces for co-processor to grab GPIOs On the Aspeed chip, the GPIOs can be under control of the ARM chip or of the ColdFire coprocessor. (There's a third command source, the LPC bus, which we don't use or support yet). The control of which master is allowed to modify a given GPIO is per-bank (8 GPIOs). Unfortunately, systems already exist for which we want to use GPIOs of both sources in the same bank. This provides an API exported by the gpio-aspeed driver that an aspeed coprocessor driver can use to "grab" some GPIOs for use by the coprocessor, and allow the coprocessor driver to provide callbacks for arbitrating access. Once at least one GPIO of a given bank has been "grabbed" by the coprocessor, the entire bank is marked as being under coprocessor control. It's command source is switched to the coprocessor. If the ARM then tries to write to a GPIO in such a marked bank, the provided callbacks are used to request access from the coprocessor driver, which is responsible to doing whatever is necessary to "pause" the coprocessor or prevent it from trying to use the GPIOs while the ARM is doing its accesses. During that time, the command source for the bank is temporarily switched back to the ARM. Signed-off-by: Benjamin Herrenschmidt Reviewed-by: Joel Stanley Reviewed-by: Andrew Jeffery Signed-off-by: Linus Walleij --- include/linux/gpio/aspeed.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 include/linux/gpio/aspeed.h (limited to 'include/linux') diff --git a/include/linux/gpio/aspeed.h b/include/linux/gpio/aspeed.h new file mode 100644 index 000000000000..1bfb3cdc86d0 --- /dev/null +++ b/include/linux/gpio/aspeed.h @@ -0,0 +1,15 @@ +#ifndef __GPIO_ASPEED_H +#define __GPIO_ASPEED_H + +struct aspeed_gpio_copro_ops { + int (*request_access)(void *data); + int (*release_access)(void *data); +}; + +int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc, + u16 *vreg_offset, u16 *dreg_offset, u8 *bit); +int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc); +int aspeed_gpio_copro_set_ops(const struct aspeed_gpio_copro_ops *ops, void *data); + + +#endif /* __GPIO_ASPEED_H */ -- cgit v1.2.3 From d5e838275c80aeb96d4c0b81442a851dfef2e948 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 5 Jun 2018 13:21:26 +1000 Subject: devres: Add devm_of_iomap() There are still quite a few cases where a device might want to get to a different node of the device-tree, obtain the resources and map them. We have of_iomap() and of_io_request_and_map() but they both have shortcomings, such as not returning the size of the resource found (which can be useful) and not being "managed". This adds a devm_of_iomap() that provides all of these and should probably replace uses of the above in most drivers. Signed-off-by: Benjamin Herrenschmidt Reviewed-by: Linus Walleij Reviewed-by: Joel Stanley --- include/linux/device.h | 4 ++++ lib/devres.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) (limited to 'include/linux') diff --git a/include/linux/device.h b/include/linux/device.h index 055a69dbcd18..6aa8d51eabe9 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -696,6 +696,10 @@ extern void devm_free_pages(struct device *dev, unsigned long addr); void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res); +void __iomem *devm_of_iomap(struct device *dev, + struct device_node *node, int index, + resource_size_t *size); + /* allows to add/remove a custom action to devres stack */ int devm_add_action(struct device *dev, void (*action)(void *), void *data); void devm_remove_action(struct device *dev, void (*action)(void *), void *data); diff --git a/lib/devres.c b/lib/devres.c index 5bec1120b392..faccf1a037d0 100644 --- a/lib/devres.c +++ b/lib/devres.c @@ -4,6 +4,7 @@ #include #include #include +#include enum devm_ioremap_type { DEVM_IOREMAP = 0, @@ -162,6 +163,41 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res) } EXPORT_SYMBOL(devm_ioremap_resource); +/* + * devm_of_iomap - Requests a resource and maps the memory mapped IO + * for a given device_node managed by a given device + * + * Checks that a resource is a valid memory region, requests the memory + * region and ioremaps it. All operations are managed and will be undone + * on driver detach of the device. + * + * This is to be used when a device requests/maps resources described + * by other device tree nodes (children or otherwise). + * + * @dev: The device "managing" the resource + * @node: The device-tree node where the resource resides + * @index: index of the MMIO range in the "reg" property + * @size: Returns the size of the resource (pass NULL if not needed) + * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded + * error code on failure. Usage example: + * + * base = devm_of_iomap(&pdev->dev, node, 0, NULL); + * if (IS_ERR(base)) + * return PTR_ERR(base); + */ +void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index, + resource_size_t *size) +{ + struct resource res; + + if (of_address_to_resource(node, index, &res)) + return IOMEM_ERR_PTR(-EINVAL); + if (size) + *size = resource_size(&res); + return devm_ioremap_resource(dev, &res); +} +EXPORT_SYMBOL(devm_of_iomap); + #ifdef CONFIG_HAS_IOPORT_MAP /* * Generic iomap devres -- cgit v1.2.3