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,8 +1865,8 @@ void __init u300_init_devices(void) ...@@ -1861,8 +1865,8 @@ 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 */
u300_i2c_register_board_devices(); u300_i2c_register_board_devices();
......
...@@ -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.
This diff is collapsed.
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