aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/platform.c')
-rw-r--r--drivers/base/platform.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 00f2208949d1..ab4f4ce02722 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -24,6 +24,7 @@
24#include <linux/idr.h> 24#include <linux/idr.h>
25#include <linux/acpi.h> 25#include <linux/acpi.h>
26#include <linux/clk/clk-conf.h> 26#include <linux/clk/clk-conf.h>
27#include <linux/limits.h>
27 28
28#include "base.h" 29#include "base.h"
29#include "power/power.h" 30#include "power/power.h"
@@ -176,7 +177,7 @@ EXPORT_SYMBOL_GPL(platform_add_devices);
176 177
177struct platform_object { 178struct platform_object {
178 struct platform_device pdev; 179 struct platform_device pdev;
179 char name[1]; 180 char name[];
180}; 181};
181 182
182/** 183/**
@@ -202,6 +203,7 @@ static void platform_device_release(struct device *dev)
202 kfree(pa->pdev.dev.platform_data); 203 kfree(pa->pdev.dev.platform_data);
203 kfree(pa->pdev.mfd_cell); 204 kfree(pa->pdev.mfd_cell);
204 kfree(pa->pdev.resource); 205 kfree(pa->pdev.resource);
206 kfree(pa->pdev.driver_override);
205 kfree(pa); 207 kfree(pa);
206} 208}
207 209
@@ -217,7 +219,7 @@ struct platform_device *platform_device_alloc(const char *name, int id)
217{ 219{
218 struct platform_object *pa; 220 struct platform_object *pa;
219 221
220 pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL); 222 pa = kzalloc(sizeof(*pa) + strlen(name) + 1, GFP_KERNEL);
221 if (pa) { 223 if (pa) {
222 strcpy(pa->name, name); 224 strcpy(pa->name, name);
223 pa->pdev.name = pa->name; 225 pa->pdev.name = pa->name;
@@ -713,8 +715,49 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
713} 715}
714static DEVICE_ATTR_RO(modalias); 716static DEVICE_ATTR_RO(modalias);
715 717
718static ssize_t driver_override_store(struct device *dev,
719 struct device_attribute *attr,
720 const char *buf, size_t count)
721{
722 struct platform_device *pdev = to_platform_device(dev);
723 char *driver_override, *old = pdev->driver_override, *cp;
724
725 if (count > PATH_MAX)
726 return -EINVAL;
727
728 driver_override = kstrndup(buf, count, GFP_KERNEL);
729 if (!driver_override)
730 return -ENOMEM;
731
732 cp = strchr(driver_override, '\n');
733 if (cp)
734 *cp = '\0';
735
736 if (strlen(driver_override)) {
737 pdev->driver_override = driver_override;
738 } else {
739 kfree(driver_override);
740 pdev->driver_override = NULL;
741 }
742
743 kfree(old);
744
745 return count;
746}
747
748static ssize_t driver_override_show(struct device *dev,
749 struct device_attribute *attr, char *buf)
750{
751 struct platform_device *pdev = to_platform_device(dev);
752
753 return sprintf(buf, "%s\n", pdev->driver_override);
754}
755static DEVICE_ATTR_RW(driver_override);
756
757
716static struct attribute *platform_dev_attrs[] = { 758static struct attribute *platform_dev_attrs[] = {
717 &dev_attr_modalias.attr, 759 &dev_attr_modalias.attr,
760 &dev_attr_driver_override.attr,
718 NULL, 761 NULL,
719}; 762};
720ATTRIBUTE_GROUPS(platform_dev); 763ATTRIBUTE_GROUPS(platform_dev);
@@ -770,6 +813,10 @@ static int platform_match(struct device *dev, struct device_driver *drv)
770 struct platform_device *pdev = to_platform_device(dev); 813 struct platform_device *pdev = to_platform_device(dev);
771 struct platform_driver *pdrv = to_platform_driver(drv); 814 struct platform_driver *pdrv = to_platform_driver(drv);
772 815
816 /* When driver_override is set, only bind to the matching driver */
817 if (pdev->driver_override)
818 return !strcmp(pdev->driver_override, drv->name);
819
773 /* Attempt an OF style match first */ 820 /* Attempt an OF style match first */
774 if (of_driver_match_device(dev, drv)) 821 if (of_driver_match_device(dev, drv))
775 return 1; 822 return 1;