This patch series adds a basic device tree based boot for Samsung's Exynos4
platforms and specifically for smdkv310 board. Device tree based driver
probe is added for uart, sdhci and watchdog drivers. These patches
enable booting to console on smdkv310 board with some of the devices
initialized with data from the device tree.
This patch series is based on
git.secretlab.ca/git/linux-2.6.git devicetree/test
and depends on the following patches which are not yet available in
the devicetree/test branch.
1. [PATCH] ARM: EXYNOS4: Fix card detection for sdhci 0 and 2
[http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg04704.html]
2. [PATCH] ARM: EXYNOS4: Fix missing S5P_VA_AUDSS definition
[http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg04866.html]
3. [PATCH 0/9] Add clkdev support for Samsung platforms
[http://www.mail-archive.com/linux-samsung-soc@vger.kernel.org/msg04874.html]
4. Consolidate the clkdev header files
[http://patchwork.ozlabs.org/patch/97862/]
Thomas Abraham (6):
serial: samsung: Keep a copy of platform data in driver's private data
serial: samsung: Add device tree support for s5pv210 uart driver
watchdog: s3c2410: Add support for device tree based probe
mmc: sdhci-s3c: Add support for device tree based probe
arm: dts: Add nodes in smdkv310 device tree source file
arm: exynos4: Add a new Exynos4 device tree enabled machine
Documentation/devicetree/bindings/arm/samsung.txt | 3 +-
.../bindings/tty/serial/samsung_uart.txt | 50 +++++++
.../devicetree/bindings/watchdog/samsung-wdt.txt | 12 ++
arch/arm/boot/dts/exynos4-smdkv310.dts | 135 +++++++++++++++++++-
arch/arm/mach-exynos4/Kconfig | 11 ++
arch/arm/mach-exynos4/Makefile | 1 +
arch/arm/mach-exynos4/mach-exynos4-dt.c | 94 ++++++++++++++
drivers/mmc/host/sdhci-s3c.c | 11 ++
drivers/tty/serial/s5pv210.c | 39 +++++-
drivers/tty/serial/samsung.c | 114 ++++++++++++++++-
drivers/tty/serial/samsung.h | 4 +-
drivers/watchdog/s3c2410_wdt.c | 10 ++
12 files changed, 473 insertions(+), 11 deletions(-)
create mode 100644 Documentation/devicetree/bindings/tty/serial/samsung_uart.txt
create mode 100644 Documentation/devicetree/bindings/watchdog/samsung-wdt.txt
create mode 100644 arch/arm/mach-exynos4/mach-exynos4-dt.c
Hi Jim,
(I'm CCing linaro-dev@ because I figure others might have similar
questions)
This is because the android patches are going to the 'Unknown'
project[1], which is ignored when generating the statistics[2]. We
currently can't automatically detect the correct project for such
patches because they are all sent to linaro-dev@ instead of their own
mailing list like other projects. Maybe we could try and detect the
correct project from the subject's prefix (e.g. [android/bionic]), but
even then I suspect these patches are not really going to AOSP, in which
case they wouldn't be included in the statistics either (much like the
gcc-linaro and linaro-kernel projects).
If I'm mistaken we can just create android projects and move the patches
from the Unknown project to them. A thread I started recently (Subject:
Please help us setup patches.linaro.org) on linaro-dev@ has more
information on how to do that.
[1] <http://patches.linaro.org/patchwork/project/other-unknown/list/?state=*>
[2] <http://patches.linaro.org/faq>
Cheers,
On Wed, 2011-06-22 at 18:22 +0800, Jim Huang wrote:
> hi Guilherme,
>
> I just checked the stat of Patches from the "Linaro Android Team" team:
> http://patches.linaro.org/team/linaro-android/
>
> I am quite confused about the number. I did submit patches to
> linaro-dev and Cc. to patches(a)linaro.org and
> you can find out the recent merged patches here: (Recently closed)
> https://review.source.android.com//#dashboard,1002471
>
> Is there any problem for stat? Or, can I help to improve it?
>
> Thanks,
> -jserv
--
Guilherme Salgado <https://launchpad.net/~salgado>
Hi -
I mentioned this already to npitre but for various reasons we are
planning to target 3.0 kernel rather than linux-linaro-2.6.39 at the
moment. 2.6.39 has some known issues like no onboard audio or HDMI
audio, but since 3.0 has a new and better ALSA implementation for Panda
I'm not sure it's worth spending time on when the old implementation
won't really go into linux-linaro even if we did forward-port it again.
I introduced two new branches yesterday:
http://git.linaro.org/gitweb?p=people/andygreen/kernel-tilt.git;a=shortlog;…
- omap4_defconfig
http://git.linaro.org/gitweb?p=people/andygreen/kernel-tilt.git;a=shortlog;…
- android_omap4_defconfig
that are linus' HEAD and common-3.0 (androidized nearly linus HEAD)
based and have the API v4403 SGX stuff on them.
The status is currently on linus HEAD, Panda EHCI is broken which is a
bit of a downer; Jassi is taking a look at it. Also video is coming up
nicely with 1080p raster, but it is stuck at 640 x 480 framebuffer
viewport inside that right now.
However, Android rootfs is able to boot to the desktop (v4403 3D
accelerated) with tilt-tracking-android, and X can come up unaccelerated
as usual as well on Ubuntu on tilt-tracking. So it's not a bad start.
When linux-linaro-3.0 is coming in the next weeks, we will use that as a
base instead as before.
-Andy
--
Andy Green | TI Landing Team Leader
Linaro.org │ Open source software for ARM SoCs | Follow Linaro
http://facebook.com/pages/Linaro/155974581091106 -
http://twitter.com/#!/linaroorg - http://linaro.org/linaro-blog
Hi,
I tried with the precompiled u-boot and MLO and it is working fine.
But failed with the sources downloaded from the link provided. Can you
please any addition settngs need to be done for the sources. I have used
OMAP4_PANDA_CONFIG.
You can find my WIP tree at
https://gitorious.org/ubuntu-experimental/linaro-u-boot/commits/u-boot-mast…
Please comment.
Regards
Krishna M.
Linus W,
This "patch" is a quick-and-dirty outline of where I'd love to see the
pinmux API go, but this time in code rather than English description.
Note that I elided a bunch of stuff from the headers; some comments weren't
updated, I removed the inline functions for when pinmux is disabled, etc.
The code has not been compiled. The main idea is just to give an idea of
what I'm thinking.
Let me know if any of this looks reasonable to you; if so, I can look into
fixing the issues above, making the core pinmux code actually work in this
model, or whatever.
Thanks!
---
drivers/pinctrl/pinmux-tegra2.c | 85 ++++++++++++++++++++++
include/linux/pinctrl/consumer.h | 47 ++++++++++++
include/linux/pinctrl/machine.h | 47 ++++++++++++
include/linux/pinctrl/provider.h | 149 ++++++++++++++++++++++++++++++++++++++
4 files changed, 328 insertions(+), 0 deletions(-)
create mode 100644 drivers/pinctrl/pinmux-tegra2.c
create mode 100644 include/linux/pinctrl/consumer.h
create mode 100644 include/linux/pinctrl/machine.h
create mode 100644 include/linux/pinctrl/provider.h
diff --git a/drivers/pinctrl/pinmux-tegra2.c b/drivers/pinctrl/pinmux-tegra2.c
new file mode 100644
index 0000000..d010f9c
--- /dev/null
+++ b/drivers/pinctrl/pinmux-tegra2.c
@@ -0,0 +1,85 @@
+/*
+ * pinctrl driver for NVIDIA Tegra 2
+ *
+ * Author: Stephen Warren <swarren(a)nvidia.com>
+ * Copyright (C) 2011 NVIDIA, Inc.
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/pinmux/provider.h>
+
+struct tegra_pin {
+ struct pinctrl_pin core;
+ int reg_addr; /* e.g. for per-pin config */
+ /* And other info */
+};
+
+struct tegra_function {
+ struct pinctrl_function core;
+ int reg_value;
+ /* And other info */
+}
+
+struct tegra_group {
+ struct pinctrl_group core;
+ int reg_addr; /* e.g. for muxing and per-pin config */
+ int reg_bit;
+ /* And other info */
+}
+
+struct tegra_pin tegra_pins[] = {
+ { .core = { .name = "a0", }, }, /* 0 */
+ { .core = { .name = "a1", }, }, /* 1 */
+ { .core = { .name = "b0", }, }, /* 2 */
+ { .core = { .name = "b1", }, }, /* 3 */
+ { .core = { .name = "c0", }, }, /* 4 */
+ { .core = { .name = "c1", }, }, /* 5 */
+ { .core = { .name = "d0", }, }, /* 6 */
+ { .core = { .name = "d1", }, }, /* 7 */
+ { .core = { .name = "e0", }, }, /* 8 */
+ { .core = { .name = "e1", }, }, /* 9 */
+
+/* Or: */
+#define PIN_B0 2
+ .PIN_B0 = { .core = { .name = "b0", }, },
+};
+
+struct tegra_function tegra_function[] = {
+ { .core = { .name = "kbc-col-1:0", }, 1 }, /* 0 */
+ { .core = { .name = "kbc-row-1:0", }, 2 }, /* 1 */
+ { .core = { .name = "i2c0", }, 3 }, /* 2 */
+ { .core = { .name = "uartrxtx0", }, 4 }, /* 3 */
+ { .core = { .name = "spiclkdata0", }, 5 }, /* 4 */
+ { .core = { .name = "gpioctrlr0", }, 0x8001}, /* 5 */
+ { .core = { .name = "gpioctrlr1", }, 0x8002}, /* 6 */
+
+/* Or: */
+#define FUNC_I2C0 2
+ .FUNC_I2C0 = { .core = { .name = "i2c0", }, 3},
+
+};
+
+int pins_kbca[] = { 0, 1 };
+int funcs_kbca[] = { 0, 5 };
+
+int pins_kbcb[] = { 2, 3 };
+int funcs_kbcb[] = { 1, 5 };
+
+int pins_ddca[] = { 4, 5 };
+int funcs_ddca[] = { 2, 3, 5, 6 };
+
+int pins_ddcb[] = { 6, 7 };
+int funcs_ddcb[] = { 2, 4, 5, 6 };
+
+int pins_xx[] = { 8, 9};
+int funcs_xx[] = { 5, 6};
+
+struct tegra_group tegra_groups[] = {
+ { .core = { .name = "kbca", npins = 2, pins = pins_kbca, nfunctions = 2, functions = funcs_kbca} },
+ { .core = { .name = "kbcb", npins = 2, pins = pins_kbcb, nfunctions = 2, functions = funcs_kbcb} },
+ { .core = { .name = "ddca", npins = 2, pins = pins_ddca, nfunctions = 4, functions = funcs_ddca} },
+ { .core = { .name = "ddcb", npins = 2, pins = pins_ddcb, nfunctions = 4, functions = funcs_ddcb} },
+ { .core = { .name = "xx", npins = 2, pins = pins_xx, nfunctions = 2, functions = funcs_xx } },
+};
+
diff --git a/include/linux/pinctrl/consumer.h b/include/linux/pinctrl/consumer.h
new file mode 100644
index 0000000..81cedf3
--- /dev/null
+++ b/include/linux/pinctrl/consumer.h
@@ -0,0 +1,47 @@
+/*
+ * pinctrl subsystem's client/consumer interface
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ * Based on bits of regulator core, gpio core and clk core
+ *
+ * Author: Linus Walleij <linus.walleij(a)linaro.org>
+ *
+ * Copyright (C) 2011 NVIDIA, Inc.
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef __LINUX_PINCTRL_CONSUMER_H
+#define __LINUX_PINCTRL_CONSUMER_H
+
+#include <linux/list.h>
+#include <linux/seq_file.h>
+
+/* This struct is private to the core and should be regarded as a cookie */
+struct pinctrl;
+
+/* Not sure this is useful: */
+extern bool pin_is_valid(int pin);
+
+/* Basic pinmux API: */
+extern struct pinctrl *pinctrl_get(struct device *dev, const char *mapping);
+extern void pinctrl_put(struct pinctrl *pmx);
+extern int pinctrl_enable(struct pinctrl *pmx);
+extern void pinctrl_disable(struct pinctrl *pmx);
+
+/*
+ * Custom config interface:
+ * Drivers would probably use the first function, since they would
+ * already have pinctrl_get()d the mapping they want to configure.
+ *
+ * Generic setup code couuldn't use pinctrl_get since that actually
+ * reserved that mapping. Plus, we potentially need a way to configure
+ * individual pins
+ */
+extern int pinctrl_config(struct pinctrl *pmx, u16 param, unsigned long *data);
+extern int pinctrl_config_group(const char *chip, const char* groupname,
+ u16 param, unsigned long *data);
+extern int pinctrl_config_pin(const char *chip, const char* pinname, u16 param,
+ unsigned long *data);
+
+#endif /* __LINUX_PINCTRL_CONSUMER_H */
diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h
new file mode 100644
index 0000000..5797e84
--- /dev/null
+++ b/include/linux/pinctrl/machine.h
@@ -0,0 +1,47 @@
+/*
+ * pinctrl subsystem's machine/board mapping configuration interface
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ * Based on bits of regulator core, gpio core and clk core
+ *
+ * Author: Linus Walleij <linus.walleij(a)linaro.org>
+ *
+ * Copyright (C) 2011 NVIDIA, Inc.
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef __LINUX_PINMUX_MACHINE_H
+#define __LINUX_PINMUX_MACHINE_H
+
+/**
+ * struct pinctrl_map - boards/machines shall provide this map for devices
+ * @dev_name: the name of the device using this specific mapping, the name
+ * must be the same as in your struct device*
+ * @mapping: the mapping name being defined
+ * @chip: the chip on which to set the mux
+ * @group: the group on which to set the mux
+ * @function: the function to select
+ */
+/*
+ * Example:
+ * { "tegra-kbc", NULL, "tegra", "kbca", "kbc-col-1:0" },
+ * { "tegra-kbc", NULL, "tegra", "kbcb", "kbc-row-1:0" },
+ * { "tegra-i2c.0", "bus0", "tegra", "ddca", "i2c0" },
+ * { "tegra-i2c.0", "bus1", "tegra", "ddcb", "i2c0" },
+ * { NULL, "bootup", "tegra", "xx", "gpioctrlr0" },
+ *
+ * (Machine boot code searches for "bootup" and activates everything there)
+ */
+struct pinctrl_map {
+ const char *dev_name;
+ const char *mapping;
+ const char *chip;
+ const char *group;
+ const char *function;
+};
+
+extern int pinctrl_register_mappings(struct pinctrl_map const *map,
+ unsigned num_maps);
+
+#endif /* __LINUX_PINCTRL_MACHINE_H */
diff --git a/include/linux/pinctrl/provider.h b/include/linux/pinctrl/provider.h
new file mode 100644
index 0000000..ee355f3
--- /dev/null
+++ b/include/linux/pinctrl/provider.h
@@ -0,0 +1,149 @@
+/*
+ * pinctrl subsystem's pinctrl driver interface
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ * Based on bits of regulator core, gpio core and clk core
+ *
+ * Author: Linus Walleij <linus.walleij(a)linaro.org>
+ *
+ * Copyright (C) 2011 NVIDIA, Inc.
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef __LINUX_PINCTRL_PROVIDER_H
+#define __LINUX_PINCTRL_PROVIDER_H
+
+#include <linux/list.h>
+#include <linux/seq_file.h>
+
+struct pinctrl_dev;
+
+struct pinctrl_pin {
+ char *name;
+};
+
+struct pinctrl_function {
+ char *name;
+};
+
+struct pinctrl_group {
+ char *name;
+ int npins;
+ int *pinids;
+ int nfunctions;
+ int *functionids;
+};
+
+/**
+ * struct pinctrl_ops - pinctrl operations, to be implemented by drivers
+ * @request: called by the core to see if a certain pin can be made available
+ * available for muxing. This is called by the core to acquire the pins
+ * before selecting any actual mux setting across a function. The driver
+ * is allowed to answer "no" by returning a negative error code
+ * @free: the reverse function of the request() callback, frees a pin after
+ * being requested
+ * @enable: enable a certain muxing enumerator. The driver does not need to
+ * figure out whether enabling this function conflicts some other use
+ * of the pins, such collisions are handled by the pinctrl subsystem
+ * @disable: disable a certain muxing enumerator
+ * @config: custom configuration function for a certain muxing enumerator -
+ * this works a bit like an ioctl() and can pass in and return arbitrary
+ * configuration data to the pinctrl
+ * @dbg_show: optional debugfs display hook that will provide per-device
+ * info for a certain pin in debugfs
+ */
+struct pinctrl_ops {
+ struct pinctrl_pin *(*get_pin) (struct pinctrl_dev *pctrldev, int id);
+ struct pinctrl_function *(*get_function) (struct pinctrl_dev *pctrldev,
+ int id);
+ struct pinctrl_group *(*get_group) (struct pinctrl_dev *pctrldev,
+ int id);
+
+ /*
+ * request is still problematic; to perform any custom rules, the
+ * driver must compare the requested assignment to the previously
+ * requested, but not necessarily enabled, state. This means the
+ * driver must:
+ * a) Maintain a mirror of the requested state that the core is
+ * already managing.
+ * b) Have some way to look into the state that the core is
+ * already managing. This could be implemented by storing (part
+ * of) that state in the driver-provided struct pinctrl_groups
+ */
+ int (*request) (struct pinctrl_dev *pctrldev, int groupid,
+ int functionid);
+ int (*free) (struct pinctrl_dev *pctrldev, int groupid);
+
+ int (*enable) (struct pinctrl_dev *pctrldev, int groupid,
+ int functionid);
+ void (*disable) (struct pinctrl_dev *pctrldev, int groupid);
+
+ int (*config_pin) (struct pinctrl_dev *pctrldev, int pinid, u16 param,
+ unsigned long *data);
+ int (*config_group) (struct pinctrl_dev *pctrldev, int groupid,
+ u16 param, unsigned long *data);
+
+ void (*dbg_show_pin) (struct pinctrl_dev *pctrldev, struct seq_file *s,
+ int pinid);
+ void (*dbg_show_group) (struct pinctrl_dev *pctrldev,
+ struct seq_file *s, int groupid);
+};
+
+/**
+ * struct pinctrl_desc - pinctrl descriptor, register this to pinctrl subsystem
+ * @name: name for the pinctrl
+ * @ops: pinctrl operation table
+ * @owner: module providing the pinctrl, used for refcounting
+ * @base: the number of the first pin handled by this pinctrl, in the global
+ * pin space, subtracted from a given pin to get the offset into the range
+ * of a certain pinctrl
+ * @npins: the number of pins handled by this pinctrl - if your driver handles
+ * 8 pins that each can be muxed in 3 different ways, you reserve 8
+ * pins in the global pin space and set this to 8
+ */
+struct pinctrl_desc {
+ const char *name;
+ struct pinctrl_ops *ops;
+ struct module *owner;
+ int base;
+ int npins;
+ int nfunctions;
+ int ngroups;
+};
+
+/**
+ * struct pinctrl_dev - pinctrl class device
+ * @desc: the descriptor supplied when initializing this pinctrl
+ * @node: node to include this pinctrl in the global pinctrl list
+ * @dev: the device entry for this pinctrl
+ * @owner: module providing the pinctrl, used for refcounting
+ * @driver_data: driver data for drivers registering to the subsystem
+ *
+ * This should be dereferenced and used by the pinctrl core ONLY
+ */
+struct pinctrl_dev {
+ const struct pinctrl_desc *desc;
+ struct list_head node;
+ struct device dev;
+ struct module *owner;
+ void *driver_data;
+};
+
+/* These should only be used from drives */
+static inline const char *pctrldev_get_name(struct pinctrl_dev *pctrldev)
+{
+ /* We're not allowed to register devices without name */
+ return pctrldev->desc->name;
+}
+
+static inline void *pctrldev_get_drvdata(struct pinctrl_dev *pctrldev)
+{
+ return pctrldev->driver_data;
+}
+
+extern struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pmxdesc,
+ struct device *dev, void *driver_data);
+extern void pinctrl_unregister(struct pinctrl_dev *pctrldev);
+
+#endif /* __LINUX_PINCTRL_PROVIDER_H */
--
1.7.0.4
Nicolas, Dave,
make omap4_defconfig
make menuconfig and turn on THUMB2_KERNEL
make
.....
CC arch/arm/kernel/smp_twd.o
CC arch/arm/kernel/machine_kexec.o
AS arch/arm/kernel/relocate_kernel.o
arch/arm/kernel/relocate_kernel.S: Assembler messages:
arch/arm/kernel/relocate_kernel.S:10: Error: invalid offset, value too
big (0xFFFFFFFFFFFFFFFC)
arch/arm/kernel/relocate_kernel.S:11: Error: invalid offset, value too
big (0xFFFFFFFFFFFFFFFC)
arch/arm/kernel/relocate_kernel.S:58: Error: invalid offset, value too
big (0xFFFFFFFFFFFFFFFC)
arch/arm/kernel/relocate_kernel.S:59: Error: invalid offset, value too
big (0xFFFFFFFFFFFFFFFC)
make[1]: *** [arch/arm/kernel/relocate_kernel.o] Error 1
make: *** [arch/arm/kernel] Error 2
Sorry it took a while to get back to you guys. I was visiting customers last week. Most of my comments are just highlighting the differences between TI's STM 1.0 driver and ST-E's STM 1.0 driver, but there are a few questions, observations and suggestions. At the end I included some discussion on TI's meta data and OST header requirements.
I have not had a chance to look at your actual implementation yet. Did you do anything to abstract the actual HW transport ports and control registers from the higher level driver functions?
I realize there is a lot here to work through so if you would rather schedule a conference call to talk through the differences I can do that. I would like to start work on a Linaro (Unified) STM Spec next week if I can get feedback from everybody over the next few days. I will be out of the office on 5/27 and 5/31.
I am especially interested in details of what you guys have in mind for a "common trace framework to receive STM drivers". If by framework you mean well defined APIs that are implemented for specific devices, then I think we are in agreement. What Michael and I have talked about is a common STM user mode experience across all Linaro supported devices, making Linux user mode code 100% portable between our devices.
ST-E STM Driver stm-trace.txt review:
1. Software Overview
In your "Software Overview" it states:
"The end of data packet is marked by a time stamp on latest byte(s) only."
I assume that user messages can be made up of any number of bytes, half-words, words or longs (what ever is most efficient) and you simply terminate the last element of the message with a time-stamp - right?
In the TI STM implementation a message can be any number and combination of bytes, half-words, or word transfers terminated with a time-stamp on the last element. In addition to that we also add an OST header to a message. (See below for discussion on OST header).
2. Lossless/Lossy modes.
TI only supports lossless mode for sw generated messages and is enforced in our hw implementation. Lossy mode is reserved for true hw messages.
I did not notice that you documented a way to modify this through the debugfs API or IOCTLS.
I am kind of thinking that may be ok since this is really a hw configuration choice in your case, but in the TI case the user does not get to make that choice.
3. Channel Assignment
TI makes the assignment with mknod using the minor number to assign a fixed channel. This allows the user mode application to overload the channel usage for categorizing data (not my idea). I think we see the error of our ways here and will be ok with a dynamic channel allocation.
I am thinking that for each unique pid a channel should be assigned when the device is opened. I would guess you are keeping a channel table around and write() just checks the table for a pid assignment (no time to look at your implementation yet), if none is found the first free channel is used. If you moved this function back to open then you could do the IOCTL STM_GET_CHANNEL_NO anytime, not just after the first write.
In write how do you flag an error if you exhaust the number of available channels?
4. Kernel API
TI does not support a Kernel API (yet). I can see that the Alloc/Free and File IO type functions are useful and should be standard.
Not sure what you mean by "lockless" trace functions?
It looks like your "low level atomic trace functions for 1, 2, 4 or 8 bytes" is similar to TI's binary library functions (not supported by the TI STM Driver). This is what we use the OST header for, allowing our tool chain to differentiate between different message formats, rather than just assuming the data is a simple stream of bytes.
5. Debugfs APIs.
TI used a different approach. The tool-chain on the host provides all the transport setup through JTAG, so our driver does not support setting up the actual STM data export (number of pins and clock rate). In our case device transport parameters must match the host receiver's collection setup.
With your approach the user can change the clock rate and export pin width effectively at any time. Our tools actually go through a calibration process during initialization so any changes to the device's transport setup (clock rate, number of pins data exported on) would cause the TI tool chain a lot of grief.
There are some parameters we know we need to add (like master enables). This are currently also handled by the host tools. TI's STM module allows up to 4 SW masters to be enabled (with id masks that can be used to enable multiple masters from the same group) and 4 HW masters that can be enabled at the same time as the SW masters. If the user tries to enable more than the HW allows do you have a mechanism to flag an error?
I don't have a lot of experience with debugfs but I am assuming it's primarily used for allowing scripts to configure a driver (like in your example) or extract information.
We may want to define a standard set of debugfs options whose implementation is vendor specific. But that raises some questions:
- How do we deal with options that don't make sense for a specific vendor?
Maybe just doing nothing is acceptable or do we want to provide a discovery mechanism?
- Would user scripts then also be vendor specific?
We should probably make an effort to avoid this. A discovery mechanism may allow user mode scripts to be generic.
6. Mapped Channels
I believe the TI hw transport channel mapping is compatible. In the TI case a channel is mapped into two spaces, the first half is for non-timestamp transfers and the second half is for time-stamped transfers. When we write a message (from a user mode write call for example) we simply write all the data except the last element through the non-timestamp port, and then the last element is written to the time-stamped port. So I think we could be compatible here.
With that said I am not sure about exposing all channels to a user mode library. You are relying on the library to use the convention of getting a free channel from the driver to make sure there are no conflicts. If the channel assignment is made when you open the device, you could conceivably map just the address space needed for the single channel, thus eliminating the need to get a free channel from the driver. In the TI case a single channel's transport mapping is 4K bytes, which matches the typical PAGE_SIZE. I realize not all hw implementations will match up with the PAGE_SIZE, which may be why you simply map all the channels back to user space.
Since free channels can become busy rapidly, maybe a better convention would be to simply use another device node if the user wants the library STM data to be transmitted on a different STM channel than the current process. This may be a case where providing a mechanism (see meta data discussion below) to allow channels to be named for the toolchain may be a good idea (provide task name and process id).
7. 8-byte Writes
TI does not support 64-bit writes with our STM 1.0 module. We may need an IOCTL to get the largest transfer supported for the mmap case. For all other cases this should just be hidden in the device dependent code.
8. Kernel Internal Usage
I like the idea of having dedicated support in the driver for common kernel logging. Any ideas on how you would support kernel STM channel assignments without hard-coding?
We may need a mechanism to communicate the definition of each hard-coded channel to our tools.
The following are TI specific:
9. Data protection
In SMP systems if the processor is switched a new master is generated (in some TI devices). So we protect the data with a mutex to guarantee a complete message is generated by the same master.
10. Meta Data
Our user mode HW libraries use meta data to transport data needed to process the HW profiling STM messages. Items like processor speed, sampling rate, processing options, ... (just a predefined byte buffer our tool-chain understands). The meta data is currently broadcasted on a dedicated channel (255), which conflicts with your hard-coded channel for logging printk output. So we will need to resolve hard-coded conflicts.
We need the driver to support registration and transport of the meta data on demand from the library (when the HW master is disabled, in case the collection buffer is small and circular).
I am thinking an IOCTL could be used to register meta data and then the data simply broadcast on a STM channel (will need to figure out which one) when the HW master is enabled and disabled.
Meta data transmission is problematic for circular buffers (like ETB's) thus the reason for also sending meta data when a hw master is disabled. SW masters are not typically disabled, and our HW does not provide a transmission byte count (remember there are HW messages also being generated in the TI case). So there is no way from a driver we can tell when the recoding buffer will wrap even if the user told us the buffer size. I am thinking the best solution would be to force the user to gracefully disable the channel to get any sw channel meta data provided by the driver.
TI supports three cases of data capture:
- DTC/Host collection (stop on buffer full)
- DTC/Host collection (circular buffer)
- ETB/on-chip collection (circular buffer)
Of if the user is at a point in their code where they know thery will stop recoding on the hOst or ETB, we provide an IOCTL that simply disables all channels.
In the ETB case we may want to simply disable any open STM channels when the user decides to stop recording as a fail safe mechanism.
Note: Periodic transmission of meta data into a small circular buffer will not work well. In cases where the data is sparse the buffer will simply be filled with meta data rather than useful data.
11. OST Headers
Adding an OST header to each message is a requirement for compatibility with TI's toolchain. There are a couple of ways to approach:
Completely hidden from the user - The device specific code will know if the header is necessary. On a write, prior to the copy from user space, the device independent code would have to make a call to get a properly sized memory buffer from the device dependent code that would include the header.
User enabled - Provide an IOCTL that allows the user to put the driver in a tool-chain specific mode (like add OST headers).
Regards,
Doug Deao
________________________________________
From: Philippe Langlais [mailto:philippe.langlais@linaro.org]
Sent: Wednesday, May 04, 2011 3:08 AM
To: Deao, Douglas
Cc: Linus Walleij
Subject: Re: STM at UDS-Budapest
Hi Doug,
On STE ux500 platforms we have the same STM module (follow MIDP STP 1.0), I have already posted our current
implementation to the LKML and Linaro ML, it's very similar to your proposal.
I can't be present to the Linaro summit but Linus Walleij can replace me for this topic, he proposes to write a common
trace framework to receive STM drivers.
Attached all our current proposal and work around STM.
Regards
Philippe Langlais
ST-Ericsson
On 3 May 2011 00:42, Deao, Douglas <d-deao(a)ti.com> wrote:
I am hosting an introductory session on System Trace at the summit. TI's System Trace Module (STM) provides a common protocol for instrumentation messages across multiple cores and system level hardware profiling in complex SoCs. Attached is a whitepaper for background reading.
Looking forward to meeting you at the summit.
Regards,
Doug Deao
Texas Instruments
_______________________________________________
linaro-dev mailing list
linaro-dev(a)lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev