Commit 7fc86a79 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pinctrl-for-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl

Pull pinctrl updates for v3.4 from Linus Walleij (*):
 - Switches the PXA 168, 910 and MMP over to use pinctrl
 - Locking revamped
 - Massive refactorings...
 - Reform the driver API to use multiple states
 - Support pin config in the mapping tables
 - Pinctrl drivers for the nVidia Tegra series
 - Generic pin config support lib for simple pin controllers
 - Implement pin config for the U300

* tag 'pinctrl-for-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (48 commits)
  ARM: u300: configure some pins as an example
  pinctrl: support pinconfig on the U300
  pinctrl/coh901: use generic pinconf enums and parameters
  pinctrl: introduce generic pin config
  pinctrl: fix error path in pinconf_map_to_setting()
  pinctrl: allow concurrent gpio and mux function ownership of pins
  pinctrl: forward-declare struct device
  pinctrl: split pincontrol states into its own header
  pinctrl: include machine header to core.h
  ARM: tegra: Select PINCTRL Kconfig variables
  pinctrl: add a driver for NVIDIA Tegra
  pinctrl: Show selected function and group in pinmux-pins debugfs
  pinctrl: enhance mapping table to support pin config operations
  pinctrl: API changes to support multiple states per device
  pinctrl: add usecount to pins for muxing
  pinctrl: refactor struct pinctrl handling in core.c vs pinmux.c
  pinctrl: fix and simplify locking
  pinctrl: fix the pin descriptor kerneldoc
  pinctrl: assume map table entries can't have a NULL name field
  pinctrl: introduce PINCTRL_STATE_DEFAULT, define hogs as that state
  ...

(*) What is it with all these Linuses these days? There's a Linus at
    google too.  Some day I will get myself my own broadsword, and run
    around screaming "There can be only one".

    I used to be _special_ dammit. Snif.
parents 90597b6c 51dddfe8
This diff is collapsed.
...@@ -7,6 +7,8 @@ config ARCH_TEGRA_2x_SOC ...@@ -7,6 +7,8 @@ config ARCH_TEGRA_2x_SOC
select CPU_V7 select CPU_V7
select ARM_GIC select ARM_GIC
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select PINCTRL
select PINCTRL_TEGRA20
select USB_ARCH_HAS_EHCI if USB_SUPPORT select USB_ARCH_HAS_EHCI if USB_SUPPORT
select USB_ULPI if USB_SUPPORT select USB_ULPI if USB_SUPPORT
select USB_ULPI_VIEWPORT if USB_SUPPORT select USB_ULPI_VIEWPORT if USB_SUPPORT
...@@ -19,6 +21,8 @@ config ARCH_TEGRA_3x_SOC ...@@ -19,6 +21,8 @@ config ARCH_TEGRA_3x_SOC
select CPU_V7 select CPU_V7
select ARM_GIC select ARM_GIC
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
select PINCTRL
select PINCTRL_TEGRA30
select USB_ARCH_HAS_EHCI if USB_SUPPORT select USB_ARCH_HAS_EHCI if USB_SUPPORT
select USB_ULPI if USB_SUPPORT select USB_ULPI if USB_SUPPORT
select USB_ULPI_VIEWPORT if USB_SUPPORT select USB_ULPI_VIEWPORT if USB_SUPPORT
......
/*
* 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
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
#include <linux/mtd/nand.h> #include <linux/mtd/nand.h>
#include <linux/mtd/fsmc.h> #include <linux/mtd/fsmc.h>
#include <linux/pinctrl/machine.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 <linux/dma-mapping.h>
#include <asm/types.h> #include <asm/types.h>
...@@ -1477,7 +1478,7 @@ static struct coh901318_platform coh901318_platform = { ...@@ -1477,7 +1478,7 @@ static struct coh901318_platform coh901318_platform = {
.max_channels = U300_DMA_CHANNELS, .max_channels = U300_DMA_CHANNELS,
}; };
static struct resource pinmux_resources[] = { static struct resource pinctrl_resources[] = {
{ {
.start = U300_SYSCON_BASE, .start = U300_SYSCON_BASE,
.end = U300_SYSCON_BASE + SZ_4K - 1, .end = U300_SYSCON_BASE + SZ_4K - 1,
...@@ -1506,6 +1507,13 @@ static struct platform_device i2c1_device = { ...@@ -1506,6 +1507,13 @@ static struct platform_device i2c1_device = {
.resource = i2c1_resources, .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 * The different variants have a few different versions of the
* GPIO block, with different number of ports. * GPIO block, with different number of ports.
...@@ -1525,6 +1533,7 @@ static struct u300_gpio_platform u300_gpio_plat = { ...@@ -1525,6 +1533,7 @@ static struct u300_gpio_platform u300_gpio_plat = {
#endif #endif
.gpio_base = 0, .gpio_base = 0,
.gpio_irq_base = IRQ_U300_GPIO_BASE, .gpio_irq_base = IRQ_U300_GPIO_BASE,
.pinctrl_device = &pinctrl_device,
}; };
static struct platform_device gpio_device = { static struct platform_device gpio_device = {
...@@ -1597,71 +1606,67 @@ static struct platform_device dma_device = { ...@@ -1597,71 +1606,67 @@ static struct platform_device dma_device = {
}, },
}; };
static struct platform_device pinmux_device = { static unsigned long pin_pullup_conf[] = {
.name = "pinmux-u300", PIN_CONF_PACKED(PIN_CONFIG_BIAS_PULL_UP, 1),
.id = -1,
.num_resources = ARRAY_SIZE(pinmux_resources),
.resource = pinmux_resources,
}; };
/* Pinmux settings */ static unsigned long pin_highz_conf[] = {
static struct pinmux_map __initdata u300_pinmux_map[] = { 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 */ /* anonymous maps for chip power and EMIFs */
PINMUX_MAP_SYS_HOG("POWER", "pinmux-u300", "power"), PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "power"),
PINMUX_MAP_SYS_HOG("EMIF0", "pinmux-u300", "emif0"), PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "emif0"),
PINMUX_MAP_SYS_HOG("EMIF1", "pinmux-u300", "emif1"), PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-u300", NULL, "emif1"),
/* per-device maps for MMC/SD, SPI and UART */ /* per-device maps for MMC/SD, SPI and UART */
PINMUX_MAP("MMCSD", "pinmux-u300", "mmc0", "mmci"), PIN_MAP_MUX_GROUP_DEFAULT("mmci", "pinctrl-u300", NULL, "mmc0"),
PINMUX_MAP("SPI", "pinmux-u300", "spi0", "pl022"), PIN_MAP_MUX_GROUP_DEFAULT("pl022", "pinctrl-u300", NULL, "spi0"),
PINMUX_MAP("UART0", "pinmux-u300", "uart0", "uart0"), 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 { struct u300_mux_hog {
const char *name;
struct device *dev; struct device *dev;
struct pinmux *pmx; struct pinctrl *p;
}; };
static struct u300_mux_hog u300_mux_hogs[] = { static struct u300_mux_hog u300_mux_hogs[] = {
{ {
.name = "uart0",
.dev = &uart0_device.dev, .dev = &uart0_device.dev,
}, },
{ {
.name = "spi0",
.dev = &pl022_device.dev, .dev = &pl022_device.dev,
}, },
{ {
.name = "mmc0",
.dev = &mmcsd_device.dev, .dev = &mmcsd_device.dev,
}, },
}; };
static int __init u300_pinmux_fetch(void) static int __init u300_pinctrl_fetch(void)
{ {
int i; int i;
for (i = 0; i < ARRAY_SIZE(u300_mux_hogs); i++) { for (i = 0; i < ARRAY_SIZE(u300_mux_hogs); i++) {
struct pinmux *pmx; struct pinctrl *p;
int ret;
pmx = pinmux_get(u300_mux_hogs[i].dev, NULL); p = pinctrl_get_select_default(u300_mux_hogs[i].dev);
if (IS_ERR(pmx)) { if (IS_ERR(p)) {
pr_err("u300: could not get pinmux hog %s\n", pr_err("u300: could not get pinmux hog for dev %s\n",
u300_mux_hogs[i].name); dev_name(u300_mux_hogs[i].dev));
continue;
}
ret = pinmux_enable(pmx);
if (ret) {
pr_err("u300: could enable pinmux hog %s\n",
u300_mux_hogs[i].name);
continue; continue;
} }
u300_mux_hogs[i].pmx = pmx; u300_mux_hogs[i].p = p;
} }
return 0; return 0;
} }
subsys_initcall(u300_pinmux_fetch); subsys_initcall(u300_pinctrl_fetch);
/* /*
* Notice that AMBA devices are initialized before platform devices. * Notice that AMBA devices are initialized before platform devices.
...@@ -1676,7 +1681,6 @@ static struct platform_device *platform_devs[] __initdata = { ...@@ -1676,7 +1681,6 @@ static struct platform_device *platform_devs[] __initdata = {
&gpio_device, &gpio_device,
&nand_device, &nand_device,
&wdog_device, &wdog_device,
&pinmux_device,
}; };
/* /*
...@@ -1861,7 +1865,7 @@ void __init u300_init_devices(void) ...@@ -1861,7 +1865,7 @@ void __init u300_init_devices(void)
u300_assign_physmem(); u300_assign_physmem();
/* Initialize pinmuxing */ /* Initialize pinmuxing */
pinmux_register_mappings(u300_pinmux_map, pinctrl_register_mappings(u300_pinmux_map,
ARRAY_SIZE(u300_pinmux_map)); ARRAY_SIZE(u300_pinmux_map));
/* Register subdevices on the I2C buses */ /* Register subdevices on the I2C buses */
......
...@@ -24,12 +24,14 @@ enum u300_gpio_variant { ...@@ -24,12 +24,14 @@ enum u300_gpio_variant {
* @ports: number of GPIO block ports * @ports: number of GPIO block ports
* @gpio_base: first GPIO number for this block (use a free range) * @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) * @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 { struct u300_gpio_platform {
enum u300_gpio_variant variant; enum u300_gpio_variant variant;
u8 ports; u8 ports;
int gpio_base; int gpio_base;
int gpio_irq_base; int gpio_irq_base;
struct platform_device *pinctrl_device;
}; };
#endif /* __MACH_U300_GPIO_U300_H */ #endif /* __MACH_U300_GPIO_U300_H */
...@@ -17,21 +17,63 @@ config PINMUX ...@@ -17,21 +17,63 @@ config PINMUX
config PINCONF config PINCONF
bool "Support pin configuration controllers" bool "Support pin configuration controllers"
config GENERIC_PINCONF
bool
select PINCONF
config DEBUG_PINCTRL config DEBUG_PINCTRL
bool "Debug PINCTRL calls" bool "Debug PINCTRL calls"
depends on DEBUG_KERNEL depends on DEBUG_KERNEL
help help
Say Y here to add some extra checks and diagnostics to PINCTRL calls. 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 config PINCTRL_SIRF
bool "CSR SiRFprimaII pin controller driver" bool "CSR SiRFprimaII pin controller driver"
depends on ARCH_PRIMA2 depends on ARCH_PRIMA2
select PINMUX 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 config PINCTRL_U300
bool "U300 pin controller driver" bool "U300 pin controller driver"
depends on ARCH_U300 depends on ARCH_U300
select PINMUX select PINMUX
select GENERIC_PINCONF
config PINCTRL_COH901 config PINCTRL_COH901
bool "ST-Ericsson U300 COH 901 335/571 GPIO" bool "ST-Ericsson U300 COH 901 335/571 GPIO"
......
...@@ -5,6 +5,14 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG ...@@ -5,6 +5,14 @@ ccflags-$(CONFIG_DEBUG_PINCTRL) += -DDEBUG
obj-$(CONFIG_PINCTRL) += core.o obj-$(CONFIG_PINCTRL) += core.o
obj-$(CONFIG_PINMUX) += pinmux.o obj-$(CONFIG_PINMUX) += pinmux.o
obj-$(CONFIG_PINCONF) += pinconf.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_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_U300) += pinctrl-u300.o
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
This diff is collapsed.
...@@ -9,7 +9,10 @@ ...@@ -9,7 +9,10 @@
* License terms: GNU General Public License (GPL) version 2 * 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/pinconf.h>
#include <linux/pinctrl/machine.h>
struct pinctrl_gpio_range; struct pinctrl_gpio_range;
...@@ -20,34 +23,94 @@ struct pinctrl_gpio_range; ...@@ -20,34 +23,94 @@ struct pinctrl_gpio_range;
* controller * controller
* @pin_desc_tree: each pin descriptor for this pin controller is stored in * @pin_desc_tree: each pin descriptor for this pin controller is stored in
* this radix tree * 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, * @gpio_ranges: a list of GPIO ranges that is handled by this pin controller,
* ranges are added to this list at runtime * 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 * @dev: the device entry for this pin controller
* @owner: module providing the pin controller, used for refcounting * @owner: module providing the pin controller, used for refcounting
* @driver_data: driver data for drivers registering to the pin controller * @driver_data: driver data for drivers registering to the pin controller
* subsystem * subsystem
* @pinmux_hogs_lock: lock for the pinmux hog list * @p: result of pinctrl_get() for this device
* @pinmux_hogs: list of pinmux maps hogged by this device * @device_root: debugfs root for this device
*/ */
struct pinctrl_dev { struct pinctrl_dev {
struct list_head node; struct list_head node;
struct pinctrl_desc *desc; struct pinctrl_desc *desc;
struct radix_tree_root pin_desc_tree; struct radix_tree_root pin_desc_tree;
spinlock_t pin_desc_tree_lock;
struct list_head gpio_ranges; struct list_head gpio_ranges;
struct mutex gpio_ranges_lock;
struct device *dev; struct device *dev;
struct module *owner; struct module *owner;
void *driver_data; void *driver_data;
struct pinctrl *p;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
struct dentry *device_root; struct dentry *device_root;
#endif #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 { ...@@ -56,28 +119,38 @@ struct pinctrl_dev {
* @name: a name for the pin, e.g. the name of the pin/pad/finger on a * @name: a name for the pin, e.g. the name of the pin/pad/finger on a
* datasheet or such * datasheet or such
* @dynamic_name: if the name of this pin was dynamically allocated * @dynamic_name: if the name of this pin was dynamically allocated
* @lock: a lock to protect the descriptor structure * @mux_usecount: If zero, the pin is not claimed, and @owner should be NULL.
* @mux_requested: whether the pin is already requested by pinmux or not * If non-zero, this pin is claimed by @owner. This field is an integer
* @mux_function: a named muxing function for the pin that will be passed to * rather than a boolean, since pinctrl_get() might process multiple
* subdrivers and shown in debugfs etc * 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 pin_desc {
struct pinctrl_dev *pctldev; struct pinctrl_dev *pctldev;
const char *name; const char *name;
bool dynamic_name; bool dynamic_name;
spinlock_t lock;
/* These fields only added when supporting pinmux drivers */ /* These fields only added when supporting pinmux drivers */
#ifdef CONFIG_PINMUX #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 #endif
}; };
struct pinctrl_dev *get_pinctrl_dev_from_dev(struct device *dev, struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name);
const char *dev_name);
struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, unsigned int pin);
int pin_get_from_name(struct pinctrl_dev *pctldev, const char *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, int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
const char *pin_group); 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;
/*
* 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
This diff is collapsed.
...@@ -14,12 +14,25 @@ ...@@ -14,12 +14,25 @@
#ifdef CONFIG_PINCONF #ifdef CONFIG_PINCONF
int pinconf_check_ops(struct pinctrl_dev *pctldev); 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, void pinconf_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev); 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, int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *config); unsigned long *config);
int pin_config_set_for_pin(struct pinctrl_dev *pctldev, unsigned pin, int pin_config_group_get(const char *dev_name, const char *pin_group,
unsigned long config); unsigned long *config);
#else #else
...@@ -28,9 +41,70 @@ static inline int pinconf_check_ops(struct pinctrl_dev *pctldev) ...@@ -28,9 +41,70 @@ static inline int pinconf_check_ops(struct pinctrl_dev *pctldev)
return 0; 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, static inline void pinconf_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev) struct pinctrl_dev *pctldev)
{ {
} }
#endif #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
...@@ -22,38 +22,10 @@ ...@@ -22,38 +22,10 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/slab.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> #include <mach/gpio-u300.h>
#include "pinctrl-coh901.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
/* /*
* Register definitions for COH 901 335 variant * Register definitions for COH 901 335 variant
...@@ -181,12 +153,12 @@ struct u300_gpio_confdata { ...@@ -181,12 +153,12 @@ struct u300_gpio_confdata {
#define BS365_GPIO_NUM_PORTS 5 #define BS365_GPIO_NUM_PORTS 5
#define U300_FLOATING_INPUT { \ #define U300_FLOATING_INPUT { \
.bias_mode = GPIO_U300_CONFIG_BIAS_FLOAT, \ .bias_mode = PIN_CONFIG_BIAS_HIGH_IMPEDANCE, \
.output = false, \ .output = false, \
} }
#define U300_PULL_UP_INPUT { \ #define U300_PULL_UP_INPUT { \
.bias_mode = GPIO_U300_CONFIG_BIAS_PULL_UP, \ .bias_mode = PIN_CONFIG_BIAS_PULL_UP, \
.output = false, \ .output = false, \
} }
...@@ -360,14 +332,14 @@ static int u300_gpio_request(struct gpio_chip *chip, unsigned offset) ...@@ -360,14 +332,14 @@ static int u300_gpio_request(struct gpio_chip *chip, unsigned offset)
*/ */
int gpio = chip->base + 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) static void u300_gpio_free(struct gpio_chip *chip, unsigned offset)
{ {
int gpio = chip->base + 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) 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) ...@@ -448,8 +420,68 @@ static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
return retirq; return retirq;
} }
static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, /* Returning -EINVAL means "supported but not available" */
u16 param, unsigned long *data) 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); struct u300_gpio *gpio = to_u300_gpio(chip);
unsigned long flags; unsigned long flags;
...@@ -457,16 +489,16 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, ...@@ -457,16 +489,16 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset,
local_irq_save(flags); local_irq_save(flags);
switch (param) { switch (param) {
case GPIO_U300_CONFIG_BIAS_UNKNOWN: case PIN_CONFIG_BIAS_DISABLE:
case GPIO_U300_CONFIG_BIAS_FLOAT: case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
val = readl(U300_PIN_REG(offset, per)); val = readl(U300_PIN_REG(offset, per));
writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, per)); writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, per));
break; break;
case GPIO_U300_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_UP:
val = readl(U300_PIN_REG(offset, per)); val = readl(U300_PIN_REG(offset, per));
writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, per)); writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, per));
break; break;
case GPIO_U300_CONFIG_DRIVE_PUSH_PULL: case PIN_CONFIG_DRIVE_PUSH_PULL:
val = readl(U300_PIN_REG(offset, pcr)); val = readl(U300_PIN_REG(offset, pcr));
val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
<< ((offset & 0x07) << 1)); << ((offset & 0x07) << 1));
...@@ -474,7 +506,7 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, ...@@ -474,7 +506,7 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset,
<< ((offset & 0x07) << 1)); << ((offset & 0x07) << 1));
writel(val, U300_PIN_REG(offset, pcr)); writel(val, U300_PIN_REG(offset, pcr));
break; break;
case GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: case PIN_CONFIG_DRIVE_OPEN_DRAIN:
val = readl(U300_PIN_REG(offset, pcr)); val = readl(U300_PIN_REG(offset, pcr));
val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
<< ((offset & 0x07) << 1)); << ((offset & 0x07) << 1));
...@@ -482,7 +514,7 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, ...@@ -482,7 +514,7 @@ static int u300_gpio_config(struct gpio_chip *chip, unsigned offset,
<< ((offset & 0x07) << 1)); << ((offset & 0x07) << 1));
writel(val, U300_PIN_REG(offset, pcr)); writel(val, U300_PIN_REG(offset, pcr));
break; break;
case GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: case PIN_CONFIG_DRIVE_OPEN_SOURCE:
val = readl(U300_PIN_REG(offset, pcr)); val = readl(U300_PIN_REG(offset, pcr));
val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK
<< ((offset & 0x07) << 1)); << ((offset & 0x07) << 1));
...@@ -650,13 +682,12 @@ static void __init u300_gpio_init_pin(struct u300_gpio *gpio, ...@@ -650,13 +682,12 @@ static void __init u300_gpio_init_pin(struct u300_gpio *gpio,
u300_gpio_direction_output(&gpio->chip, offset, conf->outval); u300_gpio_direction_output(&gpio->chip, offset, conf->outval);
/* Deactivate bias mode for output */ /* Deactivate bias mode for output */
u300_gpio_config(&gpio->chip, offset, u300_gpio_config_set(&gpio->chip, offset,
GPIO_U300_CONFIG_BIAS_FLOAT, PIN_CONFIG_BIAS_HIGH_IMPEDANCE);
NULL);
/* Set drive mode for output */ /* Set drive mode for output */
u300_gpio_config(&gpio->chip, offset, u300_gpio_config_set(&gpio->chip, offset,
GPIO_U300_CONFIG_DRIVE_PUSH_PULL, NULL); PIN_CONFIG_DRIVE_PUSH_PULL);
dev_dbg(gpio->dev, "set up pin %d as output, value: %d\n", dev_dbg(gpio->dev, "set up pin %d as output, value: %d\n",
offset, conf->outval); offset, conf->outval);
...@@ -667,7 +698,7 @@ static void __init u300_gpio_init_pin(struct u300_gpio *gpio, ...@@ -667,7 +698,7 @@ static void __init u300_gpio_init_pin(struct u300_gpio *gpio,
u300_gpio_set(&gpio->chip, offset, 0); u300_gpio_set(&gpio->chip, offset, 0);
/* Set bias mode for input */ /* 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\n", dev_dbg(gpio->dev, "set up pin %d as input, bias: %04x\n",
offset, conf->bias_mode); offset, conf->bias_mode);
...@@ -705,7 +736,6 @@ static inline void u300_gpio_free_ports(struct u300_gpio *gpio) ...@@ -705,7 +736,6 @@ static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
list_for_each_safe(p, n, &gpio->port_list) { list_for_each_safe(p, n, &gpio->port_list) {
port = list_entry(p, struct u300_gpio_port, node); port = list_entry(p, struct u300_gpio_port, node);
list_del(&port->node); list_del(&port->node);
free_irq(port->irq, port);
kfree(port); kfree(port);
} }
} }
...@@ -861,10 +891,18 @@ static int __init u300_gpio_probe(struct platform_device *pdev) ...@@ -861,10 +891,18 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
goto err_no_chip; 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); platform_set_drvdata(pdev, gpio);
return 0; return 0;
err_no_pinctrl:
err = gpiochip_remove(&gpio->chip);
err_no_chip: err_no_chip:
err_no_port: err_no_port:
u300_gpio_free_ports(gpio); u300_gpio_free_ports(gpio);
...@@ -919,7 +957,6 @@ static struct platform_driver u300_gpio_driver = { ...@@ -919,7 +957,6 @@ static struct platform_driver u300_gpio_driver = {
.remove = __exit_p(u300_gpio_remove), .remove = __exit_p(u300_gpio_remove),
}; };
static int __init u300_gpio_init(void) static int __init u300_gpio_init(void)
{ {
return platform_driver_probe(&u300_gpio_driver, u300_gpio_probe); return platform_driver_probe(&u300_gpio_driver, u300_gpio_probe);
......
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);
This diff is collapsed.
This diff is collapsed.
/*
* linux/drivers/pinctrl/pinctrl-pxa3xx.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/module.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "pinctrl-pxa3xx.h"
static struct pinctrl_gpio_range pxa3xx_pinctrl_gpio_range = {
.name = "PXA3xx GPIO",
.id = 0,
.base = 0,
.pin_base = 0,
};
static int pxa3xx_list_groups(struct pinctrl_dev *pctrldev, unsigned selector)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (selector >= info->num_grps)
return -EINVAL;
return 0;
}
static const char *pxa3xx_get_group_name(struct pinctrl_dev *pctrldev,
unsigned selector)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (selector >= info->num_grps)
return NULL;
return info->grps[selector].name;
}
static int pxa3xx_get_group_pins(struct pinctrl_dev *pctrldev,
unsigned selector,
const unsigned **pins,
unsigned *num_pins)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (selector >= info->num_grps)
return -EINVAL;
*pins = info->grps[selector].pins;
*num_pins = info->grps[selector].npins;
return 0;
}
static struct pinctrl_ops pxa3xx_pctrl_ops = {
.list_groups = pxa3xx_list_groups,
.get_group_name = pxa3xx_get_group_name,
.get_group_pins = pxa3xx_get_group_pins,
};
static int pxa3xx_pmx_list_func(struct pinctrl_dev *pctrldev, unsigned func)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
if (func >= info->num_funcs)
return -EINVAL;
return 0;
}
static const char *pxa3xx_pmx_get_func_name(struct pinctrl_dev *pctrldev,
unsigned func)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
return info->funcs[func].name;
}
static int pxa3xx_pmx_get_groups(struct pinctrl_dev *pctrldev, unsigned func,
const char * const **groups,
unsigned * const num_groups)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
*groups = info->funcs[func].groups;
*num_groups = info->funcs[func].num_groups;
return 0;
}
/* Return function number. If failure, return negative value. */
static int match_mux(struct pxa3xx_mfp_pin *mfp, unsigned mux)
{
int i;
for (i = 0; i < PXA3xx_MAX_MUX; i++) {
if (mfp->func[i] == mux)
break;
}
if (i >= PXA3xx_MAX_MUX)
return -EINVAL;
return i;
}
/* check whether current pin configuration is valid. Negative for failure */
static int match_group_mux(struct pxa3xx_pin_group *grp,
struct pxa3xx_pinmux_info *info,
unsigned mux)
{
int i, pin, ret = 0;
for (i = 0; i < grp->npins; i++) {
pin = grp->pins[i];
ret = match_mux(&info->mfp[pin], mux);
if (ret < 0) {
dev_err(info->dev, "Can't find mux %d on pin%d\n",
mux, pin);
break;
}
}
return ret;
}
static int pxa3xx_pmx_enable(struct pinctrl_dev *pctrldev, unsigned func,
unsigned group)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
struct pxa3xx_pin_group *pin_grp = &info->grps[group];
unsigned int data;
int i, mfpr, pin, pin_func;
if (!pin_grp->npins ||
(match_group_mux(pin_grp, info, pin_grp->mux) < 0)) {
dev_err(info->dev, "Failed to set the pin group: %d\n", group);
return -EINVAL;
}
for (i = 0; i < pin_grp->npins; i++) {
pin = pin_grp->pins[i];
pin_func = match_mux(&info->mfp[pin], pin_grp->mux);
mfpr = info->mfp[pin].mfpr;
data = readl_relaxed(info->virt_base + mfpr);
data &= ~MFPR_FUNC_MASK;
data |= pin_func;
writel_relaxed(data, info->virt_base + mfpr);
}
return 0;
}
static void pxa3xx_pmx_disable(struct pinctrl_dev *pctrldev, unsigned func,
unsigned group)
{
}
static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev,
struct pinctrl_gpio_range *range,
unsigned pin)
{
struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
unsigned int data;
int pin_func, mfpr;
pin_func = match_mux(&info->mfp[pin], PXA3xx_MUX_GPIO);
if (pin_func < 0) {
dev_err(info->dev, "No GPIO function on pin%d (%s)\n",
pin, info->pads[pin].name);
return -EINVAL;
}
mfpr = info->mfp[pin].mfpr;
/* write gpio function into mfpr register */
data = readl_relaxed(info->virt_base + mfpr) & ~MFPR_FUNC_MASK;
data |= pin_func;
writel_relaxed(data, info->virt_base + mfpr);
return 0;
}
static struct pinmux_ops pxa3xx_pmx_ops = {
.list_functions = pxa3xx_pmx_list_func,
.get_function_name = pxa3xx_pmx_get_func_name,
.get_function_groups = pxa3xx_pmx_get_groups,
.enable = pxa3xx_pmx_enable,
.disable = pxa3xx_pmx_disable,
.gpio_request_enable = pxa3xx_pmx_request_gpio,
};
int pxa3xx_pinctrl_register(struct platform_device *pdev,
struct pxa3xx_pinmux_info *info)
{
struct pinctrl_desc *desc;
struct resource *res;
int ret = 0;
if (!info || !info->cputype)
return -EINVAL;
desc = info->desc;
desc->pins = info->pads;
desc->npins = info->num_pads;
desc->pctlops = &pxa3xx_pctrl_ops;
desc->pmxops = &pxa3xx_pmx_ops;
info->dev = &pdev->dev;
pxa3xx_pinctrl_gpio_range.npins = info->num_gpio;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENOENT;
info->phy_base = res->start;
info->phy_size = resource_size(res);
info->virt_base = ioremap(info->phy_base, info->phy_size);
if (!info->virt_base)
return -ENOMEM;
info->pctrl = pinctrl_register(desc, &pdev->dev, info);
if (!info->pctrl) {
dev_err(&pdev->dev, "failed to register PXA pinmux driver\n");
ret = -EINVAL;
goto err;
}
pinctrl_add_gpio_range(info->pctrl, &pxa3xx_pinctrl_gpio_range);
platform_set_drvdata(pdev, info);
return 0;
err:
iounmap(info->virt_base);
return ret;
}
int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
{
struct pxa3xx_pinmux_info *info = platform_get_drvdata(pdev);
pinctrl_unregister(info->pctrl);
iounmap(info->virt_base);
platform_set_drvdata(pdev, NULL);
return 0;
}
static int __init pxa3xx_pinctrl_init(void)
{
pr_info("pxa3xx-pinctrl: PXA3xx pinctrl driver initializing\n");
return 0;
}
core_initcall_sync(pxa3xx_pinctrl_init);
static void __exit pxa3xx_pinctrl_exit(void)
{
}
module_exit(pxa3xx_pinctrl_exit);
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
MODULE_DESCRIPTION("PXA3xx pin control driver");
MODULE_LICENSE("GPL v2");
/*
* linux/drivers/pinctrl/pinctrl-pxa3xx.h
*
* 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>
*
*/
#ifndef __PINCTRL_PXA3XX_H
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
#define PXA3xx_MUX_GPIO 0
#define PXA3xx_MAX_MUX 8
#define MFPR_FUNC_MASK 0x7
enum pxa_cpu_type {
PINCTRL_INVALID = 0,
PINCTRL_PXA300,
PINCTRL_PXA310,
PINCTRL_PXA320,
PINCTRL_PXA168,
PINCTRL_PXA910,
PINCTRL_PXA930,
PINCTRL_PXA955,
PINCTRL_MMP2,
PINCTRL_MAX,
};
struct pxa3xx_mfp_pin {
const char *name;
const unsigned int pin;
const unsigned int mfpr; /* register offset */
const unsigned short func[8];
};
struct pxa3xx_pin_group {
const char *name;
const unsigned mux;
const unsigned *pins;
const unsigned npins;
};
struct pxa3xx_pmx_func {
const char *name;
const char * const * groups;
const unsigned num_groups;
};
struct pxa3xx_pinmux_info {
struct device *dev;
struct pinctrl_dev *pctrl;
enum pxa_cpu_type cputype;
unsigned int phy_base;
unsigned int phy_size;
void __iomem *virt_base;
struct pxa3xx_mfp_pin *mfp;
unsigned int num_mfp;
struct pxa3xx_pin_group *grps;
unsigned int num_grps;
struct pxa3xx_pmx_func *funcs;
unsigned int num_funcs;
unsigned int num_gpio;
struct pinctrl_desc *desc;
struct pinctrl_pin_desc *pads;
unsigned int num_pads;
unsigned ds_mask; /* drive strength mask */
unsigned ds_shift; /* drive strength shift */
unsigned slp_mask; /* sleep mask */
unsigned slp_input_low;
unsigned slp_input_high;
unsigned slp_output_low;
unsigned slp_output_high;
unsigned slp_float;
};
enum pxa3xx_pin_list {
GPIO0 = 0,
GPIO1,
GPIO2,
GPIO3,
GPIO4,
GPIO5,
GPIO6,
GPIO7,
GPIO8,
GPIO9,
GPIO10, /* 10 */
GPIO11,
GPIO12,
GPIO13,
GPIO14,
GPIO15,
GPIO16,
GPIO17,
GPIO18,
GPIO19,
GPIO20, /* 20 */
GPIO21,
GPIO22,
GPIO23,
GPIO24,
GPIO25,
GPIO26,
GPIO27,
GPIO28,
GPIO29,
GPIO30, /* 30 */
GPIO31,
GPIO32,
GPIO33,
GPIO34,
GPIO35,
GPIO36,
GPIO37,
GPIO38,
GPIO39,
GPIO40, /* 40 */
GPIO41,
GPIO42,
GPIO43,
GPIO44,
GPIO45,
GPIO46,
GPIO47,
GPIO48,
GPIO49,
GPIO50, /* 50 */
GPIO51,
GPIO52,
GPIO53,
GPIO54,
GPIO55,
GPIO56,
GPIO57,
GPIO58,
GPIO59,
GPIO60, /* 60 */
GPIO61,
GPIO62,
GPIO63,
GPIO64,
GPIO65,
GPIO66,
GPIO67,
GPIO68,
GPIO69,
GPIO70, /* 70 */
GPIO71,
GPIO72,
GPIO73,
GPIO74,
GPIO75,
GPIO76,
GPIO77,
GPIO78,
GPIO79,
GPIO80, /* 80 */
GPIO81,
GPIO82,
GPIO83,
GPIO84,
GPIO85,
GPIO86,
GPIO87,
GPIO88,
GPIO89,
GPIO90, /* 90 */
GPIO91,
GPIO92,
GPIO93,
GPIO94,
GPIO95,
GPIO96,
GPIO97,
GPIO98,
GPIO99,
GPIO100, /* 100 */
GPIO101,
GPIO102,
GPIO103,
GPIO104,
GPIO105,
GPIO106,
GPIO107,
GPIO108,
GPIO109,
GPIO110, /* 110 */
GPIO111,
GPIO112,
GPIO113,
GPIO114,
GPIO115,
GPIO116,
GPIO117,
GPIO118,
GPIO119,
GPIO120, /* 120 */
GPIO121,
GPIO122,
GPIO123,
GPIO124,
GPIO125,
GPIO126,
GPIO127,
GPIO128,
GPIO129,
GPIO130, /* 130 */
GPIO131,
GPIO132,
GPIO133,
GPIO134,
GPIO135,
GPIO136,
GPIO137,
GPIO138,
GPIO139,
GPIO140, /* 140 */
GPIO141,
GPIO142,
GPIO143,
GPIO144,
GPIO145,
GPIO146,
GPIO147,
GPIO148,
GPIO149,
GPIO150, /* 150 */
GPIO151,
GPIO152,
GPIO153,
GPIO154,
GPIO155,
GPIO156,
GPIO157,
GPIO158,
GPIO159,
GPIO160, /* 160 */
GPIO161,
GPIO162,
GPIO163,
GPIO164,
GPIO165,
GPIO166,
GPIO167,
GPIO168,
GPIO169,
};
extern int pxa3xx_pinctrl_register(struct platform_device *pdev,
struct pxa3xx_pinmux_info *info);
extern int pxa3xx_pinctrl_unregister(struct platform_device *pdev);
#endif /* __PINCTRL_PXA3XX_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include "pinctrl-coh901.h"
/* /*
* Register definitions for the U300 Padmux control registers in the * Register definitions for the U300 Padmux control registers in the
...@@ -162,7 +165,7 @@ ...@@ -162,7 +165,7 @@
#define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS 0x0100 #define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS 0x0100
#define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N 0x0200 #define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N 0x0200
#define DRIVER_NAME "pinmux-u300" #define DRIVER_NAME "pinctrl-u300"
/* /*
* The DB3350 has 467 pads, I have enumerated the pads clockwise around the * The DB3350 has 467 pads, I have enumerated the pads clockwise around the
...@@ -1044,22 +1047,82 @@ static struct pinctrl_gpio_range u300_gpio_ranges[] = { ...@@ -1044,22 +1047,82 @@ static struct pinctrl_gpio_range u300_gpio_ranges[] = {
U300_GPIO_RANGE(25, 181, 1), U300_GPIO_RANGE(25, 181, 1),
}; };
static struct pinctrl_gpio_range *u300_match_gpio_range(unsigned pin)
{
int i;
for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) {
struct pinctrl_gpio_range *range;
range = &u300_gpio_ranges[i];
if (pin >= range->pin_base &&
pin <= (range->pin_base + range->npins - 1))
return range;
}
return NULL;
}
int u300_pin_config_get(struct pinctrl_dev *pctldev,
unsigned pin,
unsigned long *config)
{
struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
/* We get config for those pins we CAN get it for and that's it */
if (!range)
return -ENOTSUPP;
return u300_gpio_config_get(range->gc,
(pin - range->pin_base + range->base),
config);
}
int u300_pin_config_set(struct pinctrl_dev *pctldev,
unsigned pin,
unsigned long config)
{
struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
int ret;
if (!range)
return -EINVAL;
/* Note: none of these configurations take any argument */
ret = u300_gpio_config_set(range->gc,
(pin - range->pin_base + range->base),
pinconf_to_config_param(config));
if (ret)
return ret;
return 0;
}
static struct pinconf_ops u300_pconf_ops = {
.is_generic = true,
.pin_config_get = u300_pin_config_get,
.pin_config_set = u300_pin_config_set,
};
static struct pinctrl_desc u300_pmx_desc = { static struct pinctrl_desc u300_pmx_desc = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.pins = u300_pads, .pins = u300_pads,
.npins = ARRAY_SIZE(u300_pads), .npins = ARRAY_SIZE(u300_pads),
.pctlops = &u300_pctrl_ops, .pctlops = &u300_pctrl_ops,
.pmxops = &u300_pmx_ops, .pmxops = &u300_pmx_ops,
.confops = &u300_pconf_ops,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static int __init u300_pmx_probe(struct platform_device *pdev) static int __devinit u300_pmx_probe(struct platform_device *pdev)
{ {
struct u300_pmx *upmx; struct u300_pmx *upmx;
struct resource *res; struct resource *res;
struct gpio_chip *gpio_chip = dev_get_platdata(&pdev->dev);
int ret; int ret;
int i; int i;
pr_err("U300 PMX PROBE\n");
/* Create state holders etc for this driver */ /* Create state holders etc for this driver */
upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL); upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL);
if (!upmx) if (!upmx)
...@@ -1095,12 +1158,14 @@ static int __init u300_pmx_probe(struct platform_device *pdev) ...@@ -1095,12 +1158,14 @@ static int __init u300_pmx_probe(struct platform_device *pdev)
} }
/* We will handle a range of GPIO pins */ /* We will handle a range of GPIO pins */
for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) {
u300_gpio_ranges[i].gc = gpio_chip;
pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_ranges[i]); pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_ranges[i]);
}
platform_set_drvdata(pdev, upmx); platform_set_drvdata(pdev, upmx);
dev_info(&pdev->dev, "initialized U300 pinmux driver\n"); dev_info(&pdev->dev, "initialized U300 pin control driver\n");
return 0; return 0;
...@@ -1115,7 +1180,7 @@ static int __init u300_pmx_probe(struct platform_device *pdev) ...@@ -1115,7 +1180,7 @@ static int __init u300_pmx_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int __exit u300_pmx_remove(struct platform_device *pdev) static int __devexit u300_pmx_remove(struct platform_device *pdev)
{ {
struct u300_pmx *upmx = platform_get_drvdata(pdev); struct u300_pmx *upmx = platform_get_drvdata(pdev);
int i; int i;
...@@ -1136,12 +1201,13 @@ static struct platform_driver u300_pmx_driver = { ...@@ -1136,12 +1201,13 @@ static struct platform_driver u300_pmx_driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.remove = __exit_p(u300_pmx_remove), .probe = u300_pmx_probe,
.remove = __devexit_p(u300_pmx_remove),
}; };
static int __init u300_pmx_init(void) static int __init u300_pmx_init(void)
{ {
return platform_driver_probe(&u300_pmx_driver, u300_pmx_probe); return platform_driver_register(&u300_pmx_driver);
} }
arch_initcall(u300_pmx_init); arch_initcall(u300_pmx_init);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -162,7 +162,7 @@ struct sirfsoc_uart_port { ...@@ -162,7 +162,7 @@ struct sirfsoc_uart_port {
unsigned char ms_enabled; unsigned char ms_enabled;
struct uart_port port; struct uart_port port;
struct pinmux *pmx; struct pinctrl *p;
}; };
/* Hardware Flow Control */ /* Hardware Flow Control */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Standard pin control state definitions
*/
#define PINCTRL_STATE_DEFAULT "default"
#define PINCTRL_STATE_IDLE "idle"
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment