Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Kevin Hilman: "Some of these are for drivers/soc, where we're now putting SoC-specific drivers these days. Some are for other driver subsystems where we have received acks from the appropriate maintainers. Some highlights: - simple-mfd: document DT bindings and misc updates - migrate mach-berlin to simple-mfd for clock, pinctrl and reset - memory: support for Tegra132 SoC - memory: introduce tegra EMC driver for scaling memory frequency - misc. updates for ARM CCI and CCN busses" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (48 commits) drivers: soc: sunxi: Introduce SoC driver to map SRAMs arm-cci: Add aliases for PMU events arm-cci: Add CCI-500 PMU support arm-cci: Sanitise CCI400 PMU driver specific code arm-cci: Abstract handling for CCI events arm-cci: Abstract out the PMU counter details arm-cci: Cleanup PMU driver code arm-cci: Do not enable CCI-400 PMU by default firmware: qcom: scm: Add HDCP Support ARM: berlin: add an ADC node for the BG2Q ARM: berlin: remove useless chip and system ctrl compatibles clk: berlin: drop direct of_iomap of nodes reg property ARM: berlin: move BG2Q clock node ARM: berlin: move BG2CD clock node ARM: berlin: move BG2 clock node clk: berlin: prepare simple-mfd conversion pinctrl: berlin: drop SoC stub provided regmap ARM: berlin: move pinctrl to simple-mfd nodes pinctrl: berlin: prepare to use regmap provided by syscon reset: berlin: drop arch_initcall initialization ...
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -66,102 +67,101 @@ static void syscon_led_set(struct led_classdev *led_cdev,
|
||||
dev_err(sled->cdev.dev, "error updating LED status\n");
|
||||
}
|
||||
|
||||
static int __init syscon_leds_spawn(struct device_node *np,
|
||||
struct device *dev,
|
||||
struct regmap *map)
|
||||
static int syscon_led_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *child;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device *parent;
|
||||
struct regmap *map;
|
||||
struct syscon_led *sled;
|
||||
const char *state;
|
||||
int ret;
|
||||
|
||||
for_each_available_child_of_node(np, child) {
|
||||
struct syscon_led *sled;
|
||||
const char *state;
|
||||
|
||||
/* Only check for register-bit-leds */
|
||||
if (of_property_match_string(child, "compatible",
|
||||
"register-bit-led") < 0)
|
||||
continue;
|
||||
|
||||
sled = devm_kzalloc(dev, sizeof(*sled), GFP_KERNEL);
|
||||
if (!sled)
|
||||
return -ENOMEM;
|
||||
|
||||
sled->map = map;
|
||||
|
||||
if (of_property_read_u32(child, "offset", &sled->offset))
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(child, "mask", &sled->mask))
|
||||
return -EINVAL;
|
||||
sled->cdev.name =
|
||||
of_get_property(child, "label", NULL) ? : child->name;
|
||||
sled->cdev.default_trigger =
|
||||
of_get_property(child, "linux,default-trigger", NULL);
|
||||
|
||||
state = of_get_property(child, "default-state", NULL);
|
||||
if (state) {
|
||||
if (!strcmp(state, "keep")) {
|
||||
u32 val;
|
||||
|
||||
ret = regmap_read(map, sled->offset, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
sled->state = !!(val & sled->mask);
|
||||
} else if (!strcmp(state, "on")) {
|
||||
sled->state = true;
|
||||
ret = regmap_update_bits(map, sled->offset,
|
||||
sled->mask,
|
||||
sled->mask);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
sled->state = false;
|
||||
ret = regmap_update_bits(map, sled->offset,
|
||||
sled->mask, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
sled->cdev.brightness_set = syscon_led_set;
|
||||
|
||||
ret = led_classdev_register(dev, &sled->cdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev_info(dev, "registered LED %s\n", sled->cdev.name);
|
||||
parent = dev->parent;
|
||||
if (!parent) {
|
||||
dev_err(dev, "no parent for syscon LED\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
map = syscon_node_to_regmap(parent->of_node);
|
||||
if (!map) {
|
||||
dev_err(dev, "no regmap for syscon LED parent\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
sled = devm_kzalloc(dev, sizeof(*sled), GFP_KERNEL);
|
||||
if (!sled)
|
||||
return -ENOMEM;
|
||||
|
||||
sled->map = map;
|
||||
|
||||
if (of_property_read_u32(np, "offset", &sled->offset))
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(np, "mask", &sled->mask))
|
||||
return -EINVAL;
|
||||
sled->cdev.name =
|
||||
of_get_property(np, "label", NULL) ? : np->name;
|
||||
sled->cdev.default_trigger =
|
||||
of_get_property(np, "linux,default-trigger", NULL);
|
||||
|
||||
state = of_get_property(np, "default-state", NULL);
|
||||
if (state) {
|
||||
if (!strcmp(state, "keep")) {
|
||||
u32 val;
|
||||
|
||||
ret = regmap_read(map, sled->offset, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
sled->state = !!(val & sled->mask);
|
||||
} else if (!strcmp(state, "on")) {
|
||||
sled->state = true;
|
||||
ret = regmap_update_bits(map, sled->offset,
|
||||
sled->mask,
|
||||
sled->mask);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
sled->state = false;
|
||||
ret = regmap_update_bits(map, sled->offset,
|
||||
sled->mask, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
sled->cdev.brightness_set = syscon_led_set;
|
||||
|
||||
ret = led_classdev_register(dev, &sled->cdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, sled);
|
||||
dev_info(dev, "registered LED %s\n", sled->cdev.name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init syscon_leds_init(void)
|
||||
static int syscon_led_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
for_each_of_allnodes(np) {
|
||||
struct platform_device *pdev;
|
||||
struct regmap *map;
|
||||
int ret;
|
||||
|
||||
if (!of_device_is_compatible(np, "syscon"))
|
||||
continue;
|
||||
|
||||
map = syscon_node_to_regmap(np);
|
||||
if (IS_ERR(map)) {
|
||||
pr_err("error getting regmap for syscon LEDs\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the map is there, the device should be there, we allocate
|
||||
* memory on the syscon device's behalf here.
|
||||
*/
|
||||
pdev = of_find_device_by_node(np);
|
||||
if (!pdev)
|
||||
return -ENODEV;
|
||||
ret = syscon_leds_spawn(np, &pdev->dev, map);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "could not spawn syscon LEDs\n");
|
||||
}
|
||||
struct syscon_led *sled = platform_get_drvdata(pdev);
|
||||
|
||||
led_classdev_unregister(&sled->cdev);
|
||||
/* Turn it off */
|
||||
regmap_update_bits(sled->map, sled->offset, sled->mask, 0);
|
||||
return 0;
|
||||
}
|
||||
device_initcall(syscon_leds_init);
|
||||
|
||||
static const struct of_device_id of_syscon_leds_match[] = {
|
||||
{ .compatible = "register-bit-led", },
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, of_syscon_leds_match);
|
||||
|
||||
static struct platform_driver syscon_led_driver = {
|
||||
.probe = syscon_led_probe,
|
||||
.remove = syscon_led_remove,
|
||||
.driver = {
|
||||
.name = "leds-syscon",
|
||||
.of_match_table = of_syscon_leds_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(syscon_led_driver);
|
||||
|
Reference in New Issue
Block a user