* Re: [PATCH 0/7] [RFC] kernel: add a netlink interface to get information about processes
From: Andrew Vagin @ 2015-02-19 21:39 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Pavel Emelyanov, Roger Luethi, Oleg Nesterov, Cyrill Gorcunov,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Andrew Morton, Linux API, Andrey Vagin
In-Reply-To: <CALCETrU5B+1g9B3GH2WpPMaB98thXxpL1fAsHjssK1t_fDM_ZQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Wed, Feb 18, 2015 at 05:18:38PM -0800, Andy Lutomirski wrote:
> On Feb 18, 2015 6:27 AM, "Andrew Vagin" <avagin-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org> wrote:
> >
> > On Tue, Feb 17, 2015 at 11:05:31AM -0800, Andy Lutomirski wrote:
> > > On Feb 17, 2015 12:40 AM, "Andrey Vagin" <avagin-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org> wrote:
> > > >
> > > > Here is a preview version. It provides restricted set of functionality.
> > > > I would like to collect feedback about this idea.
> > > >
> > > > Currently we use the proc file system, where all information are
> > > > presented in text files, what is convenient for humans. But if we need
> > > > to get information about processes from code (e.g. in C), the procfs
> > > > doesn't look so cool.
> > > >
> > > > From code we would prefer to get information in binary format and to be
> > > > able to specify which information and for which tasks are required. Here
> > > > is a new interface with all these features, which is called task_diag.
> > > > In addition it's much faster than procfs.
> > > >
> > > > task_diag is based on netlink sockets and looks like socket-diag, which
> > > > is used to get information about sockets.
> > > >
> > > > A request is described by the task_diag_pid structure:
> > > >
> > > > struct task_diag_pid {
> > > > __u64 show_flags; /* specify which information are required */
> > > > __u64 dump_stratagy; /* specify a group of processes */
> > > >
> > > > __u32 pid;
> > > > };
> > > >
> > > > A respone is a set of netlink messages. Each message describes one task.
> > > > All task properties are divided on groups. A message contains the
> > > > TASK_DIAG_MSG group and other groups if they have been requested in
> > > > show_flags. For example, if show_flags contains TASK_DIAG_SHOW_CRED, a
> > > > response will contain the TASK_DIAG_CRED group which is described by the
> > > > task_diag_creds structure.
> > > >
> > > > struct task_diag_msg {
> > > > __u32 tgid;
> > > > __u32 pid;
> > > > __u32 ppid;
> > > > __u32 tpid;
> > > > __u32 sid;
> > > > __u32 pgid;
> > > > __u8 state;
> > > > char comm[TASK_DIAG_COMM_LEN];
> > > > };
> > > >
> > > > Another good feature of task_diag is an ability to request information
> > > > for a few processes. Currently here are two stratgies
> > > > TASK_DIAG_DUMP_ALL - get information for all tasks
> > > > TASK_DIAG_DUMP_CHILDREN - get information for children of a specified
> > > > tasks
> > > >
> > > > The task diag is much faster than the proc file system. We don't need to
> > > > create a new file descriptor for each task. We need to send a request
> > > > and get a response. It allows to get information for a few task in one
> > > > request-response iteration.
> > > >
> > > > I have compared performance of procfs and task-diag for the
> > > > "ps ax -o pid,ppid" command.
> > > >
> > > > A test stand contains 10348 processes.
> > > > $ ps ax -o pid,ppid | wc -l
> > > > 10348
> > > >
> > > > $ time ps ax -o pid,ppid > /dev/null
> > > >
> > > > real 0m1.073s
> > > > user 0m0.086s
> > > > sys 0m0.903s
> > > >
> > > > $ time ./task_diag_all > /dev/null
> > > >
> > > > real 0m0.037s
> > > > user 0m0.004s
> > > > sys 0m0.020s
> > > >
> > > > And here are statistics about syscalls which were called by each
> > > > command.
> > > > $ perf stat -e syscalls:sys_exit* -- ps ax -o pid,ppid 2>&1 | grep syscalls | sort -n -r | head -n 5
> > > > 20,713 syscalls:sys_exit_open
> > > > 20,710 syscalls:sys_exit_close
> > > > 20,708 syscalls:sys_exit_read
> > > > 10,348 syscalls:sys_exit_newstat
> > > > 31 syscalls:sys_exit_write
> > > >
> > > > $ perf stat -e syscalls:sys_exit* -- ./task_diag_all 2>&1 | grep syscalls | sort -n -r | head -n 5
> > > > 114 syscalls:sys_exit_recvfrom
> > > > 49 syscalls:sys_exit_write
> > > > 8 syscalls:sys_exit_mmap
> > > > 4 syscalls:sys_exit_mprotect
> > > > 3 syscalls:sys_exit_newfstat
> > > >
> > > > You can find the test program from this experiment in the last patch.
> > > >
> > > > The idea of this functionality was suggested by Pavel Emelyanov
> > > > (xemul@), when he found that operations with /proc forms a significant
> > > > part of a checkpointing time.
> > > >
> > > > Ten years ago here was attempt to add a netlink interface to access to /proc
> > > > information:
> > > > http://lwn.net/Articles/99600/
> > >
> > > I don't suppose this could use real syscalls instead of netlink. If
> > > nothing else, netlink seems to conflate pid and net namespaces.
> >
> > What do you mean by "conflate pid and net namespaces"?
>
> A netlink socket is bound to a network namespace, but you should be
> returning data specific to a pid namespace.
Here is a good question. When we mount a procfs instance, the current
pidns is saved on a superblock. Then if we read data from
this procfs from another pidns, we will see pid-s from the pidns where
this procfs has been mounted.
$ unshare -p -- bash -c '(bash)'
$ cat /proc/self/status | grep ^Pid:
Pid: 15770
$ echo $$
1
A similar situation with socket_diag. A socket_diag socket is bound to a
network namespace. If we open a socket_diag socket and change a network
namespace, it will return infromation about the initial netns.
In this version I always use a current pid namespace.
But to be consistant with other kernel logic, a socket diag has to be
linked with a pidns where it has been created.
>
> On a related note, how does this interact with hidepid? More
Currently it always work as procfs with hidepid = 2 (highest level of
security).
> generally, what privileges are you requiring to obtain what data?
It dumps information only if ptrace_may_access(tsk, PTRACE_MODE_READ) returns true
>
> >
> > >
> > > Also, using an asynchronous interface (send, poll?, recv) for
> > > something that's inherently synchronous (as the kernel a local
> > > question) seems awkward to me.
> >
> > Actually all requests are handled synchronously. We call sendmsg to send
> > a request and it is handled in this syscall.
> > 2) | netlink_sendmsg() {
> > 2) | netlink_unicast() {
> > 2) | taskdiag_doit() {
> > 2) 2.153 us | task_diag_fill();
> > 2) | netlink_unicast() {
> > 2) 0.185 us | netlink_attachskb();
> > 2) 0.291 us | __netlink_sendskb();
> > 2) 2.452 us | }
> > 2) + 33.625 us | }
> > 2) + 54.611 us | }
> > 2) + 76.370 us | }
> > 2) | netlink_recvmsg() {
> > 2) 1.178 us | skb_recv_datagram();
> > 2) + 46.953 us | }
> >
> > If we request information for a group of tasks (NLM_F_DUMP), a first
> > portion of data is filled from the sendmsg syscall. And then when we read
> > it, the kernel fills the next portion.
> >
> > 3) | netlink_sendmsg() {
> > 3) | __netlink_dump_start() {
> > 3) | netlink_dump() {
> > 3) | taskdiag_dumpid() {
> > 3) 0.685 us | task_diag_fill();
> > ...
> > 3) 0.224 us | task_diag_fill();
> > 3) + 74.028 us | }
> > 3) + 88.757 us | }
> > 3) + 89.296 us | }
> > 3) + 98.705 us | }
> > 3) | netlink_recvmsg() {
> > 3) | netlink_dump() {
> > 3) | taskdiag_dumpid() {
> > 3) 0.594 us | task_diag_fill();
> > ...
> > 3) 0.242 us | task_diag_fill();
> > 3) + 60.634 us | }
> > 3) + 72.803 us | }
> > 3) + 88.005 us | }
> > 3) | netlink_recvmsg() {
> > 3) | netlink_dump() {
> > 3) 2.403 us | taskdiag_dumpid();
> > 3) + 26.236 us | }
> > 3) + 40.522 us | }
> > 0) + 20.407 us | netlink_recvmsg();
> >
> >
> > netlink is really good for this type of tasks. It allows to create an
> > extendable interface which can be easy customized for different needs.
> >
> > I don't think that we would want to create another similar interface
> > just to be independent from network subsystem.
>
> I guess this is a bit streamy in that you ask one question and get
> multiple answers.
It's like seq_file in procfs. The kernel allocates a buffer then fills
it, copies it into userspace, fills it again, ... repeats these actions.
And we can read data from file by portions.
Actually here is one more analogy. When we open a file in procfs,
we sends a request to the kernel and a file path is a request body in
this case. But in case of procfs, we can't construct requests, we only
have a set of predefined requests.
>
> >
> > Thanks,
> > Andrew
> >
> > >
> > > --Andy
^ permalink raw reply
* Re: [RFC PATCH 1/3] eeprom: Add a simple EEPROM framework
From: Stephen Boyd @ 2015-02-20 2:36 UTC (permalink / raw)
To: Srinivas Kandagatla,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Maxime Ripard, Rob Herring, Pawel Moll, Kumar Gala,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann,
broonie-DgEjT+Ai2ygdnm+yROfE0A, Greg Kroah-Hartman
In-Reply-To: <1424365708-26681-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On 02/19/15 09:08, Srinivas Kandagatla wrote:
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index c70d6e4..d7afc82 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -184,4 +184,6 @@ source "drivers/thunderbolt/Kconfig"
>
> source "drivers/android/Kconfig"
>
> +source "drivers/eeprom/Kconfig"
> +
> endmenu
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 527a6da..57eb5b0 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -165,3 +165,4 @@ obj-$(CONFIG_RAS) += ras/
> obj-$(CONFIG_THUNDERBOLT) += thunderbolt/
> obj-$(CONFIG_CORESIGHT) += coresight/
> obj-$(CONFIG_ANDROID) += android/
> +obj-$(CONFIG_EEPROM) += eeprom/
> diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig
> new file mode 100644
> index 0000000..2c5452a
> --- /dev/null
> +++ b/drivers/eeprom/Kconfig
> @@ -0,0 +1,19 @@
> +menuconfig EEPROM
> + bool "EEPROM Support"
> + depends on OF
Doesn't this need some sort of select REGMAP somewhere?
Also, why do we need to use regmap for the eeprom framework read/write
ops? I liked the simple eeprom::{read,write} API that Maxime had. The
regmap part could be a regmap-eeprom driver that implements read/write
ops like you've done in the core.
> + help
> + Support for EEPROM alike devices.
> +
> + This framework is designed to provide a generic interface to EEPROM
> + from both the Linux Kernel and the userspace.
> +
> + If unsure, say no.
> +
> +if EEPROM
> +
> +config EEPROM_DEBUG
> + bool "EEPROM debug support"
> + help
> + Say yes here to enable debugging support.
> +
> +endif
>
> diff --git a/include/linux/eeprom-provider.h b/include/linux/eeprom-provider.h
> new file mode 100644
> index 0000000..3943c2f
> --- /dev/null
> +++ b/include/linux/eeprom-provider.h
> @@ -0,0 +1,51 @@
> +/*
> + * EEPROM framework provider.
> + *
> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + * Copyright (C) 2013 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#ifndef _LINUX_EEPROM_PROVIDER_H
> +#define _LINUX_EEPROM_PROVIDER_H
> +
> +#include <linux/device.h>
> +#include <linux/regmap.h>
> +#include <linux/list.h>
> +
> +struct eeprom_device {
> + struct regmap *regmap;
> + int stride;
> + size_t size;
> + struct device *dev;
> +
> + /* Internal to framework */
> + struct device edev;
> + int id;
> + struct list_head list;
Should there be a module owner here to handle module removal?
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* Re: [RFC PATCH 1/3] eeprom: Add a simple EEPROM framework
From: Srinivas Kandagatla @ 2015-02-20 8:14 UTC (permalink / raw)
To: Stephen Boyd, linux-arm-kernel
Cc: Maxime Ripard, Rob Herring, Pawel Moll, Kumar Gala, linux-api,
linux-kernel, devicetree, Arnd Bergmann, broonie,
Greg Kroah-Hartman
In-Reply-To: <54E69DB0.60701@codeaurora.org>
On 20/02/15 02:36, Stephen Boyd wrote:
> On 02/19/15 09:08, Srinivas Kandagatla wrote:
>> diff --git a/drivers/Kconfig b/drivers/Kconfig
>> index c70d6e4..d7afc82 100644
>> --- a/drivers/Kconfig
>> +++ b/drivers/Kconfig
>> @@ -184,4 +184,6 @@ source "drivers/thunderbolt/Kconfig"
>>
>> source "drivers/android/Kconfig"
>>
>> +source "drivers/eeprom/Kconfig"
>> +
>> endmenu
>> diff --git a/drivers/Makefile b/drivers/Makefile
>> index 527a6da..57eb5b0 100644
>> --- a/drivers/Makefile
>> +++ b/drivers/Makefile
>> @@ -165,3 +165,4 @@ obj-$(CONFIG_RAS) += ras/
>> obj-$(CONFIG_THUNDERBOLT) += thunderbolt/
>> obj-$(CONFIG_CORESIGHT) += coresight/
>> obj-$(CONFIG_ANDROID) += android/
>> +obj-$(CONFIG_EEPROM) += eeprom/
>> diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig
>> new file mode 100644
>> index 0000000..2c5452a
>> --- /dev/null
>> +++ b/drivers/eeprom/Kconfig
>> @@ -0,0 +1,19 @@
>> +menuconfig EEPROM
>> + bool "EEPROM Support"
>> + depends on OF
>
> Doesn't this need some sort of select REGMAP somewhere?
May be depends REGMAP would be good.
>
> Also, why do we need to use regmap for the eeprom framework read/write
> ops? I liked the simple eeprom::{read,write} API that Maxime had. The
> regmap part could be a regmap-eeprom driver that implements read/write
> ops like you've done in the core.
regmap bus does the same job.
The only reason for using regmap here is to have more generic drivers
for eeprom providers based on different buses like mmio, i2c, spi...
As of today we could just make the qfprom eeprom provider as more
generic eeprom-mmio provider. May be sunxi_sid could reuse it too with
some effort.
In future It may be possible to have eeprom-i2c or eeprom-spi providers.
>
>> +
>> +struct eeprom_device {
>> + struct regmap *regmap;
>> + int stride;
>> + size_t size;
>> + struct device *dev;
>> +
>> + /* Internal to framework */
>> + struct device edev;
>> + int id;
>> + struct list_head list;
>
> Should there be a module owner here to handle module removal?
>
Good point, we should do some reference counting.
^ permalink raw reply
* Re: [RFC PATCH 1/3] eeprom: Add a simple EEPROM framework
From: Srinivas Kandagatla @ 2015-02-20 8:27 UTC (permalink / raw)
To: Andrew Lunn
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann, Pawel Moll,
Greg Kroah-Hartman, linux-api-u79uwXL29TY76Z2rM5mHXA,
broonie-DgEjT+Ai2ygdnm+yROfE0A, Stephen Boyd,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Kumar Gala,
Maxime Ripard
In-Reply-To: <20150219181230.GC795-g2DYL2Zd6BY@public.gmane.org>
Thanks Andrew for your comments,
On 19/02/15 18:12, Andrew Lunn wrote:
>> +
>> +Required properties:
>> +
>> +eeproms: List of phandle and data cell specifier triplet, one triplet
>> + for each data cell the device might be interested in. The
>> + triplet consists of the phandle to the eeprom provider, then
>> + the offset in byte within that storage device, and the length
>
> bytes
>
>> + in byte of the data we care about.
>
> bytes
Yep will fix it in next version.
>
>> +
>> +Optional properties:
>> +
>> +eeprom-names: List of data cell name strings sorted in the same order
>> + as the resets property. Consumers drivers will use
>
> resets? I guess this text was cut/paste from the reset documentation?\
>
I think so. Will fix it.
>> + eeprom-names to differentiate between multiple cells,
>> + and hence being able to know what these cells are for.
>> +
>> +For example:
>> +
>> + device {
>> + eeproms = <&at24 14 42>;
>
> I like to use 42, but is it realistic to have a soc-rev-id which is 42
> bytes long? How about using 42 as the offset and a sensible length of
> say 4?
Ok, will fix it..
>
>> + eeprom-names = "soc-rev-id";
>> +menuconfig EEPROM
>> + bool "EEPROM Support"
>> + depends on OF
>> + help
>> + Support for EEPROM alike devices.
>
> like.
Ok
>
>> +
>> + This framework is designed to provide a generic interface to EEPROM
>
> EPROMs
Ok.
>
>> +
>> +
>> +static ssize_t bin_attr_eeprom_read_write(struct kobject *kobj,
>> + char *buf, loff_t offset,
>> + size_t count, bool read)
>> +{
>> + struct device *dev = container_of(kobj, struct device, kobj);
>> + struct eeprom_device *eeprom = container_of(dev, struct eeprom_device,
>> + edev);
>> + int rc;
>> +
>> + if (offset > eeprom->size)
>> + return 0;
>> +
>> + if (offset + count > eeprom->size)
>> + count = eeprom->size - offset;
>> +
>> + if (read)
>> + rc = regmap_bulk_read(eeprom->regmap, offset,
>> + buf, count/eeprom->stride);
>
> This division will round down, so you could get one less byte than
> what you expected, and the value you actually return. It seems like
> there should be a check here, the count is a multiple of stride and
> return an error if it is not.
Thats a good catch, I will fix this for other such instances too.
>
>> + else
>> + rc = regmap_bulk_write(eeprom->regmap, offset,
>> + buf, count/eeprom->stride);
>> +
>> + if (IS_ERR_VALUE(rc))
>> + return 0;
>> +
>
> I don't think returning 0 here, and above is the best thing to
> do. Return the real error code from regmap, or EINVAL or some other
> error code for going off the end of the eerpom.
Ok, I will fix the return value here for both the cases.
>
>> + return count;
>> +}
>> +
>> +static ssize_t bin_attr_eeprom_read(struct file *filp, struct kobject *kobj,
>> + struct bin_attribute *attr,
>> + char *buf, loff_t offset, size_t count)
>> +{
>> + return bin_attr_eeprom_read_write(kobj, buf, offset, count, true);
>> +}
>> +
>> +static ssize_t bin_attr_eeprom_write(struct file *filp, struct kobject *kobj,
>> + struct bin_attribute *attr,
>> + char *buf, loff_t offset, size_t count)
>> +{
>> + return bin_attr_eeprom_read_write(kobj, buf, offset, count, false);
>> +}
>>
>
> These two functions seem to be identical. So just have one of them?
One is read and other is write.. there is a true and false flag at the
end of the call to bin_attr_eeprom_read_write().
>
> +
>> +static struct bin_attribute bin_attr_eeprom = {
>> + .attr = {
>> + .name = "eeprom",
>> + .mode = 0660,
>
> Symbolic values like S_IRUGO | S_IWUSR would be better.
Yep, thats correct, I will fix it.
>
> Are you also sure you want group write?
>
S_IWUSR should be enough.
>> + },
>> + .read = bin_attr_eeprom_read,
>> + .write = bin_attr_eeprom_write,
>> +};
>> +
>> +static struct eeprom_cell *__eeprom_cell_get(struct device_node *node,
>> + int index)
>> +{
>> + struct of_phandle_args args;
>> + struct eeprom_cell *cell;
>> + struct eeprom_device *e, *eeprom = NULL;
>> + int ret;
>> +
>> + ret = of_parse_phandle_with_args(node, "eeproms",
>> + "#eeprom-cells", index, &args);
>> + if (ret)
>> + return ERR_PTR(ret);
>> +
>> + if (args.args_count != 2)
>> + return ERR_PTR(-EINVAL);
>> +
>> + mutex_lock(&eeprom_list_mutex);
>> +
>> + list_for_each_entry(e, &eeprom_list, list) {
>> + if (args.np == e->edev.of_node) {
>> + eeprom = e;
>> + break;
>> + }
>> + }
>> + mutex_unlock(&eeprom_list_mutex);
>
> Shouldn't you increment a reference count to the eeprom here? You are
> going to have trouble if the eeprom is unregistered and there is a
> call still referring to it.
Yes, Stephen Byod also pointed the same, having owner in eeprom_device
should fix this.
I will fix it in next version.
>
>> +
>> + if (!eeprom)
>> + return ERR_PTR(-EPROBE_DEFER);
>> +
>> + cell = kzalloc(sizeof(*cell), GFP_KERNEL);
>> + if (!cell)
>> + return ERR_PTR(-ENOMEM);
>> +
>> + cell->eeprom = eeprom;
>> + cell->offset = args.args[0];
>> + cell->count = args.args[1];
>> +
>> + return cell;
>> +}
>> +
>> +
>> diff --git a/include/linux/eeprom-consumer.h b/include/linux/eeprom-consumer.h
>> new file mode 100644
>> index 0000000..706ae9d
>> --- /dev/null
>> +++ b/include/linux/eeprom-consumer.h
>> @@ -0,0 +1,73 @@
>> +/*
>> + * EEPROM framework consumer.
>> + *
>> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
>> + * Copyright (C) 2013 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +
>> +#ifndef _LINUX_EEPROM_CONSUMER_H
>> +#define _LINUX_EEPROM_CONSUMER_H
>> +
>> +struct eeprom_cell;
>> +
>> +/**
>> + * eeprom_cell_get(): Get eeprom cell of device form a given index.
>
> of a device for a
>
Ok, will be fixed in next version.
>> + *
>> + * @dev: Device that will be interacted with
>> + * @index: Index of the eeprom cell.
>> + *
>> + * The return value will be an ERR_PTR() on error or a valid pointer
>> + * to a struct eeprom_cell. The eeprom_cell will be freed by the
>> + * eeprom_cell_put().
>> + */
>> +struct eeprom_cell *eeprom_cell_get(struct device *dev, int index);
>> +
>> +/**
>> + * eeprom_cell_get(): Get eeprom cell of device form a given name.
>
> same again
Ok, will be fixed in next version.
>
>> + *
>> + * @dev: Device that will be interacted with
>> + * @name: Name of the eeprom cell.
>> + *
>> + * The return value will be an ERR_PTR() on error or a valid pointer
>> + * to a struct eeprom_cell. The eeprom_cell will be freed by the
>> + * eeprom_cell_put().
>> + */
>> +struct eeprom_cell *eeprom_cell_get_byname(struct device *dev,
>> + const char *name);
>> +
>> +/**
>> + * eeprom_cell_put(): Release previously allocated eeprom cell.
>> + *
>> + * @cell: Previously allocated eeprom cell by eeprom_cell_get()
>> + * or eeprom_cell_get_byname().
>> + */
>> +void eeprom_cell_put(struct eeprom_cell *cell);
>> +
>> +/**
>> + * eeprom_cell_read(): Read a given eeprom cell
>> + *
>> + * @cell: eeprom cell to be read.
>> + * @len: pointer to length of cell which will be populated on successful read.
>> + *
>> + * The return value will be an ERR_PTR() on error or a valid pointer
>> + * to a char * bufffer. The buffer should be freed by the consumer with a
>> + * kfree().
>> + */
>> +char *eeprom_cell_read(struct eeprom_cell *cell, ssize_t *len);
>
> Would void * be better than char *? I guess the contents is mostly
> data, not strings.
Yes, thats sounds sensible.
>
> Andrew
>
>> +
>> +/**
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Documenting MS_LAZYTIME
From: Michael Kerrisk @ 2015-02-20 8:50 UTC (permalink / raw)
To: Theodore Ts'o
Cc: Ext4 Developers List, Linux btrfs Developers List, XFS Developers,
linux-man-u79uwXL29TY76Z2rM5mHXA, Linux-Fsdevel, Linux API
Hello Ted,
Based on your commit message 0ae45f63d4e, I I wrote the documentation
below for MS_LAZYTIME, to go into the mount(2) man page. Could you
please check it over and let me know if it's accurate. In particular,
I added pieces marked with "*" below that were not part of the commit
message and I'd like confirmation that they're accurate.
Thanks,
Michael
[[
MS_LAZYTIME (since Linux 3.20)
Only update filetimes (atime, mtime, ctime) on the in-
memory version of the file inode. The on-disk time‐
stamps are updated only when:
(a) the inode needs to be updated for some change unre‐
lated to file timestamps;
(b) the application employs fsync(2), syncfs(2), or
sync(2);
(c) an undeleted inode is evicted from memory; or
* (d) more than 24 hours have passed since the i-node was
* written to disk.
This mount option significantly reduces writes to the
inode table for workloads that perform frequent random
writes to preallocated files.
* As at Linux 3.20, this option is supported only on ext4.
]]
--
Michael Kerrisk Linux man-pages maintainer;
http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface", http://blog.man7.org/
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH 1/3] eeprom: Add a simple EEPROM framework
From: Srinivas Kandagatla @ 2015-02-20 10:24 UTC (permalink / raw)
To: Stephen Boyd, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Cc: Maxime Ripard, Rob Herring, Pawel Moll, Kumar Gala,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann,
broonie-DgEjT+Ai2ygdnm+yROfE0A, Greg Kroah-Hartman
In-Reply-To: <54E6ECEA.7020604-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On 20/02/15 08:14, Srinivas Kandagatla wrote:
>>
>> Doesn't this need some sort of select REGMAP somewhere?
> May be depends REGMAP would be good.
You are right, just realized that
it should be "select REGMAP"
and for QFPROM it should be "select REGMAP_MMIO"
--srini
^ permalink raw reply
* Re: Documenting MS_LAZYTIME
From: Andreas Dilger @ 2015-02-20 12:32 UTC (permalink / raw)
To: Michael Kerrisk
Cc: Theodore Ts'o, Ext4 Developers List,
Linux btrfs Developers List, XFS Developers,
linux-man-u79uwXL29TY76Z2rM5mHXA, Linux-Fsdevel, Linux API
In-Reply-To: <CAHO5Pa0k7QkV_6BDjwTVxa7LV9tFyN9nGFFcSvOC6HYO08wfrw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Feb 20, 2015, at 1:50 AM, Michael Kerrisk <mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
>
> Hello Ted,
>
> Based on your commit message 0ae45f63d4e, I I wrote the documentation
> below for MS_LAZYTIME, to go into the mount(2) man page. Could you
> please check it over and let me know if it's accurate. In particular,
> I added pieces marked with "*" below that were not part of the commit
> message and I'd like confirmation that they're accurate.
>
> Thanks,
>
> Michael
>
> [[
> MS_LAZYTIME (since Linux 3.20)
> Only update filetimes (atime, mtime, ctime) on the in-
> memory version of the file inode. The on-disk time‐
> stamps are updated only when:
>
> (a) the inode needs to be updated for some change unre‐
> lated to file timestamps;
>
> (b) the application employs fsync(2), syncfs(2), or
> sync(2);
>
> (c) an undeleted inode is evicted from memory; or
>
> * (d) more than 24 hours have passed since the i-node was
> * written to disk.
>
> This mount option significantly reduces writes to the
> inode table for workloads that perform frequent random
> writes to preallocated files.
>
> * As at Linux 3.20, this option is supported only on ext4.
I _think_ that the lazytime mount option is generic for all filesystems.
I believe ext4 has an extra optimization for it, but that's it.
Cheers, Andreas
^ permalink raw reply
* Re: Documenting MS_LAZYTIME
From: Michael Kerrisk (man-pages) @ 2015-02-20 13:22 UTC (permalink / raw)
To: Andreas Dilger
Cc: Theodore Ts'o, Ext4 Developers List,
Linux btrfs Developers List, XFS Developers, linux-man,
Linux-Fsdevel, Linux API
In-Reply-To: <44893EA7-B11A-469A-9911-6CE2E8B26EB4@dilger.ca>
On 20 February 2015 at 13:32, Andreas Dilger <adilger@dilger.ca> wrote:
> On Feb 20, 2015, at 1:50 AM, Michael Kerrisk <mtk.manpages@gmail.com> wrote:
>>
>> Hello Ted,
>>
>> Based on your commit message 0ae45f63d4e, I I wrote the documentation
>> below for MS_LAZYTIME, to go into the mount(2) man page. Could you
>> please check it over and let me know if it's accurate. In particular,
>> I added pieces marked with "*" below that were not part of the commit
>> message and I'd like confirmation that they're accurate.
>>
>> Thanks,
>>
>> Michael
>>
>> [[
>> MS_LAZYTIME (since Linux 3.20)
>> Only update filetimes (atime, mtime, ctime) on the in-
>> memory version of the file inode. The on-disk time‐
>> stamps are updated only when:
>>
>> (a) the inode needs to be updated for some change unre‐
>> lated to file timestamps;
>>
>> (b) the application employs fsync(2), syncfs(2), or
>> sync(2);
>>
>> (c) an undeleted inode is evicted from memory; or
>>
>> * (d) more than 24 hours have passed since the i-node was
>> * written to disk.
>>
>> This mount option significantly reduces writes to the
>> inode table for workloads that perform frequent random
>> writes to preallocated files.
>>
>> * As at Linux 3.20, this option is supported only on ext4.
>
> I _think_ that the lazytime mount option is generic for all filesystems.
> I believe ext4 has an extra optimization for it, but that's it.
Ah yes, looking at the code again, that makes sense. I think you're
right, and I've struck that last sentence. Thanks, Andreas.
Cheers,
Michael
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: Documenting MS_LAZYTIME
From: Eric Sandeen @ 2015-02-20 15:49 UTC (permalink / raw)
To: Michael Kerrisk, Theodore Ts'o
Cc: Ext4 Developers List, Linux btrfs Developers List, XFS Developers,
linux-man, Linux-Fsdevel, Linux API
In-Reply-To: <CAHO5Pa0k7QkV_6BDjwTVxa7LV9tFyN9nGFFcSvOC6HYO08wfrw@mail.gmail.com>
On 2/20/15 2:50 AM, Michael Kerrisk wrote:
> Hello Ted,
>
> Based on your commit message 0ae45f63d4e, I I wrote the documentation
> below for MS_LAZYTIME, to go into the mount(2) man page. Could you
> please check it over and let me know if it's accurate. In particular,
> I added pieces marked with "*" below that were not part of the commit
> message and I'd like confirmation that they're accurate.
>
> Thanks,
>
> Michael
>
> [[
> MS_LAZYTIME (since Linux 3.20)
> Only update filetimes (atime, mtime, ctime) on the in-
> memory version of the file inode. The on-disk time‐
> stamps are updated only when:
"filetimes" and "file inode" seems a bit awkward. How about:
> MS_LAZYTIME (since Linux 3.20)
> Reduce on-disk updates of inode timestamps (atime, mtime, ctime)
> by maintaining these changes only in memory, unless:
(maybe I'm bike-shedding too much, if so, sorry).
> (a) the inode needs to be updated for some change unre‐
> lated to file timestamps;
>
> (b) the application employs fsync(2), syncfs(2), or
> sync(2);
>
> (c) an undeleted inode is evicted from memory; or
>
> * (d) more than 24 hours have passed since the i-node was
> * written to disk.
Please don't use "i-node" - simply "inode" is much more common in the manpages
AFAICT.
> This mount option significantly reduces writes to the
> inode table for workloads that perform frequent random
> writes to preallocated files.
This seems like an overly specific description of a single workload out
of many which may benefit, but what do others think? "inode table" is also
fairly extN-specific.
-Eric
> * As at Linux 3.20, this option is supported only on ext4.
> ]]
>
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [GIT PULL] Kselftest updates for 3.20-rc1
From: Shuah Khan @ 2015-02-20 16:00 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-api
In-Reply-To: <54D8FE1C.5040303@osg.samsung.com>
On 02/09/2015 11:36 AM, Shuah Khan wrote:
> Hi Linus,
>
> Please pull the following Kselftest updates for 3.20-rc1
>
> thanks,
> -- Shuah
Hi Linus,
Hope this work is on the list to be pulled in for 3.20. Please let
me know if there are any problems.
thanks,
-- Shuah
>
> The following changes since commit 97bf6af1f928216fd6c5a66e8a57bfa95a659672:
>
> Linux 3.19-rc1 (2014-12-20 17:08:50 -0800)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
> tags/linux-kselftest-3.20-rc1
>
> for you to fetch changes up to 6ddf898c23d62c974e148efd9e509731324a167a:
>
> selftests/exec: Check if the syscall exists and bail if not
> (2015-02-04 10:17:35 -0700)
>
> ----------------------------------------------------------------
> Kselftest updates for 3.20-rc1
>
> This update adds:
> - Kselftest install target feature
> - Fix for selftests/exec test
>
> ----------------------------------------------------------------
> Michael Ellerman (1):
> selftests/exec: Check if the syscall exists and bail if not
>
> Shuah Khan (20):
> selftests/breakpoints: add install target to enable test install
> selftests/cpu-hotplug: add install target to enable test install
> selftests/efivarfs: add install target to enable test install
> selftests/firmware: add install target to enable test install
> selftests/ftrace: add install target to enable test install
> selftests/ipc: add install target to enable test install
> selftests/kcmp: add install target to enable test install
> selftests/memfd: add install target to enable test install
> selftests/memory-hotplug: add install target to enable test install
> selftests/mount: add install target to enable test install
> selftests/mqueue: add install target to enable test install
> selftests/net: add install target to enable test install
> selftests/ptrace: add install target to enable test install
> selftests/size: add install target to enable test install
> selftests/sysctl: add install target to enable test install
> selftests/timers: add install target to enable test install
> selftests/user: add install target to enable test install
> selftests/vm: add install target to enable test install
> selftests: add install target to enable test install
> kbuild: add a new kselftest_install make target to install selftests
>
> Makefile | 14 +++++-
> tools/testing/selftests/Makefile | 54
> +++++++++++++++++++++-
> tools/testing/selftests/breakpoints/Makefile | 19 +++++++-
> tools/testing/selftests/cpu-hotplug/Makefile | 14 +++++-
> .../{on-off-test.sh => cpu-on-off-test.sh} | 0
> tools/testing/selftests/efivarfs/Makefile | 16 ++++++-
> tools/testing/selftests/exec/execveat.c | 10 +++-
> tools/testing/selftests/firmware/Makefile | 43 ++++++++++-------
> tools/testing/selftests/ftrace/Makefile | 13 +++++-
> tools/testing/selftests/ipc/Makefile | 19 +++++++-
> tools/testing/selftests/kcmp/Makefile | 13 +++++-
> tools/testing/selftests/memfd/Makefile | 17 +++++--
> tools/testing/selftests/memory-hotplug/Makefile | 14 +++++-
> .../{on-off-test.sh => mem-on-off-test.sh} | 0
> tools/testing/selftests/mount/Makefile | 12 ++++-
> tools/testing/selftests/mqueue/Makefile | 18 ++++++--
> tools/testing/selftests/net/Makefile | 20 ++++++--
> tools/testing/selftests/ptrace/Makefile | 16 +++++--
> tools/testing/selftests/size/Makefile | 12 ++++-
> tools/testing/selftests/sysctl/Makefile | 17 ++++++-
> tools/testing/selftests/timers/Makefile | 12 ++++-
> tools/testing/selftests/user/Makefile | 12 ++++-
> tools/testing/selftests/vm/Makefile | 11 ++++-
> 23 files changed, 326 insertions(+), 50 deletions(-)
> rename tools/testing/selftests/cpu-hotplug/{on-off-test.sh =>
> cpu-on-off-test.sh} (100%)
> rename tools/testing/selftests/memory-hotplug/{on-off-test.sh =>
> mem-on-off-test.sh} (100%)
>
--
Shuah Khan
Sr. Linux Kernel Developer
Samsung Research America (Silicon Valley)
shuahkh@osg.samsung.com | (970) 217-8978
^ permalink raw reply
* Re: [RFC PATCH 1/3] eeprom: Add a simple EEPROM framework
From: Rob Herring @ 2015-02-20 17:21 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Maxime Ripard, Rob Herring, Pawel Moll, Kumar Gala,
linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Stephen Boyd,
Arnd Bergmann, Mark Brown, Greg Kroah-Hartman
In-Reply-To: <1424365708-26681-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On Thu, Feb 19, 2015 at 11:08 AM, Srinivas Kandagatla
<srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> From: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
>
> Up until now, EEPROM drivers were stored in drivers/misc, where they all had to
> duplicate pretty much the same code to register a sysfs file, allow in-kernel
> users to access the content of the devices they were driving, etc.
>
> This was also a problem as far as other in-kernel users were involved, since
> the solutions used were pretty much different from on driver to another, there
> was a rather big abstraction leak.
>
> This introduction of this framework aims at solving this. It also introduces DT
> representation for consumer devices to go get the data they require (MAC
> Addresses, SoC/Revision ID, part numbers, and so on) from the EEPROMs.
>
> Having regmap interface to this framework would give much better
> abstraction for eeproms on different buses.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> [srinivas.kandagatla: Moved to regmap based and cleanedup apis]
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> .../devicetree/bindings/eeprom/eeprom.txt | 48 ++++
> drivers/Kconfig | 2 +
> drivers/Makefile | 1 +
> drivers/eeprom/Kconfig | 19 ++
> drivers/eeprom/Makefile | 9 +
> drivers/eeprom/core.c | 290 +++++++++++++++++++++
> include/linux/eeprom-consumer.h | 73 ++++++
> include/linux/eeprom-provider.h | 51 ++++
Who is going to be the maintainer for this?
> 8 files changed, 493 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/eeprom/eeprom.txt
> create mode 100644 drivers/eeprom/Kconfig
> create mode 100644 drivers/eeprom/Makefile
> create mode 100644 drivers/eeprom/core.c
> create mode 100644 include/linux/eeprom-consumer.h
> create mode 100644 include/linux/eeprom-provider.h
>
> diff --git a/Documentation/devicetree/bindings/eeprom/eeprom.txt b/Documentation/devicetree/bindings/eeprom/eeprom.txt
> new file mode 100644
> index 0000000..9ec1ec2
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/eeprom/eeprom.txt
Please make bindings a separate patch.
> @@ -0,0 +1,48 @@
> += EEPROM Data Device Tree Bindings =
> +
> +This binding is intended to represent the location of hardware
> +configuration data stored in EEPROMs.
> +
> +On a significant proportion of boards, the manufacturer has stored
> +some data on an EEPROM-like device, for the OS to be able to retrieve
> +these information and act upon it. Obviously, the OS has to know
> +about where to retrieve these data from, and where they are stored on
> +the storage device.
> +
> +This document is here to document this.
> +
> += Data providers =
> +
> +Required properties:
> +#eeprom-cells: Number of cells in an eeprom specifier; The common
> + case is 2.
We already have eeproms in DTs, it would be nice to be able to support
them with this framework as well.
> +
> +For example:
> +
> + at24: eeprom@42 {
> + #eeprom-cells = <2>;
> + };
> +
> += Data consumers =
> +
> +Required properties:
> +
> +eeproms: List of phandle and data cell specifier triplet, one triplet
> + for each data cell the device might be interested in. The
> + triplet consists of the phandle to the eeprom provider, then
> + the offset in byte within that storage device, and the length
> + in byte of the data we care about.
The problem with this is it assumes you know who the consumer is and
that it is a DT node. For example, how would you describe a serial
number?
Rob
> +
> +Optional properties:
> +
> +eeprom-names: List of data cell name strings sorted in the same order
> + as the resets property. Consumers drivers will use
> + eeprom-names to differentiate between multiple cells,
> + and hence being able to know what these cells are for.
> +
> +For example:
> +
> + device {
> + eeproms = <&at24 14 42>;
> + eeprom-names = "soc-rev-id";
> + };
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index c70d6e4..d7afc82 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -184,4 +184,6 @@ source "drivers/thunderbolt/Kconfig"
>
> source "drivers/android/Kconfig"
>
> +source "drivers/eeprom/Kconfig"
> +
> endmenu
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 527a6da..57eb5b0 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -165,3 +165,4 @@ obj-$(CONFIG_RAS) += ras/
> obj-$(CONFIG_THUNDERBOLT) += thunderbolt/
> obj-$(CONFIG_CORESIGHT) += coresight/
> obj-$(CONFIG_ANDROID) += android/
> +obj-$(CONFIG_EEPROM) += eeprom/
> diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig
> new file mode 100644
> index 0000000..2c5452a
> --- /dev/null
> +++ b/drivers/eeprom/Kconfig
> @@ -0,0 +1,19 @@
> +menuconfig EEPROM
> + bool "EEPROM Support"
> + depends on OF
> + help
> + Support for EEPROM alike devices.
> +
> + This framework is designed to provide a generic interface to EEPROM
> + from both the Linux Kernel and the userspace.
> +
> + If unsure, say no.
> +
> +if EEPROM
> +
> +config EEPROM_DEBUG
> + bool "EEPROM debug support"
> + help
> + Say yes here to enable debugging support.
> +
> +endif
> diff --git a/drivers/eeprom/Makefile b/drivers/eeprom/Makefile
> new file mode 100644
> index 0000000..e130079
> --- /dev/null
> +++ b/drivers/eeprom/Makefile
> @@ -0,0 +1,9 @@
> +#
> +# Makefile for eeprom drivers.
> +#
> +
> +ccflags-$(CONFIG_EEPROM_DEBUG) += -DDEBUG
> +
> +obj-$(CONFIG_EEPROM) += core.o
> +
> +# Devices
> diff --git a/drivers/eeprom/core.c b/drivers/eeprom/core.c
> new file mode 100644
> index 0000000..bc877a6
> --- /dev/null
> +++ b/drivers/eeprom/core.c
> @@ -0,0 +1,290 @@
> +/*
> + * EEPROM framework core.
> + *
> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + * Copyright (C) 2013 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/eeprom-provider.h>
> +#include <linux/eeprom-consumer.h>
> +#include <linux/export.h>
> +#include <linux/fs.h>
> +#include <linux/idr.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +
> +struct eeprom_cell {
> + struct eeprom_device *eeprom;
> + loff_t offset;
> + size_t count;
> +};
> +
> +static DEFINE_MUTEX(eeprom_list_mutex);
> +static LIST_HEAD(eeprom_list);
> +static DEFINE_IDA(eeprom_ida);
> +
> +static ssize_t bin_attr_eeprom_read_write(struct kobject *kobj,
> + char *buf, loff_t offset,
> + size_t count, bool read)
> +{
> + struct device *dev = container_of(kobj, struct device, kobj);
> + struct eeprom_device *eeprom = container_of(dev, struct eeprom_device,
> + edev);
> + int rc;
> +
> + if (offset > eeprom->size)
> + return 0;
> +
> + if (offset + count > eeprom->size)
> + count = eeprom->size - offset;
> +
> + if (read)
> + rc = regmap_bulk_read(eeprom->regmap, offset,
> + buf, count/eeprom->stride);
> + else
> + rc = regmap_bulk_write(eeprom->regmap, offset,
> + buf, count/eeprom->stride);
> +
> + if (IS_ERR_VALUE(rc))
> + return 0;
> +
> + return count;
> +}
> +
> +static ssize_t bin_attr_eeprom_read(struct file *filp, struct kobject *kobj,
> + struct bin_attribute *attr,
> + char *buf, loff_t offset, size_t count)
> +{
> + return bin_attr_eeprom_read_write(kobj, buf, offset, count, true);
> +}
> +
> +static ssize_t bin_attr_eeprom_write(struct file *filp, struct kobject *kobj,
> + struct bin_attribute *attr,
> + char *buf, loff_t offset, size_t count)
> +{
> + return bin_attr_eeprom_read_write(kobj, buf, offset, count, false);
> +}
> +
> +static struct bin_attribute bin_attr_eeprom = {
> + .attr = {
> + .name = "eeprom",
> + .mode = 0660,
> + },
> + .read = bin_attr_eeprom_read,
> + .write = bin_attr_eeprom_write,
> +};
> +
> +static struct bin_attribute *eeprom_bin_attributes[] = {
> + &bin_attr_eeprom,
> + NULL,
> +};
> +
> +static const struct attribute_group eeprom_bin_group = {
> + .bin_attrs = eeprom_bin_attributes,
> +};
> +
> +static const struct attribute_group *eeprom_dev_groups[] = {
> + &eeprom_bin_group,
> + NULL,
> +};
> +
> +static struct class eeprom_class = {
> + .name = "eeprom",
> + .dev_groups = eeprom_dev_groups,
> +};
> +
> +int eeprom_register(struct eeprom_device *eeprom)
> +{
> + int rval;
> +
> + if (!eeprom->regmap || !eeprom->size) {
> + dev_err(eeprom->dev, "Regmap not found\n");
> + return -EINVAL;
> + }
> +
> + eeprom->id = ida_simple_get(&eeprom_ida, 0, 0, GFP_KERNEL);
> + if (eeprom->id < 0)
> + return eeprom->id;
> +
> + eeprom->edev.class = &eeprom_class;
> + eeprom->edev.parent = eeprom->dev;
> + eeprom->edev.of_node = eeprom->dev ? eeprom->dev->of_node : NULL;
> + dev_set_name(&eeprom->edev, "eeprom%d", eeprom->id);
> +
> + device_initialize(&eeprom->edev);
> +
> + dev_dbg(&eeprom->edev, "Registering eeprom device %s\n",
> + dev_name(&eeprom->edev));
> +
> + rval = device_add(&eeprom->edev);
> + if (rval)
> + return rval;
> +
> + mutex_lock(&eeprom_list_mutex);
> + list_add(&eeprom->list, &eeprom_list);
> + mutex_unlock(&eeprom_list_mutex);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(eeprom_register);
> +
> +int eeprom_unregister(struct eeprom_device *eeprom)
> +{
> + device_del(&eeprom->edev);
> +
> + mutex_lock(&eeprom_list_mutex);
> + list_del(&eeprom->list);
> + mutex_unlock(&eeprom_list_mutex);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(eeprom_unregister);
> +
> +static struct eeprom_cell *__eeprom_cell_get(struct device_node *node,
> + int index)
> +{
> + struct of_phandle_args args;
> + struct eeprom_cell *cell;
> + struct eeprom_device *e, *eeprom = NULL;
> + int ret;
> +
> + ret = of_parse_phandle_with_args(node, "eeproms",
> + "#eeprom-cells", index, &args);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + if (args.args_count != 2)
> + return ERR_PTR(-EINVAL);
> +
> + mutex_lock(&eeprom_list_mutex);
> +
> + list_for_each_entry(e, &eeprom_list, list) {
> + if (args.np == e->edev.of_node) {
> + eeprom = e;
> + break;
> + }
> + }
> + mutex_unlock(&eeprom_list_mutex);
> +
> + if (!eeprom)
> + return ERR_PTR(-EPROBE_DEFER);
> +
> + cell = kzalloc(sizeof(*cell), GFP_KERNEL);
> + if (!cell)
> + return ERR_PTR(-ENOMEM);
> +
> + cell->eeprom = eeprom;
> + cell->offset = args.args[0];
> + cell->count = args.args[1];
> +
> + return cell;
> +}
> +
> +static struct eeprom_cell *__eeprom_cell_get_byname(struct device_node *node,
> + const char *id)
> +{
> + int index = 0;
> +
> + if (id)
> + index = of_property_match_string(node,
> + "eeprom-names",
> + id);
> + return __eeprom_cell_get(node, index);
> +
> +}
> +
> +struct eeprom_cell *eeprom_cell_get(struct device *dev, int index)
> +{
> + if (!dev)
> + return ERR_PTR(-EINVAL);
> +
> + /* First, attempt to retrieve the cell through the DT */
> + if (dev->of_node)
> + return __eeprom_cell_get(dev->of_node, index);
> +
> + /* We don't support anything else yet */
> + return ERR_PTR(-ENODEV);
> +}
> +EXPORT_SYMBOL(eeprom_cell_get);
> +
> +struct eeprom_cell *eeprom_cell_get_byname(struct device *dev, const char *id)
> +{
> + if (!dev)
> + return ERR_PTR(-EINVAL);
> +
> + if (id && dev->of_node)
> + return __eeprom_cell_get_byname(dev->of_node, id);
> +
> + /* We don't support anything else yet */
> + return ERR_PTR(-ENODEV);
> +}
> +EXPORT_SYMBOL(eeprom_cell_get_byname);
> +
> +void eeprom_cell_put(struct eeprom_cell *cell)
> +{
> + kfree(cell);
> +}
> +EXPORT_SYMBOL(eeprom_cell_put);
> +
> +char *eeprom_cell_read(struct eeprom_cell *cell, ssize_t *len)
> +{
> + struct eeprom_device *eeprom = cell->eeprom;
> + char *buf;
> + int rc;
> +
> + if (!eeprom || !eeprom->regmap)
> + return ERR_PTR(-EINVAL);
> +
> + buf = kzalloc(cell->count, GFP_KERNEL);
> + if (!buf)
> + return ERR_PTR(-ENOMEM);
> +
> + rc = regmap_bulk_read(eeprom->regmap, cell->offset,
> + buf, cell->count/eeprom->stride);
> + if (IS_ERR_VALUE(rc)) {
> + kfree(buf);
> + return ERR_PTR(rc);
> + }
> +
> + *len = cell->count;
> +
> + return buf;
> +}
> +EXPORT_SYMBOL(eeprom_cell_read);
> +
> +int eeprom_cell_write(struct eeprom_cell *cell, const char *buf, ssize_t len)
> +{
> + struct eeprom_device *eeprom = cell->eeprom;
> +
> + if (!eeprom || !eeprom->regmap)
> + return -EINVAL;
> +
> + return regmap_bulk_write(eeprom->regmap, cell->offset,
> + buf, cell->count/eeprom->stride);
> +}
> +EXPORT_SYMBOL(eeprom_cell_write);
> +
> +static int eeprom_init(void)
> +{
> + return class_register(&eeprom_class);
> +}
> +
> +static void eeprom_exit(void)
> +{
> + class_unregister(&eeprom_class);
> +}
> +
> +subsys_initcall(eeprom_init);
> +module_exit(eeprom_exit);
> +
> +MODULE_AUTHOR("Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org");
> +MODULE_DESCRIPTION("EEPROM Driver Core");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/eeprom-consumer.h b/include/linux/eeprom-consumer.h
> new file mode 100644
> index 0000000..706ae9d
> --- /dev/null
> +++ b/include/linux/eeprom-consumer.h
> @@ -0,0 +1,73 @@
> +/*
> + * EEPROM framework consumer.
> + *
> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + * Copyright (C) 2013 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#ifndef _LINUX_EEPROM_CONSUMER_H
> +#define _LINUX_EEPROM_CONSUMER_H
> +
> +struct eeprom_cell;
> +
> +/**
> + * eeprom_cell_get(): Get eeprom cell of device form a given index.
> + *
> + * @dev: Device that will be interacted with
> + * @index: Index of the eeprom cell.
> + *
> + * The return value will be an ERR_PTR() on error or a valid pointer
> + * to a struct eeprom_cell. The eeprom_cell will be freed by the
> + * eeprom_cell_put().
> + */
> +struct eeprom_cell *eeprom_cell_get(struct device *dev, int index);
> +
> +/**
> + * eeprom_cell_get(): Get eeprom cell of device form a given name.
> + *
> + * @dev: Device that will be interacted with
> + * @name: Name of the eeprom cell.
> + *
> + * The return value will be an ERR_PTR() on error or a valid pointer
> + * to a struct eeprom_cell. The eeprom_cell will be freed by the
> + * eeprom_cell_put().
> + */
> +struct eeprom_cell *eeprom_cell_get_byname(struct device *dev,
> + const char *name);
> +
> +/**
> + * eeprom_cell_put(): Release previously allocated eeprom cell.
> + *
> + * @cell: Previously allocated eeprom cell by eeprom_cell_get()
> + * or eeprom_cell_get_byname().
> + */
> +void eeprom_cell_put(struct eeprom_cell *cell);
> +
> +/**
> + * eeprom_cell_read(): Read a given eeprom cell
> + *
> + * @cell: eeprom cell to be read.
> + * @len: pointer to length of cell which will be populated on successful read.
> + *
> + * The return value will be an ERR_PTR() on error or a valid pointer
> + * to a char * bufffer. The buffer should be freed by the consumer with a
> + * kfree().
> + */
> +char *eeprom_cell_read(struct eeprom_cell *cell, ssize_t *len);
> +
> +/**
> + * eeprom_cell_write(): Write to a given eeprom cell
> + *
> + * @cell: eeprom cell to be written.
> + * @buf: Buffer to be written.
> + * @len: length of buffer to be written to eeprom cell.
> + *
> + * The return value will be an non zero on error or a zero on successful write.
> + */
> +int eeprom_cell_write(struct eeprom_cell *cell, const char *buf, ssize_t len);
> +
> +#endif /* ifndef _LINUX_EEPROM_CONSUMER_H */
> diff --git a/include/linux/eeprom-provider.h b/include/linux/eeprom-provider.h
> new file mode 100644
> index 0000000..3943c2f
> --- /dev/null
> +++ b/include/linux/eeprom-provider.h
> @@ -0,0 +1,51 @@
> +/*
> + * EEPROM framework provider.
> + *
> + * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> + * Copyright (C) 2013 Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#ifndef _LINUX_EEPROM_PROVIDER_H
> +#define _LINUX_EEPROM_PROVIDER_H
> +
> +#include <linux/device.h>
> +#include <linux/regmap.h>
> +#include <linux/list.h>
> +
> +struct eeprom_device {
> + struct regmap *regmap;
> + int stride;
> + size_t size;
> + struct device *dev;
> +
> + /* Internal to framework */
> + struct device edev;
> + int id;
> + struct list_head list;
> +};
> +
> +/**
> + * eeprom_register(): Register a eeprom device for given eeprom.
> + * Also creates an binary entry in /sys/class/eeprom/eeprom[id]/eeprom
> + *
> + * @eeprom: eeprom device that needs to be created
> + *
> + * The return value will be an error code on error or a zero on success.
> + * The eeprom_device and sysfs entery will be freed by the eeprom_unregister().
> + */
> +int eeprom_register(struct eeprom_device *eeprom);
> +
> +/**
> + * eeprom_unregister(): Unregister previously registered eeprom device
> + *
> + * @eeprom: Pointer to previously registered eeprom device.
> + *
> + * The return value will be an non zero on error or a zero on success.
> + */
> +int eeprom_unregister(struct eeprom_device *eeprom);
> +
> +#endif /* ifndef _LINUX_EEPROM_PROVIDER_H */
> --
> 1.9.1
>
^ permalink raw reply
* Re: [RFC PATCH 1/3] eeprom: Add a simple EEPROM framework
From: Russell King - ARM Linux @ 2015-02-20 17:46 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann, Pawel Moll,
Greg Kroah-Hartman, linux-api-u79uwXL29TY76Z2rM5mHXA,
broonie-DgEjT+Ai2ygdnm+yROfE0A, Stephen Boyd,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Kumar Gala,
Maxime Ripard
In-Reply-To: <1424365708-26681-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On Thu, Feb 19, 2015 at 05:08:28PM +0000, Srinivas Kandagatla wrote:
> +static struct class eeprom_class = {
> + .name = "eeprom",
> + .dev_groups = eeprom_dev_groups,
> +};
> +
> +int eeprom_register(struct eeprom_device *eeprom)
> +{
> + int rval;
> +
> + if (!eeprom->regmap || !eeprom->size) {
> + dev_err(eeprom->dev, "Regmap not found\n");
> + return -EINVAL;
> + }
> +
> + eeprom->id = ida_simple_get(&eeprom_ida, 0, 0, GFP_KERNEL);
> + if (eeprom->id < 0)
> + return eeprom->id;
> +
> + eeprom->edev.class = &eeprom_class;
> + eeprom->edev.parent = eeprom->dev;
> + eeprom->edev.of_node = eeprom->dev ? eeprom->dev->of_node : NULL;
> + dev_set_name(&eeprom->edev, "eeprom%d", eeprom->id);
> +
> + device_initialize(&eeprom->edev);
> +
> + dev_dbg(&eeprom->edev, "Registering eeprom device %s\n",
> + dev_name(&eeprom->edev));
> +
> + rval = device_add(&eeprom->edev);
> + if (rval)
> + return rval;
> +
> + mutex_lock(&eeprom_list_mutex);
> + list_add(&eeprom->list, &eeprom_list);
> + mutex_unlock(&eeprom_list_mutex);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(eeprom_register);
> +
> +int eeprom_unregister(struct eeprom_device *eeprom)
> +{
> + device_del(&eeprom->edev);
> +
> + mutex_lock(&eeprom_list_mutex);
> + list_del(&eeprom->list);
> + mutex_unlock(&eeprom_list_mutex);
> +
> + return 0;
There's problems with this. "edev" is embedded into eeprom, and "edev"
is a refcounted structure - it has a lifetime, and the lifetime of
eeprom is thus determined by edev.
What this means is that calling eeprom_unregister() and then freeing
the eeprom structure is a potentially unsafe operation - the memory
backing edev must only be freed when the release method for the
struct device has been called.
> +struct eeprom_device {
> + struct regmap *regmap;
> + int stride;
> + size_t size;
> + struct device *dev;
Failing to understand and address the driver model life time issues is
a major blocker for this patch. Sorry.
--
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* Re: [RFC PATCH 2/3] eeprom: sunxi: Move the SID driver to the eeprom framework
From: Russell King - ARM Linux @ 2015-02-20 17:47 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Arnd Bergmann, Pawel Moll,
Greg Kroah-Hartman, linux-api-u79uwXL29TY76Z2rM5mHXA,
broonie-DgEjT+Ai2ygdnm+yROfE0A, Stephen Boyd,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Kumar Gala,
Maxime Ripard
In-Reply-To: <1424365720-26725-1-git-send-email-srinivas.kandagatla-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On Thu, Feb 19, 2015 at 05:08:40PM +0000, Srinivas Kandagatla wrote:
> +static int sunxi_sid_probe(struct platform_device *pdev)
> +{
> + const struct of_device_id *device;
> + struct eeprom_sid *sid;
> + struct resource *res;
> + struct eeprom_device *eeprom;
> + struct device *dev = &pdev->dev;
> + int rval;
> +
> + sid = devm_kzalloc(dev, sizeof(*sid), GFP_KERNEL);
> + if (!sid)
> + return -ENOMEM;
> +
> + eeprom = &sid->eeprom;
...
> + rval = eeprom_register(eeprom);
> + if (rval)
> + return rval;
...
> +static int sunxi_sid_remove(struct platform_device *pdev)
> +{
> + struct eeprom_device *eeprom = platform_get_drvdata(pdev);
> +
> + return eeprom_unregister(eeprom);
As pointed out in the previous patch, this is unsafe as the eeprom
structure contains a struct device.
--
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* Re: [RFC PATCH 3/3] eeprom: qfprom: Add Qualcomm QFPROM support.
From: Russell King - ARM Linux @ 2015-02-20 17:48 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: linux-arm-kernel, devicetree, Arnd Bergmann, Pawel Moll,
Greg Kroah-Hartman, linux-api, broonie, Stephen Boyd,
linux-kernel, Rob Herring, Kumar Gala, Maxime Ripard
In-Reply-To: <1424365731-26768-1-git-send-email-srinivas.kandagatla@linaro.org>
On Thu, Feb 19, 2015 at 05:08:51PM +0000, Srinivas Kandagatla wrote:
> +static int qfprom_remove(struct platform_device *pdev)
> +{
> + struct eeprom_device *eeprom = platform_get_drvdata(pdev);
> +
> + return eeprom_unregister(eeprom);
Same problem...
> +static int qfprom_probe(struct platform_device *pdev)
> +{
> + struct resource *res;
> + void __iomem *base;
> + struct device *dev = &pdev->dev;
> + struct eeprom_device *eeprom;
> + int rval;
> +
> + eeprom = devm_kzalloc(dev, sizeof(*eeprom), GFP_KERNEL);
> + if (!eeprom)
> + return -ENOMEM;
...
> + rval = eeprom_register(eeprom);
--
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply
* [PATCH v2 00/18] Add support to STMicroelectronics STM32 family
From: Maxime Coquelin @ 2015-02-20 18:00 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Jonathan Corbet, Maxime Coquelin, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Arnd Bergmann, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will
Thanks for the first round of reviews.
Most of the comments made have been taken into account (see below for details),
except that I failed to find an easy/clean way to move vector_table location in
order to limit the waste of memory.
If you have any idea/example to do that, I will be pleased to add it in next
version of the series.
STM32 MCUs are Cortex-M CPU, used in various applications (consumer
electronics, industrial applications, hobbyists...).
Datasheets, user and programming manuals are publicly available on
STMicroelectronics website.
With this series applied, the STM32F419 Discovery can boot succesfully.
Changes since v1:
-----------------
- Move bindings documentation in their own patches (Andreas)
- Rename ARM System timer to armv7m-systick (Rob)
- Add clock-frequency property handling in armv7m-systick (Rob)
- Re-factor the reset controllers into a single controller (Philipp)
- Add kerneldoc to reset_controller_of_init (Philipp)
- Add named constants in include/dt-bindings/reset/ (Philipp)
- Make pinctrl driver to depend on ARCH_STM32 or COMPILE_TEST (Geert)
- Introduce CPUV7M_NUM_IRQ config flag to indicate the number of interrupts
supported by the MCU, in order to limit memory waste in vectors' table (Uwe)
Maxime Coquelin (18):
scripts: link-vmlinux: Don't pass page offset to kallsyms if XIP
Kernel
ARM: ARMv7M: Enlarge vector table to 256 entries
dt-bindings: Document the ARM System timer bindings
clocksource: Add ARM System timer driver
reset: Add reset_controller_of_init() function
dt-bindings: Document the STM32 reset bindings
drivers: reset: Add STM32 reset driver
dt-bindings: Document the STM32 timer bindings
clockevent: Add STM32 Timer driver
dt-bindings: Document the STM32 pin controller
pinctrl: Add pinctrl driver for STM32 MCUs
dt-bindings: Document the STM32 USART bindings
serial: stm32-usart: Add STM32 USART Driver
ARM: Add STM32 family machine
ARM: dts: Add ARM System timer as clockevent in armv7m
ARM: dts: Introduce STM32F429 MCU
ARM: configs: Add STM32 defconfig
MAINTAINERS: Add entry for STM32 MCUs
Documentation/arm/stm32/overview.txt | 32 +
Documentation/arm/stm32/stm32f429-overview.txt | 22 +
.../devicetree/bindings/arm/armv7m_systick.txt | 26 +
.../devicetree/bindings/pinctrl/pinctrl-stm32.txt | 99 +++
.../devicetree/bindings/reset/st,stm32-reset.txt | 36 +
.../devicetree/bindings/serial/st,stm32-usart.txt | 18 +
.../devicetree/bindings/timer/st,stm32-timer.txt | 19 +
MAINTAINERS | 7 +
arch/arm/Kconfig | 22 +
arch/arm/Makefile | 1 +
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/armv7-m.dtsi | 7 +
arch/arm/boot/dts/stm32f429-disco.dts | 41 ++
arch/arm/boot/dts/stm32f429.dtsi | 396 +++++++++++
arch/arm/configs/stm32_defconfig | 72 ++
arch/arm/kernel/entry-v7m.S | 13 +-
arch/arm/mach-stm32/Makefile | 1 +
arch/arm/mach-stm32/Makefile.boot | 0
arch/arm/mach-stm32/board-dt.c | 31 +
arch/arm/mm/Kconfig | 15 +
drivers/clocksource/Kconfig | 16 +
drivers/clocksource/Makefile | 2 +
drivers/clocksource/armv7m_systick.c | 78 +++
drivers/clocksource/timer-stm32.c | 187 +++++
drivers/pinctrl/Kconfig | 10 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/pinctrl-stm32.c | 779 +++++++++++++++++++++
drivers/reset/Makefile | 1 +
drivers/reset/core.c | 27 +
drivers/reset/reset-stm32.c | 124 ++++
drivers/tty/serial/Kconfig | 17 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/stm32-usart.c | 695 ++++++++++++++++++
include/asm-generic/vmlinux.lds.h | 4 +-
include/dt-bindings/pinctrl/pinctrl-stm32.h | 43 ++
include/dt-bindings/reset/st,stm32f429.h | 85 +++
include/linux/reset-controller.h | 6 +
include/uapi/linux/serial_core.h | 3 +
scripts/link-vmlinux.sh | 2 +-
39 files changed, 2934 insertions(+), 6 deletions(-)
create mode 100644 Documentation/arm/stm32/overview.txt
create mode 100644 Documentation/arm/stm32/stm32f429-overview.txt
create mode 100644 Documentation/devicetree/bindings/arm/armv7m_systick.txt
create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
create mode 100644 Documentation/devicetree/bindings/reset/st,stm32-reset.txt
create mode 100644 Documentation/devicetree/bindings/serial/st,stm32-usart.txt
create mode 100644 Documentation/devicetree/bindings/timer/st,stm32-timer.txt
create mode 100644 arch/arm/boot/dts/stm32f429-disco.dts
create mode 100644 arch/arm/boot/dts/stm32f429.dtsi
create mode 100644 arch/arm/configs/stm32_defconfig
create mode 100644 arch/arm/mach-stm32/Makefile
create mode 100644 arch/arm/mach-stm32/Makefile.boot
create mode 100644 arch/arm/mach-stm32/board-dt.c
create mode 100644 drivers/clocksource/armv7m_systick.c
create mode 100644 drivers/clocksource/timer-stm32.c
create mode 100644 drivers/pinctrl/pinctrl-stm32.c
create mode 100644 drivers/reset/reset-stm32.c
create mode 100644 drivers/tty/serial/stm32-usart.c
create mode 100644 include/dt-bindings/pinctrl/pinctrl-stm32.h
create mode 100644 include/dt-bindings/reset/st,stm32f429.h
--
1.9.1
^ permalink raw reply
* [PATCH v2 01/18] scripts: link-vmlinux: Don't pass page offset to kallsyms if XIP Kernel
From: Maxime Coquelin @ 2015-02-20 18:01 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Jonathan Corbet, Maxime Coquelin, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Arnd Bergmann, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will
In-Reply-To: <1424455277-29983-1-git-send-email-mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
When Kernel is executed in place from ROM, the symbol addresses can be
lower than the page offset.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
scripts/link-vmlinux.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 86a4fe7..b055d9d 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -82,7 +82,7 @@ kallsyms()
kallsymopt="${kallsymopt} --all-symbols"
fi
- if [ -n "${CONFIG_ARM}" ] && [ -n "${CONFIG_PAGE_OFFSET}" ]; then
+ if [ -n "${CONFIG_ARM}" ] && [ -z "${CONFIG_XIP_KERNEL}" ] && [ -n "${CONFIG_PAGE_OFFSET}" ]; then
kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET"
fi
--
1.9.1
^ permalink raw reply related
* [PATCH v2 02/18] ARM: ARMv7M: Enlarge vector table to 256 entries
From: Maxime Coquelin @ 2015-02-20 18:01 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Jonathan Corbet, Maxime Coquelin, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Arnd Bergmann, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will
In-Reply-To: <1424455277-29983-1-git-send-email-mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>From Cortex-M reference manuals, the nvic supports up to 240 interrupts.
So the number of entries in vectors table is up to 256.
This patch adds a new config flag to specify the number of external interrupts.
Some ifdeferies are added in order to respect the natural alignment without
wasting too much space on smaller systems.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
arch/arm/kernel/entry-v7m.S | 13 +++++++++----
arch/arm/mm/Kconfig | 15 +++++++++++++++
2 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/arch/arm/kernel/entry-v7m.S b/arch/arm/kernel/entry-v7m.S
index 8944f49..68cde36 100644
--- a/arch/arm/kernel/entry-v7m.S
+++ b/arch/arm/kernel/entry-v7m.S
@@ -117,9 +117,14 @@ ENTRY(__switch_to)
ENDPROC(__switch_to)
.data
- .align 8
+#if CONFIG_CPUV7M_NUM_IRQ <= 112
+ .align 9
+#else
+ .align 10
+#endif
+
/*
- * Vector table (64 words => 256 bytes natural alignment)
+ * Vector table (Natural alignment need to be ensured)
*/
ENTRY(vector_table)
.long 0 @ 0 - Reset stack pointer
@@ -138,6 +143,6 @@ ENTRY(vector_table)
.long __invalid_entry @ 13 - Reserved
.long __pendsv_entry @ 14 - PendSV
.long __invalid_entry @ 15 - SysTick
- .rept 64 - 16
- .long __irq_entry @ 16..64 - External Interrupts
+ .rept CONFIG_CPUV7M_NUM_IRQ
+ .long __irq_entry @ External Interrupts
.endr
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index c43c714..27eb835 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -604,6 +604,21 @@ config CPU_USE_DOMAINS
This option enables or disables the use of domain switching
via the set_fs() function.
+config CPUV7M_NUM_IRQ
+ int "Number of external interrupts connected to the NVIC"
+ depends on CPU_V7M
+ default 90 if ARCH_STM32
+ default 38 if ARCH_EFM32
+ default 240
+ help
+ This option indicates the number of interrupts connected to the NVIC.
+ The value can be larger than the real number of interrupts supported
+ by the system, but must not be lower.
+ The default value is 240, corresponding to the maximum number of
+ interrupts supported by the NVIC on Cortex-M family.
+
+ If unsure, keep default value.
+
#
# CPU supports 36-bit I/O
#
--
1.9.1
^ permalink raw reply related
* [PATCH v2 03/18] dt-bindings: Document the ARM System timer bindings
From: Maxime Coquelin @ 2015-02-20 18:01 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Jonathan Corbet, Maxime Coquelin, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Arnd Bergmann, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will
In-Reply-To: <1424455277-29983-1-git-send-email-mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This adds documentation of device tree bindings for the
ARM System timer.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
.../devicetree/bindings/arm/armv7m_systick.txt | 26 ++++++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/armv7m_systick.txt
diff --git a/Documentation/devicetree/bindings/arm/armv7m_systick.txt b/Documentation/devicetree/bindings/arm/armv7m_systick.txt
new file mode 100644
index 0000000..7cf4a24
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/armv7m_systick.txt
@@ -0,0 +1,26 @@
+* ARMv7M System Timer
+
+ARMv7-M includes a system timer, known as SysTick. Current driver only
+implements the clocksource feature.
+
+Required properties:
+- compatible : Should be "arm,armv7m-systick"
+- reg : The address range of the timer
+
+Required clocking property, have to be one of:
+- clocks : The input clock of the timer
+- clock-frequency : The rate in HZ in input of the ARM SysTick
+
+Examples:
+
+systick: timer@e000e010 {
+ compatible = "arm,armv7m-systick";
+ reg = <0xe000e010 0x10>;
+ clocks = <&clk_systick>;
+};
+
+systick: timer@e000e010 {
+ compatible = "arm,armv7m-systick";
+ reg = <0xe000e010 0x10>;
+ clock-frequency = <90000000>;
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v2 04/18] clocksource: Add ARM System timer driver
From: Maxime Coquelin @ 2015-02-20 18:01 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Jonathan Corbet, Maxime Coquelin, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Arnd Bergmann, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will
In-Reply-To: <1424455277-29983-1-git-send-email-mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This patch adds clocksource support for ARMv7-M's System timer,
also known as SysTick.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
drivers/clocksource/Kconfig | 7 ++++
drivers/clocksource/Makefile | 1 +
drivers/clocksource/armv7m_systick.c | 78 ++++++++++++++++++++++++++++++++++++
3 files changed, 86 insertions(+)
create mode 100644 drivers/clocksource/armv7m_systick.c
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index fc01ec2..fb6011e 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -124,6 +124,13 @@ config CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
help
Use ARM global timer clock source as sched_clock
+config ARMV7M_SYSTICK
+ bool
+ select CLKSRC_OF if OF
+ select CLKSRC_MMIO
+ help
+ This options enables support for the ARMv7M system timer unit
+
config ATMEL_PIT
select CLKSRC_OF if OF
def_bool SOC_AT91SAM9 || SOC_SAMA5
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 94d90b2..eeea736 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_MTK_TIMER) += mtk_timer.o
obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
+obj-$(CONFIG_ARMV7M_SYSTICK) += armv7m_systick.o
obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o
obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o
obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o
diff --git a/drivers/clocksource/armv7m_systick.c b/drivers/clocksource/armv7m_systick.c
new file mode 100644
index 0000000..23d8249
--- /dev/null
+++ b/drivers/clocksource/armv7m_systick.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk.h>
+#include <linux/bitops.h>
+
+#define SYST_CSR 0x00
+#define SYST_RVR 0x04
+#define SYST_CVR 0x08
+#define SYST_CALIB 0x0c
+
+#define SYST_CSR_ENABLE BIT(0)
+
+#define SYSTICK_LOAD_RELOAD_MASK 0x00FFFFFF
+
+static void __init system_timer_of_register(struct device_node *np)
+{
+ struct clk *clk;
+ void __iomem *base;
+ u32 rate = 0;
+ int ret;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_warn("system-timer: invalid base address\n");
+ return;
+ }
+
+ clk = of_clk_get(np, 0);
+ if (!IS_ERR(clk)) {
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ clk_put(clk);
+ goto out_unmap;
+ }
+
+ rate = clk_get_rate(clk);
+ }
+
+ /* If no clock found, try to get clock-frequency property */
+ if (!rate) {
+ ret = of_property_read_u32(np, "clock-frequency", &rate);
+ if (ret)
+ goto out_unmap;
+ }
+
+ writel_relaxed(SYSTICK_LOAD_RELOAD_MASK, base + SYST_RVR);
+ writel_relaxed(SYST_CSR_ENABLE, base + SYST_CSR);
+
+ ret = clocksource_mmio_init(base + SYST_CVR, "arm_system_timer", rate,
+ 200, 24, clocksource_mmio_readl_down);
+ if (ret) {
+ pr_err("failed to init clocksource (%d)\n", ret);
+ goto out_clk_disable;
+ }
+
+ pr_info("ARM System timer initialized as clocksource\n");
+
+ return;
+
+out_clk_disable:
+ if (!IS_ERR(clk))
+ clk_disable_unprepare(clk);
+out_unmap:
+ iounmap(base);
+ WARN(ret, "ARM System timer register failed (%d)\n", ret);
+}
+
+CLOCKSOURCE_OF_DECLARE(arm_systick, "arm,armv7m-systick",
+ system_timer_of_register);
--
1.9.1
^ permalink raw reply related
* [PATCH v2 05/18] reset: Add reset_controller_of_init() function
From: Maxime Coquelin @ 2015-02-20 18:01 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Jonathan Corbet, Maxime Coquelin, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Arnd Bergmann, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will
In-Reply-To: <1424455277-29983-1-git-send-email-mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Some platforms need to initialize the reset controller before the timers.
This patch introduces a reset_controller_of_init() function that can be
called before the timers intialization.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
drivers/reset/core.c | 27 +++++++++++++++++++++++++++
include/asm-generic/vmlinux.lds.h | 4 +++-
include/linux/reset-controller.h | 6 ++++++
3 files changed, 36 insertions(+), 1 deletion(-)
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 7955e00..7eef63e 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -86,6 +86,33 @@ void reset_controller_unregister(struct reset_controller_dev *rcdev)
}
EXPORT_SYMBOL_GPL(reset_controller_unregister);
+extern struct of_device_id __reset_ctrl_of_table[];
+
+static const struct of_device_id __reset_ctrl_of_table_sentinel
+ __used __section(__reset_ctrl_of_table_end);
+
+/**
+ * reset_controller_of_init - scan and init reset controllers from the DT
+ *
+ * This function scas the device tree for matching reset controllers. It is
+ * used on machines that need reset controls at early stage. To use it, the
+ * controller driver has to be registred with RESET_CONTROLLER_OF_DECLARE().
+ */
+void __init reset_controller_of_init(void)
+{
+ struct device_node *np;
+ const struct of_device_id *match;
+ of_init_fn_1 init_func;
+
+ for_each_matching_node_and_match(np, __reset_ctrl_of_table, &match) {
+ if (!of_device_is_available(np))
+ continue;
+
+ init_func = match->data;
+ init_func(np);
+ }
+}
+
/**
* reset_control_reset - reset the controlled device
* @rstc: reset controller
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index bee5d68..1f96365 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -168,6 +168,7 @@
#define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem)
#define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
#define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
+#define RESET_CTRL_OF_TABLES() OF_TABLE(CONFIG_RESET_CONTROLLER, reset_ctrl)
#define KERNEL_DTB() \
STRUCT_ALIGN(); \
@@ -502,7 +503,8 @@
CPU_METHOD_OF_TABLES() \
KERNEL_DTB() \
IRQCHIP_OF_MATCH_TABLE() \
- EARLYCON_OF_TABLES()
+ EARLYCON_OF_TABLES() \
+ RESET_CTRL_OF_TABLES()
#define INIT_TEXT \
*(.init.text) \
diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
index ce6b962..f8a030a 100644
--- a/include/linux/reset-controller.h
+++ b/include/linux/reset-controller.h
@@ -51,4 +51,10 @@ struct reset_controller_dev {
int reset_controller_register(struct reset_controller_dev *rcdev);
void reset_controller_unregister(struct reset_controller_dev *rcdev);
+
+#define RESET_CONTROLLER_OF_DECLARE(name, compat, fn) \
+ OF_DECLARE_1(reset_ctrl, name, compat, fn)
+
+void reset_controller_of_init(void);
+
#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v2 06/18] dt-bindings: Document the STM32 reset bindings
From: Maxime Coquelin @ 2015-02-20 18:01 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Jonathan Corbet, Maxime Coquelin, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Arnd Bergmann, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will
In-Reply-To: <1424455277-29983-1-git-send-email-mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This adds documentation of device tree bindings for the
STM32 reset controller.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
.../devicetree/bindings/reset/st,stm32-reset.txt | 36 ++++++++++++++++++++++
1 file changed, 36 insertions(+)
create mode 100644 Documentation/devicetree/bindings/reset/st,stm32-reset.txt
diff --git a/Documentation/devicetree/bindings/reset/st,stm32-reset.txt b/Documentation/devicetree/bindings/reset/st,stm32-reset.txt
new file mode 100644
index 0000000..5982528
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/st,stm32-reset.txt
@@ -0,0 +1,36 @@
+STMicroelectronics STM32 Peripheral Reset Controller
+====================================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "st,stm32-reset"
+- reg: should be register base and length as documented in the
+ datasheet
+- #reset-cells: 1, see below
+
+example:
+
+reset_ahb1: reset@40023810 {
+ #reset-cells = <1>;
+ compatible = "st,stm32-reset";
+ reg = <0x40023810 0x4>;
+};
+
+Specifying softreset control of devices
+=======================================
+
+Device nodes should specify the reset channel required in their "resets"
+property, containing a phandle to the reset device node and an index specifying
+which channel to use, as described in reset.txt
+
+example:
+
+ timer2 {
+ resets = <&resets TIM2_RESET>;
+ };
+
+Macro definitions for the supported reset channels can be found in:
+
+include/dt-bindings/reset/st,stm32f429.h
--
1.9.1
^ permalink raw reply related
* [PATCH v2 07/18] drivers: reset: Add STM32 reset driver
From: Maxime Coquelin @ 2015-02-20 18:01 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Jonathan Corbet, Maxime Coquelin, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Arnd Bergmann, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will
In-Reply-To: <1424455277-29983-1-git-send-email-mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
The STM32 MCUs family IP can be reset by accessing some shared registers.
The specificity is that some reset lines are used by the timers.
At timer initialization time, the timer has to be reset, that's why
we cannot use a regular driver.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
drivers/reset/Makefile | 1 +
drivers/reset/reset-stm32.c | 124 +++++++++++++++++++++++++++++++
include/dt-bindings/reset/st,stm32f429.h | 85 +++++++++++++++++++++
3 files changed, 210 insertions(+)
create mode 100644 drivers/reset/reset-stm32.c
create mode 100644 include/dt-bindings/reset/st,stm32f429.h
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 157d421..aed12d1 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_RESET_CONTROLLER) += core.o
obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
+obj-$(CONFIG_ARCH_STM32) += reset-stm32.o
obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
obj-$(CONFIG_ARCH_STI) += sti/
diff --git a/drivers/reset/reset-stm32.c b/drivers/reset/reset-stm32.c
new file mode 100644
index 0000000..7a96677
--- /dev/null
+++ b/drivers/reset/reset-stm32.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Heavily based on sunxi driver from Maxime Ripard.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+struct stm32_reset_data {
+ spinlock_t lock;
+ void __iomem *membase;
+ struct reset_controller_dev rcdev;
+};
+
+static int stm32_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct stm32_reset_data *data = container_of(rcdev,
+ struct stm32_reset_data,
+ rcdev);
+ int bank = id / BITS_PER_LONG;
+ int offset = id % BITS_PER_LONG;
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&data->lock, flags);
+
+ reg = readl_relaxed(data->membase + (bank * 4));
+ writel_relaxed(reg | BIT(offset), data->membase + (bank * 4));
+
+ spin_unlock_irqrestore(&data->lock, flags);
+
+ return 0;
+}
+
+static int stm32_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct stm32_reset_data *data = container_of(rcdev,
+ struct stm32_reset_data,
+ rcdev);
+ int bank = id / BITS_PER_LONG;
+ int offset = id % BITS_PER_LONG;
+ unsigned long flags;
+ u32 reg;
+
+ spin_lock_irqsave(&data->lock, flags);
+
+ reg = readl_relaxed(data->membase + (bank * 4));
+ writel_relaxed(reg & ~BIT(offset), data->membase + (bank * 4));
+
+ spin_unlock_irqrestore(&data->lock, flags);
+
+ return 0;
+}
+
+static struct reset_control_ops stm32_reset_ops = {
+ .assert = stm32_reset_assert,
+ .deassert = stm32_reset_deassert,
+};
+
+static void stm32_reset_init(struct device_node *np)
+{
+ struct stm32_reset_data *data;
+ struct resource res;
+ resource_size_t size;
+ int err;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return;
+
+ err = of_address_to_resource(np, 0, &res);
+ if (err)
+ goto err_alloc;
+
+ size = resource_size(&res);
+ if (!request_mem_region(res.start, size, np->name)) {
+ err = -EINVAL;
+ goto err_alloc;
+ }
+
+ data->membase = ioremap(res.start, size);
+ if (!data->membase) {
+ err = -ENOMEM;
+ goto err_alloc;
+ }
+
+ spin_lock_init(&data->lock);
+
+ data->rcdev.owner = THIS_MODULE;
+ data->rcdev.nr_resets = size * 8;
+ data->rcdev.ops = &stm32_reset_ops;
+ data->rcdev.of_node = np;
+
+ err = reset_controller_register(&data->rcdev);
+ if (err)
+ goto err_iomap;
+
+ pr_info("%s: %d reset lines registered\n", np->full_name,
+ data->rcdev.nr_resets);
+ return;
+
+err_iomap:
+ iounmap(data->membase);
+err_alloc:
+ kfree(data);
+ pr_err("%s: Reset ctrl registration failed (%d).\n",
+ np->full_name, err);
+}
+
+RESET_CONTROLLER_OF_DECLARE(stm32, "st,stm32-reset", stm32_reset_init);
+
diff --git a/include/dt-bindings/reset/st,stm32f429.h b/include/dt-bindings/reset/st,stm32f429.h
new file mode 100644
index 0000000..04f2ba8
--- /dev/null
+++ b/include/dt-bindings/reset/st,stm32f429.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _DT_BINDINGS_RESET_STM32F429_H
+#define _DT_BINDINGS_RESET_STM32F429_H
+
+/* AHB1 */
+#define GPIOA_RESET 0
+#define GPIOB_RESET 1
+#define GPIOC_RESET 2
+#define GPIOD_RESET 3
+#define GPIOE_RESET 4
+#define GPIOF_RESET 5
+#define GPIOG_RESET 6
+#define GPIOH_RESET 7
+#define GPIOI_RESET 8
+#define GPIOJ_RESET 9
+#define GPIOK_RESET 10
+#define CRC_RESET 12
+#define DMA1_RESET 21
+#define DMA2_RESET 22
+#define DMA2D_RESET 23
+#define ETHMAC_RESET 25
+#define OTGHS_RESET 29
+
+/* AHB2 */
+#define DCMI_RESET 32
+#define CRYP_RESET 36
+#define HASH_RESET 37
+#define RNG_RESET 38
+#define OTGFS_RESET 39
+
+/* AHB3 */
+#define FMC_RESET 64
+
+/* APB1 */
+#define TIM2_RESET 128
+#define TIM3_RESET 129
+#define TIM4_RESET 130
+#define TIM5_RESET 131
+#define TIM6_RESET 132
+#define TIM7_RESET 133
+#define TIM12_RESET 134
+#define TIM13_RESET 135
+#define TIM14_RESET 136
+#define WWDG_RESET 139
+#define SPI2_RESET 142
+#define SPI3_RESET 143
+#define UART2_RESET 145
+#define UART3_RESET 146
+#define UART4_RESET 147
+#define UART5_RESET 148
+#define I2C1_RESET 149
+#define I2C2_RESET 150
+#define I2C3_RESET 151
+#define CAN1_RESET 153
+#define CAN2_RESET 154
+#define PWR_RESET 156
+#define DAC_RESET 157
+#define UART7_RESET 158
+#define UART8_RESET 159
+
+/* APB2 */
+#define TIM1_RESET 160
+#define TIM8_RESET 161
+#define USART1_RESET 164
+#define USART6_RESET 165
+#define ADC_RESET 168
+#define SDIO_RESET 171
+#define SPI1_RESET 172
+#define SPI4_RESET 173
+#define SYSCFG_RESET 174
+#define TIM9_RESET 176
+#define TIM10_RESET 177
+#define TIM11_RESET 178
+#define SPI5_RESET 180
+#define SPI6_RESET 181
+#define SAI1_RESET 182
+#define LTDC_RESET 186
+
+#endif /* _DT_BINDINGS_RESET_STM32F429_H */
+
--
1.9.1
^ permalink raw reply related
* [PATCH v2 08/18] dt-bindings: Document the STM32 timer bindings
From: Maxime Coquelin @ 2015-02-20 18:01 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Jonathan Corbet, Maxime Coquelin, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Arnd Bergmann, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will
In-Reply-To: <1424455277-29983-1-git-send-email-mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This adds documentation of device tree bindings for the
STM32 timer.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
.../devicetree/bindings/timer/st,stm32-timer.txt | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 Documentation/devicetree/bindings/timer/st,stm32-timer.txt
diff --git a/Documentation/devicetree/bindings/timer/st,stm32-timer.txt b/Documentation/devicetree/bindings/timer/st,stm32-timer.txt
new file mode 100644
index 0000000..7fffcd8
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/st,stm32-timer.txt
@@ -0,0 +1,19 @@
+. STMicroelectronics STM32 timer
+
+The STM32 MCUs family has several general-purpose 16 and 32 bits timers.
+
+Required properties:
+- compatible : Should be st,stm32-timer"
+- reg : Address and length of the register set
+- clocks : Reference on the timer input clock
+- interrupts : Reference to the timer interrupt
+
+Example:
+
+timer5: timer@40000c00 {
+ compatible = "st,stm32-timer";
+ reg = <0x40000c00 0x400>;
+ interrupts = <50>;
+ resets = <&reset_apb1 3>;
+ clocks = <&clk_pmtr1>;
+};
--
1.9.1
^ permalink raw reply related
* [PATCH v2 09/18] clockevent: Add STM32 Timer driver
From: Maxime Coquelin @ 2015-02-20 18:01 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Jonathan Corbet, Maxime Coquelin, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Arnd Bergmann, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will
In-Reply-To: <1424455277-29983-1-git-send-email-mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
STM32 MCUs feature 16 and 32 bits general purpose timers with prescalers.
The drivers detects whether the time is 16 or 32 bits, and applies a
1024 prescaler value if it is 16 bits.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
drivers/clocksource/Kconfig | 9 ++
drivers/clocksource/Makefile | 1 +
drivers/clocksource/timer-stm32.c | 187 ++++++++++++++++++++++++++++++++++++++
3 files changed, 197 insertions(+)
create mode 100644 drivers/clocksource/timer-stm32.c
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index fb6011e..f372329 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -91,6 +91,15 @@ config CLKSRC_EFM32
Support to use the timers of EFM32 SoCs as clock source and clock
event device.
+config CLKSRC_STM32
+ bool "Clocksource for STM32 SoCs" if !ARCH_STM32
+ depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
+ select CLKSRC_MMIO
+ default ARCH_STM32
+ help
+ Support to use the timers of STM32 SoCs as clock source and clock
+ event device.
+
config ARM_ARCH_TIMER
bool
select CLKSRC_OF if OF
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index eeea736..8078178 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o
obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm_kona_timer.o
obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o
obj-$(CONFIG_CLKSRC_EFM32) += time-efm32.o
+obj-$(CONFIG_CLKSRC_STM32) += timer-stm32.o
obj-$(CONFIG_CLKSRC_EXYNOS_MCT) += exynos_mct.o
obj-$(CONFIG_CLKSRC_SAMSUNG_PWM) += samsung_pwm_timer.o
obj-$(CONFIG_FSL_FTM_TIMER) += fsl_ftm_timer.o
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
new file mode 100644
index 0000000..9839f57
--- /dev/null
+++ b/drivers/clocksource/timer-stm32.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) Maxime Coquelin 2015
+ * Author: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Inspired by time-efm32.c from Uwe Kleine-Koenig
+ */
+
+#include <linux/kernel.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+#define TIM_CR1 0x00
+#define TIM_DIER 0x0c
+#define TIM_SR 0x10
+#define TIM_EGR 0x14
+#define TIM_PSC 0x28
+#define TIM_ARR 0x2c
+
+#define TIM_CR1_CEN BIT(0)
+#define TIM_CR1_OPM BIT(3)
+#define TIM_CR1_ARPE BIT(7)
+
+#define TIM_DIER_UIE BIT(0)
+
+#define TIM_SR_UIF BIT(0)
+
+#define TIM_EGR_UG BIT(0)
+
+struct stm32_clock_event_ddata {
+ struct clock_event_device evtdev;
+ unsigned periodic_top;
+ void __iomem *base;
+};
+
+static void stm32_clock_event_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evtdev)
+{
+ struct stm32_clock_event_ddata *data =
+ container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
+ void *base = data->base;
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ writel_relaxed(data->periodic_top, base + TIM_ARR);
+ writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, base + TIM_CR1);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ default:
+ writel_relaxed(0, base + TIM_CR1);
+ break;
+ }
+}
+
+static int stm32_clock_event_set_next_event(unsigned long evt,
+ struct clock_event_device *evtdev)
+{
+ struct stm32_clock_event_ddata *data =
+ container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
+
+ writel_relaxed(evt, data->base + TIM_ARR);
+ writel_relaxed(TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_CEN,
+ data->base + TIM_CR1);
+
+ return 0;
+}
+
+static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
+{
+ struct stm32_clock_event_ddata *data = dev_id;
+
+ writel_relaxed(0, data->base + TIM_SR);
+
+ data->evtdev.event_handler(&data->evtdev);
+
+ return IRQ_HANDLED;
+}
+
+static struct stm32_clock_event_ddata clock_event_ddata = {
+ .evtdev = {
+ .name = "stm32 clockevent",
+ .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
+ .set_mode = stm32_clock_event_set_mode,
+ .set_next_event = stm32_clock_event_set_next_event,
+ .rating = 200,
+ },
+};
+
+static void __init stm32_clockevent_init(struct device_node *np)
+{
+ struct stm32_clock_event_ddata *data = &clock_event_ddata;
+ struct clk *clk;
+ struct reset_control *rstc;
+ unsigned long rate, max_delta;
+ int irq, ret, bits, prescaler = 1;
+
+ clk = of_clk_get(np, 0);
+ if (IS_ERR(clk)) {
+ ret = PTR_ERR(clk);
+ pr_err("failed to get clock for clockevent (%d)\n", ret);
+ goto err_clk_get;
+ }
+
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ pr_err("failed to enable timer clock for clockevent (%d)\n",
+ ret);
+ goto err_clk_enable;
+ }
+
+ rate = clk_get_rate(clk);
+
+ rstc = of_reset_control_get(np, NULL);
+ if (IS_ERR(rstc)) {
+ pr_err("%s: Failed to get reset\n", np->full_name);
+ return;
+ }
+
+ reset_control_assert(rstc);
+ reset_control_deassert(rstc);
+
+ data->base = of_iomap(np, 0);
+ if (!data->base) {
+ pr_err("failed to map registers for clockevent\n");
+ goto err_iomap;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (!irq) {
+ pr_err("%s: failed to get irq.\n", np->full_name);
+ goto err_get_irq;
+ }
+
+ /* Detect whether the timer is 16 or 32 bits */
+ writel_relaxed(~0UL, data->base + TIM_ARR);
+ max_delta = readl_relaxed(data->base + TIM_ARR);
+ if (max_delta == ~0UL) {
+ prescaler = 1;
+ bits = 32;
+ } else {
+ prescaler = 1024;
+ bits = 16;
+ }
+ writel_relaxed(0, data->base + TIM_ARR);
+
+ writel_relaxed(prescaler - 1, data->base + TIM_PSC);
+ writel_relaxed(TIM_EGR_UG, data->base + TIM_EGR);
+ writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
+ writel_relaxed(0, data->base + TIM_SR);
+
+ data->periodic_top = DIV_ROUND_CLOSEST(rate, prescaler * HZ);
+
+ clockevents_config_and_register(&data->evtdev,
+ DIV_ROUND_CLOSEST(rate, prescaler),
+ 0x1, max_delta);
+
+ ret = request_irq(irq, stm32_clock_event_handler, IRQF_TIMER,
+ "stm32 clockevent", data);
+ if (ret) {
+ pr_err("%s: failed to request irq.\n", np->full_name);
+ goto err_get_irq;
+ }
+
+ pr_info("%s: STM32 clockevent driver initialized (%d bits)\n",
+ np->full_name, bits);
+
+ return;
+
+err_get_irq:
+ iounmap(data->base);
+err_iomap:
+ clk_disable_unprepare(clk);
+err_clk_enable:
+ clk_put(clk);
+err_clk_get:
+ return;
+}
+
+CLOCKSOURCE_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init);
--
1.9.1
^ permalink raw reply related
* [PATCH v2 10/18] dt-bindings: Document the STM32 pin controller
From: Maxime Coquelin @ 2015-02-20 18:01 UTC (permalink / raw)
To: u.kleine-koenig-bIcnvbaLZ9MEGnE8C9+IrQ, afaerber-l3A5Bk7waGM,
geert-Td1EMuHUCqxL1ZNQvxDV9g, Rob Herring, Philipp Zabel,
Jonathan Corbet, Maxime Coquelin, Pawel Moll, Mark Rutland,
Ian Campbell, Kumar Gala, Russell King, Daniel Lezcano,
Thomas Gleixner, Linus Walleij, Greg Kroah-Hartman, Jiri Slaby,
Arnd Bergmann, Andrew Morton, David S. Miller,
Mauro Carvalho Chehab, Joe Perches, Antti Palosaari, Tejun Heo,
Will
In-Reply-To: <1424455277-29983-1-git-send-email-mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This adds documentation of device tree bindings for the
STM32 pin controller.
Signed-off-by: Maxime Coquelin <mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
.../devicetree/bindings/pinctrl/pinctrl-stm32.txt | 99 ++++++++++++++++++++++
1 file changed, 99 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
new file mode 100644
index 0000000..0fb5b24
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
@@ -0,0 +1,99 @@
+* STM32 GPIO and Pin Mux/Config controller
+
+STMicroelectronics's STM32 MCUs intregrate a GPIO and Pin mux/config hardware
+controller. It controls the input/output settings on the available pins and
+also provides ability to multiplex and configure the output of various on-chip
+controllers onto these pads.
+
+Pin controller node:
+Required properies:
+- compatible : "st,stm32-pinctrl"
+- #address-cells: The value of this property must be 1
+- #size-cells : The value of this property must be 1
+- ranges : defines mapping between pin controller node (parent) to
+ gpio-bank node (children).
+
+GPIO controller/bank node:
+Required properties:
+- gpio-controller : Indicates this device is a GPIO controller
+- #gpio-cells : Should be two.
+ The first cell is the pin number
+ The second one is the polarity:
+ - 0 for active high
+ - 1 for active low
+- reg : The gpio address range, relative to the pinctrl range
+- st,bank-name : Should be a name string for this bank as specified in
+ the datasheet
+
+Optional properties:
+- reset: : Reference to the reset controller
+
+Example:
+#include <dt-bindings/pinctrl/pinctrl-stm32.h>
+...
+
+ pin-controller {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "st,stm32-pinctrl";
+ ranges = <0 0x40020000 0x3000>;
+
+ gpioa: gpio@40020000 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ reg = <0x0 0x400>;
+ resets = <&reset_ahb1 0>;
+ st,bank-name = "GPIOA";
+ };
+ ...
+ pin-functions nodes follow...
+ };
+
+Contents of function subnode node:
+----------------------------------
+
+Required properties for pin configuration node:
+- st,pins : Child node with list of pins with configuration.
+
+Below is the format of how each pin conf should look like.
+
+<bank offset altmode pull type speed>
+
+Every PIO is represented with 4 to 6 parameters.
+Each parameter is explained as below.
+
+- bank : Should be bank phandle to which this PIO belongs.
+- offset : Offset in the PIO bank.
+- altmode : Should be mode or alternate function number associated this pin, as
+described in the datasheet (IN, OUT, ALT0...ALT15, ANALOG)
+- pull : Should be either NO_PULL, PULL_UP or PULL_DOWN
+- type : Should be either PUSH_PULL or OPEN_DRAIN.
+ Setting it is not needed for IN and ANALOG modes, or alternate
+ functions acting as inputs.
+- speed : Value taken from the datasheet, depending on the function
+(LOW_SPEED, MEDIUM_SPEED, FAST_SPEED, HIGH_SPEED)
+ Setting it is not needed for IN and ANALOG modes, or alternate
+ functions acting as inputs.
+
+usart1 {
+ pinctrl_usart1: usart1-0 {
+ st,pins {
+ tx = <&gpioa 9 ALT7 NO_PULL PUSH_PULL LOW_SPEED>;
+ rx = <&gpioa 10 ALT7 NO_PULL PUSH_PULL LOW_SPEED>;
+ };
+ };
+};
+
+adc2 {
+ pinctrl_adc2: adc2-0 {
+ st,pins {
+ adc0 = <&gpioe 4 ANALOG NO_PULL>;
+ };
+ };
+};
+
+usart1: usart@40011000 {
+ ...
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usart1>;
+};
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox