mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	drivers: move the early platform device support to arch/sh
SuperH is the only user of the current implementation of early platform device support. We want to introduce a more robust approach to early probing. As the first step - move all the current early platform code to arch/sh. In order not to export internal drivers/base functions to arch code for this temporary solution - copy the two needed routines for driver matching from drivers/base/platform.c to arch/sh/drivers/platform_early.c. Also: call early_platform_cleanup() from subsys_initcall() so that it's called after all early devices are probed. Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Cc: Rich Felker <dalias@libc.org> Link: https://lore.kernel.org/r/20191003092913.10731-2-brgl@bgdev.pl Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									d4387cd117
								
							
						
					
					
						commit
						507fd01d53
					
				
					 40 changed files with 480 additions and 342 deletions
				
			
		| 
						 | 
				
			
			@ -3,7 +3,7 @@
 | 
			
		|||
# Makefile for the Linux SuperH-specific device drivers.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
obj-y		+= dma/
 | 
			
		||||
obj-y		+= dma/ platform_early.o
 | 
			
		||||
 | 
			
		||||
obj-$(CONFIG_PCI)		+= pci/
 | 
			
		||||
obj-$(CONFIG_SUPERHYWAY)	+= superhyway/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										347
									
								
								arch/sh/drivers/platform_early.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										347
									
								
								arch/sh/drivers/platform_early.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,347 @@
 | 
			
		|||
// SPDX--License-Identifier: GPL-2.0
 | 
			
		||||
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
#include <linux/mod_devicetable.h>
 | 
			
		||||
#include <linux/pm.h>
 | 
			
		||||
 | 
			
		||||
static __initdata LIST_HEAD(early_platform_driver_list);
 | 
			
		||||
static __initdata LIST_HEAD(early_platform_device_list);
 | 
			
		||||
 | 
			
		||||
static const struct platform_device_id *
 | 
			
		||||
