2 * System Control Driver
4 * Copyright (C) 2012 Freescale Semiconductor, Inc.
5 * Copyright (C) 2012 Linaro Ltd.
7 * Author: Dong Aisheng <dong.aisheng@linaro.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
15 #include <linux/err.h>
17 #include <linux/module.h>
19 #include <linux/of_address.h>
20 #include <linux/of_platform.h>
21 #include <linux/platform_device.h>
22 #include <linux/regmap.h>
24 static struct platform_driver syscon_driver
;
29 struct regmap
*regmap
;
32 static int syscon_match(struct device
*dev
, void *data
)
34 struct syscon
*syscon
= dev_get_drvdata(dev
);
35 struct device_node
*dn
= data
;
37 return (syscon
->dev
->of_node
== dn
) ? 1 : 0;
40 struct regmap
*syscon_node_to_regmap(struct device_node
*np
)
42 struct syscon
*syscon
;
45 dev
= driver_find_device(&syscon_driver
.driver
, NULL
, np
,
48 return ERR_PTR(-EPROBE_DEFER
);
50 syscon
= dev_get_drvdata(dev
);
52 return syscon
->regmap
;
54 EXPORT_SYMBOL_GPL(syscon_node_to_regmap
);
56 struct regmap
*syscon_regmap_lookup_by_compatible(const char *s
)
58 struct device_node
*syscon_np
;
59 struct regmap
*regmap
;
61 syscon_np
= of_find_compatible_node(NULL
, NULL
, s
);
63 return ERR_PTR(-ENODEV
);
65 regmap
= syscon_node_to_regmap(syscon_np
);
66 of_node_put(syscon_np
);
70 EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_compatible
);
72 struct regmap
*syscon_regmap_lookup_by_phandle(struct device_node
*np
,
75 struct device_node
*syscon_np
;
76 struct regmap
*regmap
;
78 syscon_np
= of_parse_phandle(np
, property
, 0);
80 return ERR_PTR(-ENODEV
);
82 regmap
= syscon_node_to_regmap(syscon_np
);
83 of_node_put(syscon_np
);
87 EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle
);
89 static const struct of_device_id of_syscon_match
[] = {
90 { .compatible
= "syscon", },
94 static struct regmap_config syscon_regmap_config
= {
100 static int __devinit
syscon_probe(struct platform_device
*pdev
)
102 struct device
*dev
= &pdev
->dev
;
103 struct device_node
*np
= dev
->of_node
;
104 struct syscon
*syscon
;
111 syscon
= devm_kzalloc(dev
, sizeof(struct syscon
),
116 syscon
->base
= of_iomap(np
, 0);
118 return -EADDRNOTAVAIL
;
120 ret
= of_address_to_resource(np
, 0, &res
);
124 syscon_regmap_config
.max_register
= res
.end
- res
.start
- 3;
125 syscon
->regmap
= devm_regmap_init_mmio(dev
, syscon
->base
,
126 &syscon_regmap_config
);
127 if (IS_ERR(syscon
->regmap
)) {
128 dev_err(dev
, "regmap init failed\n");
129 return PTR_ERR(syscon
->regmap
);
133 platform_set_drvdata(pdev
, syscon
);
135 dev_info(dev
, "syscon regmap start 0x%x end 0x%x registered\n",
141 static int __devexit
syscon_remove(struct platform_device
*pdev
)
143 struct syscon
*syscon
;
145 syscon
= platform_get_drvdata(pdev
);
146 iounmap(syscon
->base
);
147 platform_set_drvdata(pdev
, NULL
);
152 static struct platform_driver syscon_driver
= {
155 .owner
= THIS_MODULE
,
156 .of_match_table
= of_syscon_match
,
158 .probe
= syscon_probe
,
159 .remove
= __devexit_p(syscon_remove
),
162 static int __init
syscon_init(void)
164 return platform_driver_register(&syscon_driver
);
166 postcore_initcall(syscon_init
);
168 static void __exit
syscon_exit(void)
170 platform_driver_unregister(&syscon_driver
);
172 module_exit(syscon_exit
);
174 MODULE_AUTHOR("Dong Aisheng <dong.aisheng@linaro.org>");
175 MODULE_DESCRIPTION("System Control driver");
176 MODULE_LICENSE("GPL v2");