early platform patches
[PATCH 001/011] early platform driver V3
[PATCH 002/011] sh: add plat_early_device_setup() function
[PATCH 003/011] sh: plat_early_device_setup() for sh2
[PATCH 004/011] sh: plat_early_device_setup() for sh2a
[PATCH 005/011] sh: plat_early_device_setup() for sh3
[PATCH 006/011] sh: plat_early_device_setup() for sh4
[PATCH 007/011] sh: plat_early_device_setup() for sh4a
[PATCH 008/011] sh: add early platform support for earlyprintk
[PATCH 009/011] sh-sci: add early platform support
[PATCH 010/011] sh: add early platform support for earlytimer
[PATCH 011/011] sh_cmt: add early platform support
These patches add early platform driver support to the serial port
driver and the CMT timer driver on the SuperH architecture.
The following patch sets posted to linuxsh-dev are required:
- [PATCH 000/013] sh-sci: platform device, clock and console changes
- [PATCH 00/05] sh: timer patches
The early platform driver V3 patch is a replacement for V2 in -mm.
Thanks for the feedback so far, more is always welcome. =)
Signed-off-by: Magnus Damm <[email protected]>
---
Documentation/driver-model/platform.txt | 59 +++++++
arch/sh/Kconfig.debug | 27 ---
arch/sh/include/asm/device.h | 2
arch/sh/kernel/cpu/sh2/setup-sh7619.c | 5
arch/sh/kernel/cpu/sh2a/setup-mxg.c | 5
arch/sh/kernel/cpu/sh2a/setup-sh7201.c | 5
arch/sh/kernel/cpu/sh2a/setup-sh7203.c | 5
arch/sh/kernel/cpu/sh2a/setup-sh7206.c | 5
arch/sh/kernel/cpu/sh3/setup-sh7705.c | 5
arch/sh/kernel/cpu/sh3/setup-sh770x.c | 5
arch/sh/kernel/cpu/sh3/setup-sh7710.c | 5
arch/sh/kernel/cpu/sh3/setup-sh7720.c | 5
arch/sh/kernel/cpu/sh4/setup-sh4-202.c | 5
arch/sh/kernel/cpu/sh4/setup-sh7750.c | 5
arch/sh/kernel/cpu/sh4/setup-sh7760.c | 5
arch/sh/kernel/cpu/sh4a/setup-sh7343.c | 5
arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 5
arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 5
arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 5
arch/sh/kernel/cpu/sh4a/setup-sh7763.c | 5
arch/sh/kernel/cpu/sh4a/setup-sh7770.c | 5
arch/sh/kernel/cpu/sh4a/setup-sh7780.c | 5
arch/sh/kernel/cpu/sh4a/setup-sh7785.c | 5
arch/sh/kernel/cpu/sh4a/setup-shx3.c | 5
arch/sh/kernel/early_printk.c | 142 ------------------
arch/sh/kernel/setup.c | 10 +
arch/sh/kernel/time_32.c | 11 +
drivers/base/platform.c | 239 +++++++++++++++++++++++++++++++
drivers/clocksource/sh_cmt.c | 18 ++
drivers/serial/sh-sci.c | 49 +++++-
include/linux/init.h | 1
include/linux/platform_device.h | 42 +++++
init/main.c | 7
33 files changed, 533 insertions(+), 179 deletions(-)
From: Magnus Damm <[email protected]>
This patch is V3 of the early platform driver implementation.
Platform drivers are great for embedded platforms because we
can separate driver configuration from the actual driver. So
base addresses, interrupts and other configuration can be kept
with the processor or board code, and the platform driver can
be reused by many different platforms.
For early devices we have nothing today. For instance, to configure
early timers and early serial ports we cannot use platform devices.
This because the setup order during boot. Timers are needed before
the platform driver core code is available. The same goes for early
printk support. Early in this case means before initcalls.
These early drivers today have their configuration either hard coded
or they receive it using some special configuration method. This is
working quite well, but if we want to support both regular kernel
modules and early devices then we need to have two ways of configuring
the same driver. A single way would be better.
The early platform driver patch is basically a set of functions that
allow drivers to register themselves and architecture code to locate
them and probe. Registration happens through early_param(). The time
for the probe is decided by the architecture code.
See Documentation/driver-model/platform.txt for more details.
Signed-off-by: Magnus Damm <[email protected]>
---
Tested with serial ports and timers on sh7722 and sh7723.
Changes since V2:
- use strict_strtoul() instead of simple_strtoul()
- command line parsing fixes to support "class_str=drv_name.id"
- added early_platform_add_devices() for device registration
- broke out early_platform_driver_register_all() function
- modified early_platform_driver_probe() to support user_only case
- added cleanup code
- added documentation
Changes since V1:
- changed function names to use "early_" prefix
- use struct early_platform_driver for data
- added support for matching against pdev->id
- use early_platform_init() in device drivers
- added more comments
Documentation/driver-model/platform.txt | 59 +++++++
drivers/base/platform.c | 239 +++++++++++++++++++++++++++++++
include/linux/init.h | 1
include/linux/platform_device.h | 42 +++++
init/main.c | 7
5 files changed, 347 insertions(+), 1 deletion(-)
--- 0001/Documentation/driver-model/platform.txt
+++ work/Documentation/driver-model/platform.txt 2009-01-23 18:41:32.000000000 +0900
@@ -169,3 +169,62 @@ three different ways to find such a matc
be probed later if another device registers. (Which is OK, since
this interface is only for use with non-hotpluggable devices.)
+
+Early Platform Devices and Drivers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The early platform interfaces provide platform data to platform device
+drivers early on during the system boot. The code is built on top of the
+early_param() command line parsing and can be executed very early on.
+
+Example: "earlyprintk" class early serial console in 6 steps
+
+1. Registering early platform device data
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The architecture code registers platform device data using the function
+early_platform_add_devices(). In the case of early serial console this
+should be hardware configuration for the serial port. Devices registered
+at this point will later on be matched against early platform drivers.
+
+2. Parsing kernel command line
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The architecture code calls parse_early_param() to parse the kernel
+command line. This will execute all matching early_param() callbacks.
+User specified early platform devices will be registered at this point.
+For the early serial console case the user can specify port on the
+kernel command line as "earlyprintk=serial.0" where "earlyprintk" is
+the class string, "serial" is the name of the platfrom driver and
+0 is the platform device id. If the id is -1 then the dot and the
+id can be omitted.
+
+3. Installing early platform drivers belonging to a certain class
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The architecture code may optionally force registration of all early
+platform drivers belonging to a certain class using the function
+early_platform_driver_register_all(). User specified devices from
+step 2 have priority over these. This step is omitted by the serial
+driver example since the early serial driver code should be disabled
+unless the user has specified port on the kernel command line.
+
+4. Early platform driver registration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Compiled-in platform drivers making use of early_platform_init() are
+automatically registered during step 2 or 3. The serial driver example
+should use early_platform_init("earlyprintk", &platform_driver).
+
+5. Probing of early platform drivers belonging to a certain class
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The architecture code calls early_platform_driver_probe() to match
+registered early platform devices associated with a certain class with
+registered early platform drivers. Matched devices will get probed().
+This step can be executed at any point during the early boot. As soon
+as possible may be good for the serial port case.
+
+6. Inside the early platform driver probe()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The driver code needs to take special care during early boot, especially
+when it comes to memory allocation and interrupt registration. The code
+in the probe() function can use is_early_platform_device() to check if
+it is called at early platform device or at the regular platform device
+time. The early serial driver performs register_console() at this point.
+
+For further information, see <linux/platform_device.h>.
--- 0001/drivers/base/platform.c
+++ work/drivers/base/platform.c 2009-01-23 16:11:24.000000000 +0900
@@ -956,6 +956,8 @@ int __init platform_bus_init(void)
{
int error;
+ early_platform_cleanup();
+
error = device_register(&platform_bus);
if (error)
return error;
@@ -986,3 +988,240 @@ u64 dma_get_required_mask(struct device
}
EXPORT_SYMBOL_GPL(dma_get_required_mask);
#endif
+
+static __initdata LIST_HEAD(early_platform_driver_list);
+static __initdata LIST_HEAD(early_platform_device_list);
+
+/**
+ * early_platform_driver_register
+ * @edrv: early_platform driver structure
+ * @buf: string passed from early_param()
+ */
+int __init early_platform_driver_register(struct early_platform_driver *epdrv,
+ char *buf)
+{
+ unsigned long index;
+ int n;
+
+ /* Simply add the driver to the end of the global list.
+ * Drivers will by default be put on the list in compiled-in order.
+ */
+ if (!epdrv->list.next) {
+ INIT_LIST_HEAD(&epdrv->list);
+ list_add_tail(&epdrv->list, &early_platform_driver_list);
+ }
+
+ /* If the user has specified device then make sure the driver
+ * gets prioritized. The driver of the last device specified on
+ * command line will be put first on the list.
+ */
+ n = strlen(epdrv->pdrv->driver.name);
+ if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
+ list_move(&epdrv->list, &early_platform_driver_list);
+
+ if (!strcmp(buf, epdrv->pdrv->driver.name))
+ epdrv->requested_id = -1;
+ else if (buf[n] == '.' && strict_strtoul(&buf[n + 1], 10,
+ &index) == 0)
+ epdrv->requested_id = index;
+ else
+ epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
+ }
+
+ return 0;
+}
+
+/**
+ * early_platform_add_devices - add a numbers of early platform devices
+ * @devs: array of early platform devices to add
+ * @num: number of early platform devices in array
+ */
+void __init early_platform_add_devices(struct platform_device **devs, int num)
+{
+ struct device *dev;
+ int i;
+
+ /* simply add the devices to list */
+ for (i = 0; i < num; i++) {
+ dev = &devs[i]->dev;
+
+ if (!dev->devres_head.next) {
+ INIT_LIST_HEAD(&dev->devres_head);
+ list_add_tail(&dev->devres_head,
+ &early_platform_device_list);
+ }
+ }
+}
+
+/**
+ * early_platform_driver_register_all
+ * @class_str: string to identify early platform driver class
+ */
+void __init early_platform_driver_register_all(char *class_str)
+{
+ /* The "class_str" parameter may or may not be present on the kernel
+ * command line. If it is present then there may be more than one
+ * matching parameter.
+ *
+ * Since we register our early platform drivers using early_param()
+ * we need to make sure that they also get registered in the case
+ * when the parameter is missing from the kernel command line.
+ *
+ * We use parse_early_options() to make sure the early_param() gets
+ * called at least once. The early_param() may be called more than
+ * once since the name of the preferred device may be specified on
+ * the kernel command line. early_platform_driver_register() handles
+ * this case for us.
+ */
+ parse_early_options(class_str);
+}
+
+/**
+ * early_platform_match
+ * @edrv: early platform driver structure
+ * @id: id to match against
+ */
+static __init struct platform_device *
+early_platform_match(struct early_platform_driver *epdrv, int id)
+{
+ struct platform_device *pd;
+
+ list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
+ if (platform_match(&pd->dev, &epdrv->pdrv->driver))
+ if(pd->id == id)
+ return pd;
+
+ return NULL;
+}
+
+/**
+ * early_platform_left
+ * @edrv: early platform driver structure
+ * @id: return true if id or above exists
+ */
+static __init int early_platform_left(struct early_platform_driver *epdrv,
+ int id)
+{
+ struct platform_device *pd;
+
+ list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
+ if (platform_match(&pd->dev, &epdrv->pdrv->driver))
+ if(pd->id >= id)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * early_platform_driver_probe_id
+ * @class_str: string to identify early platform driver class
+ * @id: id to match against
+ * @nr_probe: number of platform devices to successfully probe before exiting
+ */
+static int __init early_platform_driver_probe_id(char *class_str,
+ int id,
+ int nr_probe)
+{
+ struct early_platform_driver *epdrv;
+ struct platform_device *match;
+ int match_id;
+ int n = 0;
+ int left = 0;
+
+ list_for_each_entry(epdrv, &early_platform_driver_list, list) {
+ /* only use drivers matching our class_str */
+ if (strcmp(class_str, epdrv->class_str))
+ continue;
+
+ if (id == -2) {
+ match_id = epdrv->requested_id;
+ left = 1;
+
+ } else {
+ match_id = id;
+ left += early_platform_left(epdrv, id);
+
+ /* skip requested id */
+ switch (epdrv->requested_id) {
+ case EARLY_PLATFORM_ID_ERROR:
+ case EARLY_PLATFORM_ID_UNSET:
+ break;
+ default:
+ if (epdrv->requested_id == id)
+ match_id = EARLY_PLATFORM_ID_UNSET;
+ }
+ }
+
+ switch (match_id) {
+ case EARLY_PLATFORM_ID_ERROR:
+ pr_warning("%s: unable to parse %s parameter\n",
+ class_str, epdrv->pdrv->driver.name);
+ /* fall-through */
+ case EARLY_PLATFORM_ID_UNSET:
+ match = NULL;
+ break;
+ default:
+ match = early_platform_match(epdrv, match_id);
+ }
+
+ if (match) {
+ if (epdrv->pdrv->probe(match))
+ pr_warning("%s: unable to probe %s early.\n",
+ class_str, match->name);
+ else
+ n++;
+ }
+
+ if (n >= nr_probe)
+ break;
+ }
+
+ if (left)
+ return n;
+ else
+ return -ENODEV;
+}
+
+/**
+ * early_platform_driver_probe
+ * @class_str: string to identify early platform driver class
+ * @nr_probe: number of platform devices to successfully probe before exiting
+ * @user_only: only probe user specified early platform devices
+ */
+int __init early_platform_driver_probe(char *class_str,
+ int nr_probe,
+ int user_only)
+{
+ int k, n, i;
+
+ n = 0;
+ for (i = -2; n < nr_probe; i++) {
+ k = early_platform_driver_probe_id(class_str, i, nr_probe - n);
+
+ if (k < 0)
+ break;
+
+ n += k;
+
+ if (user_only)
+ break;
+ }
+
+ return n;
+}
+
+/**
+ * early_platform_cleanup - clean up early platform code
+ */
+void __init early_platform_cleanup(void)
+{
+ struct platform_device *pd, *pd2;
+
+ /* clean up the devres list used to chain devices */
+ list_for_each_entry_safe(pd, pd2, &early_platform_device_list,
+ dev.devres_head) {
+ list_del(&pd->dev.devres_head);
+ memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head));
+ }
+}
+
--- 0001/include/linux/init.h
+++ work/include/linux/init.h 2009-01-23 16:11:24.000000000 +0900
@@ -247,6 +247,7 @@ struct obs_kernel_param {
/* Relies on boot_command_line being set */
void __init parse_early_param(void);
+void __init parse_early_options(char *cmdline);
#endif /* __ASSEMBLY__ */
/**
--- 0001/include/linux/platform_device.h
+++ work/include/linux/platform_device.h 2009-01-23 16:11:24.000000000 +0900
@@ -70,4 +70,46 @@ extern int platform_driver_probe(struct
#define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev)
#define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data))
+/* early platform driver interface */
+struct early_platform_driver {
+ const char *class_str;
+ struct platform_driver *pdrv;
+ struct list_head list;
+ int requested_id;
+};
+
+#define EARLY_PLATFORM_ID_UNSET -2
+#define EARLY_PLATFORM_ID_ERROR -3
+
+extern int early_platform_driver_register(struct early_platform_driver *epdrv,
+ char *buf);
+extern void early_platform_add_devices(struct platform_device **devs, int num);
+
+static inline int is_early_platform_device(struct platform_device *pdev)
+{
+ return !pdev->dev.driver;
+}
+
+extern void early_platform_driver_register_all(char *class_str);
+extern int early_platform_driver_probe(char *class_str,
+ int nr_probe, int user_only);
+extern void early_platform_cleanup(void);
+
+
+#ifndef MODULE
+#define early_platform_init(class_string, platform_driver) \
+static __initdata struct early_platform_driver early_driver = { \
+ .class_str = class_string, \
+ .pdrv = platform_driver, \
+ .requested_id = EARLY_PLATFORM_ID_UNSET, \
+}; \
+static int __init early_platform_driver_setup_func(char *buf) \
+{ \
+ return early_platform_driver_register(&early_driver, buf); \
+} \
+early_param(class_string, early_platform_driver_setup_func)
+#else /* MODULE */
+#define early_platform_init(class_string, platform_driver)
+#endif /* MODULE */
+
#endif /* _PLATFORM_DEVICE_H_ */
--- 0001/init/main.c
+++ work/init/main.c 2009-01-23 16:11:24.000000000 +0900
@@ -490,6 +490,11 @@ static int __init do_early_param(char *p
return 0;
}
+void __init parse_early_options(char *cmdline)
+{
+ parse_args("early options", cmdline, NULL, 0, do_early_param);
+}
+
/* Arch code calls this early on, or if not, just before other parsing. */
void __init parse_early_param(void)
{
@@ -501,7 +506,7 @@ void __init parse_early_param(void)
/* All fall through to do_early_param. */
strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
- parse_args("early options", tmp_cmdline, NULL, 0, do_early_param);
+ parse_early_options(tmp_cmdline);
done = 1;
}
From: Magnus Damm <[email protected]>
This patch adds the function plat_early_device_setup() which
cpu code can use for early platform device registation.
Signed-off-by: Magnus Damm <[email protected]>
---
arch/sh/include/asm/device.h | 2 ++
arch/sh/kernel/setup.c | 7 +++++++
2 files changed, 9 insertions(+)
--- 0001/arch/sh/include/asm/device.h
+++ work/arch/sh/include/asm/device.h 2009-01-22 17:03:40.000000000 +0900
@@ -10,3 +10,5 @@ struct platform_device;
int platform_resource_setup_memory(struct platform_device *pdev,
char *name, unsigned long memsize);
+void plat_early_device_setup(void);
+
--- 0001/arch/sh/kernel/setup.c
+++ work/arch/sh/kernel/setup.c 2009-01-22 17:06:39.000000000 +0900
@@ -29,6 +29,7 @@
#include <linux/mmzone.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/page.h>
@@ -329,6 +330,10 @@ static int __init parse_elfcorehdr(char
early_param("elfcorehdr", parse_elfcorehdr);
#endif
+void __init __attribute__ ((weak)) plat_early_device_setup(void)
+{
+}
+
void __init setup_arch(char **cmdline_p)
{
enable_mmu();
@@ -382,6 +387,8 @@ void __init setup_arch(char **cmdline_p)
parse_early_param();
+ plat_early_device_setup();
+
sh_mv_setup();
/*
From: Magnus Damm <[email protected]>
This patch adds sh2 code to register early platform devices
using plat_early_device_setup().
Signed-off-by: Magnus Damm <[email protected]>
---
arch/sh/kernel/cpu/sh2/setup-sh7619.c | 5 +++++
1 file changed, 5 insertions(+)
--- 0013/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ work/arch/sh/kernel/cpu/sh2/setup-sh7619.c 2009-01-23 17:31:44.000000000 +0900
@@ -149,6 +149,11 @@ static int __init sh7619_devices_setup(v
}
__initcall(sh7619_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7619_devices, ARRAY_SIZE(sh7619_devices));
+}
+
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
From: Magnus Damm <[email protected]>
This patch adds sh2a code to register early platform devices
using plat_early_device_setup().
Signed-off-by: Magnus Damm <[email protected]>
---
arch/sh/kernel/cpu/sh2a/setup-mxg.c | 5 +++++
arch/sh/kernel/cpu/sh2a/setup-sh7201.c | 5 +++++
arch/sh/kernel/cpu/sh2a/setup-sh7203.c | 5 +++++
arch/sh/kernel/cpu/sh2a/setup-sh7206.c | 5 +++++
4 files changed, 20 insertions(+)
--- 0014/arch/sh/kernel/cpu/sh2a/setup-mxg.c
+++ work/arch/sh/kernel/cpu/sh2a/setup-mxg.c 2009-01-23 17:30:02.000000000 +0900
@@ -158,6 +158,11 @@ static int __init mxg_devices_setup(void
}
__initcall(mxg_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(mxg_devices, ARRAY_SIZE(mxg_devices));
+}
+
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
--- 0014/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
+++ work/arch/sh/kernel/cpu/sh2a/setup-sh7201.c 2009-01-23 17:28:28.000000000 +0900
@@ -397,6 +397,11 @@ static int __init sh7201_devices_setup(v
}
__initcall(sh7201_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7201_devices, ARRAY_SIZE(sh7201_devices));
+}
+
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
--- 0014/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
+++ work/arch/sh/kernel/cpu/sh2a/setup-sh7203.c 2009-01-23 17:28:47.000000000 +0900
@@ -342,6 +342,11 @@ static int __init sh7203_devices_setup(v
}
__initcall(sh7203_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7203_devices, ARRAY_SIZE(sh7203_devices));
+}
+
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
--- 0014/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ work/arch/sh/kernel/cpu/sh2a/setup-sh7206.c 2009-01-23 17:29:43.000000000 +0900
@@ -243,6 +243,11 @@ static int __init sh7206_devices_setup(v
}
__initcall(sh7206_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7206_devices, ARRAY_SIZE(sh7206_devices));
+}
+
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
From: Magnus Damm <[email protected]>
This patch adds sh3 code to register early platform devices
using plat_early_device_setup().
Signed-off-by: Magnus Damm <[email protected]>
---
arch/sh/kernel/cpu/sh3/setup-sh7705.c | 5 +++++
arch/sh/kernel/cpu/sh3/setup-sh770x.c | 5 +++++
arch/sh/kernel/cpu/sh3/setup-sh7710.c | 5 +++++
arch/sh/kernel/cpu/sh3/setup-sh7720.c | 5 +++++
4 files changed, 20 insertions(+)
--- 0012/arch/sh/kernel/cpu/sh3/setup-sh7705.c
+++ work/arch/sh/kernel/cpu/sh3/setup-sh7705.c 2009-01-23 17:05:57.000000000 +0900
@@ -158,6 +158,11 @@ static int __init sh7705_devices_setup(v
}
__initcall(sh7705_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7705_devices, ARRAY_SIZE(sh7705_devices));
+}
+
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
--- 0012/arch/sh/kernel/cpu/sh3/setup-sh770x.c
+++ work/arch/sh/kernel/cpu/sh3/setup-sh770x.c 2009-01-23 17:06:23.000000000 +0900
@@ -204,6 +204,11 @@ static int __init sh770x_devices_setup(v
}
__initcall(sh770x_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh770x_devices, ARRAY_SIZE(sh770x_devices));
+}
+
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
--- 0012/arch/sh/kernel/cpu/sh3/setup-sh7710.c
+++ work/arch/sh/kernel/cpu/sh3/setup-sh7710.c 2009-01-23 17:06:48.000000000 +0900
@@ -165,6 +165,11 @@ static int __init sh7710_devices_setup(v
}
__initcall(sh7710_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7710_devices, ARRAY_SIZE(sh7710_devices));
+}
+
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
--- 0012/arch/sh/kernel/cpu/sh3/setup-sh7720.c
+++ work/arch/sh/kernel/cpu/sh3/setup-sh7720.c 2009-01-23 17:07:03.000000000 +0900
@@ -152,6 +152,11 @@ static int __init sh7720_devices_setup(v
}
__initcall(sh7720_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7720_devices, ARRAY_SIZE(sh7720_devices));
+}
+
enum {
UNUSED = 0,
From: Magnus Damm <[email protected]>
This patch adds sh4 code to register early platform devices
using plat_early_device_setup().
Signed-off-by: Magnus Damm <[email protected]>
---
arch/sh/kernel/cpu/sh4/setup-sh4-202.c | 5 +++++
arch/sh/kernel/cpu/sh4/setup-sh7750.c | 5 +++++
arch/sh/kernel/cpu/sh4/setup-sh7760.c | 5 +++++
3 files changed, 15 insertions(+)
--- 0011/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
+++ work/arch/sh/kernel/cpu/sh4/setup-sh4-202.c 2009-01-23 17:01:55.000000000 +0900
@@ -38,6 +38,11 @@ static int __init sh4202_devices_setup(v
}
__initcall(sh4202_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh4202_devices, ARRAY_SIZE(sh4202_devices));
+}
+
void __init plat_irq_setup(void)
{
/* do nothing - all IRL interrupts are handled by the board code */
--- 0011/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ work/arch/sh/kernel/cpu/sh4/setup-sh7750.c 2009-01-23 17:00:28.000000000 +0900
@@ -95,6 +95,11 @@ static int __init sh7750_devices_setup(v
}
__initcall(sh7750_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7750_devices, ARRAY_SIZE(sh7750_devices));
+}
+
enum {
UNUSED = 0,
--- 0011/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ work/arch/sh/kernel/cpu/sh4/setup-sh7760.c 2009-01-23 17:01:29.000000000 +0900
@@ -207,6 +207,11 @@ static int __init sh7760_devices_setup(v
}
__initcall(sh7760_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7760_devices, ARRAY_SIZE(sh7760_devices));
+}
+
#define INTC_ICR 0xffd00000UL
#define INTC_ICR_IRLM (1 << 7)
From: Magnus Damm <[email protected]>
This patch adds sh4a code to register early platform devices
using plat_early_device_setup().
Signed-off-by: Magnus Damm <[email protected]>
---
arch/sh/kernel/cpu/sh4a/setup-sh7343.c | 5 +++++
arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 5 +++++
arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 5 +++++
arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 5 +++++
arch/sh/kernel/cpu/sh4a/setup-sh7763.c | 5 +++++
arch/sh/kernel/cpu/sh4a/setup-sh7770.c | 5 +++++
arch/sh/kernel/cpu/sh4a/setup-sh7780.c | 5 +++++
arch/sh/kernel/cpu/sh4a/setup-sh7785.c | 5 +++++
arch/sh/kernel/cpu/sh4a/setup-shx3.c | 5 +++++
9 files changed, 45 insertions(+)
--- 0019/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
+++ work/arch/sh/kernel/cpu/sh4a/setup-sh7343.c 2009-01-23 14:26:37.000000000 +0900
@@ -267,6 +267,11 @@ static int __init sh7343_devices_setup(v
}
__initcall(sh7343_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7343_devices, ARRAY_SIZE(sh7343_devices));
+}
+
enum {
UNUSED = 0,
--- 0019/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ work/arch/sh/kernel/cpu/sh4a/setup-sh7366.c 2009-01-23 14:28:10.000000000 +0900
@@ -223,6 +223,11 @@ static int __init sh7366_devices_setup(v
}
__initcall(sh7366_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7366_devices, ARRAY_SIZE(sh7366_devices));
+}
+
enum {
UNUSED=0,
--- 0019/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ work/arch/sh/kernel/cpu/sh4a/setup-sh7722.c 2009-01-23 14:25:34.000000000 +0900
@@ -288,6 +288,11 @@ static int __init sh7722_devices_setup(v
}
__initcall(sh7722_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7722_devices, ARRAY_SIZE(sh7722_devices));
+}
+
enum {
UNUSED=0,
--- 0019/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ work/arch/sh/kernel/cpu/sh4a/setup-sh7723.c 2009-01-23 14:26:02.000000000 +0900
@@ -338,6 +338,11 @@ static int __init sh7723_devices_setup(v
}
__initcall(sh7723_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7723_devices, ARRAY_SIZE(sh7723_devices));
+}
+
enum {
UNUSED=0,
--- 0010/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+++ work/arch/sh/kernel/cpu/sh4a/setup-sh7763.c 2009-01-23 14:28:36.000000000 +0900
@@ -155,6 +155,11 @@ static int __init sh7763_devices_setup(v
}
__initcall(sh7763_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7363_devices, ARRAY_SIZE(sh7363_devices));
+}
+
enum {
UNUSED = 0,
--- 0001/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
+++ work/arch/sh/kernel/cpu/sh4a/setup-sh7770.c 2009-01-23 14:29:14.000000000 +0900
@@ -87,6 +87,11 @@ static int __init sh7770_devices_setup(v
}
__initcall(sh7770_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7770_devices, ARRAY_SIZE(sh7770_devices));
+}
+
void __init plat_irq_setup(void)
{
}
--- 0010/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ work/arch/sh/kernel/cpu/sh4a/setup-sh7780.c 2009-01-23 14:29:46.000000000 +0900
@@ -86,6 +86,11 @@ static int __init sh7780_devices_setup(v
}
__initcall(sh7780_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7780_devices, ARRAY_SIZE(sh7780_devices));
+}
+
enum {
UNUSED = 0,
--- 0010/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ work/arch/sh/kernel/cpu/sh4a/setup-sh7785.c 2009-01-23 14:30:02.000000000 +0900
@@ -121,6 +121,11 @@ static int __init sh7785_devices_setup(v
}
__initcall(sh7785_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7785_devices, ARRAY_SIZE(sh7785_devices));
+}
+
enum {
UNUSED = 0,
--- 0010/arch/sh/kernel/cpu/sh4a/setup-shx3.c
+++ work/arch/sh/kernel/cpu/sh4a/setup-shx3.c 2009-01-23 14:30:29.000000000 +0900
@@ -88,6 +88,11 @@ static int __init shx3_devices_setup(voi
}
__initcall(shx3_devices_setup);
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(shx3_devices, ARRAY_SIZE(shx3_devices));
+}
+
enum {
UNUSED = 0,
From: Magnus Damm <[email protected]>
This patch adds early platform "earlyprintk" class support.
Signed-off-by: Magnus Damm <[email protected]>
---
arch/sh/kernel/setup.c | 3 +++
1 file changed, 3 insertions(+)
--- 0021/arch/sh/kernel/setup.c
+++ work/arch/sh/kernel/setup.c 2009-01-23 16:38:16.000000000 +0900
@@ -389,6 +389,9 @@ void __init setup_arch(char **cmdline_p)
plat_early_device_setup();
+ /* Let earlyprintk output early console messages */
+ early_platform_driver_probe("earlyprintk", 1, 1);
+
sh_mv_setup();
/*
From: Magnus Damm <[email protected]>
This patch removes the old duplicated early serial code and
adds early platform support to the sh-sci driver.
Signed-off-by: Magnus Damm <[email protected]>
---
arch/sh/Kconfig.debug | 27 -------
arch/sh/kernel/early_printk.c | 142 -----------------------------------------
drivers/serial/sh-sci.c | 48 +++++++++++--
3 files changed, 41 insertions(+), 176 deletions(-)
--- 0001/arch/sh/Kconfig.debug
+++ work/arch/sh/Kconfig.debug 2009-01-22 17:16:56.000000000 +0900
@@ -19,34 +19,9 @@ config SH_STANDARD_BIOS
mask ROM and no flash (WindowsCE machines fall in this category).
If unsure, say N.
-config EARLY_SCIF_CONSOLE
- bool "Use early SCIF console"
- help
- This enables an early console using a fixed SCIF port. This can
- be used by platforms that are either not running the SH
- standard BIOS, or do not wish to use the BIOS callbacks for the
- serial I/O.
-
-config EARLY_SCIF_CONSOLE_PORT
- hex
- depends on EARLY_SCIF_CONSOLE
- default "0xa4400000" if CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7705
- default "0xa4430000" if CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721
- default "0xf8420000" if CPU_SUBTYPE_SH7619
- default "0xff804000" if CPU_SUBTYPE_MXG
- default "0xffc30000" if CPU_SUBTYPE_SHX3
- default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \
- CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 || \
- CPU_SUBTYPE_SH7343
- default "0xffe80000" if CPU_SH4
- default "0xffea0000" if CPU_SUBTYPE_SH7785
- default "0xfffe8000" if CPU_SUBTYPE_SH7203
- default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263
- default "0x00000000"
-
config EARLY_PRINTK
bool "Early printk support"
- depends on SH_STANDARD_BIOS || EARLY_SCIF_CONSOLE
+ depends on SH_STANDARD_BIOS
help
Say Y here to redirect kernel printk messages to the serial port
used by the SH-IPL bootloader, starting very early in the boot
--- 0001/arch/sh/kernel/early_printk.c
+++ work/arch/sh/kernel/early_printk.c 2009-01-22 17:16:56.000000000 +0900
@@ -59,134 +59,6 @@ static struct console bios_console = {
};
#endif
-#ifdef CONFIG_EARLY_SCIF_CONSOLE
-#include <linux/serial_core.h>
-#include "../../../drivers/serial/sh-sci.h"
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721)
-#define EPK_SCSMR_VALUE 0x000
-#define EPK_SCBRR_VALUE 0x00C
-#define EPK_FIFO_SIZE 64
-#define EPK_FIFO_BITS (0x7f00 >> 8)
-#else
-#define EPK_FIFO_SIZE 16
-#define EPK_FIFO_BITS (0x1f00 >> 8)
-#endif
-
-static struct uart_port scif_port = {
- .type = PORT_SCIF,
- .mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT,
- .membase = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
-};
-
-static void scif_sercon_putc(int c)
-{
- while (((sci_in(&scif_port, SCFDR) & EPK_FIFO_BITS) >= EPK_FIFO_SIZE))
- ;
-
- sci_in(&scif_port, SCxSR);
- sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
- sci_out(&scif_port, SCxTDR, c);
-
- while ((sci_in(&scif_port, SCxSR) & 0x40) == 0)
- ;
-
- if (c == '\n')
- scif_sercon_putc('\r');
-}
-
-static void scif_sercon_write(struct console *con, const char *s,
- unsigned count)
-{
- while (count-- > 0)
- scif_sercon_putc(*s++);
-}
-
-static int __init scif_sercon_setup(struct console *con, char *options)
-{
- con->cflag = CREAD | HUPCL | CLOCAL | B115200 | CS8;
-
- return 0;
-}
-
-static struct console scif_console = {
- .name = "sercon",
- .write = scif_sercon_write,
- .setup = scif_sercon_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-#if !defined(CONFIG_SH_STANDARD_BIOS)
-#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721)
-static void scif_sercon_init(char *s)
-{
- sci_out(&scif_port, SCSCR, 0x0000); /* clear TE and RE */
- sci_out(&scif_port, SCFCR, 0x4006); /* reset */
- sci_out(&scif_port, SCSCR, 0x0000); /* select internal clock */
- sci_out(&scif_port, SCSMR, EPK_SCSMR_VALUE);
- sci_out(&scif_port, SCBRR, EPK_SCBRR_VALUE);
-
- mdelay(1); /* wait 1-bit time */
-
- sci_out(&scif_port, SCFCR, 0x0030); /* TTRG=b'11 */
- sci_out(&scif_port, SCSCR, 0x0030); /* TE, RE */
-}
-#elif defined(CONFIG_CPU_SH4)
-#define DEFAULT_BAUD 115200
-/*
- * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
- * devices that aren't using sh-ipl+g.
- */
-static void scif_sercon_init(char *s)
-{
- struct uart_port *port = &scif_port;
- unsigned baud = DEFAULT_BAUD;
- unsigned int status;
- char *e;
-
- if (*s == ',')
- ++s;
-
- if (*s) {
- /* ignore ioport/device name */
- s += strcspn(s, ",");
- if (*s == ',')
- s++;
- }
-
- if (*s) {
- baud = simple_strtoul(s, &e, 0);
- if (baud == 0 || s == e)
- baud = DEFAULT_BAUD;
- }
-
- do {
- status = sci_in(port, SCxSR);
- } while (!(status & SCxSR_TEND(port)));
-
- sci_out(port, SCSCR, 0); /* TE=0, RE=0 */
- sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
- sci_out(port, SCSMR, 0);
-
- /* Set baud rate */
- sci_out(port, SCBRR, (CONFIG_SH_PCLK_FREQ + 16 * baud) /
- (32 * baud) - 1);
- udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
-
- sci_out(port, SCSPTR, 0);
- sci_out(port, SCxSR, 0x60);
- sci_out(port, SCLSR, 0);
-
- sci_out(port, SCFCR, 0);
- sci_out(port, SCSCR, 0x30); /* TE=1, RE=1 */
-}
-#endif /* defined(CONFIG_CPU_SUBTYPE_SH7720) */
-#endif /* !defined(CONFIG_SH_STANDARD_BIOS) */
-#endif /* CONFIG_EARLY_SCIF_CONSOLE */
-
/*
* Setup a default console, if more than one is compiled in, rely on the
* earlyprintk= parsing to give priority.
@@ -194,8 +66,6 @@ static void scif_sercon_init(char *s)
static struct console *early_console =
#ifdef CONFIG_SH_STANDARD_BIOS
&bios_console
-#elif defined(CONFIG_EARLY_SCIF_CONSOLE)
- &scif_console
#else
NULL
#endif
@@ -215,18 +85,6 @@ static int __init setup_early_printk(cha
if (!strncmp(buf, "bios", 4))
early_console = &bios_console;
#endif
-#if defined(CONFIG_EARLY_SCIF_CONSOLE)
- if (!strncmp(buf, "serial", 6)) {
- early_console = &scif_console;
-
-#if !defined(CONFIG_SH_STANDARD_BIOS)
-#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SUBTYPE_SH7720) || \
- defined(CONFIG_CPU_SUBTYPE_SH7721)
- scif_sercon_init(buf + 6);
-#endif
-#endif
- }
-#endif
if (likely(early_console)) {
if (keep_early)
--- 0009/drivers/serial/sh-sci.c
+++ work/drivers/serial/sh-sci.c 2009-01-22 17:14:27.000000000 +0900
@@ -1074,10 +1075,13 @@ static void __devinit sci_init_single(st
#endif
sci_port->port.uartclk = CONFIG_CPU_CLOCK;
#elif defined(CONFIG_HAVE_CLK)
- sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL;
- sci_port->dclk = clk_get(&dev->dev, "module_clk");
- sci_port->enable = sci_clk_enable;
- sci_port->disable = sci_clk_disable;
+
+ if (dev) {
+ sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL;
+ sci_port->dclk = clk_get(&dev->dev, "module_clk");
+ sci_port->enable = sci_clk_enable;
+ sci_port->disable = sci_clk_disable;
+ }
#else
#error "Need a valid uartclk"
#endif
@@ -1091,11 +1095,12 @@ static void __devinit sci_init_single(st
sci_port->port.irq = p->irqs[SCIx_TXI_IRQ];
sci_port->port.flags = p->flags;
- sci_port->port.dev = &dev->dev;
sci_port->type = sci_port->port.type = p->type;
memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
+ if (dev)
+ sci_port->port.dev = &dev->dev;
}
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
@@ -1155,9 +1160,14 @@ static int __init serial_console_setup(s
if (co->index >= SCI_NPORTS)
co->index = 0;
- sci_port = &sci_ports[co->index];
- port = &sci_port->port;
- co->data = port;
+ if (co->data) {
+ port = co->data;
+ sci_port = to_sci_port(port);
+ } else {
+ sci_port = &sci_ports[co->index];
+ port = &sci_port->port;
+ co->data = port;
+ }
/*
* Also need to check port->type, we don't actually have any
@@ -1201,6 +1211,15 @@ static int __init sci_console_init(void)
return 0;
}
console_initcall(sci_console_init);
+
+static struct sci_port early_serial_port;
+static struct console early_serial_console = {
+ .name = "early_ttySC",
+ .write = serial_console_write,
+ .setup = serial_console_setup,
+ .flags = CON_PRINTBUFFER | CON_BOOT,
+};
+
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
@@ -1289,6 +1308,19 @@ static int __devinit sci_probe(struct pl
struct sh_sci_priv *priv;
int i, ret = -EINVAL;
+ if (is_early_platform_device(dev)) {
+#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
+ if (dev->id == -1)
+ return -ENOTSUPP;
+
+ early_serial_console.index = dev->id;
+ early_serial_console.data = &early_serial_port.port;
+ sci_init_single(NULL, &early_serial_port, dev->id, p);
+ register_console(&early_serial_console);
+#endif
+ return 0;
+ }
+
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -1388,6 +1420,7 @@ static void __exit sci_exit(void)
uart_unregister_driver(&sci_uart_driver);
}
+early_platform_init("earlyprintk", &sci_driver);
module_init(sci_init);
module_exit(sci_exit);
From: Magnus Damm <[email protected]>
This patch adds early platform "earlytimer" class support.
Signed-off-by: Magnus Damm <[email protected]>
---
arch/sh/kernel/time_32.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- 0017/arch/sh/kernel/time_32.c
+++ work/arch/sh/kernel/time_32.c 2009-01-23 16:41:21.000000000 +0900
@@ -218,6 +218,8 @@ unsigned long long sched_clock(void)
void __init time_init(void)
{
+ int n;
+
if (board_time_init)
board_time_init();
@@ -236,6 +238,15 @@ void __init time_init(void)
* initialized for us.
*/
sys_timer = get_sys_timer();
+
+ /* Make sure all compiled-in early timers register themselves.
+ * Run probe() for one "earlytimer" device.
+ */
+ early_platform_driver_register_all("earlytimer");
+ n = early_platform_driver_probe("earlytimer", 1, 0);
+ if (n)
+ return;
+
if (sys_timer)
pr_info("Using %s for system timer\n", sys_timer->name);
else
From: Magnus Damm <[email protected]>
This adds early platform support to the sh_cmt timer driver.
Signed-off-by: Magnus Damm <[email protected]>
---
drivers/clocksource/sh_cmt.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
--- 0016/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c 2009-01-22 17:30:35.000000000 +0900
@@ -567,9 +567,19 @@ static int sh_cmt_setup(struct sh_cmt_pr
static int __devinit sh_cmt_probe(struct platform_device *pdev)
{
struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+ struct sh_cmt_config *cfg = pdev->dev.platform_data;
int ret;
- p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p) {
+ pr_info("sh_cmt: %s kept as earlytimer\n", cfg->name);
+ return 0;
+ }
+
+ if (is_early_platform_device(pdev))
+ p = alloc_bootmem(sizeof(*p));
+ else
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+
if (p == NULL) {
dev_err(&pdev->dev, "failed to allocate driver data\n");
return -ENOMEM;
@@ -577,7 +587,10 @@ static int __devinit sh_cmt_probe(struct
ret = sh_cmt_setup(p, pdev);
if (ret) {
- kfree(p);
+ if (is_early_platform_device(pdev))
+ free_bootmem(__pa(p), sizeof(*p));
+ else
+ kfree(p);
platform_set_drvdata(pdev, NULL);
}
@@ -607,6 +620,7 @@ static void __exit sh_cmt_exit(void)
platform_driver_unregister(&sh_cmt_device_driver);
}
+early_platform_init("earlytimer", &sh_cmt_device_driver);
module_init(sh_cmt_init);
module_exit(sh_cmt_exit);
On Fri, 23 Jan 2009 19:57:21 +0900
Magnus Damm <[email protected]> wrote:
> early platform patches
>
> [PATCH 001/011] early platform driver V3
> [PATCH 002/011] sh: add plat_early_device_setup() function
> [PATCH 003/011] sh: plat_early_device_setup() for sh2
> [PATCH 004/011] sh: plat_early_device_setup() for sh2a
> [PATCH 005/011] sh: plat_early_device_setup() for sh3
> [PATCH 006/011] sh: plat_early_device_setup() for sh4
> [PATCH 007/011] sh: plat_early_device_setup() for sh4a
> [PATCH 008/011] sh: add early platform support for earlyprintk
> [PATCH 009/011] sh-sci: add early platform support
> [PATCH 010/011] sh: add early platform support for earlytimer
> [PATCH 011/011] sh_cmt: add early platform support
>
> These patches add early platform driver support to the serial port
> driver and the CMT timer driver on the SuperH architecture.
>
> The following patch sets posted to linuxsh-dev are required:
>
> - [PATCH 000/013] sh-sci: platform device, clock and console changes
> - [PATCH 00/05] sh: timer patches
Oh, that explains all the rejects.
> The early platform driver V3 patch is a replacement for V2 in -mm.
>
Well, it looks OK to me, but I don't really know what I'm looking at.
David, Kay, Tejun: would you be able to take a look at 001/011
sometime, please?
Thanks