diff options
Diffstat (limited to 'drivers/of/platform.c')
| -rw-r--r-- | drivers/of/platform.c | 83 | 
1 files changed, 64 insertions, 19 deletions
| diff --git a/drivers/of/platform.c b/drivers/of/platform.c index a16b74f32aa9..176ed71d20c0 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -507,7 +507,6 @@ int of_platform_default_populate(struct device_node *root,  }  EXPORT_SYMBOL_GPL(of_platform_default_populate); -#ifndef CONFIG_PPC  static const struct of_device_id reserved_mem_matches[] = {  	{ .compatible = "qcom,rmtfs-mem" },  	{ .compatible = "qcom,cmd-db" }, @@ -527,26 +526,73 @@ static int __init of_platform_default_populate_init(void)  	if (!of_have_populated_dt())  		return -ENODEV; -	/* -	 * Handle certain compatibles explicitly, since we don't want to create -	 * platform_devices for every node in /reserved-memory with a -	 * "compatible", -	 */ -	for_each_matching_node(node, reserved_mem_matches) -		of_platform_device_create(node, NULL, NULL); +	if (IS_ENABLED(CONFIG_PPC)) { +		struct device_node *boot_display = NULL; +		struct platform_device *dev; +		int ret; + +		/* Check if we have a MacOS display without a node spec */ +		if (of_get_property(of_chosen, "linux,bootx-noscreen", NULL)) { +			/* +			 * The old code tried to work out which node was the MacOS +			 * display based on the address. I'm dropping that since the +			 * lack of a node spec only happens with old BootX versions +			 * (users can update) and with this code, they'll still get +			 * a display (just not the palette hacks). +			 */ +			dev = platform_device_alloc("bootx-noscreen", 0); +			if (WARN_ON(!dev)) +				return -ENOMEM; +			ret = platform_device_add(dev); +			if (WARN_ON(ret)) { +				platform_device_put(dev); +				return ret; +			} +		} -	node = of_find_node_by_path("/firmware"); -	if (node) { -		of_platform_populate(node, NULL, NULL, NULL); -		of_node_put(node); -	} +		/* +		 * For OF framebuffers, first create the device for the boot display, +		 * then for the other framebuffers. Only fail for the boot display; +		 * ignore errors for the rest. +		 */ +		for_each_node_by_type(node, "display") { +			if (!of_get_property(node, "linux,opened", NULL) || +			    !of_get_property(node, "linux,boot-display", NULL)) +				continue; +			dev = of_platform_device_create(node, "of-display", NULL); +			if (WARN_ON(!dev)) +				return -ENOMEM; +			boot_display = node; +			break; +		} +		for_each_node_by_type(node, "display") { +			if (!of_get_property(node, "linux,opened", NULL) || node == boot_display) +				continue; +			of_platform_device_create(node, "of-display", NULL); +		} -	node = of_get_compatible_child(of_chosen, "simple-framebuffer"); -	of_platform_device_create(node, NULL, NULL); -	of_node_put(node); +	} else { +		/* +		 * Handle certain compatibles explicitly, since we don't want to create +		 * platform_devices for every node in /reserved-memory with a +		 * "compatible", +		 */ +		for_each_matching_node(node, reserved_mem_matches) +			of_platform_device_create(node, NULL, NULL); + +		node = of_find_node_by_path("/firmware"); +		if (node) { +			of_platform_populate(node, NULL, NULL, NULL); +			of_node_put(node); +		} -	/* Populate everything else. */ -	of_platform_default_populate(NULL, NULL, NULL); +		node = of_get_compatible_child(of_chosen, "simple-framebuffer"); +		of_platform_device_create(node, NULL, NULL); +		of_node_put(node); + +		/* Populate everything else. */ +		of_platform_default_populate(NULL, NULL, NULL); +	}  	return 0;  } @@ -558,7 +604,6 @@ static int __init of_platform_sync_state_init(void)  	return 0;  }  late_initcall_sync(of_platform_sync_state_init); -#endif  int of_platform_device_destroy(struct device *dev, void *data)  { | 
