On Fri, Aug 19, 2011 at 5:18 AM, Pauli Nieminen
<pauli.nieminen(a)linux.intel.com> wrote:
> On Thu, Aug 18, 2011 at 09:58:07PM -0500, Rob Clark wrote:
>> From: Rob Clark <rob(a)ti.com>
>>
>> To allow the potential use of overlays to display video content, a few
>> extra parameters are required:
>>
>> + source buffer in different format (for example, various YUV formats)
>> and size as compared to destination drawable
>> + multi-planar formats where discontiguous buffers are used for
>> different planes. For example, luma and chroma split across
>> multiple memory banks or with different tiled formats.
>> + flipping between multiple back buffers, perhaps not in order (to
>> handle video formats with B-frames)
>> + cropping during swap.. in case of video, perhaps the required hw
>> buffers are larger than the visible picture to account for codec
>> borders (for example, reference frames where a block/macroblock
>> moves past the edge of the visible picture, but back again in
>> subsequent frames).
>>
>> Current solutions use the GPU to do a scaled/colorconvert into a DRI2
>> buffer from the client context. The goal of this protocol change is
>> to push the decision to use overlay or GPU blit to the xorg driver.
>> ---
>> Eventually this should replace Xv. With a few additions, like attributes,
>> it could perhaps be possible to implement the client side Xv API on top
>> of dri2.
>>
>> Note: video is not exactly the same as 3d, there are a number of other
>> things to consider (scaling, colorconvert, multi-planar formats). But
>> on the other hand the principle is similar (direct rendering from hw
>> video codecs). And a lot infrastructure of connection, authentication,
>> is same. So there are two options, either extend DRI2 or add a new
>> protocol which duplicates some parts. I'd like to consider extending
>> DRI2 first, but if people think the requirements for video are too
>> much different from 3d, then I could split this into a new protocol.
>>
>> In either case, I will implement the xserver side infrastructure, but
>> I wanted to get some feel for what is the preferred approach (extend
>> dri2 or new videoproto) first.
>>
>
> XvPutVideo is already existing alternative to use for video playback
> to overlays. But XvPutVideo API isn't perfect for the job either.
We have until now actually used an unholy marriage of v4l2 and
XvPutVideo.. part of the motivation to either extend dri2 or introduce
a direct-video-rendering proto is have a better solution for some of
the sort-comings of the current solution:
+ currently the client has to realize it is using an overlay.. and
which overlay.. switching between overlay and GPU blitting is not
transparent to the client
+ which results in a resource management issue if there are multiple
videos playing, or if you need to scale beyond what can be done w/
overlay, etc
+ in some cases, you might want some way for the window-manager to
signal to xorg driver to switch to blitting because there are some
transformational effects.. ie. wobbly windows and that sort of thing..
(I'm thinking maybe setting some property on the root window?)
Ideally this would be transparent to the video player app.
some of this could be accomplished w/ XvPutImage, but then you are
restricted to memory that can be obtained from shmem, which is not
sufficient for hw video codecs in most cases.
> How would client know which formats are supported by driver? Xv expose
> list of supported image formats to client.
well, in current version of the patch, the client would "just have to
know".. which is sort of how it is on the 3d side for dri2.
Although if there was an attribute mechanism, then I guess we could
actually make it possible to have a completely generic client. One
other issue to tackle then is what exactly is the buffer name.
Currently for dri2 this is left as an implementation detail between
the client and server. But we could decree that it is a GEM buffer
flink name, or possibly that it is a dmabuf file-descriptor (see
http://lists.linaro.org/pipermail/linaro-mm-sig/2011-August/000509.html
)
For a first step, I was ok that the client side of the dri2 connection
would have to know some implementation details of the xorg driver that
it is talking too, since this is how it already is for dri2, and it
could be handled by an approach like vaapi/vdpau where there is some
driver specific code on the client side, above dri2.
But on the other hand, allowing for a completely generic client using
the video/dri2 proto could be interesting. I guess it depends on what
folk's general feeling is.. if completely generic client side is
important, then I'll go back and start adding attributes and this sort
of thing. I think it is doable although it would require adding more
to dri2proto than what I have proposed so far.
>> dri2proto.txt | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>> 1 files changed, 59 insertions(+), 1 deletions(-)
>>
>> diff --git a/dri2proto.txt b/dri2proto.txt
>> index df763c7..aa83b1a 100644
>> --- a/dri2proto.txt
>> +++ b/dri2proto.txt
>> @@ -163,7 +163,8 @@ and DRI2InvalidateBuffers.
>> 6. Protocol Types
>>
>> DRI2DRIVER { DRI2DriverDRI
>> - DRI2DriverVDPAU }
>> + DRI2DriverVDPAU,
>> + DRI2DriverXV }
>>
>> These values describe the type of driver the client will want
>> to load. The server sends back the name of the driver to use
>> @@ -184,6 +185,10 @@ DRI2ATTACHMENT { DRI2BufferFrontLeft
>> These values describe various attachment points for DRI2
>> buffers.
>>
>> + In the case of video driver (DRI2DriverXV) the attachment,
>> + other than DRI2BufferFrontLeft, just indicates buffer
>> + number and has no other special significance.
>> +
>> DRI2BUFFER { attachment: CARD32
>> name: CARD32
>> pitch: CARD32
>> @@ -203,6 +208,16 @@ DRI2ATTACH_FORMAT { attachment: CARD32
>> format. 'attachment' describes the attachment point for the buffer,
>> 'format' describes an opaque, device-dependent format for the buffer.
>>
>> +
>> +DRI2ATTACH_VIDEO { attachment: CARD32
>> + format: CARD32,
>> + width, height: CARD32 }
>> +
>> + The DRI2ATTACH_VIDEO describes an attachment and the associated
>> + format for video buffers. 'attachment' describes the attachment
>> + point for the buffer, 'format' describes a fourcc value for the
>> + buffer.
>> +
>
> I think you will anyway need Xv port attribute like system to expose
> HW features like color conversion. Width and height for buffers source
> buffers could be one of attributes.
>
> If width and height are in attributes video can use
> DRI2GetBuffersWithFormat.
>
> Format should include already information about excepted memory layout
> in buffer. Format would also include information about memory layout
> (packed/planar and tiled/linear)
agreed, if we go the attribute route, then DRI2GetBuffersWithFormat
would be enough
>> ⚙ ⚙ ⚙ ⚙ ⚙ ⚙
>>
>>
>> @@ -367,6 +382,15 @@ The name of this extension is "DRI2".
>> later.
>>
>> ┌───
>> + DRI2GetVideoBuffers
>> + drawable: DRAWABLE
>> + attachments: LISTofDRI2ATTACH_VIDEO
>> + ▶
>> + width, height: CARD32
>> + buffers: LISTofDRI2BUFFER
>> +└───
>> +
>> +┌───
>> DRI2GetMSC
>> drawable: DRAWABLE
>> ▶
>> @@ -585,11 +609,21 @@ A.1 Common Types
>> 4 CARD32 pitch
>> 4 CARD32 cpp
>> 4 CARD32 flags
>> + 4 n extra names length
>> + 4n LISTof extra names
>> └───
>> A DRI2 buffer specifies the attachment, the kernel memory
>> manager name, the pitch and chars per pixel for a buffer
>> attached to a given drawable.
>>
>> + In case of multi-planar video formats, 'extra names' will give the
>> + list of additional buffer names if there is one buffer per plane.
>> + For example, I420 has one Y plane in with a 8bit luma value per
>> + pixel, followed by one U plane subsampled 2x2 (with one 8bit U value
>> + per 2x2 pixel block), followed by one V plane subsampled 2x2. This
>> + could either be represented as a single buffer name, or three
>> + separate buffer names, one each for Y, U, and V.
>> +
>
> I think buffer format should already describe the internal memory
> layout for buffer.
>
> Do you have example where client couldn't know memory layout from
> format, width, height and stride?
well, it isn't so much a format/width/height/stride issue. But it is
likely that the different planes would not be contiguous in a single
buffer. For example, some SoC's require that luma and chroma exist in
different memory banks (different range of physical addresses). For
TI OMAP, we use different tiling formats for luma and chroma in an
NV12 buffer. Having the option for multiple buffer names per
attachment point seemed to give the most flexibility in
implementation.
It would be possible to stuff these all under a single buffer name,
although that brings some wrinkles.. for example, does plane n+1
start immediately after the previous plane (which it would for
contiguous buffers) or on next page boundary (which would be more
likely for non-contiguous buffers). And if different tiling formats
are used, that further complicates the kernel side code in case the
buffer is mmap'd to userspace.
Having the option for either one buffer name, or one buffer name per
plane avoids those complications. But I'm open to hear other opinions
on the idea of 1 vs n names per attachment point.
BR,
-R
>> ┌───
>> DRI2ATTACH_FORMAT
>> 4 CARD32 attachment
>> @@ -599,6 +633,17 @@ A.1 Common Types
>> This data type is only available with protocol version 1.1 or
>> later.
>>
>> +┌───
>> + DRI2ATTACH_VIDEO
>> + 4 CARD32 attachment
>> + 4 CARD32 format
>> + 4 CARD32 width
>> + 4 CARD32 height
>> +└───
>> + Used to describe the attachment and format requested from the server.
>> + This data type is only available with protocol version 1.? or
>> + later.
>> +
>> A.2 Protocol Requests
>>
>> ┌───
>> @@ -745,6 +790,11 @@ A.2 Protocol Requests
>> 4 CARD32 divisor_lo
>> 4 CARD32 remainder_hi
>> 4 CARD32 remainder_lo
>> + 4 DRI2ATTACHMENT source
>> + 4 CARD32 x1
>> + 4 CARD32 y1
>> + 4 CARD32 x2
>> + 4 CARD32 y2
>> ▶
>> 1 1 Reply
>> 1 unused
>> @@ -754,6 +804,14 @@ A.2 Protocol Requests
>> 4 CARD32 swap_lo
>> 5n LISTofDRI2BUFFER buffers
>> └───
>> + The 'source', if not zero (DRI2BufferFrontLeft) indicates the
>> + attachment point of the buffer to swap w/ DRI2BufferFrontLeft.
>> + If zero is specified, DRI2BufferBackLeft is swapped with the
>> + DRI2BufferFrontLeft buffer, for compatibility.
>> +
>> + If 'source' is not zero, (x1,y1), (x2,y2) specify the bounding
>> + box in coordinates of the source buffer which should be scaled
>> + to (0,0), (width,height) of the destination drawable.
>>
>> ┌───
>> DRI2GetMSC
>> --
>> 1.7.5.4
>>
>> _______________________________________________
>> xorg-devel(a)lists.x.org: X.Org development
>> Archives: http://lists.x.org/archives/xorg-devel
>> Info: http://lists.x.org/mailman/listinfo/xorg-devel
>
From: Per Forlin <per.forlin(a)linaro.org>
FSG_NUM_BUFFERS is set to 2 as default.
Usually 2 buffers are enough to establish a good buffering pipeline.
The number may be increased in order to compensate a for bursty VFS
behaviour.
Here follows a description of system that may require more than
2 buffers.
* CPU ondemand governor active
* latency cost for wake up and/or frequency change
* DMA for IO
Use case description.
* Data transfer from MMC via VFS to USB.
* DMA shuffles data from MMC and to USB.
* The CPU wakes up every now and then to pass data in and out from VFS,
which cause the bursty VFS behaviour.
Test set up
* Running dd on the host reading from the mass storage device
* cmdline: dd if=/dev/sdb of=/dev/null bs=4k count=$((256*100))
* Caches are dropped on the host and on the device before each run
Measurements on a Snowball board with ondemand_govenor active.
FSG_NUM_BUFFERS 2
104857600 bytes (105 MB) copied, 5.62173 s, 18.7 MB/s
104857600 bytes (105 MB) copied, 5.61811 s, 18.7 MB/s
104857600 bytes (105 MB) copied, 5.57817 s, 18.8 MB/s
FSG_NUM_BUFFERS 4
104857600 bytes (105 MB) copied, 5.26839 s, 19.9 MB/s
104857600 bytes (105 MB) copied, 5.2691 s, 19.9 MB/s
104857600 bytes (105 MB) copied, 5.2711 s, 19.9 MB/s
There may not be one optimal number for all boards. This is why
the number is added to Kconfig. If selecting USB_DEBUG this value may be
set by a module parameter as well.
Signed-off-by: Per Forlin <per.forlin(a)linaro.org>
---
Change log.
v2: Update after proofreading comments from Michal Nazarewicz
v3: Clarify the description of this patch based on input from Alan Stern
v4: - Introduce a module_param to set number of pipeline buffers
if USB_DEBUG is set. In order to add this support fsg_common is
allocated at runtime. The fsg_buffhd list size is appended to fsg_dev
and fsg_common at runtime allocation.
- The previous acks from Michal and Alan on v3 are not applicable
for this version since it's a new implementation.
drivers/usb/gadget/Kconfig | 16 ++++++++++++++++
drivers/usb/gadget/f_mass_storage.c | 10 +++++++---
drivers/usb/gadget/file_storage.c | 10 ++++++++--
drivers/usb/gadget/mass_storage.c | 16 +++++++++-------
drivers/usb/gadget/storage_common.c | 20 ++++++++++++++++++--
5 files changed, 58 insertions(+), 14 deletions(-)
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 44b6b40..37ec2ce 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -96,6 +96,22 @@ config USB_GADGET_VBUS_DRAW
This value will be used except for system-specific gadget
drivers that have more specific information.
+config USB_GADGET_STORAGE_NUM_BUFFERS
+ int "Number of storage pipeline buffers"
+ range 2 4
+ default 2
+ help
+ Usually 2 buffers are enough to establish a good buffering
+ pipeline. The number may be increased in order to compensate
+ for a bursty VFS behaviour. For instance there may be cpu wake up
+ latencies that makes the VFS to appear bursty in a system with
+ an cpu on-demand governor. Especially if DMA is doing IO to
+ offload the CPU. In this case the CPU will go into power
+ save often and spin up occasionally to move data within VFS.
+ If selecting USB_DEBUG this value may be set by a module
+ parameter as well.
+ If unsure, say 2.
+
#
# USB Peripheral Controller Support
#
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 5b93395..3e546d9 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -363,7 +363,6 @@ struct fsg_common {
struct fsg_buffhd *next_buffhd_to_fill;
struct fsg_buffhd *next_buffhd_to_drain;
- struct fsg_buffhd buffhds[FSG_NUM_BUFFERS];
int cmnd_size;
u8 cmnd[MAX_COMMAND_SIZE];
@@ -407,6 +406,8 @@ struct fsg_common {
char inquiry_string[8 + 16 + 4 + 1];
struct kref ref;
+ /* Must be the last entry */
+ struct fsg_buffhd buffhds[0];
};
struct fsg_config {
@@ -2728,12 +2729,15 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
/* Allocate? */
if (!common) {
- common = kzalloc(sizeof *common, GFP_KERNEL);
+ common = kzalloc(sizeof(struct fsg_common) +
+ sizeof(struct fsg_buffhd) * FSG_NUM_BUFFERS,
+ GFP_KERNEL);
if (!common)
return ERR_PTR(-ENOMEM);
common->free_storage_on_release = 1;
} else {
- memset(common, 0, sizeof *common);
+ memset(common, 0, sizeof(struct fsg_common) +
+ sizeof(struct fsg_buffhd) * FSG_NUM_BUFFERS);
common->free_storage_on_release = 0;
}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 639e14a..21d366d 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -461,7 +461,6 @@ struct fsg_dev {
struct fsg_buffhd *next_buffhd_to_fill;
struct fsg_buffhd *next_buffhd_to_drain;
- struct fsg_buffhd buffhds[FSG_NUM_BUFFERS];
int thread_wakeup_needed;
struct completion thread_notifier;
@@ -488,6 +487,8 @@ struct fsg_dev {
unsigned int nluns;
struct fsg_lun *luns;
struct fsg_lun *curlun;
+ /* Must be the last entry */
+ struct fsg_buffhd buffhds[0];
};
typedef void (*fsg_routine_t)(struct fsg_dev *);
@@ -3587,7 +3588,9 @@ static int __init fsg_alloc(void)
{
struct fsg_dev *fsg;
- fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
+ fsg = kzalloc(sizeof(struct fsg_dev) +
+ sizeof(struct fsg_buffhd) * FSG_NUM_BUFFERS, GFP_KERNEL);
+
if (!fsg)
return -ENOMEM;
spin_lock_init(&fsg->lock);
@@ -3605,6 +3608,9 @@ static int __init fsg_init(void)
int rc;
struct fsg_dev *fsg;
+ if (!FSG_NUM_BUFFERS_IS_VALID(FSG_NUM_BUFFERS))
+ return -EINVAL;
+
if ((rc = fsg_alloc()) != 0)
return rc;
fsg = the_fsg;
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c
index d3eb274..67c58d0 100644
--- a/drivers/usb/gadget/mass_storage.c
+++ b/drivers/usb/gadget/mass_storage.c
@@ -116,9 +116,8 @@ static int __init msg_do_config(struct usb_configuration *c)
static const struct fsg_operations ops = {
.thread_exits = msg_thread_exits,
};
- static struct fsg_common common;
+ struct fsg_common *common = NULL;
- struct fsg_common *retp;
struct fsg_config config;
int ret;
@@ -130,12 +129,12 @@ static int __init msg_do_config(struct usb_configuration *c)
fsg_config_from_params(&config, &mod_data);
config.ops = &ops;
- retp = fsg_common_init(&common, c->cdev, &config);
- if (IS_ERR(retp))
- return PTR_ERR(retp);
+ common = fsg_common_init(common, c->cdev, &config);
+ if (IS_ERR(common))
+ return PTR_ERR(common);
- ret = fsg_bind_config(c->cdev, c, &common);
- fsg_common_put(&common);
+ ret = fsg_bind_config(c->cdev, c, common);
+ fsg_common_put(common);
return ret;
}
@@ -179,6 +178,9 @@ MODULE_LICENSE("GPL");
static int __init msg_init(void)
{
+ if (!FSG_NUM_BUFFERS_IS_VALID(FSG_NUM_BUFFERS))
+ return -EINVAL;
+
return usb_composite_probe(&msg_driver, msg_bind);
}
module_init(msg_init);
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index d3dd227..197eace 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -262,8 +262,24 @@ static struct fsg_lun *fsg_lun_from_dev(struct device *dev)
#define EP0_BUFSIZE 256
#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */
-/* Number of buffers we will use. 2 is enough for double-buffering */
-#define FSG_NUM_BUFFERS 2
+#ifdef CONFIG_USB_DEBUG
+
+static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+module_param(fsg_num_buffers, uint, S_IRUGO);
+MODULE_PARM_DESC(fsg_num_buffers, "Number of pipeline buffers");
+#define FSG_NUM_BUFFERS fsg_num_buffers
+
+#else
+
+/*
+ * Number of buffers we will use.
+ * 2 is usually enough for good buffering pipeline
+ */
+#define FSG_NUM_BUFFERS CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
+
+#endif /* CONFIG_USB_DEBUG */
+
+#define FSG_NUM_BUFFERS_IS_VALID(num) (num >= 2 && num <= 4 ? true : false)
/* Default size of buffer length. */
#define FSG_BUFLEN ((u32)16384)
--
1.7.4.1
From: Linus Walleij <linus.walleij(a)linaro.org>
This creates a subsystem for handling of pinmux devices. These are
devices that enable and disable groups of pins on primarily PGA and
BGA type of chip packages and common in embedded systems.
This is being done to depopulate the arch/arm/* directory of such
custom drivers and try to abstract the infrastructure they all
need. See the Documentation/pinmux.txt file that is part of this
patch for more details.
Cc: Grant Likely <grant.likely(a)secretlab.ca>
Cc: Stephen Warren <swarren(a)nvidia.com>
Cc: Joe Perches <joe(a)perches.com>
Cc: Russell King <linux(a)arm.linux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij(a)linaro.org>
---
ChangeLog v2->v3:
- Renamed subsystem folder to "pinctrl" since we will likely
want to keep other pin control such as biasing in this
subsystem too, so let us keep to something generic even though
we're mainly doing pinmux now.
- As a consequence, register pins as an abstract entity separate
from the pinmux. The muxing functions will claim pins out of the
pin pool and make sure they do not collide. Pins can now be
named by the pinctrl core.
- Converted the pin lookup from a static array into a radix tree,
I agreed with Grant Likely to try to avoid any static allocation
(which is crap for device tree stuff) so I just rewrote this
to be dynamic, just like irq number descriptors. The
platform-wide definition of number of pins goes away - this is
now just the sum total of the pins registered to the subsystem.
- Make sure mappings with only a function name and no device
works properly.
---
Documentation/ABI/testing/sysfs-class-pinmux | 11 +
Documentation/pinctrl.txt | 397 ++++++++++
MAINTAINERS | 5 +
drivers/Kconfig | 4 +
drivers/Makefile | 2 +
drivers/pinctrl/Kconfig | 29 +
drivers/pinctrl/Makefile | 6 +
drivers/pinctrl/core.c | 1028 ++++++++++++++++++++++++++
include/linux/pinctrl/machine.h | 57 ++
include/linux/pinctrl/pinmux.h | 180 +++++
10 files changed, 1719 insertions(+), 0 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-class-pinmux
create mode 100644 Documentation/pinctrl.txt
create mode 100644 drivers/pinctrl/Kconfig
create mode 100644 drivers/pinctrl/Makefile
create mode 100644 drivers/pinctrl/core.c
create mode 100644 include/linux/pinctrl/machine.h
create mode 100644 include/linux/pinctrl/pinmux.h
diff --git a/Documentation/ABI/testing/sysfs-class-pinmux b/Documentation/ABI/testing/sysfs-class-pinmux
new file mode 100644
index 0000000..c2ea843
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-pinmux
@@ -0,0 +1,11 @@
+What: /sys/class/pinmux/.../name
+Date: May 2011
+KernelVersion: 3.1
+Contact: Linus Walleij <linus.walleij(a)linaro.org>
+Description:
+ Each pinmux directory will contain a field called
+ name. This holds a string identifying the pinmux for
+ display purposes.
+
+ NOTE: this will be empty if no suitable name is provided
+ by platform or pinmux drivers.
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
new file mode 100644
index 0000000..c4b6f48
--- /dev/null
+++ b/Documentation/pinctrl.txt
@@ -0,0 +1,397 @@
+PINCTRL (PIN CONTROL) subsystem
+This document outlines the pin control subsystem in Linux
+
+This subsystem deals with:
+
+- Multiplexing of pins, pads, fingers (etc) see below for details
+
+The intention is to also deal with:
+
+- Software-controlled biasing and driving mode specific pins, such as
+ pull-up/down, open drain etc, load capacitance configuration when controlled
+ by software, etc.
+
+
+Top-level interface
+===================
+
+Definition of PIN:
+
+- PINS are equal to pads or fingers or whatever packaging output you want to
+ mux and these are denoted by unsigned integers in the range 0..MAX_INT. Every
+ pin on your system (or atleast every pin that can be muxed) should have a
+ unique number. The numberspace can span several chips if you have more chips
+ on your system that can be subject to muxing.
+
+All pins, pads, fingers, balls or other controllable units on the system shall
+be given a unique number in the global number space beginning on zero.
+
+All pins on the system need to be registered, typically by board code or a
+device tree. Board/machine code will #include <linux/pinctrl/machine.h>
+and use one of:
+
+ pinctrl_register_pins_sparse();
+ pinctrl_register_pins_dense();
+
+To register all the pins on the system. Both are supplied with a list of
+descriptor items, the difference is that the _dense version will also
+register anonymous pins for each "hole" in the pin map, from zero to the
+supplied extra argument giving the number of pins.
+
+Here is an example of a PGA (Pin Grid Array) chip seen from underneath:
+
+ A B C D E F G H
+
+ 8 o o o o o o o o
+
+ 7 o o o o o o o o
+
+ 6 o o o o o o o o
+
+ 5 o o o o o o o o
+
+ 4 o o o o o o o o
+
+ 3 o o o o o o o o
+
+ 2 o o o o o o o o
+
+ 1 o o o o o o o o
+
+To register and name all the pins on this package we can do this in a board
+file:
+
+#include <linux/pinctrl/machine.h>
+
+const struct pinctrl_pin_desc __initdata my_pins[] = {
+ PINCTRL_PIN(0, "A1"),
+ PINCTRL_PIN(1, "A2"),
+ PINCTRL_PIN(2, "A3"),
+ ...
+ PINCTRL_PIN(61, "H6"),
+ PINCTRL_PIN(62, "H7"),
+ PINCTRL_PIN(63, "H8"),
+};
+
+int __init register_pins(void)
+{
+ pinctrl_register_pins_dense(&my_pins, ARRAY_SIZE(my_pins), 64);
+}
+
+Pins usually have fancier names than this. You can find these in the dataheet
+for your chip. Notice that the core machine.h file provides a fancy macro
+called PINCTRL_PIN() to create the struct entries.
+
+
+PINMUX interfaces
+=================
+
+These calls use the pinmux_* naming prefix. No other calls should use that
+prefix.
+
+
+What is pinmuxing?
+==================
+
+Pinmux, also known as padmux, ballmux, alternate functions or mission modes
+is a way for chip vendors producing some kind of electrical packages to use
+a certain physical bin (ball, pad, finger, etc) for multiple mutually exclusive
+functions, depending on the application. By "application" in this context
+we usually mean a way of soldering or wiring the package into an electronic
+system, even though the framework makes it possible to handle also change the
+function at runtime.
+
+Here is an example of a PGA (Pin Grid Array) chip seen from underneath:
+
+ A B C D E F G H
+ +---+
+ 8 | o | o o o o o o o
+ | |
+ 7 | o | o o o o o o o
+ | |
+ 6 | o | o o o o o o o
+ +---+---+
+ 5 | o | o | o o o o o o
+ +---+---+ +---+
+ 4 o o o o o o | o | o
+ | |
+ 3 o o o o o o | o | o
+ | |
+ 2 o o o o o o | o | o
+ | |
+ 1 o o o o o o | o | o
+ +---+
+
+This is not tetris. The game to think of is chess. Not all PGA/BGA packages
+are chessboard-like, big ones have "holes" in some arrangement according to
+different design patterns, but we're using this as a simple example. Of the
+pins you see some will be taken by things like a few VCC and GND to feed power
+to the chip, and quite a few will be taken by large ports like an external
+memory interface. The remaining pins will often be subject to pin multiplexing.
+
+The example 8x8 PGA package above will have pin numbers 0 thru 63 assigned to
+its physical pins. It will name the pins { A1, A2, A3 ... H6, H7, H8 } using
+pinctrl_register_pins_[sparse|dense]() and a suitable data set as shown
+earlier.
+
+In this 8x8 BGA package the pins { A8, A7, A6, A5 } can be used as an SPI port
+(these are four pins: CLK, RXD, TXD, FRM). In that case, pin B5 can be used as
+some general-purpose GPIO pin. However, in another setting, pins { A5, B5 } can
+be used as an I2C port (these are just two pins: SCL, SDA). Needless to say,
+we cannot use the SPI port and I2C port at the same time. However in the inside
+of the package the silicon performing the SPI logic can alternatively be routed
+out on pins { G4, G3, G2, G1 }.
+
+This way the silicon blocks present inside the chip can be multiplexed "muxed"
+out on different pin ranges. Often contemporary SoC (systems on chip) will
+contain several I2C, SPI, SDIO/MMC, etc silicon blocks that can be routed to
+different pins by pinmux settings.
+
+Since general-purpose I/O pins (GPIO) are typically always in shortage, it is
+common to be able to use almost any pin as a GPIO pin if it is not currently
+in use by some other I/O port.
+
+
+Pinmux conventions
+==================
+
+The purpose of the pinmux subsystem is to abstract and provide pinmux settings
+to the devices you choose to instantiate in your machine configuration. It is
+inspired by the clk, GPIO and regulator subsystems, so devices will request
+their mux setting, but it's also possible to request a single pin for e.g.
+GPIO.
+
+Definitions:
+
+- FUNCTIONS can be switched in and out by a driver residing with the pinmux
+ subsystem in the drivers/pinmux/* directory of the kernel. The pinmux driver
+ knows the possible functions. In the example above you can identify three
+ pinmux functions, two for spi and one for i2c.
+
+- FUNCTIONS are assumed to be enumerable from zero in a one-dimensional array.
+ In this case the array could be something like: { spi0-0, spi0-1, i2c0-0 }
+ for the three available settings. The knowledge of this one-dimensional array
+ and it's machine-specific particulars is kept inside the pinmux driver,
+ from the outside only these enumerators are known, and the driver core
+ can request the name or the list of pins belonging to a certain enumerator.
+
+- FUNCTIONS are MAPPED to a certain device by the board file, device tree or
+ similar machine setup configuration mechanism, similar to how regulators are
+ connected to devices, usually by name. In the example case we can define
+ that this particular machine shall use device spi0 with pinmux setting
+ spi0-1 and i2c0 on i2c0-1, something like the two-tuple:
+ { {spi0, spi0-1}, {i2c0, i2c0-1} }
+
+- FUNCTIONS are provided on a first-come first-serve basis, so if some other
+ device mux setting or GPIO pin request has already taken your physical pin,
+ you will be denied the use of it. To get (activate) a new setting, the old
+ one has to be put (deactivated) first.
+
+Sometimes the documentation and hardware registers will be oriented around
+pads (or "fingers") rather than pins - these are the soldering surfaces on the
+silicon inside the package, and may or may not match the actual number of
+pins/balls underneath the capsule. Pick some enumeration that makes sense to
+you. Define enumerators only for the pins you can control if that makes sense.
+
+
+Pinmux drivers
+==============
+
+The driver will for all calls be provided an offset pin number into its own
+pin range. If you have 2 chips with 8x8 pins, the first chips pins will have
+numbers 0 thru 63 and the second one pins 64 thru 127, but the driver for the
+second chip will be passed numbers in the range 0 thru 63 anyway, base offset
+subtracted.
+
+Pinmux drivers are required to supply a few callback functions, some are
+optional. Usually the enable() and disable() functions are implemented,
+writing values into some certain registers to activate a certain mux setting
+for a certain pin.
+
+A simple driver for the above example will work by setting bits 0, 1 or 2
+into some register mamed MUX, so it enumerates its available settings and
+their pin assignments, and expose them like this:
+
+#include <linux/pinctrl/pinmux.h>
+
+struct foo_pmx_func {
+ char *name;
+ const unsigned int *pins;
+ const unsigned num_pins;
+};
+
+static unsigned int spi0_0_pins[] = { 0, 8, 16, 24 };
+static unsigned int i2c0_pins[] = { 24, 25 };
+static unsigned int spi0_1_pins[] = { 38, 46, 54, 62 };
+
+static struct foo_pmx_func myfuncs[] = {
+ {
+ .name = "spi0-0",
+ .pins = spi0_0_pins,
+ .num_pins = ARRAY_SIZE(spi0_1_pins),
+ },
+ {
+ .name = "i2c0",
+ .pins = i2c0_pins,
+ .num_pins = ARRAY_SIZE(i2c0_pins),
+ },
+ {
+ .name = "spi0-1",
+ .pins = spi0_1_pins,
+ .num_pins = ARRAY_SIZE(spi0_1_pins),
+ },
+};
+
+int foo_list(struct pinmux_dev *pmxdev, unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(myfuncs))
+ return -EINVAL;
+ return 0;
+}
+
+const char *foo_get_fname(struct pinmux_dev *pmxdev, unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(myfuncs))
+ return NULL;
+ return myfuncs[selector].name;
+}
+
+static int foo_get_pins(struct pinmux_dev *pmxdev, unsigned selector,
+ unsigned ** const pins, unsigned * const num_pins)
+{
+ if (selector >= ARRAY_SIZE(myfuncs))
+ return -EINVAL;
+ *pins = myfuncs[selector].pins;
+ *num_pins = myfuncs[selector].num_pins;
+ return 0;
+}
+
+
+int foo_enable(struct pinmux_dev *pmxdev, unsigned selector)
+{
+ if (selector < ARRAY_SIZE(myfuncs))
+ write((read(MUX)|(1<<selector)), MUX)
+ return 0;
+ }
+ return -EINVAL;
+}
+
+int foo_disable(struct pinmux_dev *pmxdev, unsigned selector)
+{
+ if (selector < ARRAY_SIZE(myfuncs))
+ write((read(MUX) & ~(1<<selector)), MUX)
+ return 0;
+ }
+ return -EINVAL;
+}
+
+struct pinmux_ops ops = {
+ .list_functions = foo_list,
+ .get_function_name = foo_get_fname,
+ .get_function_pins = foo_get_pins,
+ .enable = foo_enable,
+ .disable = foo_disable,
+};
+
+Now the able reader will say: "wait - the driver needs to make sure it
+can set this and that bit at the same time, because else it will collide
+and wreak havoc in my electronics, and make sure noone else is using the
+other setting that it's incompatible with".
+
+In the example activating muxing 0 and 1 at the same time setting bits
+0 and 1, uses one pin in common so they would collide.
+
+The beauty of the pinmux subsystem is that since it keeps track of all
+pins and who is using them, it will already have denied an impossible
+request like that, so the driver does not need to worry about such
+things - when it gets a selector passed in, the pinmux subsystem makes
+sure no other device or GPIO assignment is already using the selected
+pins.
+
+The above functions are mandatory to implement for a pinmux driver.
+
+The function list could become long, especially if you can convert every
+individual pin into a GPIO pin independent of any other pins, then your
+function array can become 64 entries for each GPIO setting and then the
+device functions. For this reason there is an additional function you
+can implement to enable only GPIO on an individual pin: gpio_enable().
+
+
+Pinmux board/machine configuration
+==================================
+
+Boards and machines define how a certain complete running system is put
+together, including how GPIOs and devices are muxed, how regulators are
+constrained and how the clock tree looks. Of course pinmux settings are also
+part of this.
+
+A pinmux config for a machine looks pretty much like a simple regulator
+configuration, so for the example array above we want to enable i2c and
+spi on the second function mapping:
+
+#include <linux/pinctrl/machine.h>
+
+static struct pinmux_map pmx_mapping[] = {
+ {
+ .function = "spi0-1",
+ .dev_name = "foo-spi.0",
+ },
+ {
+ .function = "i2c0",
+ .dev_name = "foo-i2c.0",
+ },
+};
+
+Since the above construct is pretty common there is a helper macro to make
+it even more compact:
+
+static struct pinmux_map pmx_mapping[] = {
+ PINMUX_MAP("spi0-1", "foo-spi.0"),
+ PINMUX_MAP("i2c0", "foo-i2c.0"),
+};
+
+The dev_name here matches to the unique device name that can be used to look
+up the device struct (just like with clockdev or regulators). The function name
+must match a function provided by the pinmux driver handling this pin range.
+You register this pinmux mapping to the pinmux subsystem by simply:
+
+ ret = pinmux_register_mappings(&pmx_mapping, ARRAY_SIZE(pmx_mapping));
+
+
+Pinmux requests from drivers
+============================
+
+A driver may request a certain mux to be activated, usually just the default
+mux like this:
+
+#include <linux/pinctrl/pinmux.h>
+
+foo_probe()
+{
+ /* Allocate a state holder named "state" etc */
+ struct pinmux pmx;
+
+ pmx = pinmux_get(&device, NULL);
+ if IS_ERR(pmx)
+ return PTR_ERR(pmx);
+ pinmux_enable(pmx);
+
+ state->pmx = pmx;
+}
+
+foo_remove()
+{
+ pinmux_disable(state->pmx);
+ pinmux_put(state->pmx);
+}
+
+If you want a specific mux setting and not just the first one found for this
+device you can specify a specific mux setting, for example in the above example
+the second i2c0 setting: pinmux_get(&device, "spi0-2");
+
+This get/enable/disable/put sequence can just as well be handled by bus drivers
+if you don't want each and every driver to handle it and you know the
+arrangement on your bus.
+
+The pins are allocated for your device when you issue the pinmux_get() call,
+after this you should be able to see this in the debugfs listing of all pins.
diff --git a/MAINTAINERS b/MAINTAINERS
index 29801f7..5caea5a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4933,6 +4933,11 @@ L: linux-mtd(a)lists.infradead.org
S: Maintained
F: drivers/mtd/devices/phram.c
+PINMUX SUBSYSTEM
+M: Linus Walleij <linus.walleij(a)linaro.org>
+S: Maintained
+F: drivers/pinmux/
+
PKTCDVD DRIVER
M: Peter Osterlund <petero2(a)telia.com>
S: Maintained
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 3bb154d..6998d78 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -56,6 +56,10 @@ source "drivers/pps/Kconfig"
source "drivers/ptp/Kconfig"
+# pinctrl before gpio - gpio drivers may need it
+
+source "drivers/pinctrl/Kconfig"
+
source "drivers/gpio/Kconfig"
source "drivers/w1/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 09f3232..a590a01 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -5,6 +5,8 @@
# Rewritten to use lists instead of if-statements.
#
+# GPIO must come after pinctrl as gpios may need to mux pins etc
+obj-y += pinctrl/
obj-y += gpio/
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_PARISC) += parisc/
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
new file mode 100644
index 0000000..8050fdf
--- /dev/null
+++ b/drivers/pinctrl/Kconfig
@@ -0,0 +1,29 @@
+#
+# PINCTRL infrastructure and drivers
+#
+
+menuconfig PINCTRL
+ bool "PINCTRL Support"
+ depends on SYSFS && EXPERIMENTAL
+ help
+ This enables the PINCTRL subsystem for controlling pins
+ on chip packages, for example multiplexing pins on primarily
+ PGA and BGA packages for systems on chip.
+
+ If unsure, say N.
+
+if PINCTRL
+
+config DEBUG_PINCTRL
+ bool "Debug PINCTRL calls"
+ depends on DEBUG_KERNEL
+ help
+ Say Y here to add some extra checks and diagnostics to PINCTRL calls.
+
+config PINMUX_U300
+ bool "U300 pinmux driver"
+ depends on ARCH_U300
+ help
+ Say Y here to enable the U300 pinmux driver
+
+endif
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
new file mode 100644
index 0000000..44d8933
--- /dev/null
+++ b/drivers/pinctrl/Makefile
@@ -0,0 +1,6 @@
+# generic pinmux support
+
+ccflags-$(CONFIG_DEBUG_PINMUX) += -DDEBUG
+
+obj-$(CONFIG_PINCTRL) += core.o
+obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
new file mode 100644
index 0000000..8fd1437
--- /dev/null
+++ b/drivers/pinctrl/core.c
@@ -0,0 +1,1028 @@
+/*
+ * Core driver for the pinmux subsystem
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ * Based on bits of regulator core, gpio core and clk core
+ *
+ * Author: Linus Walleij <linus.walleij(a)linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#define pr_fmt(fmt) "pinctrl core: " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/radix-tree.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/sysfs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinmux.h>
+
+/* Global list of pinmuxes */
+static DEFINE_MUTEX(pinmux_list_mutex);
+static LIST_HEAD(pinmux_list);
+
+/* Global list of pinmux devices */
+static DEFINE_MUTEX(pinmuxdev_list_mutex);
+static LIST_HEAD(pinmuxdev_list);
+
+/**
+ * struct pin_desc - pin descriptor for each physical pin in the arch
+ * @pmxdev: corresponding pinmux device
+ * @requested: whether the pin is already requested by pinmux or not
+ * @name: a name for the pin, e.g. the name of the pin/pad/finger on a
+ * datasheet or such
+ * @function: a named muxing function for the pin that will be passed to
+ * subdrivers and shown in debugfs etc
+ */
+struct pin_desc {
+ struct pinmux_dev *pmxdev;
+ bool requested;
+ char name[16];
+ char function[16];
+};
+/* Global lookup of per-pin descriptors, one for each physical pin */
+static DEFINE_SPINLOCK(pin_desc_tree_lock);
+static RADIX_TREE(pin_desc_tree, GFP_KERNEL);
+static unsigned int num_pins = 0;
+
+/**
+ * struct pinmux - per-device pinmux state holder
+ * @node: global list node - only for internal use
+ * @dev: the device using this pinmux
+ * @pmxdev: the pinmux device controlling this pinmux
+ * @map: corresponding pinmux map active for this pinmux setting
+ * @usecount: the number of active users of this mux setting, used to keep
+ * track of nested use cases
+ * @pins: an array of discrete physical pins used in this mapping, taken
+ * from the global pin enumeration space (copied from pinmux map)
+ * @num_pins: the number of pins in this mapping array, i.e. the number of
+ * elements in .pins so we can iterate over that array (copied from
+ * pinmux map)
+ * @pmxdev: pinmux device handling this pinmux
+ * @pmxdev_selector: the selector for the pinmux device handling this pinmux
+ * @mutex: a lock for the pinmux state holder
+ */
+struct pinmux {
+ struct list_head node;
+ struct device *dev;
+ struct pinmux_map const *map;
+ unsigned usecount;
+ struct pinmux_dev *pmxdev;
+ unsigned pmxdev_selector;
+ struct mutex mutex;
+};
+
+int pin_is_valid(int pin)
+{
+ return pin >= 0 && pin < num_pins;
+}
+EXPORT_SYMBOL_GPL(pin_is_valid);
+
+static ssize_t pinmux_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pinmux_dev *pmxdev = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", pmxdev_get_name(pmxdev));
+}
+
+static struct device_attribute pinmux_dev_attrs[] = {
+ __ATTR(name, 0444, pinmux_name_show, NULL),
+ __ATTR_NULL,
+};
+
+static void pinmux_dev_release(struct device *dev)
+{
+ struct pinmux_dev *pmxdev = dev_get_drvdata(dev);
+ kfree(pmxdev);
+}
+
+static struct class pinmux_class = {
+ .name = "pinmux",
+ .dev_release = pinmux_dev_release,
+ .dev_attrs = pinmux_dev_attrs,
+};
+
+/* Deletes a range of pin descriptors */
+static void pinctrl_free_pindescs(struct pinctrl_pin_desc const *pins,
+ unsigned num_pins)
+{
+ int i;
+
+ for (i = 0; i < num_pins; i++) {
+ struct pin_desc *pindesc;
+
+ spin_lock(&pin_desc_tree_lock);
+ pindesc = radix_tree_lookup(&pin_desc_tree, pins[i].number);
+ if (pindesc != NULL) {
+ radix_tree_delete(&pin_desc_tree, pins[i].number);
+ num_pins --;
+ }
+ spin_unlock(&pin_desc_tree_lock);
+ kfree(pindesc);
+ }
+}
+
+static int pinctrl_register_one_pin(unsigned number, const char *name)
+{
+ struct pin_desc *pindesc;
+
+ spin_lock(&pin_desc_tree_lock);
+ pindesc = radix_tree_lookup(&pin_desc_tree, number);
+ spin_unlock(&pin_desc_tree_lock);
+
+ if (pindesc != NULL) {
+ pr_err("pin %d already registered\n", number);
+ return -EINVAL;
+ }
+
+ pindesc = kzalloc(sizeof(*pindesc), GFP_KERNEL);
+ if (pindesc == NULL)
+ return -ENOMEM;
+
+ /* Copy optional basic pin info */
+ if (name) {
+ strncpy(pindesc->name, name, 16);
+ pindesc->name[15] = '\0';
+ }
+
+ spin_lock(&pin_desc_tree_lock);
+ radix_tree_insert(&pin_desc_tree, number, pindesc);
+ num_pins ++;
+ spin_unlock(&pin_desc_tree_lock);
+ return 0;
+}
+
+/* Passing in 0 num_pins means "sparse" */
+static int pinctrl_register_pins(struct pinctrl_pin_desc const *pins,
+ unsigned num_descs, unsigned num_pins)
+{
+ unsigned i;
+ int ret = 0;
+
+ for (i = 0; i < num_descs; i++) {
+ ret = pinctrl_register_one_pin(pins[i].number, pins[i].name);
+ if (ret)
+ return ret;
+ }
+
+ if (num_pins == 0)
+ return 0;
+
+ /*
+ * If we are registerering dense pinlists, fill in all holes with
+ * anonymous pins.
+ */
+ for (i = 0; i < num_pins; i++) {
+ char pinname[16];
+ struct pin_desc *pindesc;
+
+ spin_lock(&pin_desc_tree_lock);
+ pindesc = radix_tree_lookup(&pin_desc_tree, i);
+ spin_unlock(&pin_desc_tree_lock);
+ /* Already registered this one, take next */
+ if (pindesc)
+ continue;
+
+ snprintf(pinname, 15, "anonymous %u", i);
+ pinname[15] = '\0';
+
+ ret = pinctrl_register_one_pin(i, pinname);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * pinctrl_register_pins_sparse() - register a range of pins for a
+ * board/machine with potential holes in the pin map. The pins in
+ * the holes will not be usable.
+ * @pins: a range of pins to register
+ * @num_descs: the number of pins descriptors passed in through the previous
+ * pointer
+ */
+int pinctrl_register_pins_sparse(struct pinctrl_pin_desc const *pins,
+ unsigned num_descs)
+{
+ int ret;
+
+ ret = pinctrl_register_pins(pins, num_descs, 0);
+ if (ret)
+ pinctrl_free_pindescs(pins, num_descs);
+ return ret;
+
+}
+EXPORT_SYMBOL_GPL(pinctrl_register_pins);
+
+/**
+ * pinctrl_register_pins_dense() - register a range of pins for a
+ * board/machine, if there are holes in the pin map, they will be
+ * allocated by anonymous pins.
+ * @pins: a range of pins to register
+ * @num_descs: the number of pins descriptors passed in through the previous
+ * pointer
+ * @num_pins: the total number of pins including holes in the pin map and
+ * any "air" at the end of the map, all pins from 0 to this number
+ * will be allocated, the ones that does not have descriptors passed
+ * in will be marked "anonymous"
+ */
+int pinctrl_register_pins_dense(struct pinctrl_pin_desc const *pins,
+ unsigned num_descs, unsigned num_pins)
+{
+ int ret;
+ unsigned i;
+
+ ret = pinctrl_register_pins(pins, num_descs, num_pins);
+ if (ret) {
+ for (i = 0; i < num_pins; i++) {
+ struct pin_desc *pindesc;
+
+ spin_lock(&pin_desc_tree_lock);
+ pindesc = radix_tree_lookup(&pin_desc_tree, i);
+ if (pindesc != NULL) {
+ radix_tree_delete(&pin_desc_tree, i);
+ num_pins --;
+ }
+ spin_unlock(&pin_desc_tree_lock);
+ kfree(pindesc);
+ }
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pinctrl_register_pins_sparse);
+
+/**
+ * pin_request() - request a single pin to be muxed in, typically for GPIO
+ * @pin: the pin number in the global pin space
+ * @function: a functional name to give to this pin, passed to the driver
+ * so it knows what function to mux in, e.g. the string "gpioNN"
+ * means that you want to mux in the pin for use as GPIO number NN
+ * @gpio: if this request concerns a single GPIO pin
+ */
+static int pin_request(int pin, const char *function, bool gpio)
+{
+ struct pin_desc *desc;
+ struct pinmux_dev *pmxdev;
+ const struct pinmux_ops *ops;
+ int status = -EINVAL;
+ unsigned long flags;
+
+ pr_debug("request pin %d for %s\n", pin, function);
+ if (!pin_is_valid(pin)) {
+ pr_err("pin is invalid\n");
+ return -EINVAL;
+ }
+
+ if (!function) {
+ pr_err("no function name given\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&pin_desc_tree_lock, flags);
+ desc = radix_tree_lookup(&pin_desc_tree, pin);
+ if (desc == NULL) {
+ pr_err("pin is not registered so it cannot be requested\n");
+ goto out;
+ }
+ pmxdev = desc->pmxdev;
+ if (desc->requested) {
+ pr_err("pin already requested\n");
+ goto out;
+ }
+ if (!pmxdev) {
+ pr_warn("no pinmux device is handling pin %d\n", pin);
+ goto out;
+ }
+ ops = pmxdev->desc->ops;
+
+ /* Let each pin increase references to this module */
+ if (!try_module_get(pmxdev->owner)) {
+ pr_err("could not increase module refcount for pin %d\n", pin);
+ status = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * If there is no kind of request function for the pin we just assume
+ * we got it by default and proceed.
+ */
+ if (gpio && ops->gpio_request_enable)
+ /* This requests and enables a single GPIO pin */
+ status = ops->gpio_request_enable(pmxdev,
+ pin - pmxdev->desc->base);
+ else if (ops->request)
+ status = ops->request(pmxdev,
+ pin - pmxdev->desc->base);
+ else
+ status = 0;
+
+ if (status) {
+ pr_err("->request on device %s failed "
+ "for pin %d (offset %d)\n",
+ pmxdev->desc->name, pin,
+ pin - pmxdev->desc->base);
+ goto out;
+ }
+
+ desc->requested = true;
+ strncpy(desc->function, function, 16);
+ desc->function[15] = '\0';
+
+out:
+ spin_unlock_irqrestore(&pin_desc_tree_lock, flags);
+ if (status)
+ pr_err("pin-%d (%s) status %d\n",
+ pin, function ? : "?", status);
+
+ return status;
+}
+
+/**
+ * pin_free() - release a single muxed in pin so something else can be muxed in
+ * instead
+ * @pin: the pin to free
+ */
+static void pin_free(int pin)
+{
+ struct pin_desc *desc;
+ struct pinmux_dev *pmxdev;
+ unsigned long flags;
+
+ if (!pin_is_valid(pin))
+ return;
+
+ spin_lock_irqsave(&pin_desc_tree_lock, flags);
+ desc = radix_tree_lookup(&pin_desc_tree, pin);
+ if (desc == NULL) {
+ pr_err("pin is not registered so it cannot be freed\n");
+ goto out;
+ }
+ pmxdev = desc->pmxdev;
+ if (pmxdev) {
+ const struct pinmux_ops *ops = pmxdev->desc->ops;
+
+ if (ops->free)
+ ops->free(pmxdev, pin - pmxdev->desc->base);
+ }
+ desc->requested = false;
+ desc->function[0] = '\0';
+ module_put(pmxdev->owner);
+out:
+ spin_unlock_irqrestore(&pin_desc_tree_lock, flags);
+}
+
+/**
+ * pinmux_request_gpio() - request a single pin to be muxed in to be used
+ * as a GPIO pin
+ * @pin: the pin to mux in as GPIO
+ * @gpio: the corresponding GPIO pin number
+ */
+int pinmux_request_gpio(int pin, unsigned gpio)
+{
+ char gpiostr[16];
+
+ snprintf(gpiostr, 15, "gpio%d", gpio);
+ return pin_request(pin, gpiostr, true);
+}
+EXPORT_SYMBOL_GPL(pinmux_request_gpio);
+
+/**
+ * pinmux_free_gpio() - free a single pin, currently muxed in to be used
+ * as a GPIO pin
+ * @pin: the pin to mux out from GPIO
+ */
+void pinmux_free_gpio(int pin)
+{
+ return pin_free(pin);
+}
+EXPORT_SYMBOL_GPL(pinmux_free_gpio);
+
+int pinmux_register_mappings(struct pinmux_map const *maps, unsigned num_maps)
+{
+ int ret = 0;
+ int i;
+
+ pr_debug("add %d functions\n", num_maps);
+ for (i = 0; i < num_maps; i++) {
+ struct pinmux *pmx;
+
+ /* Sanity check the mapping */
+ if (!maps[i].function) {
+ pr_err("failed to register map %d - no function ID given\n", i);
+ ret = -EINVAL;
+ goto out;
+ }
+ if (!maps[i].dev && !maps[i].dev_name) {
+ pr_err("failed to register map %d - no device or device name given\n", i);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /*
+ * create the state cookie holder struct pinmux for each
+ * mapping, this is what consumers will get when requesting
+ * a pinmux handle with pinmux_get()
+ */
+ pmx = kzalloc(sizeof(struct pinmux), GFP_KERNEL);
+ if (pmx == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ mutex_init(&pmx->mutex);
+ pmx->map = &maps[i];
+
+ /* Add the pinmux */
+ mutex_lock(&pinmux_list_mutex);
+ list_add(&pmx->node, &pinmux_list);
+ mutex_unlock(&pinmux_list_mutex);
+ pr_debug("add function %s\n", maps[i].function);
+ }
+
+out:
+ return ret;
+}
+
+/**
+ * acquire_pins() - acquire all the pins for a certain funcion on a certain
+ * pinmux device
+ * @pmxdev: the device to take the function on
+ * @selector: the selector to acquire the pins for
+ */
+int acquire_pins(struct pinmux_dev *pmxdev, unsigned selector)
+{
+ const struct pinmux_ops *ops = pmxdev->desc->ops;
+ unsigned *pins;
+ unsigned num_pins;
+ const char *func = ops->get_function_name(pmxdev, selector);
+ int ret;
+ int i;
+
+ ret = ops->get_function_pins(pmxdev, selector, &pins, &num_pins);
+ if (ret)
+ return ret;
+
+ /* Try to allocate all pins in this pinmux map, one by one */
+ for (i = 0; i < num_pins; i++) {
+ ret = pin_request(pins[i], func, false);
+ if (ret) {
+ pr_err("could not get pin %d for function %s "
+ "on device %s - conflicting mux mappings?\n",
+ pins[i], func ? : "(undefined)",
+ pmxdev->desc->name);
+ /* On error release all taken pins */
+ i--; /* this pin just failed */
+ for (; i >= 0; i--)
+ pin_free(pins[i]);
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+/**
+ * pinmux_get() - retrieves the pinmux for a certain device
+ * @dev: the device to get the pinmux for
+ * @func: an optional mux name or NULL, the name is only needed
+ * if a single device has multiple pinmux settings (i.e. if the
+ * same device can be muxed out on different sets of pins) or if
+ * you need an anonymous pinmux (not tied to any specific device)
+ */
+struct pinmux *pinmux_get(struct device *dev, const char *func)
+{
+ struct pinmux_map const *map = NULL;
+ struct pinmux_dev *pmxdev = NULL;
+ const char *devname = NULL;
+ struct pinmux *pmx;
+ bool found = false;
+ int ret = -ENODEV;
+
+ /* We must have dev or ID or both */
+ if (!dev && !func)
+ return ERR_PTR(-EINVAL);
+
+ mutex_lock(&pinmux_list_mutex);
+
+ if (dev)
+ devname = dev_name(dev);
+
+ /* Locate the pinmux map */
+ list_for_each_entry(pmx, &pinmux_list, node) {
+ map = pmx->map;
+
+ /* If an function is given, it MUST match */
+ if ((func != NULL) && strcmp(map->function, func))
+ continue;
+
+ /*
+ * This is for the case where no device name is given, we
+ * already know that the function name matches from above
+ * code.
+ */
+ if (!map->dev_name && (func != NULL)) {
+ found = true;
+ break;
+ }
+
+ /* If the mapping has a device set up it must match */
+ if (map->dev_name &&
+ (!devname || !strcmp(map->dev_name, devname))) {
+ /* MATCH! */
+ found = true;
+ break;
+ }
+ }
+
+ mutex_unlock(&pinmux_list_mutex);
+
+ if (!found) {
+ pr_err("could not find mux map for device %s, ID %s\n",
+ devname ? : "(anonymous)", func ? : "(undefined)");
+ goto out;
+ }
+
+ /* Make sure that noone else is using this function mapping */
+ mutex_lock(&pmx->mutex);
+ if (pmx->dev) {
+ if (pmx->dev != dev) {
+ mutex_unlock(&pmx->mutex);
+ pr_err("mapping already in use device %s, ID %s\n",
+ devname ? : "(anonymous)", func ? : "(undefined)");
+ goto out;
+ } else {
+ /* We already fetched this and requested pins */
+ mutex_unlock(&pmx->mutex);
+ ret = 0;
+ goto out;
+ }
+ }
+ mutex_unlock(&pmx->mutex);
+
+
+ /*
+ * Iterate over the drivers so see which ones that may handle this
+ * specific muxing. NOTE: there can be only one as of now.
+ */
+ list_for_each_entry(pmxdev, &pinmuxdev_list, node) {
+ const struct pinmux_ops *ops = pmxdev->desc->ops;
+ unsigned selector = 0;
+
+ /* See if this pmxdev has this function */
+ while (ops->list_functions(pmxdev, selector) >= 0) {
+ const char *fname = ops->get_function_name(pmxdev,
+ selector);
+
+ if (!strcmp(map->function, fname)) {
+ ret = acquire_pins(pmxdev, selector);
+ if (ret)
+ goto out;
+ /* Found it! */
+ mutex_lock(&pmx->mutex);
+ pmx->dev = dev;
+ pmx->pmxdev = pmxdev;
+ pmx->pmxdev_selector = selector;
+ mutex_unlock(&pmx->mutex);
+ ret = 0;
+ goto out;
+ }
+ selector++;
+ }
+ }
+ /* We couldn't find the driver for this pinmux */
+ ret = -ENODEV;
+
+out:
+ if (ret)
+ pmx = ERR_PTR(ret);
+
+ return pmx;
+}
+EXPORT_SYMBOL_GPL(pinmux_get);
+
+/**
+ * pinmux_put() - release a previously claimed pinmux
+ * @pmx: a pinmux previously claimed by pinmux_get()
+ */
+void pinmux_put(struct pinmux *pmx)
+{
+ if (pmx == NULL)
+ return;
+ mutex_lock(&pmx->mutex);
+ if (pmx->usecount)
+ pr_warn("pinmux: releasing pinmux with active users!\n");
+ pmx->dev = NULL;
+ pmx->pmxdev = NULL;
+ pmx->pmxdev_selector = 0;
+ mutex_unlock(&pmx->mutex);
+}
+EXPORT_SYMBOL_GPL(pinmux_put);
+
+/**
+ * pinmux_enable() - enable a certain pinmux setting
+ * @pmx: the pinmux to enable, previously claimed by pinmux_get()
+ */
+int pinmux_enable(struct pinmux *pmx)
+{
+ int ret = 0;
+
+ if (pmx == NULL)
+ return -EINVAL;
+ mutex_lock(&pmx->mutex);
+ if (pmx->usecount++ == 0) {
+ struct pinmux_dev *pmxdev = pmx->pmxdev;
+ const struct pinmux_ops *ops = pmxdev->desc->ops;
+
+ ret = ops->enable(pmxdev, pmx->pmxdev_selector);
+ if (ret)
+ pmx->usecount--;
+ }
+ mutex_unlock(&pmx->mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pinmux_enable);
+
+/**
+ * pinmux_disable() - disable a certain pinmux setting
+ * @pmx: the pinmux to disable, previously claimed by pinmux_get()
+ */
+void pinmux_disable(struct pinmux *pmx)
+{
+ if (pmx == NULL)
+ return;
+
+ mutex_lock(&pmx->mutex);
+ if (--pmx->usecount == 0) {
+ struct pinmux_dev *pmxdev = pmx->pmxdev;
+ const struct pinmux_ops *ops = pmxdev->desc->ops;
+
+ ops->disable(pmxdev, pmx->pmxdev_selector);
+ }
+ mutex_unlock(&pmx->mutex);
+}
+EXPORT_SYMBOL_GPL(pinmux_disable);
+
+/**
+ * pinmux_config() - configure a certain pinmux setting
+ * @pmx: the pinmux setting to configure
+ * @param: the parameter to configure
+ * @data: extra data to be passed to the configuration, also works as a
+ * pointer to data returned from the function on success
+ */
+int pinmux_config(struct pinmux *pmx, u16 param, unsigned long *data)
+{
+ struct pinmux_dev *pmxdev;
+ const struct pinmux_ops *ops;
+ int ret = 0;
+
+ if (pmx == NULL)
+ return -ENODEV;
+
+ pmxdev = pmx->pmxdev;
+ ops = pmxdev->desc->ops;
+
+ /* This operation is not mandatory to implement */
+ if (ops->config) {
+ mutex_lock(&pmx->mutex);
+ ret = ops->config(pmxdev, pmx->pmxdev_selector, param, data);
+ mutex_unlock(&pmx->mutex);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pinmux_config);
+
+static void pinmux_unclaim_pindescs(int first, int last)
+{
+ int i;
+
+ for (i = first; i < last; i++) {
+ struct pin_desc *pindesc;
+
+ spin_lock(&pin_desc_tree_lock);
+ pindesc = radix_tree_lookup(&pin_desc_tree, i);
+ spin_unlock(&pin_desc_tree_lock);
+ if (pindesc) {
+ /* Mark as unclaimed by drivers or functions */
+ pindesc->pmxdev = NULL;
+ pindesc->function[0] = '\0';
+ }
+ }
+}
+
+/* Helper to claim the individual descs for each pin on a pinmux device */
+static int pinmux_claim_pindescs(struct pinmux_desc *pmxdesc,
+ struct pinmux_dev *pmxdev)
+{
+ int i;
+
+ /* Put self as handler of the indicated pin range */
+ for (i = pmxdesc->base; i < (pmxdesc->base + pmxdesc->npins); i++) {
+ struct pin_desc *pindesc;
+
+ /* Check that none of the pins are already there */
+ spin_lock(&pin_desc_tree_lock);
+ pindesc = radix_tree_lookup(&pin_desc_tree, i);
+ spin_unlock(&pin_desc_tree_lock);
+ if (pindesc == NULL) {
+ dev_err(&pmxdev->dev, "pin %d is not registered, yet "
+ "attempted to add pinmux driver for it\n", i);
+ return -EINVAL;
+ }
+ if (pindesc->pmxdev != NULL) {
+ dev_err(&pmxdev->dev, "pin %d taken by other pinmux "
+ "device\n", i);
+ return -EINVAL;
+ }
+ pindesc->pmxdev = pmxdev;
+ }
+ return 0;
+}
+
+/**
+ * pinmux_register() - register a pinmux device
+ * @pmxdesc: descriptor for this pinmux
+ * @dev: parent device for this pinmux
+ * @driver_data: private pinmux data for this pinmux
+ */
+struct pinmux_dev *pinmux_register(struct pinmux_desc *pmxdesc,
+ struct device *dev, void *driver_data)
+{
+ static atomic_t pinmux_no = ATOMIC_INIT(0);
+ struct pinmux_dev *pmxdev;
+ int ret;
+
+ if (pmxdesc == NULL)
+ return ERR_PTR(-EINVAL);
+ if (pmxdesc->name == NULL || pmxdesc->ops == NULL)
+ return ERR_PTR(-EINVAL);
+ /* These functions are mandatory */
+ if (!pmxdesc->ops->list_functions ||
+ !pmxdesc->ops->get_function_name ||
+ !pmxdesc->ops->enable ||
+ !pmxdesc->ops->disable)
+ return ERR_PTR(-EINVAL);
+
+ pmxdev = kzalloc(sizeof(struct pinmux_dev), GFP_KERNEL);
+ if (pmxdev == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ mutex_lock(&pinmuxdev_list_mutex);
+ pmxdev->owner = pmxdesc->owner;
+ pmxdev->desc = pmxdesc;
+ pmxdev->driver_data = driver_data;
+
+ /* Register device with sysfs */
+ pmxdev->dev.class = &pinmux_class;
+ pmxdev->dev.parent = dev;
+ dev_set_name(&pmxdev->dev, "pinmux.%d",
+ atomic_inc_return(&pinmux_no) - 1);
+ ret = device_register(&pmxdev->dev);
+ if (ret != 0) {
+ put_device(&pmxdev->dev);
+ kfree(pmxdev);
+ goto out_err;
+ }
+ dev_set_drvdata(&pmxdev->dev, pmxdev);
+
+ ret = pinmux_claim_pindescs(pmxdesc, pmxdev);
+ if (ret)
+ goto out_err;
+
+ list_add(&pmxdev->node, &pinmuxdev_list);
+ mutex_unlock(&pinmuxdev_list_mutex);
+ return pmxdev;
+
+out_err:
+ mutex_unlock(&pinmuxdev_list_mutex);
+ put_device(&pmxdev->dev);
+ kfree(pmxdev);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(pinmux_register);
+
+/**
+ * pinmux_unregister() - unregister pinmux
+ * @pmxdev: pinmux to unregister
+ *
+ * Called by pinmux drivers to unregister a pinmux.
+ */
+void pinmux_unregister(struct pinmux_dev *pmxdev)
+{
+ if (pmxdev == NULL)
+ return;
+
+ mutex_lock(&pinmuxdev_list_mutex);
+ list_del(&pmxdev->node);
+ device_unregister(&pmxdev->dev);
+ mutex_unlock(&pinmuxdev_list_mutex);
+ pinmux_unclaim_pindescs(pmxdev->desc->base,
+ pmxdev->desc->base + pmxdev->desc->npins);
+}
+EXPORT_SYMBOL_GPL(pinmux_unregister);
+
+#ifdef CONFIG_DEBUG_FS
+
+static int pins_show(struct seq_file *s, void *what)
+{
+ unsigned pin;
+
+ seq_puts(s, "Pins:\n");
+ spin_lock(&pin_desc_tree_lock);
+ for (pin = 0; pin < num_pins; pin++) {
+ struct pin_desc *desc;
+
+ desc = radix_tree_lookup(&pin_desc_tree, pin);
+
+ seq_printf(s, "pin %d (%s)\n", pin,
+ desc->name ? desc->name : "(unnamed)");
+ }
+ spin_unlock(&pin_desc_tree_lock);
+
+ return 0;
+}
+
+static int pinmux_devices_show(struct seq_file *s, void *what)
+{
+ struct pinmux_dev *pmxdev;
+
+ seq_puts(s, "Available pinmux settings per pinmux device:\n");
+ list_for_each_entry(pmxdev, &pinmuxdev_list, node) {
+ const struct pinmux_ops *ops = pmxdev->desc->ops;
+ unsigned selector = 0;
+
+ seq_printf(s, "Device %s:\n", pmxdev->desc->name);
+ while (ops->list_functions(pmxdev, selector) >= 0) {
+ unsigned *pins;
+ unsigned num_pins;
+ const char *func = ops->get_function_name(pmxdev,
+ selector);
+ int ret;
+ int i;
+
+ ret = ops->get_function_pins(pmxdev, selector,
+ &pins, &num_pins);
+
+ if (ret)
+ seq_printf(s, "%s [ERROR GETTING PINS]\n",
+ func);
+
+ else {
+ seq_printf(s, "function: %s, pins = [ ", func);
+ for (i = 0; i < num_pins; i++)
+ seq_printf(s, "%d ", pins[i]);
+ seq_puts(s, "]\n");
+ }
+
+ selector++;
+
+ }
+ }
+
+ return 0;
+}
+
+static int pinmux_maps_show(struct seq_file *s, void *what)
+{
+ struct pinmux *pmx;
+ const struct pinmux_map *map;
+
+ seq_puts(s, "Pinmux maps:\n");
+ list_for_each_entry(pmx, &pinmux_list, node) {
+ map = pmx->map;
+
+ seq_printf(s, "map: %s -> %s\n", map->function,
+ pmx->dev ? dev_name(pmx->dev) : "(unassigned)");
+ }
+
+ return 0;
+}
+
+static int pinmux_pins_show(struct seq_file *s, void *what)
+{
+ unsigned pin;
+
+ seq_puts(s, "Pinmux settings per pin\n");
+ seq_puts(s, "Format: pin (name): pinmuxfunction pinmuxdriver\n");
+ spin_lock(&pin_desc_tree_lock);
+ for (pin = 0; pin < num_pins; pin++) {
+ struct pin_desc *desc;
+ struct pinmux_dev *pmxdev;
+
+ desc = radix_tree_lookup(&pin_desc_tree, pin);
+ pmxdev = desc->pmxdev;
+
+ seq_printf(s, "pin %d (%s): %s", pin,
+ desc->name ? desc->name : "(unnamed)",
+ desc->requested ? desc->function : "(unclaimed)");
+
+ if (pmxdev && pmxdev->desc->ops->dbg_show)
+ pmxdev->desc->ops->dbg_show(pmxdev, s,
+ pin - pmxdev->desc->base);
+
+ seq_puts(s, "\n");
+ }
+ spin_unlock(&pin_desc_tree_lock);
+
+ return 0;
+}
+
+static int pins_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pins_show, NULL);
+}
+
+static int pinmux_devices_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinmux_devices_show, NULL);
+}
+
+static int pinmux_maps_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinmux_maps_show, NULL);
+}
+
+static int pinmux_pins_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pinmux_pins_show, NULL);
+}
+
+static const struct file_operations pins_ops = {
+ .open = pins_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pinmux_devices_ops = {
+ .open = pinmux_devices_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pinmux_maps_ops = {
+ .open = pinmux_maps_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pinmux_pins_ops = {
+ .open = pinmux_pins_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static struct dentry *debugfs_root;
+
+static void pinctrl_init_debugfs(void)
+{
+ debugfs_root = debugfs_create_dir("pinctrl", NULL);
+ if (IS_ERR(debugfs_root) || !debugfs_root) {
+ pr_warn("failed to create debugfs directory\n");
+ debugfs_root = NULL;
+ return;
+ }
+
+ debugfs_create_file("pins", S_IFREG | S_IRUGO,
+ debugfs_root, NULL, &pins_ops);
+ debugfs_create_file("pinmux-devices", S_IFREG | S_IRUGO,
+ debugfs_root, NULL, &pinmux_devices_ops);
+ debugfs_create_file("pinmux-maps", S_IFREG | S_IRUGO,
+ debugfs_root, NULL, &pinmux_maps_ops);
+ debugfs_create_file("pinmux-pins", S_IFREG | S_IRUGO,
+ debugfs_root, NULL, &pinmux_pins_ops);
+}
+
+#else /* CONFIG_DEBUG_FS */
+
+static void pinctrl_init_debugfs(void)
+{
+}
+
+#endif
+
+static int __init pinctrl_init(void)
+{
+ int ret;
+
+ ret = class_register(&pinmux_class);
+ pr_info("initialized pinctrl subsystem\n");
+
+ pinctrl_init_debugfs();
+ return ret;
+}
+
+/* init early since many drivers really need to initialized pinmux early */
+core_initcall(pinctrl_init);
diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h
new file mode 100644
index 0000000..1bc29f7
--- /dev/null
+++ b/include/linux/pinctrl/machine.h
@@ -0,0 +1,57 @@
+/*
+ * Machine interface for the pinctrl subsystem.
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ * Based on bits of regulator core, gpio core and clk core
+ *
+ * Author: Linus Walleij <linus.walleij(a)linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef __LINUX_PINMUX_MACHINE_H
+#define __LINUX_PINMUX_MACHINE_H
+
+/**
+ * struct pinmux_map - boards/machines shall provide this map for devices
+ * @function: a functional name for this mapping so it can be passed down
+ * to the driver to invoke that function and be referenced by this ID
+ * in e.g. pinmux_get()
+ * @dev: the device using this specific mapping, may be NULL if you provide
+ * .dev_name instead (this is more common)
+ * @dev_name: the name of the device using this specific mapping, the name
+ * must be the same that will return your struct device*
+ */
+struct pinmux_map {
+ const char *function;
+ struct device *dev;
+ const char *dev_name;
+};
+
+/* Convenience macro to set a simple map from a function to a named device */
+#define PINMUX_MAP(a, b) { .function = a, .dev_name = b }
+
+/**
+ * struct pinctrl_pin_desc - boards/machines provide information on their
+ * pins, pads or other muxable units in this struct
+ * @number: unique pin number from the global pin number space
+ * @name: a name for this pin
+ */
+struct pinctrl_pin_desc {
+ unsigned number;
+ const char *name;
+};
+
+/* Convenience macro to define a single named or anonymous pin descriptor */
+#define PINCTRL_PIN(a, b) { .number = a, .name = b }
+#define PINCTRL_PIN_ANON(a) { .number = a }
+
+extern int pinctrl_register_pins_sparse(struct pinctrl_pin_desc const *pins,
+ unsigned num_descs);
+extern int pinctrl_register_pins_dense(struct pinctrl_pin_desc const *pins,
+ unsigned num_descs, unsigned num_pins);
+extern int pinctrl_register_anon_pins(unsigned first, unsigned last);
+extern int pinmux_register_mappings(struct pinmux_map const *map,
+ unsigned num_maps);
+
+#endif
diff --git a/include/linux/pinctrl/pinmux.h b/include/linux/pinctrl/pinmux.h
new file mode 100644
index 0000000..7b40893
--- /dev/null
+++ b/include/linux/pinctrl/pinmux.h
@@ -0,0 +1,180 @@
+/*
+ * Interface the pinmux subsystem
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ * Based on bits of regulator core, gpio core and clk core
+ *
+ * Author: Linus Walleij <linus.walleij(a)linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef __LINUX_PINCTRL_PINMUX_H
+#define __LINUX_PINCTRL_PINMUX_H
+
+#include <linux/list.h>
+#include <linux/seq_file.h>
+
+struct pinmux;
+
+#ifdef CONFIG_PINCTRL
+
+struct pinmux_dev;
+
+/**
+ * struct pinmux_ops - pinmux operations, to be implemented by drivers
+ * @request: called by the core to see if a certain pin can be muxed in
+ * and made available in a certain mux setting The driver is allowed
+ * to answer "no" by returning a negative error code
+ * @list_functions: list the number of selectable named functions available
+ * in this pinmux driver, the core will begin on 0 and call this
+ * repeatedly as long as it returns >= 0 to enumerate mux settings
+ * @get_function_name: return the function name of the muxing selector,
+ * called by the core to figure out which mux setting it shall map a
+ * certain device to
+ * @get_function_pins: return an array of pins corresponding to a certain
+ * function selector in @pins, and the size of the array in @num_pins
+ * @enable: enable a certain muxing enumerator. The driver does not need to
+ * figure out whether enabling this function conflicts some other use
+ * of the pins, such collisions are handled by the pinmux subsystem
+ * @disable: disable a certain muxing enumerator
+ * @config: custom configuration function for a certain muxing enumerator -
+ * this works a bit like an ioctl() and can pass in and return arbitrary
+ * configuration data to the pinmux
+ * @gpio_request_enable: requests and enables GPIO on a certain pin.
+ * Implement this only if you can mux every pin individually as GPIO. If
+ * your gpio assignments are grouped, so you cannot control the GPIO
+ * muxing of every indvidual pin.
+ * @dbg_show: optional debugfs display hook that will provide per-device
+ * info for a certain pin in debugfs
+ */
+struct pinmux_ops {
+ int (*request) (struct pinmux_dev *pmxdev, unsigned offset);
+ int (*free) (struct pinmux_dev *pmxdev, unsigned offset);
+ int (*list_functions) (struct pinmux_dev *pmxdev, unsigned selector);
+ const char *(*get_function_name) (struct pinmux_dev *pmxdev,
+ unsigned selector);
+ int (*get_function_pins) (struct pinmux_dev *pmxdev, unsigned selector,
+ unsigned ** const pins, unsigned * const num_pins);
+ int (*enable) (struct pinmux_dev *pmxdev, unsigned selector);
+ void (*disable) (struct pinmux_dev *pmxdev, unsigned selector);
+ int (*config) (struct pinmux_dev *pmxdev, unsigned selector,
+ u16 param, unsigned long *data);
+ int (*gpio_request_enable) (struct pinmux_dev *pmxdev, unsigned offset);
+ void (*dbg_show) (struct pinmux_dev *pmxdev, struct seq_file *s,
+ unsigned offset);
+};
+
+/**
+ * struct pinmux_desc - pinmux descriptor, register this to pinmux subsystem
+ * @name: name for the pinmux
+ * @ops: pinmux operation table
+ * @owner: module providing the pinmux, used for refcounting
+ * @base: the number of the first pin handled by this pinmux, in the global
+ * pin space, subtracted from a given pin to get the offset into the range
+ * of a certain pinmux
+ * @npins: the number of pins handled by this pinmux - note that
+ * this is the number of possible pin settings, if your driver handles
+ * 8 pins that each can be muxed in 3 different ways, you reserve 24
+ * pins in the global pin space and set this to 24
+ */
+struct pinmux_desc {
+ const char *name;
+ struct pinmux_ops *ops;
+ struct module *owner;
+ int base;
+ int npins;
+};
+
+/**
+ * struct pinmux_dev - pinmux class device
+ * @desc: the descriptor supplied when initializing this pinmux
+ * @node: node to include this pinmux in the global pinmux list
+ * @dev: the device entry for this pinmux
+ * @owner: module providing the pinmux, used for refcounting
+ * @driver_data: driver data for drivers registering to the subsystem
+ *
+ * This should be dereferenced and used by the pinmux core ONLY
+ */
+struct pinmux_dev {
+ struct pinmux_desc *desc;
+ struct list_head node;
+ struct device dev;
+ struct module *owner;
+ void *driver_data;
+};
+
+/* These should only be used from drives */
+static inline const char *pmxdev_get_name(struct pinmux_dev *pmxdev)
+{
+ /* We're not allowed to register devices without name */
+ return pmxdev->desc->name;
+}
+
+static inline void *pmxdev_get_drvdata(struct pinmux_dev *pmxdev)
+{
+ return pmxdev->driver_data;
+}
+
+/* External interface to pinmux */
+extern int pin_is_valid(int pin);
+extern int pinmux_request_gpio(int pin, unsigned gpio);
+extern void pinmux_free_gpio(int pin);
+extern struct pinmux *pinmux_get(struct device *dev, const char *func);
+extern void pinmux_put(struct pinmux *pmx);
+extern int pinmux_enable(struct pinmux *pmx);
+extern void pinmux_disable(struct pinmux *pmx);
+extern int pinmux_config(struct pinmux *pmx, u16 param, unsigned long *data);
+extern struct pinmux_dev *pinmux_register(struct pinmux_desc *pmxdesc,
+ struct device *dev, void *driver_data);
+extern void pinmux_unregister(struct pinmux_dev *pmxdev);
+
+#else /* !CONFIG_PINMUX */
+
+static inline int pin_is_valid(int pin)
+{
+ return pin >= 0;
+}
+
+static inline int pinmux_request_gpio(int pin, unsigned gpio)
+{
+ return 0;
+}
+
+static inline void pinmux_free_gpio(int pin)
+{
+}
+
+static inline int pinmux_register_mappings(struct pinmux_map const *map,
+ unsigned num_maps)
+{
+ return 0;
+}
+
+static inline struct pinmux *pinmux_get(struct device *dev, const char *func)
+{
+ return NULL;
+}
+
+static inline void pinmux_put(struct pinmux *pmx)
+{
+}
+
+static inline int pinmux_enable(struct pinmux *pmx)
+{
+ return 0;
+}
+
+static inline void pinmux_disable(struct pinmux *pmx)
+{
+}
+
+static inline int pinmux_config(struct pinmux *pmx, u16 param,
+ unsigned long *data)
+{
+ return 0;
+}
+
+#endif /* CONFIG_PINMUX */
+
+#endif /* __LINUX_PINCTRL_PINMUX_H */
--
1.7.3.2
Hi All,
Please can I encourage you to register and organise your attendance at
Linaro Connect Q4.11 as soon as possible. In particular:
· if you're going to need a visa you should register now so we can
get the process going with your respective embassy
· if you need internal company approvals for attendance, make sure
its underway - and let me know if you need any additional supporting
information
· if you are a Canonical secondee to Linaro, you should register to
Linaro Connect (not UDS)
The hotel registration and booking details are now here:
http://connect.linaro.org/events/event/linaro-connect-q411/
Schedule information should be following in early September.
We will archive the existing connect(a)linaro.org e-mail alias after this
e-mail and switch over to a new list containing delegates who have
registered for Q4.11 - an additional reason to register.
Thx
Stephen Doel
Chief Operating Officer
T: +44 1223 45 00 23 │ M: +44 77 66 014 247
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro/155974581091106>
Facebook | <http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
On Tue, Aug 16, 2011 at 05:43:08PM +0100, Tixy wrote:
> On Tue, 2011-08-16 at 17:06 +0100, Dave Martin wrote:
> > On Tue, Aug 16, 2011 at 3:58 PM, Tixy <tixy(a)yxit.co.uk> wrote:
[...]
> I've been re-reading Documentation/SubmittingPatches to try and work out
> when it's appropriate to use Acked-by, but it seems a bit woolly -
> mostly for maintainers?
Actually I asked the question semi-automatically since you are CC'd
on this series -- because I was originally touching kprobes code,
which you have in-depth understanding of.
But now the series doesn't touch that code any more, reviewed-by
makes more sense.
Here's my own interpretation of the tags, based on how they appear
to be used (obviously, this doesn't override SubmittingPatches; it's
my additional interpretation)
I could of course be wrong in some aspects.
Any comments on this from the more experienced kernel developers out
there?
Signed-off-by = I take full responsibility for this patch,
and can maintain it in the author's absence if required.
In practice, this implies Acked-by.
Acked-by = This patch is definitely right, or I fully agree with the
patch and trust the author's judgement ("I will share
responsibility for the correctness and appropriateness of this
patch"). This implies Reviewed-by. Normally an ack shouldn't
get added unless the acker is confident that the patch is
adequately tested (where the level of testing deemed adequate
depends on the complexity of the patch) Again, this may rely on
judgement of the comptence of the author and the other
reviewers.
Reviewed-by = This patch looks correct and appropriate and I judge it
ok to merge, but I assume the author knows what they're
doing, and I don't necessarily take responsibility for the
change.
Tested-by = I have built and tested the patch, and saw reasonable
evidence that it achieves the intended result and has no
harmful effects. I make no comment about contents of the patch,
and I don't necessarily take responsibility for the change.
In all cases, the tag may influence upstreams' judgement about
whether to merge the patch: adding a tag implies understanding of this,
and takes responsibility for the effect this has (wise or unwise)
on the decision to merge.
NA(C)K = Informal indication that this patch is definitely wrong
(not listed in SubmittingPatches, because if someone is that convinced
the patch is wrong, it isn't normally going to get merged without
rework... or the NACKer is themselves known by upstream to be
reliably untrustworthy, biased, or wrong. In that case, the
upstream maintainter effectively overrides the NACKer.
An Ack is normally not useful unless it comes from someone who is
themselves known to and trusted by the maintainer of the tree where
the patch will get merged, or unless it comes from the original
author or a maintainer of the code that was modified (since they are
normally the best people to judge). Acked-by: randomnewbie(a)hotmail.com
isn't likely to carry much weight. In fact, including blatantly
frivolous or fraudulent acks from people in your upstream patch
submissions may harm their chance of merging (and your reputation).
So for now, I don't often ack patches -- I generally do so when someone
touches code I modified/added, to indicate that I understand their change
well enough, and am confident enough that it is correct, that I would be
happy to share some responsiibility for their change and any resulting
impacts on the maintenance of the code I added.
In areas where I know I have and am known to have a good understanding
(such as Thumb-2 related issues), I may ack patches touching code that
is nothing to do with me, because in such cases the Ack has a useful
meaning for the upstream maintainer.
Cheers
---Dave