

index 150fd3833d0bf..d97bccf46147d 100644

--- a/

+++ b/ diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txtindex 150fd3833d0bf..d97bccf46147d 100644--- a/ Documentation/pinctrl.txt +++ b/ Documentation/pinctrl.txt @@ -206,12 +206,21 @@ using a certain resistor value - pull up and pull down - so that the pin has a stable value when nothing is driving the rail it is connected to, or when it's unconnected. -For example, a platform may do this: +Pin configuration can be programmed either using the explicit APIs described +immediately below, or by adding configuration entries into the mapping table; +see section "Board/machine configuration" below. + +For example, a platform may do the following to pull up a pin to VDD: + +#include <linux/pinctrl/consumer.h> ret = pin_config_set("foo-dev", "FOO_GPIO_PIN", PLATFORM_X_PULL_UP); -To pull up a pin to VDD. The pin configuration driver implements callbacks for -changing pin configuration in the pin controller ops like this: +The format and meaning of the configuration parameter, PLATFORM_X_PULL_UP +above, is entirely defined by the pin controller driver. + +The pin configuration driver implements callbacks for changing pin +configuration in the pin controller ops like this: #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinconf.h> @@ -492,14 +501,10 @@ Definitions: {"map-i2c0", i2c0, pinctrl0, fi2c0, gi2c0} } - Every map must be assigned a symbolic name, pin controller and function. - The group is not compulsory - if it is omitted the first group presented by - the driver as applicable for the function will be selected, which is - useful for simple cases. - - The device name is present in map entries tied to specific devices. Maps - without device names are referred to as SYSTEM pinmuxes, such as can be taken - by the machine implementation on boot and not tied to any specific device. + Every map must be assigned a state name, pin controller, device and + function. The group is not compulsory - if it is omitted the first group + presented by the driver as applicable for the function will be selected, + which is useful for simple cases. It is possible to map several groups to the same combination of device, pin controller and function. This is for cases where a certain function on @@ -726,19 +731,19 @@ same time. All the above functions are mandatory to implement for a pinmux driver. -Pinmux interaction with the GPIO subsystem -========================================== +Pin control interaction with the GPIO subsystem +=============================================== -The public pinmux API contains two functions named pinmux_request_gpio() -and pinmux_free_gpio(). These two functions shall *ONLY* be called from +The public pinmux API contains two functions named pinctrl_request_gpio() +and pinctrl_free_gpio(). These two functions shall *ONLY* be called from gpiolib-based drivers as part of their gpio_request() and -gpio_free() semantics. Likewise the pinmux_gpio_direction_[input|output] +gpio_free() semantics. Likewise the pinctrl_gpio_direction_[input|output] shall only be called from within respective gpio_direction_[input|output] gpiolib implementation. NOTE that platforms and individual drivers shall *NOT* request GPIO pins to be -muxed in. Instead, implement a proper gpiolib driver and have that driver -request proper muxing for its pins. +controlled e.g. muxed in. Instead, implement a proper gpiolib driver and have +that driver request proper muxing and other control for its pins. The function list could become long, especially if you can convert every individual pin into a GPIO pin independent of any other pins, and then try @@ -747,7 +752,7 @@ the approach to define every pin as a function. In this case, the function array would become 64 entries for each GPIO setting and then the device functions. -For this reason there are two functions a pinmux driver can implement +For this reason there are two functions a pin control driver can implement to enable only GPIO on an individual pin: .gpio_request_enable() and .gpio_disable_free(). @@ -762,12 +767,12 @@ gpiolib driver and the affected GPIO range, pin offset and desired direction will be passed along to this function. Alternatively to using these special functions, it is fully allowed to use -named functions for each GPIO pin, the pinmux_request_gpio() will attempt to +named functions for each GPIO pin, the pinctrl_request_gpio() will attempt to obtain the function "gpioN" where "N" is the global GPIO pin number if no special GPIO-handler is registered. -Pinmux board/machine configuration +Board/machine configuration ================================== Boards and machines define how a certain complete running system is put @@ -775,27 +780,33 @@ together, including how GPIOs and devices are muxed, how regulators are constrained and how the clock tree looks. Of course pinmux settings are also part of this. -A pinmux config for a machine looks pretty much like a simple regulator -configuration, so for the example array above we want to enable i2c and -spi on the second function mapping: +A pin controller configuration for a machine looks pretty much like a simple +regulator configuration, so for the example array above we want to enable i2c +and spi on the second function mapping: #include <linux/pinctrl/machine.h> -static const struct pinmux_map __initdata pmx_mapping[] = { +static const struct pinctrl_map __initdata mapping[] = { { - .ctrl_dev_name = "pinctrl-foo", - .function = "spi0", .dev_name = "foo-spi.0", + .name = PINCTRL_STATE_DEFAULT, + .type = PIN_MAP_TYPE_MUX_GROUP, + .ctrl_dev_name = "pinctrl-foo", + .data.mux.function = "spi0", }, { - .ctrl_dev_name = "pinctrl-foo", - .function = "i2c0", .dev_name = "foo-i2c.0", + .name = PINCTRL_STATE_DEFAULT, + .type = PIN_MAP_TYPE_MUX_GROUP, + .ctrl_dev_name = "pinctrl-foo", + .data.mux.function = "i2c0", }, { - .ctrl_dev_name = "pinctrl-foo", - .function = "mmc0", .dev_name = "foo-mmc.0", + .name = PINCTRL_STATE_DEFAULT, + .type = PIN_MAP_TYPE_MUX_GROUP, + .ctrl_dev_name = "pinctrl-foo", + .data.mux.function = "mmc0", }, }; @@ -805,21 +816,51 @@ must match a function provided by the pinmux driver handling this pin range. As you can see we may have several pin controllers on the system and thus we need to specify which one of them that contain the functions we wish -to map. The map can also use struct device * directly, so there is no -inherent need to use strings to specify .dev_name or .ctrl_dev_name, these -are for the situation where you do not have a handle to the struct device *, -for example if they are not yet instantiated or cumbersome to obtain. +to map. You register this pinmux mapping to the pinmux subsystem by simply: - ret = pinmux_register_mappings(pmx_mapping, ARRAY_SIZE(pmx_mapping)); + ret = pinctrl_register_mappings(mapping, ARRAY_SIZE(mapping)); Since the above construct is pretty common there is a helper macro to make it even more compact which assumes you want to use pinctrl-foo and position 0 for mapping, for example: -static struct pinmux_map __initdata pmx_mapping[] = { - PINMUX_MAP("I2CMAP", "pinctrl-foo", "i2c0", "foo-i2c.0"), +static struct pinctrl_map __initdata mapping[] = { + PIN_MAP_MUX_GROUP("foo-i2c.o", PINCTRL_STATE_DEFAULT, "pinctrl-foo", NULL, "i2c0"), +}; + +The mapping table may also contain pin configuration entries. It's common for +each pin/group to have a number of configuration entries that affect it, so +the table entries for configuration reference an array of config parameters +and values. An example using the convenience macros is shown below: + +static unsigned long i2c_grp_configs[] = { + FOO_PIN_DRIVEN, + FOO_PIN_PULLUP, +}; + +static unsigned long i2c_pin_configs[] = { + FOO_OPEN_COLLECTOR, + FOO_SLEW_RATE_SLOW, +}; + +static struct pinctrl_map __initdata mapping[] = { + PIN_MAP_MUX_GROUP("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", "i2c0"), + PIN_MAP_MUX_CONFIGS_GROUP("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0", i2c_grp_configs), + PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0scl", i2c_pin_configs), + PIN_MAP_MUX_CONFIGS_PIN("foo-i2c.0", PINCTRL_STATE_DEFAULT, "pinctrl-foo", "i2c0sda", i2c_pin_configs), +}; + +Finally, some devices expect the mapping table to contain certain specific +named states. When running on hardware that doesn't need any pin controller +configuration, the mapping table must still contain those named states, in +order to explicitly indicate that the states were provided and intended to +be empty. Table entry macro PIN_MAP_DUMMY_STATE serves the purpose of defining +a named state without causing any pin controller to be programmed: + +static struct pinctrl_map __initdata mapping[] = { + PIN_MAP_DUMMY_STATE("foo-i2c.0", PINCTRL_STATE_DEFAULT), }; @@ -831,81 +872,96 @@ As it is possible to map a function to different groups of pins an optional ... { + .dev_name = "foo-spi.0", .name = "spi0-pos-A", + .type = PIN_MAP_TYPE_MUX_GROUP, .ctrl_dev_name = "pinctrl-foo", .function = "spi0", .group = "spi0_0_grp", - .dev_name = "foo-spi.0", }, { + .dev_name = "foo-spi.0", .name = "spi0-pos-B", + .type = PIN_MAP_TYPE_MUX_GROUP, .ctrl_dev_name = "pinctrl-foo", .function = "spi0", .group = "spi0_1_grp", - .dev_name = "foo-spi.0", }, ... This example mapping is used to switch between two positions for spi0 at runtime, as described further below under the heading "Runtime pinmuxing". -Further it is possible to match several groups of pins to the same function -for a single device, say for example in the mmc0 example above, where you can +Further it is possible for one named state to affect the muxing of several +groups of pins, say for example in the mmc0 example above, where you can additively expand the mmc0 bus from 2 to 4 to 8 pins. If we want to use all three groups for a total of 2+2+4 = 8 pins (for an 8-bit MMC bus as is the case), we define a mapping like this: ... { + .dev_name = "foo-mmc.0", .name = "2bit" + .type = PIN_MAP_TYPE_MUX_GROUP, .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_1_grp", - .dev_name = "foo-mmc.0", }, { + .dev_name = "foo-mmc.0", .name = "4bit" + .type = PIN_MAP_TYPE_MUX_GROUP, .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_1_grp", - .dev_name = "foo-mmc.0", }, { + .dev_name = "foo-mmc.0", .name = "4bit" + .type = PIN_MAP_TYPE_MUX_GROUP, .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_2_grp", - .dev_name = "foo-mmc.0", }, { + .dev_name = "foo-mmc.0", .name = "8bit" + .type = PIN_MAP_TYPE_MUX_GROUP, .ctrl_dev_name = "pinctrl-foo", + .function = "mmc0", .group = "mmc0_1_grp", - .dev_name = "foo-mmc.0", }, { + .dev_name = "foo-mmc.0", .name = "8bit" + .type = PIN_MAP_TYPE_MUX_GROUP, .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_2_grp", - .dev_name = "foo-mmc.0", }, { + .dev_name = "foo-mmc.0", .name = "8bit" + .type = PIN_MAP_TYPE_MUX_GROUP, .ctrl_dev_name = "pinctrl-foo", .function = "mmc0", .group = "mmc0_3_grp", - .dev_name = "foo-mmc.0", }, ... The result of grabbing this mapping from the device with something like this (see next paragraph): - pmx = pinmux_get(&device, "8bit"); + p = pinctrl_get(dev); + s = pinctrl_lookup_state(p, "8bit"); + ret = pinctrl_select_state(p, s); + +or more simply: + + p = pinctrl_get_select(dev, "8bit"); Will be that you activate all the three bottom records in the mapping at -once. Since they share the same name, pin controller device, funcion and +once. Since they share the same name, pin controller device, function and device, and since we allow multiple groups to match to a single device, they all get selected, and they all get enabled and disable simultaneously by the pinmux core. @@ -914,97 +970,111 @@ pinmux core. Pinmux requests from drivers ============================ -Generally it is discouraged to let individual drivers get and enable pinmuxes. -So if possible, handle the pinmuxes in platform code or some other place where -you have access to all the affected struct device * pointers. In some cases -where a driver needs to switch between different mux mappings at runtime -this is not possible. +Generally it is discouraged to let individual drivers get and enable pin +control. So if possible, handle the pin control in platform code or some other +place where you have access to all the affected struct device * pointers. In +some cases where a driver needs to e.g. switch between different mux mappings +at runtime this is not possible. -A driver may request a certain mux to be activated, usually just the default -mux like this: +A driver may request a certain control state to be activated, usually just the +default state like this: -#include <linux/pinctrl/pinmux.h> +#include <linux/pinctrl/consumer.h> struct foo_state { - struct pinmux *pmx; + struct pinctrl *p; + struct pinctrl_state *s; ... }; foo_probe() { - /* Allocate a state holder named "state" etc */ - struct pinmux pmx; + /* Allocate a state holder named "foo" etc */ + struct foo_state *foo = ...; + + foo->p = pinctrl_get(&device); + if (IS_ERR(foo->p)) { + /* FIXME: clean up "foo" here */ + return PTR_ERR(foo->p); + } - pmx = pinmux_get(&device, NULL); - if IS_ERR(pmx) - return PTR_ERR(pmx); - pinmux_enable(pmx); + foo->s = pinctrl_lookup_state(foo->p, PINCTRL_STATE_DEFAULT); + if (IS_ERR(foo->s)) { + pinctrl_put(foo->p); + /* FIXME: clean up "foo" here */ + return PTR_ERR(s); + } - state->pmx = pmx; + ret = pinctrl_select_state(foo->s); + if (ret < 0) { + pinctrl_put(foo->p); + /* FIXME: clean up "foo" here */ + return ret; + } } foo_remove() { - pinmux_disable(state->pmx); - pinmux_put(state->pmx); + pinctrl_put(state->p); } -If you want to grab a specific mux mapping and not just the first one found for -this device you can specify a specific mapping name, for example in the above -example the second i2c0 setting: pinmux_get(&device, "spi0-pos-B"); - -This get/enable/disable/put sequence can just as well be handled by bus drivers +This get/lookup/select/put sequence can just as well be handled by bus drivers if you don't want each and every driver to handle it and you know the arrangement on your bus. -The semantics of the get/enable respective disable/put is as follows: +The semantics of the pinctrl APIs are: + +- pinctrl_get() is called in process context to obtain a handle to all pinctrl + information for a given client device. It will allocate a struct from the + kernel memory to hold the pinmux state. All mapping table parsing or similar + slow operations take place within this API. -- pinmux_get() is called in process context to reserve the pins affected with - a certain mapping and set up the pinmux core and the driver. It will allocate - a struct from the kernel memory to hold the pinmux state. +- pinctrl_lookup_state() is called in process context to obtain a handle to a + specific state for a the client device. This operation may be slow too. -- pinmux_enable()/pinmux_disable() is quick and can be called from fastpath - (irq context) when you quickly want to set up/tear down the hardware muxing - when running a device driver. Usually it will just poke some values into a - register. +- pinctrl_select_state() programs pin controller hardware according to the + definition of the state as given by the mapping table. In theory this is a + fast-path operation, since it only involved blasting some register settings + into hardware. However, note that some pin controllers may have their + registers on a slow/IRQ-based bus, so client devices should not assume they + can call pinctrl_select_state() from non-blocking contexts. -- pinmux_disable() is called in process context to tear down the pin requests - and release the state holder struct for the mux setting. +- pinctrl_put() frees all information associated with a pinctrl handle. -Usually the pinmux core handled the get/put pair and call out to the device -drivers bookkeeping operations, like checking available functions and the -associated pins, whereas the enable/disable pass on to the pin controller +Usually the pin control core handled the get/put pair and call out to the +device drivers bookkeeping operations, like checking available functions and +the associated pins, whereas the enable/disable pass on to the pin controller driver which takes care of activating and/or deactivating the mux setting by quickly poking some registers. -The pins are allocated for your device when you issue the pinmux_get() call, +The pins are allocated for your device when you issue the pinctrl_get() call, after this you should be able to see this in the debugfs listing of all pins. -System pinmux hogging -===================== +System pin control hogging +========================== -A system pinmux map entry, i.e. a pinmux setting that does not have a device -associated with it, can be hogged by the core when the pin controller is -registered. This means that the core will attempt to call pinmux_get() and -pinmux_enable() on it immediately after the pin control device has been -registered. +Pin control map entries can be hogged by the core when the pin controller +is registered. This means that the core will attempt to call pinctrl_get(), +lookup_state() and select_state() on it immediately after the pin control +device has been registered. -This is enabled by simply setting the .hog_on_boot field in the map to true, -like this: +This occurs for mapping table entries where the client device name is equal +to the pin controller device name, and the state name is PINCTRL_STATE_DEFAULT. { - .name = "POWERMAP" + .dev_name = "pinctrl-foo", + .name = PINCTRL_STATE_DEFAULT, + .type = PIN_MAP_TYPE_MUX_GROUP, .ctrl_dev_name = "pinctrl-foo", .function = "power_func", - .hog_on_boot = true, }, Since it may be common to request the core to hog a few always-applicable mux settings on the primary pin controller, there is a convenience macro for this: -PINMUX_MAP_PRIMARY_SYS_HOG("POWERMAP", "power_func") +PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-foo", NULL /* group */, "power_func") This gives the exact same result as the above construction. @@ -1016,32 +1086,47 @@ It is possible to mux a certain function in and out at runtime, say to move an SPI port from one set of pins to another set of pins. Say for example for spi0 in the example above, we expose two different groups of pins for the same function, but with different named in the mapping as described under -"Advanced mapping" above. So we have two mappings named "spi0-pos-A" and -"spi0-pos-B". +"Advanced mapping" above. So that for an SPI device, we have two states named +"pos-A" and "pos-B". This snippet first muxes the function in the pins defined by group A, enables it, disables and releases it, and muxes it in on the pins defined by group B: +#include <linux/pinctrl/consumer.h> + foo_switch() { - struct pinmux *pmx; + struct pinctrl *p; + struct pinctrl_state *s1, *s2; + + /* Setup */ + p = pinctrl_get(&device); + if (IS_ERR(p)) + ... + + s1 = pinctrl_lookup_state(foo->p, "pos-A"); + if (IS_ERR(s1)) + ... + + s2 = pinctrl_lookup_state(foo->p, "pos-B"); + if (IS_ERR(s2)) + ... /* Enable on position A */ - pmx = pinmux_get(&device, "spi0-pos-A"); - if IS_ERR(pmx) - return PTR_ERR(pmx); - pinmux_enable(pmx); + ret = pinctrl_select_state(s1); + if (ret < 0) + ... - /* This releases the pins again */ - pinmux_disable(pmx); - pinmux_put(pmx); + ... /* Enable on position B */ - pmx = pinmux_get(&device, "spi0-pos-B"); - if IS_ERR(pmx) - return PTR_ERR(pmx); - pinmux_enable(pmx); + ret = pinctrl_select_state(s2); + if (ret < 0) + ... + ... + + pinctrl_put(p); } The above has to be done from process context.

index 373652d76b900..32b420a90c3de 100644

--- a/

+++ b/ diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfigindex 373652d76b900..32b420a90c3de 100644--- a/ arch/arm/mach-tegra/Kconfig +++ b/ arch/arm/mach-tegra/Kconfig @@ -7,6 +7,8 @@ config ARCH_TEGRA_2x_SOC select CPU_V7 select ARM_GIC select ARCH_REQUIRE_GPIOLIB + select PINCTRL + select PINCTRL_TEGRA20 select USB_ARCH_HAS_EHCI if USB_SUPPORT select USB_ULPI if USB_SUPPORT select USB_ULPI_VIEWPORT if USB_SUPPORT @@ -19,6 +21,8 @@ config ARCH_TEGRA_3x_SOC select CPU_V7 select ARM_GIC select ARCH_REQUIRE_GPIOLIB + select PINCTRL + select PINCTRL_TEGRA30 select USB_ARCH_HAS_EHCI if USB_SUPPORT select USB_ULPI if USB_SUPPORT select USB_ULPI_VIEWPORT if USB_SUPPORT

new file mode 100644

index 0000000000000..1f24d304921e7

--- /dev/null

+++ b/ diff --git a/arch/arm/mach-tegra/include/mach/pinconf-tegra.h b/arch/arm/mach-tegra/include/mach/pinconf-tegra.hnew file mode 100644index 0000000000000..1f24d304921e7--- /dev/null+++ b/ arch/arm/mach-tegra/include/mach/pinconf-tegra.h @@ -0,0 +1,63 @@ +/* + * pinctrl configuration definitions for the NVIDIA Tegra pinmux + * + * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __PINCONF_TEGRA_H__ +#define __PINCONF_TEGRA_H__ + +enum tegra_pinconf_param { + /* argument: tegra_pinconf_pull */ + TEGRA_PINCONF_PARAM_PULL, + /* argument: tegra_pinconf_tristate */ + TEGRA_PINCONF_PARAM_TRISTATE, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_ENABLE_INPUT, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_OPEN_DRAIN, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_LOCK, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_IORESET, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_SCHMITT, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_LOW_POWER_MODE, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, +}; + +enum tegra_pinconf_pull { + TEGRA_PINCONFIG_PULL_NONE, + TEGRA_PINCONFIG_PULL_DOWN, + TEGRA_PINCONFIG_PULL_UP, +}; + +enum tegra_pinconf_tristate { + TEGRA_PINCONFIG_DRIVEN, + TEGRA_PINCONFIG_TRISTATE, +}; + +#define TEGRA_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_)) +#define TEGRA_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16) +#define TEGRA_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff) + +#endif

index b4c6926a700cc..a7b3f36e22622 100644

--- a/

+++ b/ diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.cindex b4c6926a700cc..a7b3f36e22622 100644--- a/ arch/arm/mach-u300/core.c +++ b/ arch/arm/mach-u300/core.c @@ -26,7 +26,8 @@ #include <linux/mtd/nand.h> #include <linux/mtd/fsmc.h> #include <linux/pinctrl/machine.h> -#include <linux/pinctrl/pinmux.h> +#include <linux/pinctrl/consumer.h> +#include <linux/pinctrl/pinconf-generic.h> #include <linux/dma-mapping.h> #include <asm/types.h> @@ -1477,7 +1478,7 @@ static struct coh901318_platform coh901318_platform = { .max_channels = U300_DMA_CHANNELS, }; -static struct resource pinmux_resources[] = { +static struct resource pinctrl_resources[] = { { .start = U300_SYSCON_BASE, .end = U300_SYSCON_BASE + SZ_4K - 1, @@ -1506,6 +1507,13 @@ static struct platform_device i2c1_device = { .resource = i2c1_resources, }; +static struct platform_device pinctrl_device = { + .name = "pinctrl-u300", + .id = -1, + .num_resources = ARRAY_SIZE(pinctrl_resources), + .resource = pinctrl_resources, +}; + /* * The different variants have a few different versions of the * GPIO block, with different number of ports. @@ -1525,6 +1533,7 @@ static struct u300_gpio_platform u300_gpio_plat = { #endif .gpio_base = 0, .gpio_irq_base = IRQ_U300_GPIO_BASE, + .pinctrl_device = &pinctrl_device, }; static struct platform_device gpio_device = { @@ -1597,71 +1606,67 @@ static struct platform_device dma_device = { }, }; -static struct platform_device pinmux_device = { - .name = "pinmux-u300", - .id = -1, - .num_resources = ARRAY_SIZE(pinmux_resources), - .resource = pinmux_resources, +static unsigned long pin_pullup_conf[] = { + PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 1), }; -/* Pinmux settings */ -static struct pinmux_map __initdata u300_pinmux_map[] = { +static unsigned long pin_highz_conf[] = { + PIN_CONF_PACKED(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0), +}; + +/* Pin control settings */ +static struct pinctrl_map __initdata u300_pinmux_map[] = { /* anonymous maps for chip power and EMIFs */ - PINMUX_MAP_SYS_HOG("POWER", "pinmux-u300", "power"), - PINMUX_MAP_SYS_HOG("EMIF0", "pinmux-u300", "emif0"), - PINMUX_MAP_SYS_HOG("EMIF1", "pinmux-u300", "emif1"), + PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "power"), + PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "emif0"), + PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "emif1"), /* per-device maps for MMC/SD, SPI and UART */ - PINMUX_MAP("MMCSD", "pinmux-u300", "mmc0", "mmci"), - PINMUX_MAP("SPI", "pinmux-u300", "spi0", "pl022"), - PINMUX_MAP("UART0", "pinmux-u300", "uart0", "uart0"), + PIN_MAP_MUX_GROUP_DEFAULT("mmci", "pinctrl-u300", NULL, "mmc0"), + PIN_MAP_MUX_GROUP_DEFAULT("pl022", "pinctrl-u300", NULL, "spi0"), + PIN_MAP_MUX_GROUP_DEFAULT("uart0", "pinctrl-u300", NULL, "uart0"), + /* This pin is used for clock return rather than GPIO */ + PIN_MAP_CONFIGS_PIN_DEFAULT("mmci", "pinctrl-u300", "PIO APP GPIO 11", + pin_pullup_conf), + /* This pin is used for card detect */ + PIN_MAP_CONFIGS_PIN_DEFAULT("mmci", "pinctrl-u300", "PIO MS INS", + pin_highz_conf), }; struct u300_mux_hog { - const char *name; struct device *dev; - struct pinmux *pmx; + struct pinctrl *p; }; static struct u300_mux_hog u300_mux_hogs[] = { { - .name = "uart0", .dev = &uart0_device.dev, }, { - .name = "spi0", .dev = &pl022_device.dev, }, { - .name = "mmc0", .dev = &mmcsd_device.dev, }, }; -static int __init u300_pinmux_fetch(void) +static int __init u300_pinctrl_fetch(void) { int i; for (i = 0; i < ARRAY_SIZE(u300_mux_hogs); i++) { - struct pinmux *pmx; - int ret; + struct pinctrl *p; - pmx = pinmux_get(u300_mux_hogs[i].dev, NULL); - if (IS_ERR(pmx)) { - pr_err("u300: could not get pinmux hog %s

", - u300_mux_hogs[i].name); - continue; - } - ret = pinmux_enable(pmx); - if (ret) { - pr_err("u300: could enable pinmux hog %s

", - u300_mux_hogs[i].name); + p = pinctrl_get_select_default(u300_mux_hogs[i].dev); + if (IS_ERR(p)) { + pr_err("u300: could not get pinmux hog for dev %s

", + dev_name(u300_mux_hogs[i].dev)); continue; } - u300_mux_hogs[i].pmx = pmx; + u300_mux_hogs[i].p = p; } return 0; } -subsys_initcall(u300_pinmux_fetch); +subsys_initcall(u300_pinctrl_fetch); /* * Notice that AMBA devices are initialized before platform devices. @@ -1676,7 +1681,6 @@ static struct platform_device *platform_devs[] __initdata = { &gpio_device, &nand_device, &wdog_device, - &pinmux_device, }; /* @@ -1861,8 +1865,8 @@ void __init u300_init_devices(void) u300_assign_physmem(); /* Initialize pinmuxing */ - pinmux_register_mappings(u300_pinmux_map, - ARRAY_SIZE(u300_pinmux_map)); + pinctrl_register_mappings(u300_pinmux_map, + ARRAY_SIZE(u300_pinmux_map)); /* Register subdevices on the I2C buses */ u300_i2c_register_board_devices();

index bf4c7935aecdf..e81400c1753aa 100644

--- a/

+++ b/ diff --git a/arch/arm/mach-u300/include/mach/gpio-u300.h b/arch/arm/mach-u300/include/mach/gpio-u300.hindex bf4c7935aecdf..e81400c1753aa 100644--- a/ arch/arm/mach-u300/include/mach/gpio-u300.h +++ b/ arch/arm/mach-u300/include/mach/gpio-u300.h @@ -24,12 +24,14 @@ enum u300_gpio_variant { * @ports: number of GPIO block ports * @gpio_base: first GPIO number for this block (use a free range) * @gpio_irq_base: first GPIO IRQ number for this block (use a free range) + * @pinctrl_device: pin control device to spawn as child */ struct u300_gpio_platform { enum u300_gpio_variant variant; u8 ports; int gpio_base; int gpio_irq_base; + struct platform_device *pinctrl_device; }; #endif /* __MACH_U300_GPIO_U300_H */

index afaf885581251..abfb96408779c 100644

--- a/

+++ b/ diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfigindex afaf885581251..abfb96408779c 100644--- a/ drivers/pinctrl/Kconfig +++ b/ drivers/pinctrl/Kconfig @@ -17,21 +17,63 @@ config PINMUX config PINCONF bool "Support pin configuration controllers" +config GENERIC_PINCONF + bool + select PINCONF + config DEBUG_PINCTRL bool "Debug PINCTRL calls" depends on DEBUG_KERNEL help Say Y here to add some extra checks and diagnostics to PINCTRL calls. +config PINCTRL_PXA3xx + bool + select PINMUX + +config PINCTRL_MMP2 + bool "MMP2 pin controller driver" + depends on ARCH_MMP + select PINCTRL_PXA3xx + select PINCONF + +config PINCTRL_PXA168 + bool "PXA168 pin controller driver" + depends on ARCH_MMP + select PINCTRL_PXA3xx + select PINCONF + +config PINCTRL_PXA910 + bool "PXA910 pin controller driver" + depends on ARCH_MMP + select PINCTRL_PXA3xx + select PINCONF + config PINCTRL_SIRF bool "CSR SiRFprimaII pin controller driver" depends on ARCH_PRIMA2 select PINMUX +config PINCTRL_TEGRA + bool + +config PINCTRL_TEGRA20 + bool + select PINMUX + select PINCONF + select PINCTRL_TEGRA + +config PINCTRL_TEGRA30 + bool + select PINMUX + select PINCONF + select PINCTRL_TEGRA + config PINCTRL_U300 bool "U300 pin controller driver" depends on ARCH_U300 select PINMUX + select GENERIC_PINCONF config PINCTRL_COH901 bool "ST-Ericsson U300 COH 901 335/571 GPIO"

index 827601cc68f6c..6d4150b4eced2 100644

--- a/

+++ b/ diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefileindex 827601cc68f6c..6d4150b4eced2 100644--- a/ drivers/pinctrl/Makefile +++ b/ drivers/pinctrl/Makefile @@ -5,6 +5,14 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG obj-$(CONFIG_PINCTRL) += core.o obj-$(CONFIG_PINMUX) += pinmux.o obj-$(CONFIG_PINCONF) += pinconf.o +obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o +obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o +obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o +obj-$(CONFIG_PINCTRL_PXA168) += pinctrl-pxa168.o +obj-$(CONFIG_PINCTRL_PXA910) += pinctrl-pxa910.o obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o +obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o +obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o +obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o

index 894cd5e103da6..ec3b8cc188af5 100644

--- a/

+++ b/ diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.cindex 894cd5e103da6..ec3b8cc188af5 100644--- a/ drivers/pinctrl/core.c +++ b/ drivers/pinctrl/core.c @@ -1,12 +1,14 @@ /* * Core driver for the pin control subsystem * - * Copyright (C) 2011 ST-Ericsson SA + * Copyright (C) 2011-2012 ST-Ericsson SA * Written on behalf of Linaro for ST-Ericsson * Based on bits of regulator core, gpio core and clk core * * Author: Linus Walleij <linus.walleij@linaro.org> * + * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved. + * * License terms: GNU General Public License (GPL) version 2 */ #define pr_fmt(fmt) "pinctrl core: " fmt @@ -16,11 +18,8 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/slab.h> -#include <linux/radix-tree.h> #include <linux/err.h> #include <linux/list.h> -#include <linux/mutex.h> -#include <linux/spinlock.h> #include <linux/sysfs.h> #include <linux/debugfs.h> #include <linux/seq_file.h> @@ -30,10 +29,36 @@ #include "pinmux.h" #include "pinconf.h" -/* Global list of pin control devices */ -static DEFINE_MUTEX(pinctrldev_list_mutex); +/** + * struct pinctrl_maps - a list item containing part of the mapping table + * @node: mapping table list node + * @maps: array of mapping table entries + * @num_maps: the number of entries in @maps + */ +struct pinctrl_maps { + struct list_head node; + struct pinctrl_map const *maps; + unsigned num_maps; +}; + +/* Mutex taken by all entry points */ +DEFINE_MUTEX(pinctrl_mutex); + +/* Global list of pin control devices (struct pinctrl_dev) */ static LIST_HEAD(pinctrldev_list); +/* List of pin controller handles (struct pinctrl) */ +static LIST_HEAD(pinctrl_list); + +/* List of pinctrl maps (struct pinctrl_maps) */ +static LIST_HEAD(pinctrl_maps); + +#define for_each_maps(_maps_node_, _i_, _map_) \ + list_for_each_entry(_maps_node_, &pinctrl_maps, node) \ + for (_i_ = 0, _map_ = &_maps_node_->maps[_i_]; \ + _i_ < _maps_node_->num_maps; \ + i++, _map_ = &_maps_node_->maps[_i_]) + const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev) { /* We're not allowed to register devices without name */ @@ -48,53 +73,31 @@ void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev) EXPORT_SYMBOL_GPL(pinctrl_dev_get_drvdata); /** - * get_pinctrl_dev_from_dev() - look up pin controller device - * @dev: a device pointer, this may be NULL but then devname needs to be - * defined instead - * @devname: the name of a device instance, as returned by dev_name(), this - * may be NULL but then dev needs to be defined instead + * get_pinctrl_dev_from_devname() - look up pin controller device + * @devname: the name of a device instance, as returned by dev_name() * * Looks up a pin control device matching a certain device name or pure device * pointer, the pure device pointer will take precedence. */ -struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev, - const char *devname) +struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *devname) { struct pinctrl_dev *pctldev = NULL; bool found = false; - mutex_lock(&pinctrldev_list_mutex); - list_for_each_entry(pctldev, &pinctrldev_list, node) { - if (dev && pctldev->dev == dev) { - /* Matched on device pointer */ - found = true; - break; - } + if (!devname) + return NULL; - if (devname && - !strcmp(dev_name(pctldev->dev), devname)) { + list_for_each_entry(pctldev, &pinctrldev_list, node) { + if (!strcmp(dev_name(pctldev->dev), devname)) { /* Matched on device name */ found = true; break; } } - mutex_unlock(&pinctrldev_list_mutex); return found ? pctldev : NULL; } -struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin) -{ - struct pin_desc *pindesc; - unsigned long flags; - - spin_lock_irqsave(&pctldev->pin_desc_tree_lock, flags); - pindesc = radix_tree_lookup(&pctldev->pin_desc_tree, pin); - spin_unlock_irqrestore(&pctldev->pin_desc_tree_lock, flags); - - return pindesc; -} - /** * pin_get_from_name() - look up a pin number from a name * @pctldev: the pin control device to lookup the pin on @@ -135,11 +138,11 @@ bool pin_is_valid(struct pinctrl_dev *pctldev, int pin) if (pin < 0) return false; + mutex_lock(&pinctrl_mutex); pindesc = pin_desc_get(pctldev, pin); - if (pindesc == NULL) - return false; + mutex_unlock(&pinctrl_mutex); - return true; + return pindesc != NULL; } EXPORT_SYMBOL_GPL(pin_is_valid); @@ -150,7 +153,6 @@ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev, { int i; - spin_lock(&pctldev->pin_desc_tree_lock); for (i = 0; i < num_pins; i++) { struct pin_desc *pindesc; @@ -164,7 +166,6 @@ static void pinctrl_free_pindescs(struct pinctrl_dev *pctldev, } kfree(pindesc); } - spin_unlock(&pctldev->pin_desc_tree_lock); } static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev, @@ -180,10 +181,10 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev, } pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL); - if (pindesc == NULL) + if (pindesc == NULL) { + dev_err(pctldev->dev, "failed to alloc struct pin_desc

"); return -ENOMEM; - - spin_lock_init(&pindesc->lock); + } /* Set owner */ pindesc->pctldev = pctldev; @@ -198,9 +199,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev, pindesc->dynamic_name = true; } - spin_lock(&pctldev->pin_desc_tree_lock); radix_tree_insert(&pctldev->pin_desc_tree, number, pindesc); - spin_unlock(&pctldev->pin_desc_tree_lock); pr_debug("registered pin %d (%s) on %s

", number, pindesc->name, pctldev->desc->name); return 0; @@ -237,16 +236,13 @@ pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio) struct pinctrl_gpio_range *range = NULL; /* Loop over the ranges */ - mutex_lock(&pctldev->gpio_ranges_lock); list_for_each_entry(range, &pctldev->gpio_ranges, node) { /* Check if we're in the valid range */ if (gpio >= range->base && gpio < range->base + range->npins) { - mutex_unlock(&pctldev->gpio_ranges_lock); return range; } } - mutex_unlock(&pctldev->gpio_ranges_lock); return NULL; } @@ -261,14 +257,13 @@ pinctrl_match_gpio_range(struct pinctrl_dev *pctldev, unsigned gpio) * the GPIO subsystem, return the device and the matching GPIO range. Returns * negative if the GPIO range could not be found in any device. */ -int pinctrl_get_device_gpio_range(unsigned gpio, - struct pinctrl_dev **outdev, - struct pinctrl_gpio_range **outrange) +static int pinctrl_get_device_gpio_range(unsigned gpio, + struct pinctrl_dev **outdev, + struct pinctrl_gpio_range **outrange) { struct pinctrl_dev *pctldev = NULL; /* Loop over the pin controllers */ - mutex_lock(&pinctrldev_list_mutex); list_for_each_entry(pctldev, &pinctrldev_list, node) { struct pinctrl_gpio_range *range; @@ -276,11 +271,9 @@ int pinctrl_get_device_gpio_range(unsigned gpio, if (range != NULL) { *outdev = pctldev; *outrange = range; - mutex_unlock(&pinctrldev_list_mutex); return 0; } } - mutex_unlock(&pinctrldev_list_mutex); return -EINVAL; } @@ -296,10 +289,11 @@ int pinctrl_get_device_gpio_range(unsigned gpio, void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range) { - mutex_lock(&pctldev->gpio_ranges_lock); - list_add(&range->node, &pctldev->gpio_ranges); - mutex_unlock(&pctldev->gpio_ranges_lock); + mutex_lock(&pinctrl_mutex); + list_add_tail(&range->node, &pctldev->gpio_ranges); + mutex_unlock(&pinctrl_mutex); } +EXPORT_SYMBOL_GPL(pinctrl_add_gpio_range); /** * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller @@ -309,10 +303,11 @@ void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev, void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range) { - mutex_lock(&pctldev->gpio_ranges_lock); + mutex_lock(&pinctrl_mutex); list_del(&range->node); - mutex_unlock(&pctldev->gpio_ranges_lock); + mutex_unlock(&pinctrl_mutex); } +EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range); /** * pinctrl_get_group_selector() - returns the group selector for a group @@ -345,6 +340,531 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, return -EINVAL; } +/** + * pinctrl_request_gpio() - request a single pin to be used in as GPIO + * @gpio: the GPIO pin number from the GPIO subsystem number space + * + * This function should *ONLY* be used from gpiolib-based GPIO drivers, + * as part of their gpio_request() semantics, platforms and individual drivers + * shall *NOT* request GPIO pins to be muxed in. + */ +int pinctrl_request_gpio(unsigned gpio) +{ + struct pinctrl_dev *pctldev; + struct pinctrl_gpio_range *range; + int ret; + int pin; + + mutex_lock(&pinctrl_mutex); + + ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range); + if (ret) { + mutex_unlock(&pinctrl_mutex); + return -EINVAL; + } + + /* Convert to the pin controllers number space */ + pin = gpio - range->base + range->pin_base; + + ret = pinmux_request_gpio(pctldev, range, pin, gpio); + + mutex_unlock(&pinctrl_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(pinctrl_request_gpio); + +/** + * pinctrl_free_gpio() - free control on a single pin, currently used as GPIO + * @gpio: the GPIO pin number from the GPIO subsystem number space + * + * This function should *ONLY* be used from gpiolib-based GPIO drivers, + * as part of their gpio_free() semantics, platforms and individual drivers + * shall *NOT* request GPIO pins to be muxed out. + */ +void pinctrl_free_gpio(unsigned gpio) +{ + struct pinctrl_dev *pctldev; + struct pinctrl_gpio_range *range; + int ret; + int pin; + + mutex_lock(&pinctrl_mutex); + + ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range); + if (ret) { + mutex_unlock(&pinctrl_mutex); + return; + } + + /* Convert to the pin controllers number space */ + pin = gpio - range->base + range->pin_base; + + pinmux_free_gpio(pctldev, pin, range); + + mutex_unlock(&pinctrl_mutex); +} +EXPORT_SYMBOL_GPL(pinctrl_free_gpio); + +static int pinctrl_gpio_direction(unsigned gpio, bool input) +{ + struct pinctrl_dev *pctldev; + struct pinctrl_gpio_range *range; + int ret; + int pin; + + ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range); + if (ret) + return ret; + + /* Convert to the pin controllers number space */ + pin = gpio - range->base + range->pin_base; + + return pinmux_gpio_direction(pctldev, range, pin, input); +} + +/** + * pinctrl_gpio_direction_input() - request a GPIO pin to go into input mode + * @gpio: the GPIO pin number from the GPIO subsystem number space + * + * This function should *ONLY* be used from gpiolib-based GPIO drivers, + * as part of their gpio_direction_input() semantics, platforms and individual + * drivers shall *NOT* touch pin control GPIO calls. + */ +int pinctrl_gpio_direction_input(unsigned gpio) +{ + int ret; + mutex_lock(&pinctrl_mutex); + ret = pinctrl_gpio_direction(gpio, true); + mutex_unlock(&pinctrl_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_input); + +/** + * pinctrl_gpio_direction_output() - request a GPIO pin to go into output mode + * @gpio: the GPIO pin number from the GPIO subsystem number space + * + * This function should *ONLY* be used from gpiolib-based GPIO drivers, + * as part of their gpio_direction_output() semantics, platforms and individual + * drivers shall *NOT* touch pin control GPIO calls. + */ +int pinctrl_gpio_direction_output(unsigned gpio) +{ + int ret; + mutex_lock(&pinctrl_mutex); + ret = pinctrl_gpio_direction(gpio, false); + mutex_unlock(&pinctrl_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output); + +static struct pinctrl_state *find_state(struct pinctrl *p, + const char *name) +{ + struct pinctrl_state *state; + + list_for_each_entry(state, &p->states, node) + if (!strcmp(state->name, name)) + return state; + + return NULL; +} + +static struct pinctrl_state *create_state(struct pinctrl *p, + const char *name) +{ + struct pinctrl_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (state == NULL) { + dev_err(p->dev, + "failed to alloc struct pinctrl_state

"); + return ERR_PTR(-ENOMEM); + } + + state->name = name; + INIT_LIST_HEAD(&state->settings); + + list_add_tail(&state->node, &p->states); + + return state; +} + +static int add_setting(struct pinctrl *p, struct pinctrl_map const *map) +{ + struct pinctrl_state *state; + struct pinctrl_setting *setting; + int ret; + + state = find_state(p, map->name); + if (!state) + state = create_state(p, map->name); + if (IS_ERR(state)) + return PTR_ERR(state); + + if (map->type == PIN_MAP_TYPE_DUMMY_STATE) + return 0; + + setting = kzalloc(sizeof(*setting), GFP_KERNEL); + if (setting == NULL) { + dev_err(p->dev, + "failed to alloc struct pinctrl_setting

"); + return -ENOMEM; + } + + setting->type = map->type; + + setting->pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name); + if (setting->pctldev == NULL) { + dev_err(p->dev, "unknown pinctrl device %s in map entry", + map->ctrl_dev_name); + kfree(setting); + /* Eventually, this should trigger deferred probe */ + return -ENODEV; + } + + switch (map->type) { + case PIN_MAP_TYPE_MUX_GROUP: + ret = pinmux_map_to_setting(map, setting); + break; + case PIN_MAP_TYPE_CONFIGS_PIN: + case PIN_MAP_TYPE_CONFIGS_GROUP: + ret = pinconf_map_to_setting(map, setting); + break; + default: + ret = -EINVAL; + break; + } + if (ret < 0) { + kfree(setting); + return ret; + } + + list_add_tail(&setting->node, &state->settings); + + return 0; +} + +static struct pinctrl *find_pinctrl(struct device *dev) +{ + struct pinctrl *p; + + list_for_each_entry(p, &pinctrl_list, node) + if (p->dev == dev) + return p; + + return NULL; +} + +static void pinctrl_put_locked(struct pinctrl *p, bool inlist); + +static struct pinctrl *create_pinctrl(struct device *dev) +{ + struct pinctrl *p; + const char *devname; + struct pinctrl_maps *maps_node; + int i; + struct pinctrl_map const *map; + int ret; + + /* + * create the state cookie holder struct pinctrl for each + * mapping, this is what consumers will get when requesting + * a pin control handle with pinctrl_get() + */ + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (p == NULL) { + dev_err(dev, "failed to alloc struct pinctrl

"); + return ERR_PTR(-ENOMEM); + } + p->dev = dev; + INIT_LIST_HEAD(&p->states); + + devname = dev_name(dev); + + /* Iterate over the pin control maps to locate the right ones */ + for_each_maps(maps_node, i, map) { + /* Map must be for this device */ + if (strcmp(map->dev_name, devname)) + continue; + + ret = add_setting(p, map); + if (ret < 0) { + pinctrl_put_locked(p, false); + return ERR_PTR(ret); + } + } + + /* Add the pinmux to the global list */ + list_add_tail(&p->node, &pinctrl_list); + + return p; +} + +static struct pinctrl *pinctrl_get_locked(struct device *dev) +{ + struct pinctrl *p; + + if (WARN_ON(!dev)) + return ERR_PTR(-EINVAL); + + p = find_pinctrl(dev); + if (p != NULL) + return ERR_PTR(-EBUSY); + + p = create_pinctrl(dev); + if (IS_ERR(p)) + return p; + + return p; +} + +/** + * pinctrl_get() - retrieves the pinctrl handle for a device + * @dev: the device to obtain the handle for + */ +struct pinctrl *pinctrl_get(struct device *dev) +{ + struct pinctrl *p; + + mutex_lock(&pinctrl_mutex); + p = pinctrl_get_locked(dev); + mutex_unlock(&pinctrl_mutex); + + return p; +} +EXPORT_SYMBOL_GPL(pinctrl_get); + +static void pinctrl_put_locked(struct pinctrl *p, bool inlist) +{ + struct pinctrl_state *state, *n1; + struct pinctrl_setting *setting, *n2; + + list_for_each_entry_safe(state, n1, &p->states, node) { + list_for_each_entry_safe(setting, n2, &state->settings, node) { + switch (setting->type) { + case PIN_MAP_TYPE_MUX_GROUP: + if (state == p->state) + pinmux_disable_setting(setting); + pinmux_free_setting(setting); + break; + case PIN_MAP_TYPE_CONFIGS_PIN: + case PIN_MAP_TYPE_CONFIGS_GROUP: + pinconf_free_setting(setting); + break; + default: + break; + } + list_del(&setting->node); + kfree(setting); + } + list_del(&state->node); + kfree(state); + } + + if (inlist) + list_del(&p->node); + kfree(p); +} + +/** + * pinctrl_put() - release a previously claimed pinctrl handle + * @p: the pinctrl handle to release + */ +void pinctrl_put(struct pinctrl *p) +{ + mutex_lock(&pinctrl_mutex); + pinctrl_put_locked(p, true); + mutex_unlock(&pinctrl_mutex); +} +EXPORT_SYMBOL_GPL(pinctrl_put); + +static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p, + const char *name) +{ + struct pinctrl_state *state; + + state = find_state(p, name); + if (!state) + return ERR_PTR(-ENODEV); + + return state; +} + +/** + * pinctrl_lookup_state() - retrieves a state handle from a pinctrl handle + * @p: the pinctrl handle to retrieve the state from + * @name: the state name to retrieve + */ +struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name) +{ + struct pinctrl_state *s; + + mutex_lock(&pinctrl_mutex); + s = pinctrl_lookup_state_locked(p, name); + mutex_unlock(&pinctrl_mutex); + + return s; +} +EXPORT_SYMBOL_GPL(pinctrl_lookup_state); + +static int pinctrl_select_state_locked(struct pinctrl *p, + struct pinctrl_state *state) +{ + struct pinctrl_setting *setting, *setting2; + int ret; + + if (p->state == state) + return 0; + + if (p->state) { + /* + * The set of groups with a mux configuration in the old state + * may not be identical to the set of groups with a mux setting + * in the new state. While this might be unusual, it's entirely + * possible for the "user"-supplied mapping table to be written + * that way. For each group that was configured in the old state + * but not in the new state, this code puts that group into a + * safe/disabled state. + */ + list_for_each_entry(setting, &p->state->settings, node) { + bool found = false; + if (setting->type != PIN_MAP_TYPE_MUX_GROUP) + continue; + list_for_each_entry(setting2, &state->settings, node) { + if (setting2->type != PIN_MAP_TYPE_MUX_GROUP) + continue; + if (setting2->data.mux.group == + setting->data.mux.group) { + found = true; + break; + } + } + if (!found) + pinmux_disable_setting(setting); + } + } + + p->state = state; + + /* Apply all the settings for the new state */ + list_for_each_entry(setting, &state->settings, node) { + switch (setting->type) { + case PIN_MAP_TYPE_MUX_GROUP: + ret = pinmux_enable_setting(setting); + break; + case PIN_MAP_TYPE_CONFIGS_PIN: + case PIN_MAP_TYPE_CONFIGS_GROUP: + ret = pinconf_apply_setting(setting); + break; + default: + ret = -EINVAL; + break; + } + if (ret < 0) { + /* FIXME: Difficult to return to prev state */ + return ret; + } + } + + return 0; +} + +/** + * pinctrl_select() - select/activate/program a pinctrl state to HW + * @p: the pinctrl handle for the device that requests configuratio + * @state: the state handle to select/activate/program + */ +int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state) +{ + int ret; + + mutex_lock(&pinctrl_mutex); + ret = pinctrl_select_state_locked(p, state); + mutex_unlock(&pinctrl_mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(pinctrl_select_state); + +/** + * pinctrl_register_mappings() - register a set of pin controller mappings + * @maps: the pincontrol mappings table to register. This should probably be + * marked with __initdata so it can be discarded after boot. This + * function will perform a shallow copy for the mapping entries. + * @num_maps: the number of maps in the mapping table + */ +int pinctrl_register_mappings(struct pinctrl_map const *maps, + unsigned num_maps) +{ + int i, ret; + struct pinctrl_maps *maps_node; + + pr_debug("add %d pinmux maps

", num_maps); + + /* First sanity check the new mapping */ + for (i = 0; i < num_maps; i++) { + if (!maps[i].dev_name) { + pr_err("failed to register map %s (%d): no device given

", + maps[i].name, i); + return -EINVAL; + } + + if (!maps[i].name) { + pr_err("failed to register map %d: no map name given

", + i); + return -EINVAL; + } + + if (maps[i].type != PIN_MAP_TYPE_DUMMY_STATE && + !maps[i].ctrl_dev_name) { + pr_err("failed to register map %s (%d): no pin control device given

", + maps[i].name, i); + return -EINVAL; + } + + switch (maps[i].type) { + case PIN_MAP_TYPE_DUMMY_STATE: + break; + case PIN_MAP_TYPE_MUX_GROUP: + ret = pinmux_validate_map(&maps[i], i); + if (ret < 0) + return 0; + break; + case PIN_MAP_TYPE_CONFIGS_PIN: + case PIN_MAP_TYPE_CONFIGS_GROUP: + ret = pinconf_validate_map(&maps[i], i); + if (ret < 0) + return 0; + break; + default: + pr_err("failed to register map %s (%d): invalid type given

", + maps[i].name, i); + return -EINVAL; + } + } + + maps_node = kzalloc(sizeof(*maps_node), GFP_KERNEL); + if (!maps_node) { + pr_err("failed to alloc struct pinctrl_maps

"); + return -ENOMEM; + } + + maps_node->num_maps = num_maps; + maps_node->maps = kmemdup(maps, sizeof(*maps) * num_maps, GFP_KERNEL); + if (!maps_node->maps) { + pr_err("failed to duplicate mapping table

"); + kfree(maps_node); + return -ENOMEM; + } + + mutex_lock(&pinctrl_mutex); + list_add_tail(&maps_node->node, &pinctrl_maps); + mutex_unlock(&pinctrl_mutex); + + return 0; +} + #ifdef CONFIG_DEBUG_FS static int pinctrl_pins_show(struct seq_file *s, void *what) @@ -355,6 +875,8 @@ static int pinctrl_pins_show(struct seq_file *s, void *what) seq_printf(s, "registered pins: %d

", pctldev->desc->npins); + mutex_lock(&pinctrl_mutex); + /* The pin number can be retrived from the pin controller descriptor */ for (i = 0; i < pctldev->desc->npins; i++) { struct pin_desc *desc; @@ -375,6 +897,8 @@ static int pinctrl_pins_show(struct seq_file *s, void *what) seq_puts(s, "

"); } + mutex_unlock(&pinctrl_mutex); + return 0; } @@ -388,6 +912,8 @@ static int pinctrl_groups_show(struct seq_file *s, void *what) if (!ops) return 0; + mutex_lock(&pinctrl_mutex); + seq_puts(s, "registered pin groups:

"); while (ops->list_groups(pctldev, selector) >= 0) { const unsigned *pins; @@ -410,6 +936,7 @@ static int pinctrl_groups_show(struct seq_file *s, void *what) selector++; } + mutex_unlock(&pinctrl_mutex); return 0; } @@ -421,8 +948,9 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what) seq_puts(s, "GPIO ranges handled:

"); + mutex_lock(&pinctrl_mutex); + /* Loop over the ranges */ - mutex_lock(&pctldev->gpio_ranges_lock); list_for_each_entry(range, &pctldev->gpio_ranges, node) { seq_printf(s, "%u: %s GPIOS [%u - %u] PINS [%u - %u]

", range->id, range->name, @@ -430,7 +958,8 @@ static int pinctrl_gpioranges_show(struct seq_file *s, void *what) range->pin_base, (range->pin_base + range->npins - 1)); } - mutex_unlock(&pctldev->gpio_ranges_lock); + + mutex_unlock(&pinctrl_mutex); return 0; } @@ -440,7 +969,9 @@ static int pinctrl_devices_show(struct seq_file *s, void *what) struct pinctrl_dev *pctldev; seq_puts(s, "name [pinmux] [pinconf]

"); - mutex_lock(&pinctrldev_list_mutex); + + mutex_lock(&pinctrl_mutex); + list_for_each_entry(pctldev, &pinctrldev_list, node) { seq_printf(s, "%s ", pctldev->desc->name); if (pctldev->desc->pmxops) @@ -453,7 +984,108 @@ static int pinctrl_devices_show(struct seq_file *s, void *what) seq_puts(s, "no"); seq_puts(s, "

"); } - mutex_unlock(&pinctrldev_list_mutex); + + mutex_unlock(&pinctrl_mutex); + + return 0; +} + +static inline const char *map_type(enum pinctrl_map_type type) +{ + static const char * const names[] = { + "INVALID", + "DUMMY_STATE", + "MUX_GROUP", + "CONFIGS_PIN", + "CONFIGS_GROUP", + }; + + if (type >= ARRAY_SIZE(names)) + return "UNKNOWN"; + + return names[type]; +} + +static int pinctrl_maps_show(struct seq_file *s, void *what) +{ + struct pinctrl_maps *maps_node; + int i; + struct pinctrl_map const *map; + + seq_puts(s, "Pinctrl maps:

"); + + mutex_lock(&pinctrl_mutex); + + for_each_maps(maps_node, i, map) { + seq_printf(s, "device %s

state %s

type %s (%d)

", + map->dev_name, map->name, map_type(map->type), + map->type); + + if (map->type != PIN_MAP_TYPE_DUMMY_STATE) + seq_printf(s, "controlling device %s

", + map->ctrl_dev_name); + + switch (map->type) { + case PIN_MAP_TYPE_MUX_GROUP: + pinmux_show_map(s, map); + break; + case PIN_MAP_TYPE_CONFIGS_PIN: + case PIN_MAP_TYPE_CONFIGS_GROUP: + pinconf_show_map(s, map); + break; + default: + break; + } + + seq_printf(s, "

"); + } + + mutex_unlock(&pinctrl_mutex); + + return 0; +} + +static int pinctrl_show(struct seq_file *s, void *what) +{ + struct pinctrl *p; + struct pinctrl_state *state; + struct pinctrl_setting *setting; + + seq_puts(s, "Requested pin control handlers their pinmux maps:

"); + + mutex_lock(&pinctrl_mutex); + + list_for_each_entry(p, &pinctrl_list, node) { + seq_printf(s, "device: %s current state: %s

", + dev_name(p->dev), + p->state ? p->state->name : "none"); + + list_for_each_entry(state, &p->states, node) { + seq_printf(s, " state: %s

", state->name); + + list_for_each_entry(setting, &state->settings, node) { + struct pinctrl_dev *pctldev = setting->pctldev; + + seq_printf(s, " type: %s controller %s ", + map_type(setting->type), + pinctrl_dev_get_name(pctldev)); + + switch (setting->type) { + case PIN_MAP_TYPE_MUX_GROUP: + pinmux_show_setting(s, setting); + break; + case PIN_MAP_TYPE_CONFIGS_PIN: + case PIN_MAP_TYPE_CONFIGS_GROUP: + pinconf_show_setting(s, setting); + break; + default: + break; + } + } + } + } + + mutex_unlock(&pinctrl_mutex); return 0; } @@ -478,6 +1110,16 @@ static int pinctrl_devices_open(struct inode *inode, struct file *file) return single_open(file, pinctrl_devices_show, NULL); } +static int pinctrl_maps_open(struct inode *inode, struct file *file) +{ + return single_open(file, pinctrl_maps_show, NULL); +} + +static int pinctrl_open(struct inode *inode, struct file *file) +{ + return single_open(file, pinctrl_show, NULL); +} + static const struct file_operations pinctrl_pins_ops = { .open = pinctrl_pins_open, .read = seq_read, @@ -506,6 +1148,20 @@ static const struct file_operations pinctrl_devices_ops = { .release = single_release, }; +static const struct file_operations pinctrl_maps_ops = { + .open = pinctrl_maps_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static const struct file_operations pinctrl_ops = { + .open = pinctrl_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static struct dentry *debugfs_root; static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev) @@ -547,7 +1203,10 @@ static void pinctrl_init_debugfs(void) debugfs_create_file("pinctrl-devices", S_IFREG | S_IRUGO, debugfs_root, NULL, &pinctrl_devices_ops); - pinmux_init_debugfs(debugfs_root); + debugfs_create_file("pinctrl-maps", S_IFREG | S_IRUGO, + debugfs_root, NULL, &pinctrl_maps_ops); + debugfs_create_file("pinctrl-handles", S_IFREG | S_IRUGO, + debugfs_root, NULL, &pinctrl_ops); } #else /* CONFIG_DEBUG_FS */ @@ -583,18 +1242,18 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, if (pctldesc->name == NULL) return NULL; - pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL); - if (pctldev == NULL) + pctldev = kzalloc(sizeof(*pctldev), GFP_KERNEL); + if (pctldev == NULL) { + dev_err(dev, "failed to alloc struct pinctrl_dev

"); return NULL; + } /* Initialize pin control device struct */ pctldev->owner = pctldesc->owner; pctldev->desc = pctldesc; pctldev->driver_data = driver_data; INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL); - spin_lock_init(&pctldev->pin_desc_tree_lock); INIT_LIST_HEAD(&pctldev->gpio_ranges); - mutex_init(&pctldev->gpio_ranges_lock); pctldev->dev = dev; /* If we're implementing pinmuxing, check the ops for sanity */ @@ -628,11 +1287,23 @@ struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc, goto out_err; } + mutex_lock(&pinctrl_mutex); + + list_add_tail(&pctldev->node, &pinctrldev_list); + + pctldev->p = pinctrl_get_locked(pctldev->dev); + if (!IS_ERR(pctldev->p)) { + struct pinctrl_state *s = + pinctrl_lookup_state_locked(pctldev->p, + PINCTRL_STATE_DEFAULT); + if (!IS_ERR(s)) + pinctrl_select_state_locked(pctldev->p, s); + } + + mutex_unlock(&pinctrl_mutex); + pinctrl_init_device_debugfs(pctldev); - mutex_lock(&pinctrldev_list_mutex); - list_add(&pctldev->node, &pinctrldev_list); - mutex_unlock(&pinctrldev_list_mutex); - pinmux_hog_maps(pctldev); + return pctldev; out_err: @@ -653,15 +1324,20 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev) return; pinctrl_remove_device_debugfs(pctldev); - pinmux_unhog_maps(pctldev); + + mutex_lock(&pinctrl_mutex); + + if (!IS_ERR(pctldev->p)) + pinctrl_put_locked(pctldev->p, true); + /* TODO: check that no pinmuxes are still active? */ - mutex_lock(&pinctrldev_list_mutex); list_del(&pctldev->node); - mutex_unlock(&pinctrldev_list_mutex); /* Destroy descriptor tree */ pinctrl_free_pindescs(pctldev, pctldev->desc->pins, pctldev->desc->npins); kfree(pctldev); + + mutex_unlock(&pinctrl_mutex); } EXPORT_SYMBOL_GPL(pinctrl_unregister);

index cfa86da6b4b15..17ecf651b123c 100644

--- a/

+++ b/ diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.hindex cfa86da6b4b15..17ecf651b123c 100644--- a/ drivers/pinctrl/core.h +++ b/ drivers/pinctrl/core.h @@ -9,7 +9,10 @@ * License terms: GNU General Public License (GPL) version 2 */ +#include <linux/mutex.h> +#include <linux/radix-tree.h> #include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/machine.h> struct pinctrl_gpio_range; @@ -20,34 +23,94 @@ struct pinctrl_gpio_range; * controller * @pin_desc_tree: each pin descriptor for this pin controller is stored in * this radix tree - * @pin_desc_tree_lock: lock for the descriptor tree * @gpio_ranges: a list of GPIO ranges that is handled by this pin controller, * ranges are added to this list at runtime - * @gpio_ranges_lock: lock for the GPIO ranges list * @dev: the device entry for this pin controller * @owner: module providing the pin controller, used for refcounting * @driver_data: driver data for drivers registering to the pin controller * subsystem - * @pinmux_hogs_lock: lock for the pinmux hog list - * @pinmux_hogs: list of pinmux maps hogged by this device + * @p: result of pinctrl_get() for this device + * @device_root: debugfs root for this device */ struct pinctrl_dev { struct list_head node; struct pinctrl_desc *desc; struct radix_tree_root pin_desc_tree; - spinlock_t pin_desc_tree_lock; struct list_head gpio_ranges; - struct mutex gpio_ranges_lock; struct device *dev; struct module *owner; void *driver_data; + struct pinctrl *p; #ifdef CONFIG_DEBUG_FS struct dentry *device_root; #endif -#ifdef CONFIG_PINMUX - struct mutex pinmux_hogs_lock; - struct list_head pinmux_hogs; -#endif +}; + +/** + * struct pinctrl - per-device pin control state holder + * @node: global list node + * @dev: the device using this pin control handle + * @states: a list of states for this device + * @state: the current state + */ +struct pinctrl { + struct list_head node; + struct device *dev; + struct list_head states; + struct pinctrl_state *state; +}; + +/** + * struct pinctrl_state - a pinctrl state for a device + * @node: list not for struct pinctrl's @states field + * @name: the name of this state + * @settings: a list of settings for this state + */ +struct pinctrl_state { + struct list_head node; + const char *name; + struct list_head settings; +}; + +/** + * struct pinctrl_setting_mux - setting data for MAP_TYPE_MUX_GROUP + * @group: the group selector to program + * @func: the function selector to program + */ +struct pinctrl_setting_mux { + unsigned group; + unsigned func; +}; + +/** + * struct pinctrl_setting_configs - setting data for MAP_TYPE_CONFIGS_* + * @group_or_pin: the group selector or pin ID to program + * @configs: a pointer to an array of config parameters/values to program into + * hardware. Each individual pin controller defines the format and meaning + * of config parameters. + * @num_configs: the number of entries in array @configs + */ +struct pinctrl_setting_configs { + unsigned group_or_pin; + unsigned long *configs; + unsigned num_configs; +}; + +/** + * struct pinctrl_setting - an individual mux or config setting + * @node: list node for struct pinctrl_settings's @settings field + * @type: the type of setting + * @pctldev: pin control device handling to be programmed + * @data: Data specific to the setting type + */ +struct pinctrl_setting { + struct list_head node; + enum pinctrl_map_type type; + struct pinctrl_dev *pctldev; + union { + struct pinctrl_setting_mux mux; + struct pinctrl_setting_configs configs; + } data; }; /** @@ -56,28 +119,38 @@ struct pinctrl_dev { * @name: a name for the pin, e.g. the name of the pin/pad/finger on a * datasheet or such * @dynamic_name: if the name of this pin was dynamically allocated - * @lock: a lock to protect the descriptor structure - * @mux_requested: whether the pin is already requested by pinmux or not - * @mux_function: a named muxing function for the pin that will be passed to - * subdrivers and shown in debugfs etc + * @mux_usecount: If zero, the pin is not claimed, and @owner should be NULL. + * If non-zero, this pin is claimed by @owner. This field is an integer + * rather than a boolean, since pinctrl_get() might process multiple + * mapping table entries that refer to, and hence claim, the same group + * or pin, and each of these will increment the @usecount. + * @mux_owner: The name of device that called pinctrl_get(). + * @mux_setting: The most recent selected mux setting for this pin, if any. + * @gpio_owner: If pinctrl_request_gpio() was called for this pin, this is + * the name of the GPIO that "owns" this pin. */ struct pin_desc { struct pinctrl_dev *pctldev; const char *name; bool dynamic_name; - spinlock_t lock; /* These fields only added when supporting pinmux drivers */ #ifdef CONFIG_PINMUX - const char *mux_function; + unsigned mux_usecount; + const char *mux_owner; + const struct pinctrl_setting_mux *mux_setting; + const char *gpio_owner; #endif }; -struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev, - const char *dev_name); -struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin); +struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name); int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name); -int pinctrl_get_device_gpio_range(unsigned gpio, - struct pinctrl_dev **outdev, - struct pinctrl_gpio_range **outrange); int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, const char *pin_group); + +static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, + unsigned int pin) +{ + return radix_tree_lookup(&pctldev->pin_desc_tree, pin); +} + +extern struct mutex pinctrl_mutex;

new file mode 100644

index 0000000000000..33fbaeaa65dd9

--- /dev/null

+++ b/ diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.cnew file mode 100644index 0000000000000..33fbaeaa65dd9--- /dev/null+++ b/ drivers/pinctrl/pinconf-generic.c @@ -0,0 +1,120 @@ +/* + * Core driver for the generic pin config portions of the pin control subsystem + * + * Copyright (C) 2011 ST-Ericsson SA + * Written on behalf of Linaro for ST-Ericsson + * + * Author: Linus Walleij <linus.walleij@linaro.org> + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#define pr_fmt(fmt) "generic pinconfig core: " fmt + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/device.h> +#include <linux/slab.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinconf-generic.h> +#include "core.h" +#include "pinconf.h" + +#ifdef CONFIG_DEBUG_FS + +struct pin_config_item { + const enum pin_config_param param; + const char * const display; + const char * const format; +}; + +#define PCONFDUMP(a, b, c) { .param = a, .display = b, .format = c } + +struct pin_config_item conf_items[] = { + PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL), + PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL), + PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL), + PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL), + PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL), + PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL), + PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL), + PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL), + PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"), + PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector"), + PCONFDUMP(PIN_CONFIG_LOW_POWER_MODE, "pin low power", "mode"), +}; + +void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned pin) +{ + const struct pinconf_ops *ops = pctldev->desc->confops; + int i; + + if (!ops->is_generic) + return; + + for(i = 0; i < ARRAY_SIZE(conf_items); i++) { + unsigned long config; + int ret; + + /* We want to check out this parameter */ + config = pinconf_to_config_packed(conf_items[i].param, 0); + ret = pin_config_get_for_pin(pctldev, pin, &config); + /* These are legal errors */ + if (ret == -EINVAL || ret == -ENOTSUPP) + continue; + if (ret) { + seq_printf(s, "ERROR READING CONFIG SETTING %d ", i); + continue; + } + /* Space between multiple configs */ + seq_puts(s, " "); + seq_puts(s, conf_items[i].display); + /* Print unit if available */ + if (conf_items[i].format && + pinconf_to_config_argument(config) != 0) + seq_printf(s, " (%u %s)", + pinconf_to_config_argument(config), + conf_items[i].format); + } +} + +void pinconf_generic_dump_group(struct pinctrl_dev *pctldev, + struct seq_file *s, const char *gname) +{ + const struct pinconf_ops *ops = pctldev->desc->confops; + int i; + + if (!ops->is_generic) + return; + + for(i = 0; i < ARRAY_SIZE(conf_items); i++) { + unsigned long config; + int ret; + + /* We want to check out this parameter */ + config = pinconf_to_config_packed(conf_items[i].param, 0); + ret = pin_config_group_get(dev_name(pctldev->dev), gname, + &config); + /* These are legal errors */ + if (ret == -EINVAL || ret == -ENOTSUPP) + continue; + if (ret) { + seq_printf(s, "ERROR READING CONFIG SETTING %d ", i); + continue; + } + /* Space between multiple configs */ + seq_puts(s, " "); + seq_puts(s, conf_items[i].display); + /* Print unit if available */ + if (conf_items[i].format && config != 0) + seq_printf(s, " (%u %s)", + pinconf_to_config_argument(config), + conf_items[i].format); + } +} + +#endif

index 9fb75456824c3..7321e86012940 100644

--- a/

+++ b/ diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.cindex 9fb75456824c3..7321e86012940 100644--- a/ drivers/pinctrl/pinconf.c +++ b/ drivers/pinctrl/pinconf.c @@ -23,6 +23,37 @@ #include "core.h" #include "pinconf.h" +int pinconf_check_ops(struct pinctrl_dev *pctldev) +{ + const struct pinconf_ops *ops = pctldev->desc->confops; + + /* We must be able to read out pin status */ + if (!ops->pin_config_get && !ops->pin_config_group_get) + return -EINVAL; + /* We have to be able to config the pins in SOME way */ + if (!ops->pin_config_set && !ops->pin_config_group_set) + return -EINVAL; + return 0; +} + +int pinconf_validate_map(struct pinctrl_map const *map, int i) +{ + if (!map->data.configs.group_or_pin) { + pr_err("failed to register map %s (%d): no group/pin given

", + map->name, i); + return -EINVAL; + } + + if (map->data.configs.num_configs && + !map->data.configs.configs) { + pr_err("failed to register map %s (%d): no configs ptr given

", + map->name, i); + return -EINVAL; + } + + return 0; +} + int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, unsigned long *config) { @@ -51,19 +82,27 @@ int pin_config_get(const char *dev_name, const char *name, struct pinctrl_dev *pctldev; int pin; - pctldev = get_pinctrl_dev_from_dev(NULL, dev_name); - if (!pctldev) - return -EINVAL; + mutex_lock(&pinctrl_mutex); + + pctldev = get_pinctrl_dev_from_devname(dev_name); + if (!pctldev) { + pin = -EINVAL; + goto unlock; + } pin = pin_get_from_name(pctldev, name); if (pin < 0) - return pin; + goto unlock; + + pin = pin_config_get_for_pin(pctldev, pin, config); - return pin_config_get_for_pin(pctldev, pin, config); +unlock: + mutex_unlock(&pinctrl_mutex); + return pin; } EXPORT_SYMBOL(pin_config_get); -int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, +static int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, unsigned long config) { const struct pinconf_ops *ops = pctldev->desc->confops; @@ -97,17 +136,27 @@ int pin_config_set(const char *dev_name, const char *name, unsigned long config) { struct pinctrl_dev *pctldev; - int pin; + int pin, ret; - pctldev = get_pinctrl_dev_from_dev(NULL, dev_name); - if (!pctldev) - return -EINVAL; + mutex_lock(&pinctrl_mutex); + + pctldev = get_pinctrl_dev_from_devname(dev_name); + if (!pctldev) { + ret = -EINVAL; + goto unlock; + } pin = pin_get_from_name(pctldev, name); - if (pin < 0) - return pin; + if (pin < 0) { + ret = pin; + goto unlock; + } + + ret = pin_config_set_for_pin(pctldev, pin, config); - return pin_config_set_for_pin(pctldev, pin, config); +unlock: + mutex_unlock(&pinctrl_mutex); + return ret; } EXPORT_SYMBOL(pin_config_set); @@ -116,29 +165,39 @@ int pin_config_group_get(const char *dev_name, const char *pin_group, { struct pinctrl_dev *pctldev; const struct pinconf_ops *ops; - int selector; + int selector, ret; - pctldev = get_pinctrl_dev_from_dev(NULL, dev_name); - if (!pctldev) - return -EINVAL; + mutex_lock(&pinctrl_mutex); + + pctldev = get_pinctrl_dev_from_devname(dev_name); + if (!pctldev) { + ret = -EINVAL; + goto unlock; + } ops = pctldev->desc->confops; if (!ops || !ops->pin_config_group_get) { dev_err(pctldev->dev, "cannot get configuration for pin " "group, missing group config get function in " "driver

"); - return -EINVAL; + ret = -EINVAL; + goto unlock; } selector = pinctrl_get_group_selector(pctldev, pin_group); - if (selector < 0) - return selector; + if (selector < 0) { + ret = selector; + goto unlock; + } + + ret = ops->pin_config_group_get(pctldev, selector, config); - return ops->pin_config_group_get(pctldev, selector, config); +unlock: + mutex_unlock(&pinctrl_mutex); + return ret; } EXPORT_SYMBOL(pin_config_group_get); - int pin_config_group_set(const char *dev_name, const char *pin_group, unsigned long config) { @@ -151,27 +210,34 @@ int pin_config_group_set(const char *dev_name, const char *pin_group, int ret; int i; - pctldev = get_pinctrl_dev_from_dev(NULL, dev_name); - if (!pctldev) - return -EINVAL; + mutex_lock(&pinctrl_mutex); + + pctldev = get_pinctrl_dev_from_devname(dev_name); + if (!pctldev) { + ret = -EINVAL; + goto unlock; + } ops = pctldev->desc->confops; pctlops = pctldev->desc->pctlops; if (!ops || (!ops->pin_config_group_set && !ops->pin_config_set)) { dev_err(pctldev->dev, "cannot configure pin group, missing " "config function in driver

"); - return -EINVAL; + ret = -EINVAL; + goto unlock; } selector = pinctrl_get_group_selector(pctldev, pin_group); - if (selector < 0) - return selector; + if (selector < 0) { + ret = selector; + goto unlock; + } ret = pctlops->get_group_pins(pctldev, selector, &pins, &num_pins); if (ret) { dev_err(pctldev->dev, "cannot configure pin group, error " "getting pins

"); - return ret; + goto unlock; } /* @@ -185,46 +251,196 @@ int pin_config_group_set(const char *dev_name, const char *pin_group, * pin-by-pin as well, it returns -EAGAIN. */ if (ret != -EAGAIN) - return ret; + goto unlock; } /* * If the controller cannot handle entire groups, we configure each pin * individually. */ - if (!ops->pin_config_set) - return 0; + if (!ops->pin_config_set) { + ret = 0; + goto unlock; + } for (i = 0; i < num_pins; i++) { ret = ops->pin_config_set(pctldev, pins[i], config); if (ret < 0) - return ret; + goto unlock; } - return 0; + ret = 0; + +unlock: + mutex_unlock(&pinctrl_mutex); + + return ret; } EXPORT_SYMBOL(pin_config_group_set); -int pinconf_check_ops(struct pinctrl_dev *pctldev) +int pinconf_map_to_setting(struct pinctrl_map const *map, + struct pinctrl_setting *setting) { + struct pinctrl_dev *pctldev = setting->pctldev; + int pin; + + switch (setting->type) { + case PIN_MAP_TYPE_CONFIGS_PIN: + pin = pin_get_from_name(pctldev, + map->data.configs.group_or_pin); + if (pin < 0) { + dev_err(pctldev->dev, "could not map pin config for \"%s\"", + map->data.configs.group_or_pin); + return pin; + } + setting->data.configs.group_or_pin = pin; + break; + case PIN_MAP_TYPE_CONFIGS_GROUP: + pin = pinctrl_get_group_selector(pctldev, + map->data.configs.group_or_pin); + if (pin < 0) { + dev_err(pctldev->dev, "could not map group config for \"%s\"", + map->data.configs.group_or_pin); + return pin; + } + setting->data.configs.group_or_pin = pin; + break; + default: + return -EINVAL; + } + + setting->data.configs.num_configs = map->data.configs.num_configs; + setting->data.configs.configs = map->data.configs.configs; + + return 0; +} + +void pinconf_free_setting(struct pinctrl_setting const *setting) +{ +} + +int pinconf_apply_setting(struct pinctrl_setting const *setting) +{ + struct pinctrl_dev *pctldev = setting->pctldev; const struct pinconf_ops *ops = pctldev->desc->confops; + int i, ret; - /* We must be able to read out pin status */ - if (!ops->pin_config_get && !ops->pin_config_group_get) + if (!ops) { + dev_err(pctldev->dev, "missing confops

"); return -EINVAL; - /* We have to be able to config the pins in SOME way */ - if (!ops->pin_config_set && !ops->pin_config_group_set) + } + + switch (setting->type) { + case PIN_MAP_TYPE_CONFIGS_PIN: + if (!ops->pin_config_set) { + dev_err(pctldev->dev, "missing pin_config_set op

"); + return -EINVAL; + } + for (i = 0; i < setting->data.configs.num_configs; i++) { + ret = ops->pin_config_set(pctldev, + setting->data.configs.group_or_pin, + setting->data.configs.configs[i]); + if (ret < 0) { + dev_err(pctldev->dev, + "pin_config_set op failed for pin %d config %08lx

", + setting->data.configs.group_or_pin, + setting->data.configs.configs[i]); + return ret; + } + } + break; + case PIN_MAP_TYPE_CONFIGS_GROUP: + if (!ops->pin_config_group_set) { + dev_err(pctldev->dev, + "missing pin_config_group_set op

"); + return -EINVAL; + } + for (i = 0; i < setting->data.configs.num_configs; i++) { + ret = ops->pin_config_group_set(pctldev, + setting->data.configs.group_or_pin, + setting->data.configs.configs[i]); + if (ret < 0) { + dev_err(pctldev->dev, + "pin_config_group_set op failed for group %d config %08lx

", + setting->data.configs.group_or_pin, + setting->data.configs.configs[i]); + return ret; + } + } + break; + default: return -EINVAL; + } + return 0; } #ifdef CONFIG_DEBUG_FS +void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map) +{ + int i; + + switch (map->type) { + case PIN_MAP_TYPE_CONFIGS_PIN: + seq_printf(s, "pin "); + break; + case PIN_MAP_TYPE_CONFIGS_GROUP: + seq_printf(s, "group "); + break; + default: + break; + } + + seq_printf(s, "%s

", map->data.configs.group_or_pin); + + for (i = 0; i < map->data.configs.num_configs; i++) + seq_printf(s, "config %08lx

", map->data.configs.configs[i]); +} + +void pinconf_show_setting(struct seq_file *s, + struct pinctrl_setting const *setting) +{ + struct pinctrl_dev *pctldev = setting->pctldev; + const struct pinctrl_ops *pctlops = pctldev->desc->pctlops; + struct pin_desc *desc; + int i; + + switch (setting->type) { + case PIN_MAP_TYPE_CONFIGS_PIN: + desc = pin_desc_get(setting->pctldev, + setting->data.configs.group_or_pin); + seq_printf(s, "pin %s (%d)", + desc->name ? desc->name : "unnamed", + setting->data.configs.group_or_pin); + break; + case PIN_MAP_TYPE_CONFIGS_GROUP: + seq_printf(s, "group %s (%d)", + pctlops->get_group_name(pctldev, + setting->data.configs.group_or_pin), + setting->data.configs.group_or_pin); + break; + default: + break; + } + + /* + * FIXME: We should really get the pin controler to dump the config + * values, so they can be decoded to something meaningful. + */ + for (i = 0; i < setting->data.configs.num_configs; i++) + seq_printf(s, " %08lx", setting->data.configs.configs[i]); + + seq_printf(s, "

"); +} + static void pinconf_dump_pin(struct pinctrl_dev *pctldev, struct seq_file *s, int pin) { const struct pinconf_ops *ops = pctldev->desc->confops; + /* no-op when not using generic pin config */ + pinconf_generic_dump_pin(pctldev, s, pin); if (ops && ops->pin_config_dbg_show) ops->pin_config_dbg_show(pctldev, s, pin); } @@ -237,6 +453,8 @@ static int pinconf_pins_show(struct seq_file *s, void *what) seq_puts(s, "Pin config settings per pin

"); seq_puts(s, "Format: pin (name): pinmux setting array

"); + mutex_lock(&pinctrl_mutex); + /* The pin number can be retrived from the pin controller descriptor */ for (i = 0; i < pctldev->desc->npins; i++) { struct pin_desc *desc; @@ -255,6 +473,8 @@ static int pinconf_pins_show(struct seq_file *s, void *what) seq_printf(s, "

"); } + mutex_unlock(&pinctrl_mutex); + return 0; } @@ -264,6 +484,8 @@ static void pinconf_dump_group(struct pinctrl_dev *pctldev, { const struct pinconf_ops *ops = pctldev->desc->confops; + /* no-op when not using generic pin config */ + pinconf_generic_dump_group(pctldev, s, gname); if (ops && ops->pin_config_group_dbg_show) ops->pin_config_group_dbg_show(pctldev, s, selector); } @@ -281,14 +503,20 @@ static int pinconf_groups_show(struct seq_file *s, void *what) seq_puts(s, "Pin config settings per pin group

"); seq_puts(s, "Format: group (name): pinmux setting array

"); + mutex_lock(&pinctrl_mutex); + while (pctlops->list_groups(pctldev, selector) >= 0) { const char *gname = pctlops->get_group_name(pctldev, selector); seq_printf(s, "%u (%s):", selector, gname); pinconf_dump_group(pctldev, s, selector, gname); + seq_printf(s, "

"); + selector++; } + mutex_unlock(&pinctrl_mutex); + return 0; }

index 006b77fa737e8..54510de5e8c6d 100644

--- a/

+++ b/ diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.hindex 006b77fa737e8..54510de5e8c6d 100644--- a/ drivers/pinctrl/pinconf.h +++ b/ drivers/pinctrl/pinconf.h @@ -14,12 +14,25 @@ #ifdef CONFIG_PINCONF int pinconf_check_ops(struct pinctrl_dev *pctldev); +int pinconf_validate_map(struct pinctrl_map const *map, int i); +int pinconf_map_to_setting(struct pinctrl_map const *map, + struct pinctrl_setting *setting); +void pinconf_free_setting(struct pinctrl_setting const *setting); +int pinconf_apply_setting(struct pinctrl_setting const *setting); +void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map); +void pinconf_show_setting(struct seq_file *s, + struct pinctrl_setting const *setting); void pinconf_init_device_debugfs(struct dentry *devroot, struct pinctrl_dev *pctldev); + +/* + * You will only be interested in these if you're using PINCONF + * so don't supply any stubs for these. + */ int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, unsigned long *config); -int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, - unsigned long config); +int pin_config_group_get(const char *dev_name, const char *pin_group, + unsigned long *config); #else @@ -28,9 +41,70 @@ static inline int pinconf_check_ops(struct pinctrl_dev *pctldev) return 0; } +static inline int pinconf_validate_map(struct pinctrl_map const *map, int i) +{ + return 0; +} + +static inline int pinconf_map_to_setting(struct pinctrl_map const *map, + struct pinctrl_setting *setting) +{ + return 0; +} + +static inline void pinconf_free_setting(struct pinctrl_setting const *setting) +{ +} + +static inline int pinconf_apply_setting(struct pinctrl_setting const *setting) +{ + return 0; +} + +static inline void pinconf_show_map(struct seq_file *s, + struct pinctrl_map const *map) +{ +} + +static inline void pinconf_show_setting(struct seq_file *s, + struct pinctrl_setting const *setting) +{ +} + static inline void pinconf_init_device_debugfs(struct dentry *devroot, struct pinctrl_dev *pctldev) { } #endif + +/* + * The following functions are available if the driver uses the generic + * pin config. + */ + +#ifdef CONFIG_GENERIC_PINCONF + +void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned pin); + +void pinconf_generic_dump_group(struct pinctrl_dev *pctldev, + struct seq_file *s, const char *gname); + +#else + +static inline void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned pin) +{ + return; +} + +static inline void pinconf_generic_dump_group(struct pinctrl_dev *pctldev, + struct seq_file *s, + const char *gname) +{ + return; +} + +#endif

index 69fb7072a23ea..0797eba3e33a9 100644

--- a/

+++ b/ diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.cindex 69fb7072a23ea..0797eba3e33a9 100644--- a/ drivers/pinctrl/pinctrl-coh901.c +++ b/ drivers/pinctrl/pinctrl-coh901.c @@ -22,38 +22,10 @@ #include <linux/gpio.h> #include <linux/list.h> #include <linux/slab.h> -#include <linux/pinctrl/pinmux.h> +#include <linux/pinctrl/consumer.h> +#include <linux/pinctrl/pinconf-generic.h> #include <mach/gpio-u300.h> - -/* - * Bias modes for U300 GPIOs - * - * GPIO_U300_CONFIG_BIAS_UNKNOWN: this bias mode is not known to us - * GPIO_U300_CONFIG_BIAS_FLOAT: no specific bias, the GPIO will float or state - * is not controlled by software - * GPIO_U300_CONFIG_BIAS_PULL_UP: the GPIO will be pulled up (usually with high - * impedance to VDD) - */ -#define GPIO_U300_CONFIG_BIAS_UNKNOWN 0x1000 -#define GPIO_U300_CONFIG_BIAS_FLOAT 0x1001 -#define GPIO_U300_CONFIG_BIAS_PULL_UP 0x1002 - -/* - * Drive modes for U300 GPIOs (output) - * - * GPIO_U300_CONFIG_DRIVE_PUSH_PULL: the GPIO will be driven actively high and - * low, this is the most typical case and is typically achieved with two - * active transistors on the output - * GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: the GPIO will be driven with open drain - * (open collector) which means it is usually wired with other output - * ports which are then pulled up with an external resistor - * GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: the GPIO will be driven with open drain - * (open emitter) which is the same as open drain mutatis mutandis but - * pulled to ground - */ -#define GPIO_U300_CONFIG_DRIVE_PUSH_PULL 0x2000 -#define GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN 0x2001 -#define GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE 0x2002 +#include "pinctrl-coh901.h" /* * Register definitions for COH 901 335 variant @@ -181,12 +153,12 @@ struct u300_gpio_confdata { #define BS365_GPIO_NUM_PORTS 5 #define U300_FLOATING_INPUT { \ - .bias_mode = GPIO_U300_CONFIG_BIAS_FLOAT, \ + .bias_mode = PIN_CONFIG_BIAS_HIGH_IMPEDANCE, \ .output = false, \ } #define U300_PULL_UP_INPUT { \ - .bias_mode = GPIO_U300_CONFIG_BIAS_PULL_UP, \ + .bias_mode = PIN_CONFIG_BIAS_PULL_UP, \ .output = false, \ } @@ -360,14 +332,14 @@ static int u300_gpio_request(struct gpio_chip *chip, unsigned offset) */ int gpio = chip->base + offset; - return pinmux_request_gpio(gpio); + return pinctrl_request_gpio(gpio); } static void u300_gpio_free(struct gpio_chip *chip, unsigned offset) { int gpio = chip->base + offset; - pinmux_free_gpio(gpio); + pinctrl_free_gpio(gpio); } static int u300_gpio_get(struct gpio_chip *chip, unsigned offset) @@ -448,8 +420,68 @@ static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset) return retirq; } -static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, - u16 param, unsigned long *data) +/* Returning -EINVAL means "supported but not available" */ +int u300_gpio_config_get(struct gpio_chip *chip, + unsigned offset, + unsigned long *config) +{ + struct u300_gpio *gpio = to_u300_gpio(chip); + enum pin_config_param param = (enum pin_config_param) *config; + bool biasmode; + u32 drmode; + + /* One bit per pin, clamp to bool range */ + biasmode = !!(readl(U300_PIN_REG(offset, per)) & U300_PIN_BIT(offset)); + + /* Mask out the two bits for this pin and shift to bits 0,1 */ + drmode = readl(U300_PIN_REG(offset, pcr)); + drmode &= (U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1)); + drmode >>= ((offset & 0x07) << 1); + + switch(param) { + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: + *config = 0; + if (biasmode) + return 0; + else + return -EINVAL; + break; + case PIN_CONFIG_BIAS_PULL_UP: + *config = 0; + if (!biasmode) + return 0; + else + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + *config = 0; + if (drmode == U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL) + return 0; + else + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + *config = 0; + if (drmode == U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN) + return 0; + else + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_OPEN_SOURCE: + *config = 0; + if (drmode == U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE) + return 0; + else + return -EINVAL; + break; + default: + break; + } + return -ENOTSUPP; +} + +int u300_gpio_config_set(struct gpio_chip *chip, unsigned offset, + enum pin_config_param param) { struct u300_gpio *gpio = to_u300_gpio(chip); unsigned long flags; @@ -457,16 +489,16 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, local_irq_save(flags); switch (param) { - case GPIO_U300_CONFIG_BIAS_UNKNOWN: - case GPIO_U300_CONFIG_BIAS_FLOAT: + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: val = readl(U300_PIN_REG(offset, per)); writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, per)); break; - case GPIO_U300_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_UP: val = readl(U300_PIN_REG(offset, per)); writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, per)); break; - case GPIO_U300_CONFIG_DRIVE_PUSH_PULL: + case PIN_CONFIG_DRIVE_PUSH_PULL: val = readl(U300_PIN_REG(offset, pcr)); val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1)); @@ -474,7 +506,7 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, << ((offset & 0x07) << 1)); writel(val, U300_PIN_REG(offset, pcr)); break; - case GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: + case PIN_CONFIG_DRIVE_OPEN_DRAIN: val = readl(U300_PIN_REG(offset, pcr)); val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1)); @@ -482,7 +514,7 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, << ((offset & 0x07) << 1)); writel(val, U300_PIN_REG(offset, pcr)); break; - case GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: + case PIN_CONFIG_DRIVE_OPEN_SOURCE: val = readl(U300_PIN_REG(offset, pcr)); val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1)); @@ -650,13 +682,12 @@ static void __init u300_gpio_init_pin(struct u300_gpio *gpio, u300_gpio_direction_output(&gpio->chip, offset, conf->outval); /* Deactivate bias mode for output */ - u300_gpio_config(&gpio->chip, offset, - GPIO_U300_CONFIG_BIAS_FLOAT, - NULL); + u300_gpio_config_set(&gpio->chip, offset, + PIN_CONFIG_BIAS_HIGH_IMPEDANCE); /* Set drive mode for output */ - u300_gpio_config(&gpio->chip, offset, - GPIO_U300_CONFIG_DRIVE_PUSH_PULL, NULL); + u300_gpio_config_set(&gpio->chip, offset, + PIN_CONFIG_DRIVE_PUSH_PULL); dev_dbg(gpio->dev, "set up pin %d as output, value: %d

", offset, conf->outval); @@ -667,7 +698,7 @@ static void __init u300_gpio_init_pin(struct u300_gpio *gpio, u300_gpio_set(&gpio->chip, offset, 0); /* Set bias mode for input */ - u300_gpio_config(&gpio->chip, offset, conf->bias_mode, NULL); + u300_gpio_config_set(&gpio->chip, offset, conf->bias_mode); dev_dbg(gpio->dev, "set up pin %d as input, bias: %04x

", offset, conf->bias_mode); @@ -705,7 +736,6 @@ static inline void u300_gpio_free_ports(struct u300_gpio *gpio) list_for_each_safe(p, n, &gpio->port_list) { port = list_entry(p, struct u300_gpio_port, node); list_del(&port->node); - free_irq(port->irq, port); kfree(port); } } @@ -861,10 +891,18 @@ static int __init u300_gpio_probe(struct platform_device *pdev) goto err_no_chip; } + /* Spawn pin controller device as child of the GPIO, pass gpio chip */ + plat->pinctrl_device->dev.platform_data = &gpio->chip; + err = platform_device_register(plat->pinctrl_device); + if (err) + goto err_no_pinctrl; + platform_set_drvdata(pdev, gpio); return 0; +err_no_pinctrl: + err = gpiochip_remove(&gpio->chip); err_no_chip: err_no_port: u300_gpio_free_ports(gpio); @@ -919,7 +957,6 @@ static struct platform_driver u300_gpio_driver = { .remove = __exit_p(u300_gpio_remove), }; - static int __init u300_gpio_init(void) { return platform_driver_probe(&u300_gpio_driver, u300_gpio_probe);

new file mode 100644

index 0000000000000..87294222583ea

--- /dev/null

+++ b/ diff --git a/drivers/pinctrl/pinctrl-coh901.h b/drivers/pinctrl/pinctrl-coh901.hnew file mode 100644index 0000000000000..87294222583ea--- /dev/null+++ b/ drivers/pinctrl/pinctrl-coh901.h @@ -0,0 +1,5 @@ +int u300_gpio_config_get(struct gpio_chip *chip, + unsigned offset, + unsigned long *config); +int u300_gpio_config_set(struct gpio_chip *chip, unsigned offset, + enum pin_config_param param);

new file mode 100644

index 0000000000000..2cfed552bbe4a

--- /dev/null

+++ b/ diff --git a/drivers/pinctrl/pinctrl-mmp2.c b/drivers/pinctrl/pinctrl-mmp2.cnew file mode 100644index 0000000000000..2cfed552bbe4a--- /dev/null+++ b/ drivers/pinctrl/pinctrl-mmp2.c @@ -0,0 +1,722 @@ +/* + * linux/drivers/pinctrl/pinmux-mmp2.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * publishhed by the Free Software Foundation. + * + * Copyright (C) 2011, Marvell Technology Group Ltd. + * + * Author: Haojian Zhuang <haojian.zhuang@marvell.com> + * + */ + +#include <linux/device.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include "pinctrl-pxa3xx.h" + +#define MMP2_DS_MASK 0x1800 +#define MMP2_DS_SHIFT 11 +#define MMP2_SLEEP_MASK 0x38 +#define MMP2_SLEEP_SELECT (1 << 9) +#define MMP2_SLEEP_DATA (1 << 8) +#define MMP2_SLEEP_DIR (1 << 7) + +#define MFPR_MMP2(a, r, f0, f1, f2, f3, f4, f5, f6, f7) \ + { \ + .name = #a, \ + .pin = a, \ + .mfpr = r, \ + .func = { \ + MMP2_MUX_##f0, \ + MMP2_MUX_##f1, \ + MMP2_MUX_##f2, \ + MMP2_MUX_##f3, \ + MMP2_MUX_##f4, \ + MMP2_MUX_##f5, \ + MMP2_MUX_##f6, \ + MMP2_MUX_##f7, \ + }, \ + } + +#define GRP_MMP2(a, m, p) \ + { .name = a, .mux = MMP2_MUX_##m, .pins = p, .npins = ARRAY_SIZE(p), } + +/* 174 pins */ +enum mmp2_pin_list { + /* 0~168: GPIO0~GPIO168 */ + TWSI4_SCL = 169, + TWSI4_SDA, /* 170 */ + G_CLKREQ, + VCXO_REQ, + VCXO_OUT, +}; + +enum mmp2_mux { + /* PXA3xx_MUX_GPIO = 0 (predefined in pinctrl-pxa3xx.h) */ + MMP2_MUX_GPIO = 0, + MMP2_MUX_G_CLKREQ, + MMP2_MUX_VCXO_REQ, + MMP2_MUX_VCXO_OUT, + MMP2_MUX_KP_MK, + MMP2_MUX_KP_DK, + MMP2_MUX_CCIC1, + MMP2_MUX_CCIC2, + MMP2_MUX_SPI, + MMP2_MUX_SSPA2, + MMP2_MUX_ROT, + MMP2_MUX_I2S, + MMP2_MUX_TB, + MMP2_MUX_CAM2, + MMP2_MUX_HDMI, + MMP2_MUX_TWSI2, + MMP2_MUX_TWSI3, + MMP2_MUX_TWSI4, + MMP2_MUX_TWSI5, + MMP2_MUX_TWSI6, + MMP2_MUX_UART1, + MMP2_MUX_UART2, + MMP2_MUX_UART3, + MMP2_MUX_UART4, + MMP2_MUX_SSP1_RX, + MMP2_MUX_SSP1_FRM, + MMP2_MUX_SSP1_TXRX, + MMP2_MUX_SSP2_RX, + MMP2_MUX_SSP2_FRM, + MMP2_MUX_SSP1, + MMP2_MUX_SSP2, + MMP2_MUX_SSP3, + MMP2_MUX_SSP4, + MMP2_MUX_MMC1, + MMP2_MUX_MMC2, + MMP2_MUX_MMC3, + MMP2_MUX_MMC4, + MMP2_MUX_ULPI, + MMP2_MUX_AC, + MMP2_MUX_CA, + MMP2_MUX_PWM, + MMP2_MUX_USIM, + MMP2_MUX_TIPU, + MMP2_MUX_PLL, + MMP2_MUX_NAND, + MMP2_MUX_FSIC, + MMP2_MUX_SLEEP_IND, + MMP2_MUX_EXT_DMA, + MMP2_MUX_ONE_WIRE, + MMP2_MUX_LCD, + MMP2_MUX_SMC, + MMP2_MUX_SMC_INT, + MMP2_MUX_MSP, + MMP2_MUX_G_CLKOUT, + MMP2_MUX_32K_CLKOUT, + MMP2_MUX_PRI_JTAG, + MMP2_MUX_AAS_JTAG, + MMP2_MUX_AAS_GPIO, + MMP2_MUX_AAS_SPI, + MMP2_MUX_AAS_TWSI, + MMP2_MUX_AAS_DEU_EX, + MMP2_MUX_NONE = 0xffff, +}; + +static struct pinctrl_pin_desc mmp2_pads[] = { + /* + * The name indicates function 0 of this pin. + * After reset, function 0 is the default function of pin. + */ + PINCTRL_PIN(GPIO0, "GPIO0"), + PINCTRL_PIN(GPIO1, "GPIO1"), + PINCTRL_PIN(GPIO2, "GPIO2"), + PINCTRL_PIN(GPIO3, "GPIO3"), + PINCTRL_PIN(GPIO4, "GPIO4"), + PINCTRL_PIN(GPIO5, "GPIO5"), + PINCTRL_PIN(GPIO6, "GPIO6"), + PINCTRL_PIN(GPIO7, "GPIO7"), + PINCTRL_PIN(GPIO8, "GPIO8"), + PINCTRL_PIN(GPIO9, "GPIO9"), + PINCTRL_PIN(GPIO10, "GPIO10"), + PINCTRL_PIN(GPIO11, "GPIO11"), + PINCTRL_PIN(GPIO12, "GPIO12"), + PINCTRL_PIN(GPIO13, "GPIO13"), + PINCTRL_PIN(GPIO14, "GPIO14"), + PINCTRL_PIN(GPIO15, "GPIO15"), + PINCTRL_PIN(GPIO16, "GPIO16"), + PINCTRL_PIN(GPIO17, "GPIO17"), + PINCTRL_PIN(GPIO18, "GPIO18"), + PINCTRL_PIN(GPIO19, "GPIO19"), + PINCTRL_PIN(GPIO20, "GPIO20"), + PINCTRL_PIN(GPIO21, "GPIO21"), + PINCTRL_PIN(GPIO22, "GPIO22"), + PINCTRL_PIN(GPIO23, "GPIO23"), + PINCTRL_PIN(GPIO24, "GPIO24"), + PINCTRL_PIN(GPIO25, "GPIO25"), + PINCTRL_PIN(GPIO26, "GPIO26"), + PINCTRL_PIN(GPIO27, "GPIO27"), + PINCTRL_PIN(GPIO28, "GPIO28"), + PINCTRL_PIN(GPIO29, "GPIO29"), + PINCTRL_PIN(GPIO30, "GPIO30"), + PINCTRL_PIN(GPIO31, "GPIO31"), + PINCTRL_PIN(GPIO32, "GPIO32"), + PINCTRL_PIN(GPIO33, "GPIO33"), + PINCTRL_PIN(GPIO34, "GPIO34"), + PINCTRL_PIN(GPIO35, "GPIO35"), + PINCTRL_PIN(GPIO36, "GPIO36"), + PINCTRL_PIN(GPIO37, "GPIO37"), + PINCTRL_PIN(GPIO38, "GPIO38"), + PINCTRL_PIN(GPIO39, "GPIO39"), + PINCTRL_PIN(GPIO40, "GPIO40"), + PINCTRL_PIN(GPIO41, "GPIO41"), + PINCTRL_PIN(GPIO42, "GPIO42"), + PINCTRL_PIN(GPIO43, "GPIO43"), + PINCTRL_PIN(GPIO44, "GPIO44"), + PINCTRL_PIN(GPIO45, "GPIO45"), + PINCTRL_PIN(GPIO46, "GPIO46"), + PINCTRL_PIN(GPIO47, "GPIO47"), + PINCTRL_PIN(GPIO48, "GPIO48"), + PINCTRL_PIN(GPIO49, "GPIO49"), + PINCTRL_PIN(GPIO50, "GPIO50"), + PINCTRL_PIN(GPIO51, "GPIO51"), + PINCTRL_PIN(GPIO52, "GPIO52"), + PINCTRL_PIN(GPIO53, "GPIO53"), + PINCTRL_PIN(GPIO54, "GPIO54"), + PINCTRL_PIN(GPIO55, "GPIO55"), + PINCTRL_PIN(GPIO56, "GPIO56"), + PINCTRL_PIN(GPIO57, "GPIO57"), + PINCTRL_PIN(GPIO58, "GPIO58"), + PINCTRL_PIN(GPIO59, "GPIO59"), + PINCTRL_PIN(GPIO60, "GPIO60"), + PINCTRL_PIN(GPIO61, "GPIO61"), + PINCTRL_PIN(GPIO62, "GPIO62"), + PINCTRL_PIN(GPIO63, "GPIO63"), + PINCTRL_PIN(GPIO64, "GPIO64"), + PINCTRL_PIN(GPIO65, "GPIO65"), + PINCTRL_PIN(GPIO66, "GPIO66"), + PINCTRL_PIN(GPIO67, "GPIO67"), + PINCTRL_PIN(GPIO68, "GPIO68"), + PINCTRL_PIN(GPIO69, "GPIO69"), + PINCTRL_PIN(GPIO70, "GPIO70"), + PINCTRL_PIN(GPIO71, "GPIO71"), + PINCTRL_PIN(GPIO72, "GPIO72"), + PINCTRL_PIN(GPIO73, "GPIO73"), + PINCTRL_PIN(GPIO74, "GPIO74"), + PINCTRL_PIN(GPIO75, "GPIO75"), + PINCTRL_PIN(GPIO76, "GPIO76"), + PINCTRL_PIN(GPIO77, "GPIO77"), + PINCTRL_PIN(GPIO78, "GPIO78"), + PINCTRL_PIN(GPIO79, "GPIO79"), + PINCTRL_PIN(GPIO80, "GPIO80"), + PINCTRL_PIN(GPIO81, "GPIO81"), + PINCTRL_PIN(GPIO82, "GPIO82"), + PINCTRL_PIN(GPIO83, "GPIO83"), + PINCTRL_PIN(GPIO84, "GPIO84"), + PINCTRL_PIN(GPIO85, "GPIO85"), + PINCTRL_PIN(GPIO86, "GPIO86"), + PINCTRL_PIN(GPIO87, "GPIO87"), + PINCTRL_PIN(GPIO88, "GPIO88"), + PINCTRL_PIN(GPIO89, "GPIO89"), + PINCTRL_PIN(GPIO90, "GPIO90"), + PINCTRL_PIN(GPIO91, "GPIO91"), + PINCTRL_PIN(GPIO92, "GPIO92"), + PINCTRL_PIN(GPIO93, "GPIO93"), + PINCTRL_PIN(GPIO94, "GPIO94"), + PINCTRL_PIN(GPIO95, "GPIO95"), + PINCTRL_PIN(GPIO96, "GPIO96"), + PINCTRL_PIN(GPIO97, "GPIO97"), + PINCTRL_PIN(GPIO98, "GPIO98"), + PINCTRL_PIN(GPIO99, "GPIO99"), + PINCTRL_PIN(GPIO100, "GPIO100"), + PINCTRL_PIN(GPIO101, "GPIO101"), + PINCTRL_PIN(GPIO102, "GPIO102"), + PINCTRL_PIN(GPIO103, "GPIO103"), + PINCTRL_PIN(GPIO104, "GPIO104"), + PINCTRL_PIN(GPIO105, "GPIO105"), + PINCTRL_PIN(GPIO106, "GPIO106"), + PINCTRL_PIN(GPIO107, "GPIO107"), + PINCTRL_PIN(GPIO108, "GPIO108"), + PINCTRL_PIN(GPIO109, "GPIO109"), + PINCTRL_PIN(GPIO110, "GPIO110"), + PINCTRL_PIN(GPIO111, "GPIO111"), + PINCTRL_PIN(GPIO112, "GPIO112"), + PINCTRL_PIN(GPIO113, "GPIO113"), + PINCTRL_PIN(GPIO114, "GPIO114"), + PINCTRL_PIN(GPIO115, "GPIO115"), + PINCTRL_PIN(GPIO116, "GPIO116"), + PINCTRL_PIN(GPIO117, "GPIO117"), + PINCTRL_PIN(GPIO118, "GPIO118"), + PINCTRL_PIN(GPIO119, "GPIO119"), + PINCTRL_PIN(GPIO120, "GPIO120"), + PINCTRL_PIN(GPIO121, "GPIO121"), + PINCTRL_PIN(GPIO122, "GPIO122"), + PINCTRL_PIN(GPIO123, "GPIO123"), + PINCTRL_PIN(GPIO124, "GPIO124"), + PINCTRL_PIN(GPIO125, "GPIO125"), + PINCTRL_PIN(GPIO126, "GPIO126"), + PINCTRL_PIN(GPIO127, "GPIO127"), + PINCTRL_PIN(GPIO128, "GPIO128"), + PINCTRL_PIN(GPIO129, "GPIO129"), + PINCTRL_PIN(GPIO130, "GPIO130"), + PINCTRL_PIN(GPIO131, "GPIO131"), + PINCTRL_PIN(GPIO132, "GPIO132"), + PINCTRL_PIN(GPIO133, "GPIO133"), + PINCTRL_PIN(GPIO134, "GPIO134"), + PINCTRL_PIN(GPIO135, "GPIO135"), + PINCTRL_PIN(GPIO136, "GPIO136"), + PINCTRL_PIN(GPIO137, "GPIO137"), + PINCTRL_PIN(GPIO138, "GPIO138"), + PINCTRL_PIN(GPIO139, "GPIO139"), + PINCTRL_PIN(GPIO140, "GPIO140"), + PINCTRL_PIN(GPIO141, "GPIO141"), + PINCTRL_PIN(GPIO142, "GPIO142"), + PINCTRL_PIN(GPIO143, "GPIO143"), + PINCTRL_PIN(GPIO144, "GPIO144"), + PINCTRL_PIN(GPIO145, "GPIO145"), + PINCTRL_PIN(GPIO146, "GPIO146"), + PINCTRL_PIN(GPIO147, "GPIO147"), + PINCTRL_PIN(GPIO148, "GPIO148"), + PINCTRL_PIN(GPIO149, "GPIO149"), + PINCTRL_PIN(GPIO150, "GPIO150"), + PINCTRL_PIN(GPIO151, "GPIO151"), + PINCTRL_PIN(GPIO152, "GPIO152"), + PINCTRL_PIN(GPIO153, "GPIO153"), + PINCTRL_PIN(GPIO154, "GPIO154"), + PINCTRL_PIN(GPIO155, "GPIO155"), + PINCTRL_PIN(GPIO156, "GPIO156"), + PINCTRL_PIN(GPIO157, "GPIO157"), + PINCTRL_PIN(GPIO158, "GPIO158"), + PINCTRL_PIN(GPIO159, "GPIO159"), + PINCTRL_PIN(GPIO160, "GPIO160"), + PINCTRL_PIN(GPIO161, "GPIO161"), + PINCTRL_PIN(GPIO162, "GPIO162"), + PINCTRL_PIN(GPIO163, "GPIO163"), + PINCTRL_PIN(GPIO164, "GPIO164"), + PINCTRL_PIN(GPIO165, "GPIO165"), + PINCTRL_PIN(GPIO166, "GPIO166"), + PINCTRL_PIN(GPIO167, "GPIO167"), + PINCTRL_PIN(GPIO168, "GPIO168"), + PINCTRL_PIN(TWSI4_SCL, "TWSI4_SCL"), + PINCTRL_PIN(TWSI4_SDA, "TWSI4_SDA"), + PINCTRL_PIN(G_CLKREQ, "G_CLKREQ"), + PINCTRL_PIN(VCXO_REQ, "VCXO_REQ"), + PINCTRL_PIN(VCXO_OUT, "VCXO_OUT"), +}; + +