diff options
Diffstat (limited to 'drivers/base/platform.c')
-rw-r--r-- | drivers/base/platform.c | 51 |
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 | ||
177 | struct platform_object { | 178 | struct 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 | } |
714 | static DEVICE_ATTR_RO(modalias); | 716 | static DEVICE_ATTR_RO(modalias); |
715 | 717 | ||
718 | static 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 | |||
748 | static 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 | } | ||
755 | static DEVICE_ATTR_RW(driver_override); | ||
756 | |||
757 | |||
716 | static struct attribute *platform_dev_attrs[] = { | 758 | static 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 | }; |
720 | ATTRIBUTE_GROUPS(platform_dev); | 763 | ATTRIBUTE_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; |