diff options
| -rw-r--r-- | drivers/mfd/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/mfd/syscon.c | 75 | ||||
| -rw-r--r-- | include/linux/mfd/syscon.h | 1 |
3 files changed, 46 insertions, 31 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 67e56dcdcbf6..3c50c388c78f 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
| @@ -1100,7 +1100,6 @@ config MFD_STA2X11 | |||
| 1100 | 1100 | ||
| 1101 | config MFD_SYSCON | 1101 | config MFD_SYSCON |
| 1102 | bool "System Controller Register R/W Based on Regmap" | 1102 | bool "System Controller Register R/W Based on Regmap" |
| 1103 | depends on OF | ||
| 1104 | select REGMAP_MMIO | 1103 | select REGMAP_MMIO |
| 1105 | help | 1104 | help |
| 1106 | Select this option to enable accessing system control registers | 1105 | Select this option to enable accessing system control registers |
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index 674af1432807..7905d36d0517 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c | |||
| @@ -29,7 +29,7 @@ struct syscon { | |||
| 29 | struct regmap *regmap; | 29 | struct regmap *regmap; |
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | static int syscon_match(struct device *dev, void *data) | 32 | static int syscon_match_node(struct device *dev, void *data) |
| 33 | { | 33 | { |
| 34 | struct device_node *dn = data; | 34 | struct device_node *dn = data; |
| 35 | 35 | ||
| @@ -42,7 +42,7 @@ struct regmap *syscon_node_to_regmap(struct device_node *np) | |||
| 42 | struct device *dev; | 42 | struct device *dev; |
| 43 | 43 | ||
| 44 | dev = driver_find_device(&syscon_driver.driver, NULL, np, | 44 | dev = driver_find_device(&syscon_driver.driver, NULL, np, |
| 45 | syscon_match); | 45 | syscon_match_node); |
| 46 | if (!dev) | 46 | if (!dev) |
| 47 | return ERR_PTR(-EPROBE_DEFER); | 47 | return ERR_PTR(-EPROBE_DEFER); |
| 48 | 48 | ||
| @@ -68,6 +68,34 @@ struct regmap *syscon_regmap_lookup_by_compatible(const char *s) | |||
| 68 | } | 68 | } |
| 69 | EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible); | 69 | EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible); |
| 70 | 70 | ||
| 71 | static int syscon_match_pdevname(struct device *dev, void *data) | ||
| 72 | { | ||
| 73 | struct platform_device *pdev = to_platform_device(dev); | ||
| 74 | const struct platform_device_id *id = platform_get_device_id(pdev); | ||
| 75 | |||
| 76 | if (id) | ||
| 77 | if (!strcmp(id->name, (const char *)data)) | ||
| 78 | return 1; | ||
| 79 | |||
| 80 | return !strcmp(dev_name(dev), (const char *)data); | ||
| 81 | } | ||
| 82 | |||
| 83 | struct regmap *syscon_regmap_lookup_by_pdevname(const char *s) | ||
| 84 | { | ||
| 85 | struct device *dev; | ||
| 86 | struct syscon *syscon; | ||
| 87 | |||
| 88 | dev = driver_find_device(&syscon_driver.driver, NULL, (void *)s, | ||
| 89 | syscon_match_pdevname); | ||
| 90 | if (!dev) | ||
| 91 | return ERR_PTR(-EPROBE_DEFER); | ||
| 92 | |||
| 93 | syscon = dev_get_drvdata(dev); | ||
| 94 | |||
| 95 | return syscon->regmap; | ||
| 96 | } | ||
| 97 | EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_pdevname); | ||
| 98 | |||
| 71 | struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np, | 99 | struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np, |
| 72 | const char *property) | 100 | const char *property) |
| 73 | { | 101 | { |
| @@ -99,28 +127,22 @@ static struct regmap_config syscon_regmap_config = { | |||
| 99 | static int syscon_probe(struct platform_device *pdev) | 127 | static int syscon_probe(struct platform_device *pdev) |
| 100 | { | 128 | { |
| 101 | struct device *dev = &pdev->dev; | 129 | struct device *dev = &pdev->dev; |
| 102 | struct device_node *np = dev->of_node; | ||
| 103 | struct syscon *syscon; | 130 | struct syscon *syscon; |
| 104 | struct resource res; | 131 | struct resource *res; |
| 105 | int ret; | ||
| 106 | |||
| 107 | if (!np) | ||
| 108 | return -ENOENT; | ||
| 109 | 132 | ||
| 110 | syscon = devm_kzalloc(dev, sizeof(struct syscon), | 133 | syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL); |
| 111 | GFP_KERNEL); | ||
| 112 | if (!syscon) | 134 | if (!syscon) |
| 113 | return -ENOMEM; | 135 | return -ENOMEM; |
| 114 | 136 | ||
| 115 | syscon->base = of_iomap(np, 0); | 137 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 116 | if (!syscon->base) | 138 | if (!res) |
| 117 | return -EADDRNOTAVAIL; | 139 | return -ENOENT; |
| 118 | 140 | ||
| 119 | ret = of_address_to_resource(np, 0, &res); | 141 | syscon->base = devm_ioremap(dev, res->start, resource_size(res)); |
| 120 | if (ret) | 142 | if (!syscon->base) |
| 121 | return ret; | 143 | return -ENOMEM; |
| 122 | 144 | ||
| 123 | syscon_regmap_config.max_register = res.end - res.start - 3; | 145 | syscon_regmap_config.max_register = res->end - res->start - 3; |
| 124 | syscon->regmap = devm_regmap_init_mmio(dev, syscon->base, | 146 | syscon->regmap = devm_regmap_init_mmio(dev, syscon->base, |
| 125 | &syscon_regmap_config); | 147 | &syscon_regmap_config); |
| 126 | if (IS_ERR(syscon->regmap)) { | 148 | if (IS_ERR(syscon->regmap)) { |
| @@ -130,22 +152,15 @@ static int syscon_probe(struct platform_device *pdev) | |||
| 130 | 152 | ||
| 131 | platform_set_drvdata(pdev, syscon); | 153 | platform_set_drvdata(pdev, syscon); |
| 132 | 154 | ||
| 133 | dev_info(dev, "syscon regmap start 0x%x end 0x%x registered\n", | 155 | dev_info(dev, "regmap 0x%x-0x%x registered\n", res->start, res->end); |
| 134 | res.start, res.end); | ||
| 135 | 156 | ||
| 136 | return 0; | 157 | return 0; |
| 137 | } | 158 | } |
| 138 | 159 | ||
| 139 | static int syscon_remove(struct platform_device *pdev) | 160 | static const struct platform_device_id syscon_ids[] = { |
| 140 | { | 161 | { "syscon", }, |
| 141 | struct syscon *syscon; | 162 | { } |
| 142 | 163 | }; | |
| 143 | syscon = platform_get_drvdata(pdev); | ||
| 144 | iounmap(syscon->base); | ||
| 145 | platform_set_drvdata(pdev, NULL); | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | 164 | ||
| 150 | static struct platform_driver syscon_driver = { | 165 | static struct platform_driver syscon_driver = { |
| 151 | .driver = { | 166 | .driver = { |
| @@ -154,7 +169,7 @@ static struct platform_driver syscon_driver = { | |||
| 154 | .of_match_table = of_syscon_match, | 169 | .of_match_table = of_syscon_match, |
| 155 | }, | 170 | }, |
| 156 | .probe = syscon_probe, | 171 | .probe = syscon_probe, |
| 157 | .remove = syscon_remove, | 172 | .id_table = syscon_ids, |
| 158 | }; | 173 | }; |
| 159 | 174 | ||
| 160 | static int __init syscon_init(void) | 175 | static int __init syscon_init(void) |
diff --git a/include/linux/mfd/syscon.h b/include/linux/mfd/syscon.h index 6aeb6b8da64d..5c9ee6ee7960 100644 --- a/include/linux/mfd/syscon.h +++ b/include/linux/mfd/syscon.h | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | extern struct regmap *syscon_node_to_regmap(struct device_node *np); | 18 | extern struct regmap *syscon_node_to_regmap(struct device_node *np); |
| 19 | extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s); | 19 | extern struct regmap *syscon_regmap_lookup_by_compatible(const char *s); |
| 20 | extern struct regmap *syscon_regmap_lookup_by_pdevname(const char *s); | ||
| 20 | extern struct regmap *syscon_regmap_lookup_by_phandle( | 21 | extern struct regmap *syscon_regmap_lookup_by_phandle( |
| 21 | struct device_node *np, | 22 | struct device_node *np, |
| 22 | const char *property); | 23 | const char *property); |
