aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2014-02-12 11:12:40 -0500
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2014-07-04 09:46:17 -0400
commit1768aa2f4c1248051013282c6cf63b368016cb53 (patch)
treec909c0b40d2579027061ed70ca8b5609fab8ebec /drivers/clocksource
parent628627bfd943c077c65489acd8b23c7bb14eb0e2 (diff)
clocksource: sh_cmt: Add DT support
Document DT bindings and parse them in the CMT driver. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Tested-by: Simon Horman <horms+renesas@verge.net.au>
Diffstat (limited to 'drivers/clocksource')
-rw-r--r--drivers/clocksource/sh_cmt.c66
1 files changed, 48 insertions, 18 deletions
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 190c655d8352..2bd13b53b727 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -24,6 +24,7 @@
24#include <linux/ioport.h> 24#include <linux/ioport.h>
25#include <linux/irq.h> 25#include <linux/irq.h>
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/of.h>
27#include <linux/platform_device.h> 28#include <linux/platform_device.h>
28#include <linux/pm_domain.h> 29#include <linux/pm_domain.h>
29#include <linux/pm_runtime.h> 30#include <linux/pm_runtime.h>
@@ -122,6 +123,7 @@ struct sh_cmt_device {
122 123
123 struct sh_cmt_channel *channels; 124 struct sh_cmt_channel *channels;
124 unsigned int num_channels; 125 unsigned int num_channels;
126 unsigned int hw_channels;
125 127
126 bool has_clockevent; 128 bool has_clockevent;
127 bool has_clocksource; 129 bool has_clocksource;
@@ -924,10 +926,35 @@ static int sh_cmt_map_memory(struct sh_cmt_device *cmt)
924 return 0; 926 return 0;
925} 927}
926 928
929static const struct platform_device_id sh_cmt_id_table[] = {
930 { "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
931 { "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
932 { "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] },
933 { "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] },
934 { "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] },
935 { }
936};
937MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
938
939static const struct of_device_id sh_cmt_of_table[] __maybe_unused = {
940 { .compatible = "renesas,cmt-32", .data = &sh_cmt_info[SH_CMT_32BIT] },
941 { .compatible = "renesas,cmt-32-fast", .data = &sh_cmt_info[SH_CMT_32BIT_FAST] },
942 { .compatible = "renesas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] },
943 { .compatible = "renesas,cmt-48-gen2", .data = &sh_cmt_info[SH_CMT_48BIT_GEN2] },
944 { }
945};
946MODULE_DEVICE_TABLE(of, sh_cmt_of_table);
947
948static int sh_cmt_parse_dt(struct sh_cmt_device *cmt)
949{
950 struct device_node *np = cmt->pdev->dev.of_node;
951
952 return of_property_read_u32(np, "renesas,channels-mask",
953 &cmt->hw_channels);
954}
955
927static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) 956static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
928{ 957{
929 struct sh_timer_config *cfg = pdev->dev.platform_data;
930 const struct platform_device_id *id = pdev->id_entry;
931 unsigned int mask; 958 unsigned int mask;
932 unsigned int i; 959 unsigned int i;
933 int ret; 960 int ret;
@@ -936,13 +963,26 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
936 cmt->pdev = pdev; 963 cmt->pdev = pdev;
937 raw_spin_lock_init(&cmt->lock); 964 raw_spin_lock_init(&cmt->lock);
938 965
939 if (!cfg) { 966 if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
967 const struct of_device_id *id;
968
969 id = of_match_node(sh_cmt_of_table, pdev->dev.of_node);
970 cmt->info = id->data;
971
972 ret = sh_cmt_parse_dt(cmt);
973 if (ret < 0)
974 return ret;
975 } else if (pdev->dev.platform_data) {
976 struct sh_timer_config *cfg = pdev->dev.platform_data;
977 const struct platform_device_id *id = pdev->id_entry;
978
979 cmt->info = (const struct sh_cmt_info *)id->driver_data;
980 cmt->hw_channels = cfg->channels_mask;
981 } else {
940 dev_err(&cmt->pdev->dev, "missing platform data\n"); 982 dev_err(&cmt->pdev->dev, "missing platform data\n");
941 return -ENXIO; 983 return -ENXIO;
942 } 984 }
943 985
944 cmt->info = (const struct sh_cmt_info *)id->driver_data;
945
946 /* Get hold of clock. */ 986 /* Get hold of clock. */
947 cmt->clk = clk_get(&cmt->pdev->dev, "fck"); 987 cmt->clk = clk_get(&cmt->pdev->dev, "fck");
948 if (IS_ERR(cmt->clk)) { 988 if (IS_ERR(cmt->clk)) {
@@ -960,8 +1000,7 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
960 goto err_clk_unprepare; 1000 goto err_clk_unprepare;
961 1001
962 /* Allocate and setup the channels. */ 1002 /* Allocate and setup the channels. */
963 cmt->num_channels = hweight8(cfg->channels_mask); 1003 cmt->num_channels = hweight8(cmt->hw_channels);
964
965 cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels), 1004 cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels),
966 GFP_KERNEL); 1005 GFP_KERNEL);
967 if (cmt->channels == NULL) { 1006 if (cmt->channels == NULL) {
@@ -973,7 +1012,7 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
973 * Use the first channel as a clock event device and the second channel 1012 * Use the first channel as a clock event device and the second channel
974 * as a clock source. If only one channel is available use it for both. 1013 * as a clock source. If only one channel is available use it for both.
975 */ 1014 */
976 for (i = 0, mask = cfg->channels_mask; i < cmt->num_channels; ++i) { 1015 for (i = 0, mask = cmt->hw_channels; i < cmt->num_channels; ++i) {
977 unsigned int hwidx = ffs(mask) - 1; 1016 unsigned int hwidx = ffs(mask) - 1;
978 bool clocksource = i == 1 || cmt->num_channels == 1; 1017 bool clocksource = i == 1 || cmt->num_channels == 1;
979 bool clockevent = i == 0; 1018 bool clockevent = i == 0;
@@ -1042,21 +1081,12 @@ static int sh_cmt_remove(struct platform_device *pdev)
1042 return -EBUSY; /* cannot unregister clockevent and clocksource */ 1081 return -EBUSY; /* cannot unregister clockevent and clocksource */
1043} 1082}
1044 1083
1045static const struct platform_device_id sh_cmt_id_table[] = {
1046 { "sh-cmt-16", (kernel_ulong_t)&sh_cmt_info[SH_CMT_16BIT] },
1047 { "sh-cmt-32", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT] },
1048 { "sh-cmt-32-fast", (kernel_ulong_t)&sh_cmt_info[SH_CMT_32BIT_FAST] },
1049 { "sh-cmt-48", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT] },
1050 { "sh-cmt-48-gen2", (kernel_ulong_t)&sh_cmt_info[SH_CMT_48BIT_GEN2] },
1051 { }
1052};
1053MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
1054
1055static struct platform_driver sh_cmt_device_driver = { 1084static struct platform_driver sh_cmt_device_driver = {
1056 .probe = sh_cmt_probe, 1085 .probe = sh_cmt_probe,
1057 .remove = sh_cmt_remove, 1086 .remove = sh_cmt_remove,
1058 .driver = { 1087 .driver = {
1059 .name = "sh_cmt", 1088 .name = "sh_cmt",
1089 .of_match_table = of_match_ptr(sh_cmt_of_table),
1060 }, 1090 },
1061 .id_table = sh_cmt_id_table, 1091 .id_table = sh_cmt_id_table,
1062}; 1092};