platform_match_id(const struct platform_device_id *id,
 | 
			
		||||
		  struct platform_device *pdev)
 | 
			
		||||
{
 | 
			
		||||
	while (id->name[0]) {
 | 
			
		||||
		if (strcmp(pdev->name, id->name) == 0) {
 | 
			
		||||
			pdev->id_entry = id;
 | 
			
		||||
			return id;
 | 
			
		||||
		}
 | 
			
		||||
		id++;
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int platform_match(struct device *dev, struct device_driver *drv)
 | 
			
		||||
{
 | 
			
		||||
	struct platform_device *pdev = to_platform_device(dev);
 | 
			
		||||
	struct platform_driver *pdrv = to_platform_driver(drv);
 | 
			
		||||
 | 
			
		||||
	/* When driver_override is set, only bind to the matching driver */
 | 
			
		||||
	if (pdev->driver_override)
 | 
			
		||||
		return !strcmp(pdev->driver_override, drv->name);
 | 
			
		||||
 | 
			
		||||
	/* Then try to match against the id table */
 | 
			
		||||
	if (pdrv->id_table)
 | 
			
		||||
		return platform_match_id(pdrv->id_table, pdev) != NULL;
 | 
			
		||||
 | 
			
		||||
	/* fall-back to driver name match */
 | 
			
		||||
	return (strcmp(pdev->name, drv->name) == 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_PM
 | 
			
		||||
static void device_pm_init_common(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	if (!dev->power.early_init) {
 | 
			
		||||
		spin_lock_init(&dev->power.lock);
 | 
			
		||||
		dev->power.qos = NULL;
 | 
			
		||||
		dev->power.early_init = true;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pm_runtime_early_init(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	dev->power.disable_depth = 1;
 | 
			
		||||
	device_pm_init_common(dev);
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
static void pm_runtime_early_init(struct device *dev) {}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * early_platform_driver_register - register early platform driver
 | 
			
		||||
 * @epdrv: early_platform driver structure
 | 
			
		||||
 * @buf: string passed from early_param()
 | 
			
		||||
 *
 | 
			
		||||
 * Helper function for early_platform_init() / early_platform_init_buffer()
 | 
			
		||||
 */
 | 
			
		||||
int __init early_platform_driver_register(struct early_platform_driver *epdrv,
 | 
			
		||||
					  char *buf)
 | 
			
		||||
{
 | 
			
		||||
	char *tmp;
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
		/* Allow passing parameters after device name */
 | 
			
		||||
		if (buf[n] == '\0' || buf[n] == ',')
 | 
			
		||||
			epdrv->requested_id = -1;
 | 
			
		||||
		else {
 | 
			
		||||
			epdrv->requested_id = simple_strtoul(&buf[n + 1],
 | 
			
		||||
							     &tmp, 10);
 | 
			
		||||
 | 
			
		||||
			if (buf[n] != '.' || (tmp == &buf[n + 1])) {
 | 
			
		||||
				epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
 | 
			
		||||
				n = 0;
 | 
			
		||||
			} else
 | 
			
		||||
				n += strcspn(&buf[n + 1], ",") + 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (buf[n] == ',')
 | 
			
		||||
			n++;
 | 
			
		||||
 | 
			
		||||
		if (epdrv->bufsize) {
 | 
			
		||||
			memcpy(epdrv->buffer, &buf[n],
 | 
			
		||||
			       min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1));
 | 
			
		||||
			epdrv->buffer[epdrv->bufsize - 1] = '\0';
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * early_platform_add_devices - adds a number of early platform devices
 | 
			
		||||
 * @devs: array of early platform devices to add
 | 
			
		||||
 * @num: number of early platform devices in array
 | 
			
		||||
 *
 | 
			
		||||
 * Used by early architecture code to register early platform devices and
 | 
			
		||||
 * their platform data.
 | 
			
		||||
 */
 | 
			
		||||
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) {
 | 
			
		||||
			pm_runtime_early_init(dev);
 | 
			
		||||
			INIT_LIST_HEAD(&dev->devres_head);
 | 
			
		||||
			list_add_tail(&dev->devres_head,
 | 
			
		||||
				      &early_platform_device_list);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * early_platform_driver_register_all - register early platform drivers
 | 
			
		||||
 * @class_str: string to identify early platform driver class
 | 
			
		||||
 *
 | 
			
		||||
 * Used by architecture code to register all early platform drivers
 | 
			
		||||
 * for a certain class. If omitted then only early platform drivers
 | 
			
		||||
 * with matching kernel command line class parameters will be registered.
 | 
			
		||||
 */
 | 
			
		||||
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 - find early platform device matching driver
 | 
			
		||||
 * @epdrv: early platform driver structure
 | 
			
		||||
 * @id: id to match against
 | 
			
		||||
 */
 | 
			
		||||
static struct platform_device * __init
 | 
			
		||||
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 - check if early platform driver has matching devices
 | 
			
		||||
 * @epdrv: early platform driver structure
 | 
			
		||||
 * @id: return true if id or above exists
 | 
			
		||||
 */
 | 
			
		||||
static int __init 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 - probe drivers matching class_str and 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_warn("%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) {
 | 
			
		||||
			/*
 | 
			
		||||
			 * Set up a sensible init_name to enable
 | 
			
		||||
			 * dev_name() and others to be used before the
 | 
			
		||||
			 * rest of the driver core is initialized.
 | 
			
		||||
			 */
 | 
			
		||||
			if (!match->dev.init_name && slab_is_available()) {
 | 
			
		||||
				if (match->id != -1)
 | 
			
		||||
					match->dev.init_name =
 | 
			
		||||
						kasprintf(GFP_KERNEL, "%s.%d",
 | 
			
		||||
							  match->name,
 | 
			
		||||
							  match->id);
 | 
			
		||||
				else
 | 
			
		||||
					match->dev.init_name =
 | 
			
		||||
						kasprintf(GFP_KERNEL, "%s",
 | 
			
		||||
							  match->name);
 | 
			
		||||
 | 
			
		||||
				if (!match->dev.init_name)
 | 
			
		||||
					return -ENOMEM;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (epdrv->pdrv->probe(match))
 | 
			
		||||
				pr_warn("%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 - probe a class of registered drivers
 | 
			
		||||
 * @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
 | 
			
		||||
 *
 | 
			
		||||
 * Used by architecture code to probe registered early platform drivers
 | 
			
		||||
 * within a certain class. For probe to happen a registered early platform
 | 
			
		||||
 * device matching a registered early platform driver is needed.
 | 
			
		||||
 */
 | 
			
		||||
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
 | 
			
		||||
 */
 | 
			
		||||
static int __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));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
 * This must happen once after all early devices are probed but before probing
 | 
			
		||||
 * real platform devices.
 | 
			
		||||
 */
 | 
			
		||||
subsys_initcall(early_platform_cleanup);
 | 
			
		||||
							
								
								
									
										61
									
								
								arch/sh/include/asm/platform_early.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								arch/sh/include/asm/platform_early.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,61 @@
 | 
			
		|||
/* SPDX--License-Identifier: GPL-2.0 */
 | 
			
		||||
 | 
			
		||||
#ifndef __PLATFORM_EARLY__
 | 
			
		||||
#define __PLATFORM_EARLY__
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/platform_device.h>
 | 
			
		||||
#include <linux/pm_runtime.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
 | 
			
		||||
struct early_platform_driver {
 | 
			
		||||
	const char *class_str;
 | 
			
		||||
	struct platform_driver *pdrv;
 | 
			
		||||
	struct list_head list;
 | 
			
		||||
	int requested_id;
 | 
			
		||||
	char *buffer;
 | 
			
		||||
	int bufsize;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
 | 
			
		||||
#define early_platform_init(class_string, platdrv)		\
 | 
			
		||||
	early_platform_init_buffer(class_string, platdrv, NULL, 0)
 | 
			
		||||
 | 
			
		||||
#ifndef MODULE
 | 
			
		||||
#define early_platform_init_buffer(class_string, platdrv, buf, bufsiz)	\
 | 
			
		||||
static __initdata struct early_platform_driver early_driver = {		\
 | 
			
		||||
	.class_str = class_string,					\
 | 
			
		||||
	.buffer = buf,							\
 | 
			
		||||
	.bufsize = bufsiz,						\
 | 
			
		||||
	.pdrv = platdrv,						\
 | 
			
		||||
	.requested_id = EARLY_PLATFORM_ID_UNSET,			\
 | 
			
		||||
};									\
 | 
			
		||||
static int __init early_platform_driver_setup_func(char *buffer)	\
 | 
			
		||||
{									\
 | 
			
		||||
	return early_platform_driver_register(&early_driver, buffer);	\
 | 
			
		||||
}									\
 | 
			
		||||
early_param(class_string, early_platform_driver_setup_func)
 | 
			
		||||
#else /* MODULE */
 | 
			
		||||
#define early_platform_init_buffer(class_string, platdrv, buf, bufsiz)	\
 | 
			
		||||
static inline char *early_platform_driver_setup_func(void)		\
 | 
			
		||||
{									\
 | 
			
		||||
	return bufsiz ? buf : NULL;					\
 | 
			
		||||
}
 | 
			
		||||
#endif /* MODULE */
 | 
			
		||||
 | 
			
		||||
#endif /* __PLATFORM_EARLY__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -12,6 +12,7 @@
 | 
			
		|||
#include <linux/sh_eth.h>
 | 
			
		||||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	UNUSED = 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@
 | 
			
		|||
#include <linux/serial.h>
 | 
			
		||||
#include <linux/serial_sci.h>
 | 
			
		||||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	UNUSED = 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@
 | 
			
		|||
#include <linux/serial_sci.h>
 | 
			
		||||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	UNUSED = 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@
 | 
			
		|||
#include <linux/serial_sci.h>
 | 
			
		||||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	UNUSED = 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@
 | 
			
		|||
#include <linux/serial_sci.h>
 | 
			
		||||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	UNUSED = 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@
 | 
			
		|||
#include <linux/usb/r8a66597.h>
 | 
			
		||||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	UNUSED = 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@
 | 
			
		|||
#include <linux/usb/r8a66597.h>
 | 
			
		||||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	UNUSED = 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@
 | 
			
		|||
#include <linux/init.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
/* All SH3 devices are equipped with IRQ0->5 (except sh7708) */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@
 | 
			
		|||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <asm/rtc.h>
 | 
			
		||||
#include <cpu/serial.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	UNUSED = 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@
 | 
			
		|||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <cpu/serial.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	UNUSED = 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@
 | 
			
		|||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <asm/rtc.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	UNUSED = 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <linux/usb/ohci_pdriver.h>
 | 
			
		||||
#include <asm/rtc.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
#include <cpu/serial.h>
 | 
			
		||||
 | 
			
		||||
static struct resource rtc_resources[] = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@
 | 
			
		|||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
static struct plat_sci_port scif0_platform_data = {
 | 
			
		||||
	.scscr		= SCSCR_REIE,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@
 | 
			
		|||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <linux/serial_sci.h>
 | 
			
		||||
#include <generated/machtypes.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
static struct resource rtc_resources[] = {
 | 
			
		||||
	[0] = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@
 | 
			
		|||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <linux/serial_sci.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	UNUSED = 0,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@
 | 
			
		|||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <asm/clock.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
/* Serial */
 | 
			
		||||
static struct plat_sci_port scif0_platform_data = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,7 @@
 | 
			
		|||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <linux/usb/r8a66597.h>
 | 
			
		||||
#include <asm/clock.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
static struct plat_sci_port scif0_platform_data = {
 | 
			
		||||
	.scscr		= SCSCR_REIE,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@
 | 
			
		|||
#include <asm/clock.h>
 | 
			
		||||
#include <asm/mmzone.h>
 | 
			
		||||
#include <asm/siu.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
#include <cpu/dma-register.h>
 | 
			
		||||
#include <cpu/sh7722.h>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@
 | 
			
		|||
#include <linux/io.h>
 | 
			
		||||
#include <asm/clock.h>
 | 
			
		||||
#include <asm/mmzone.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
#include <cpu/sh7723.h>
 | 
			
		||||
 | 
			
		||||
/* Serial */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@
 | 
			
		|||
#include <asm/suspend.h>
 | 
			
		||||
#include <asm/clock.h>
 | 
			
		||||
#include <asm/mmzone.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
#include <cpu/dma-register.h>
 | 
			
		||||
#include <cpu/sh7724.h>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@
 | 
			
		|||
#include <linux/io.h>
 | 
			
		||||
#include <asm/clock.h>
 | 
			
		||||
#include <asm/irq.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
#include <cpu/sh7734.h>
 | 
			
		||||
 | 
			
		||||
/* SCIF */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
#include <linux/usb/ohci_pdriver.h>
 | 
			
		||||
#include <cpu/dma-register.h>
 | 
			
		||||
#include <cpu/sh7757.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
static struct plat_sci_port scif2_platform_data = {
 | 
			
		||||
	.scscr		= SCSCR_REIE,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@
 | 
			
		|||
#include <linux/io.h>
 | 
			
		||||
#include <linux/serial_sci.h>
 | 
			
		||||
#include <linux/usb/ohci_pdriver.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
static struct plat_sci_port scif0_platform_data = {
 | 
			
		||||
	.scscr		= SCSCR_REIE,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@
 | 
			
		|||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <linux/io.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
static struct plat_sci_port scif0_platform_data = {
 | 
			
		||||
	.scscr		= SCSCR_REIE | SCSCR_TOIE,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@
 | 
			
		|||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <cpu/dma-register.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
static struct plat_sci_port scif0_platform_data = {
 | 
			
		||||
	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@
 | 
			
		|||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <asm/mmzone.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
#include <cpu/dma-register.h>
 | 
			
		||||
 | 
			
		||||
static struct plat_sci_port scif0_platform_data = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@
 | 
			
		|||
#include <linux/usb/ohci_pdriver.h>
 | 
			
		||||
#include <cpu/dma-register.h>
 | 
			
		||||
#include <asm/mmzone.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
static struct plat_sci_port scif0_platform_data = {
 | 
			
		||||
	.scscr		= SCSCR_REIE | SCSCR_CKE1,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,7 @@
 | 
			
		|||
#include <linux/sh_intc.h>
 | 
			
		||||
#include <cpu/shx3.h>
 | 
			
		||||
#include <asm/mmzone.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This intentionally only registers SCIF ports 0, 1, and 3. SCIF 2
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@
 | 
			
		|||
#include <linux/mm.h>
 | 
			
		||||
#include <linux/sh_timer.h>
 | 
			
		||||
#include <asm/addrspace.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
static struct plat_sci_port scif0_platform_data = {
 | 
			
		||||
	.flags		= UPF_IOREMAP,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,7 @@
 | 
			
		|||
#include <asm/mmu_context.h>
 | 
			
		||||
#include <asm/mmzone.h>
 | 
			
		||||
#include <asm/sparsemem.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Initialize loops_per_jiffy as 10000000 (1000MIPS).
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@
 | 
			
		|||
#include <linux/rtc.h>
 | 
			
		||||
#include <asm/clock.h>
 | 
			
		||||
#include <asm/rtc.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
 | 
			
		||||
static void __init sh_late_time_init(void)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1264,8 +1264,6 @@ int __init platform_bus_init(void)
 | 
			
		|||
{
 | 
			
		||||
	int error;
 | 
			
		||||
 | 
			
		||||
	early_platform_cleanup();
 | 
			
		||||
 | 
			
		||||
	error = device_register(&platform_bus);
 | 
			
		||||
	if (error) {
 | 
			
		||||
		put_device(&platform_bus);
 | 
			
		||||
| 
						 | 
				
			
			@ -1277,289 +1275,3 @@ int __init platform_bus_init(void)
 | 
			
		|||
	of_platform_register_reconfig_notifier();
 | 
			
		||||
	return error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static __initdata LIST_HEAD(early_platform_driver_list);
 | 
			
		||||
static __initdata LIST_HEAD(early_platform_device_list);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * early_platform_driver_register - register early platform driver
 | 
			
		||||
 * @epdrv: early_platform driver structure
 | 
			
		||||
 * @buf: string passed from early_param()
 | 
			
		||||
 *
 | 
			
		||||
 * Helper function for early_platform_init() / early_platform_init_buffer()
 | 
			
		||||
 */
 | 
			
		||||
int __init early_platform_driver_register(struct early_platform_driver *epdrv,
 | 
			
		||||
					  char *buf)
 | 
			
		||||
{
 | 
			
		||||
	char *tmp;
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
		/* Allow passing parameters after device name */
 | 
			
		||||
		if (buf[n] == '\0' || buf[n] == ',')
 | 
			
		||||
			epdrv->requested_id = -1;
 | 
			
		||||
		else {
 | 
			
		||||
			epdrv->requested_id = simple_strtoul(&buf[n + 1],
 | 
			
		||||
							     &tmp, 10);
 | 
			
		||||
 | 
			
		||||
			if (buf[n] != '.' || (tmp == &buf[n + 1])) {
 | 
			
		||||
				epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
 | 
			
		||||
				n = 0;
 | 
			
		||||
			} else
 | 
			
		||||
				n += strcspn(&buf[n + 1], ",") + 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (buf[n] == ',')
 | 
			
		||||
			n++;
 | 
			
		||||
 | 
			
		||||
		if (epdrv->bufsize) {
 | 
			
		||||
			memcpy(epdrv->buffer, &buf[n],
 | 
			
		||||
			       min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1));
 | 
			
		||||
			epdrv->buffer[epdrv->bufsize - 1] = '\0';
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * early_platform_add_devices - adds a number of early platform devices
 | 
			
		||||
 * @devs: array of early platform devices to add
 | 
			
		||||
 * @num: number of early platform devices in array
 | 
			
		||||
 *
 | 
			
		||||
 * Used by early architecture code to register early platform devices and
 | 
			
		||||
 * their platform data.
 | 
			
		||||
 */
 | 
			
		||||
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) {
 | 
			
		||||
			pm_runtime_early_init(dev);
 | 
			
		||||
			INIT_LIST_HEAD(&dev->devres_head);
 | 
			
		||||
			list_add_tail(&dev->devres_head,
 | 
			
		||||
				      &early_platform_device_list);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * early_platform_driver_register_all - register early platform drivers
 | 
			
		||||
 * @class_str: string to identify early platform driver class
 | 
			
		||||
 *
 | 
			
		||||
 * Used by architecture code to register all early platform drivers
 | 
			
		||||
 * for a certain class. If omitted then only early platform drivers
 | 
			
		||||
 * with matching kernel command line class parameters will be registered.
 | 
			
		||||
 */
 | 
			
		||||
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 - find early platform device matching driver
 | 
			
		||||
 * @epdrv: early platform driver structure
 | 
			
		||||
 * @id: id to match against
 | 
			
		||||
 */
 | 
			
		||||
static struct platform_device * __init
 | 
			
		||||
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 - check if early platform driver has matching devices
 | 
			
		||||
 * @epdrv: early platform driver structure
 | 
			
		||||
 * @id: return true if id or above exists
 | 
			
		||||
 */
 | 
			
		||||
static int __init 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 - probe drivers matching class_str and 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_warn("%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) {
 | 
			
		||||
			/*
 | 
			
		||||
			 * Set up a sensible init_name to enable
 | 
			
		||||
			 * dev_name() and others to be used before the
 | 
			
		||||
			 * rest of the driver core is initialized.
 | 
			
		||||
			 */
 | 
			
		||||
			if (!match->dev.init_name && slab_is_available()) {
 | 
			
		||||
				if (match->id != -1)
 | 
			
		||||
					match->dev.init_name =
 | 
			
		||||
						kasprintf(GFP_KERNEL, "%s.%d",
 | 
			
		||||
							  match->name,
 | 
			
		||||
							  match->id);
 | 
			
		||||
				else
 | 
			
		||||
					match->dev.init_name =
 | 
			
		||||
						kasprintf(GFP_KERNEL, "%s",
 | 
			
		||||
							  match->name);
 | 
			
		||||
 | 
			
		||||
				if (!match->dev.init_name)
 | 
			
		||||
					return -ENOMEM;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (epdrv->pdrv->probe(match))
 | 
			
		||||
				pr_warn("%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 - probe a class of registered drivers
 | 
			
		||||
 * @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
 | 
			
		||||
 *
 | 
			
		||||
 * Used by architecture code to probe registered early platform drivers
 | 
			
		||||
 * within a certain class. For probe to happen a registered early platform
 | 
			
		||||
 * device matching a registered early platform driver is needed.
 | 
			
		||||
 */
 | 
			
		||||
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));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,10 @@
 | 
			
		|||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SUPERH
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct sh_cmt_device;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -1109,7 +1113,10 @@ static void __exit sh_cmt_exit(void)
 | 
			
		|||
	platform_driver_unregister(&sh_cmt_device_driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SUPERH
 | 
			
		||||
early_platform_init("earlytimer", &sh_cmt_device_driver);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
subsys_initcall(sh_cmt_init);
 | 
			
		||||
module_exit(sh_cmt_exit);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,10 @@
 | 
			
		|||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SUPERH
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct sh_mtu2_device;
 | 
			
		||||
 | 
			
		||||
struct sh_mtu2_channel {
 | 
			
		||||
| 
						 | 
				
			
			@ -511,7 +515,10 @@ static void __exit sh_mtu2_exit(void)
 | 
			
		|||
	platform_driver_unregister(&sh_mtu2_device_driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SUPERH
 | 
			
		||||
early_platform_init("earlytimer", &sh_mtu2_device_driver);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
subsys_initcall(sh_mtu2_init);
 | 
			
		||||
module_exit(sh_mtu2_exit);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,10 @@
 | 
			
		|||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/spinlock.h>
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SUPERH
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum sh_tmu_model {
 | 
			
		||||
	SH_TMU,
 | 
			
		||||
	SH_TMU_SH3,
 | 
			
		||||
| 
						 | 
				
			
			@ -615,6 +619,7 @@ static int sh_tmu_probe(struct platform_device *pdev)
 | 
			
		|||
		pm_runtime_idle(&pdev->dev);
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (is_early_platform_device(pdev))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -665,7 +670,10 @@ static void __exit sh_tmu_exit(void)
 | 
			
		|||
	platform_driver_unregister(&sh_tmu_device_driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SUPERH
 | 
			
		||||
early_platform_init("earlytimer", &sh_tmu_device_driver);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
subsys_initcall(sh_tmu_init);
 | 
			
		||||
module_exit(sh_tmu_exit);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,6 +54,7 @@
 | 
			
		|||
 | 
			
		||||
#ifdef CONFIG_SUPERH
 | 
			
		||||
#include <asm/sh_bios.h>
 | 
			
		||||
#include <asm/platform_early.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "serial_mctrl_gpio.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -3086,6 +3087,7 @@ static struct console serial_console = {
 | 
			
		|||
	.data		= &sci_uart_driver,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SUPERH
 | 
			
		||||
static struct console early_serial_console = {
 | 
			
		||||
	.name           = "early_ttySC",
 | 
			
		||||
	.write          = serial_console_write,
 | 
			
		||||
| 
						 | 
				
			
			@ -3114,6 +3116,7 @@ static int sci_probe_earlyprintk(struct platform_device *pdev)
 | 
			
		|||
	register_console(&early_serial_console);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define SCI_CONSOLE	(&serial_console)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3314,8 +3317,10 @@ static int sci_probe(struct platform_device *dev)
 | 
			
		|||
	 * the special early probe. We don't have sufficient device state
 | 
			
		||||
	 * to make it beyond this yet.
 | 
			
		||||
	 */
 | 
			
		||||
#ifdef CONFIG_SUPERH
 | 
			
		||||
	if (is_early_platform_device(dev))
 | 
			
		||||
		return sci_probe_earlyprintk(dev);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (dev->dev.of_node) {
 | 
			
		||||
		p = sci_parse_dt(dev, &dev_id);
 | 
			
		||||
| 
						 | 
				
			
			@ -3410,7 +3415,7 @@ static void __exit sci_exit(void)
 | 
			
		|||
		uart_unregister_driver(&sci_uart_driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
 | 
			
		||||
#if defined(CONFIG_SUPERH) && defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
 | 
			
		||||
early_platform_init_buffer("earlyprintk", &sci_driver,
 | 
			
		||||
			   early_serial_buf, ARRAY_SIZE(early_serial_buf));
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -292,58 +292,6 @@ void platform_unregister_drivers(struct platform_driver * const *drivers,
 | 
			
		|||
#define platform_register_drivers(drivers, count) \
 | 
			
		||||
	__platform_register_drivers(drivers, count, THIS_MODULE)
 | 
			
		||||
 | 
			
		||||
/* early platform driver interface */
 | 
			
		||||
struct early_platform_driver {
 | 
			
		||||
	const char *class_str;
 | 
			
		||||
	struct platform_driver *pdrv;
 | 
			
		||||
	struct list_head list;
 | 
			
		||||
	int requested_id;
 | 
			
		||||
	char *buffer;
 | 
			
		||||
	int bufsize;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#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);
 | 
			
		||||
 | 
			
		||||
#define early_platform_init(class_string, platdrv)		\
 | 
			
		||||
	early_platform_init_buffer(class_string, platdrv, NULL, 0)
 | 
			
		||||
 | 
			
		||||
#ifndef MODULE
 | 
			
		||||
#define early_platform_init_buffer(class_string, platdrv, buf, bufsiz)	\
 | 
			
		||||
static __initdata struct early_platform_driver early_driver = {		\
 | 
			
		||||
	.class_str = class_string,					\
 | 
			
		||||
	.buffer = buf,							\
 | 
			
		||||
	.bufsize = bufsiz,						\
 | 
			
		||||
	.pdrv = platdrv,						\
 | 
			
		||||
	.requested_id = EARLY_PLATFORM_ID_UNSET,			\
 | 
			
		||||
};									\
 | 
			
		||||
static int __init early_platform_driver_setup_func(char *buffer)	\
 | 
			
		||||
{									\
 | 
			
		||||
	return early_platform_driver_register(&early_driver, buffer);	\
 | 
			
		||||
}									\
 | 
			
		||||
early_param(class_string, early_platform_driver_setup_func)
 | 
			
		||||
#else /* MODULE */
 | 
			
		||||
#define early_platform_init_buffer(class_string, platdrv, buf, bufsiz)	\
 | 
			
		||||
static inline char *early_platform_driver_setup_func(void)		\
 | 
			
		||||
{									\
 | 
			
		||||
	return bufsiz ? buf : NULL;					\
 | 
			
		||||
}
 | 
			
		||||
#endif /* MODULE */
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SUSPEND
 | 
			
		||||
extern int platform_pm_suspend(struct device *dev);
 | 
			
		||||
extern int platform_pm_resume(struct device *dev);
 | 
			
		||||
| 
						 | 
				
			
			@ -378,4 +326,16 @@ extern int platform_dma_configure(struct device *dev);
 | 
			
		|||
#define USE_PLATFORM_PM_SLEEP_OPS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef CONFIG_SUPERH
 | 
			
		||||
/*
 | 
			
		||||
 * REVISIT: This stub is needed for all non-SuperH users of early platform
 | 
			
		||||
 * drivers. It should go away once we introduce the new platform_device-based
 | 
			
		||||
 * early driver framework.
 | 
			
		||||
 */
 | 
			
		||||
static inline int is_early_platform_device(struct platform_device *pdev)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif /* CONFIG_SUPERH */
 | 
			
		||||
 | 
			
		||||
#endif /* _PLATFORM_DEVICE_H_ */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue