.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * SuperH Timer Support - CMT |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2008 Magnus Damm |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License as published by |
---|
8 | | - * the Free Software Foundation; either version 2 of the License |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, |
---|
11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | | - * GNU General Public License for more details. |
---|
14 | 6 | */ |
---|
15 | 7 | |
---|
16 | 8 | #include <linux/clk.h> |
---|
.. | .. |
---|
21 | 13 | #include <linux/init.h> |
---|
22 | 14 | #include <linux/interrupt.h> |
---|
23 | 15 | #include <linux/io.h> |
---|
| 16 | +#include <linux/iopoll.h> |
---|
24 | 17 | #include <linux/ioport.h> |
---|
25 | 18 | #include <linux/irq.h> |
---|
26 | 19 | #include <linux/module.h> |
---|
.. | .. |
---|
32 | 25 | #include <linux/sh_timer.h> |
---|
33 | 26 | #include <linux/slab.h> |
---|
34 | 27 | #include <linux/spinlock.h> |
---|
| 28 | + |
---|
| 29 | +#ifdef CONFIG_SUPERH |
---|
| 30 | +#include <asm/platform_early.h> |
---|
| 31 | +#endif |
---|
35 | 32 | |
---|
36 | 33 | struct sh_cmt_device; |
---|
37 | 34 | |
---|
.. | .. |
---|
120 | 117 | void __iomem *mapbase; |
---|
121 | 118 | struct clk *clk; |
---|
122 | 119 | unsigned long rate; |
---|
| 120 | + unsigned int reg_delay; |
---|
123 | 121 | |
---|
124 | 122 | raw_spinlock_t lock; /* Protect the shared start/stop register */ |
---|
125 | 123 | |
---|
.. | .. |
---|
239 | 237 | #define CMCNT 1 /* channel register */ |
---|
240 | 238 | #define CMCOR 2 /* channel register */ |
---|
241 | 239 | |
---|
| 240 | +#define CMCLKE 0x1000 /* CLK Enable Register (R-Car Gen2) */ |
---|
| 241 | + |
---|
242 | 242 | static inline u32 sh_cmt_read_cmstr(struct sh_cmt_channel *ch) |
---|
243 | 243 | { |
---|
244 | 244 | if (ch->iostart) |
---|
.. | .. |
---|
249 | 249 | |
---|
250 | 250 | static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, u32 value) |
---|
251 | 251 | { |
---|
252 | | - if (ch->iostart) |
---|
253 | | - ch->cmt->info->write_control(ch->iostart, 0, value); |
---|
254 | | - else |
---|
255 | | - ch->cmt->info->write_control(ch->cmt->mapbase, 0, value); |
---|
| 252 | + u32 old_value = sh_cmt_read_cmstr(ch); |
---|
| 253 | + |
---|
| 254 | + if (value != old_value) { |
---|
| 255 | + if (ch->iostart) { |
---|
| 256 | + ch->cmt->info->write_control(ch->iostart, 0, value); |
---|
| 257 | + udelay(ch->cmt->reg_delay); |
---|
| 258 | + } else { |
---|
| 259 | + ch->cmt->info->write_control(ch->cmt->mapbase, 0, value); |
---|
| 260 | + udelay(ch->cmt->reg_delay); |
---|
| 261 | + } |
---|
| 262 | + } |
---|
256 | 263 | } |
---|
257 | 264 | |
---|
258 | 265 | static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch) |
---|
.. | .. |
---|
262 | 269 | |
---|
263 | 270 | static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch, u32 value) |
---|
264 | 271 | { |
---|
265 | | - ch->cmt->info->write_control(ch->ioctrl, CMCSR, value); |
---|
| 272 | + u32 old_value = sh_cmt_read_cmcsr(ch); |
---|
| 273 | + |
---|
| 274 | + if (value != old_value) { |
---|
| 275 | + ch->cmt->info->write_control(ch->ioctrl, CMCSR, value); |
---|
| 276 | + udelay(ch->cmt->reg_delay); |
---|
| 277 | + } |
---|
266 | 278 | } |
---|
267 | 279 | |
---|
268 | 280 | static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch) |
---|
.. | .. |
---|
270 | 282 | return ch->cmt->info->read_count(ch->ioctrl, CMCNT); |
---|
271 | 283 | } |
---|
272 | 284 | |
---|
273 | | -static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value) |
---|
| 285 | +static inline int sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value) |
---|
274 | 286 | { |
---|
| 287 | + /* Tests showed that we need to wait 3 clocks here */ |
---|
| 288 | + unsigned int cmcnt_delay = DIV_ROUND_UP(3 * ch->cmt->reg_delay, 2); |
---|
| 289 | + u32 reg; |
---|
| 290 | + |
---|
| 291 | + if (ch->cmt->info->model > SH_CMT_16BIT) { |
---|
| 292 | + int ret = read_poll_timeout_atomic(sh_cmt_read_cmcsr, reg, |
---|
| 293 | + !(reg & SH_CMT32_CMCSR_WRFLG), |
---|
| 294 | + 1, cmcnt_delay, false, ch); |
---|
| 295 | + if (ret < 0) |
---|
| 296 | + return ret; |
---|
| 297 | + } |
---|
| 298 | + |
---|
275 | 299 | ch->cmt->info->write_count(ch->ioctrl, CMCNT, value); |
---|
| 300 | + udelay(cmcnt_delay); |
---|
| 301 | + return 0; |
---|
276 | 302 | } |
---|
277 | 303 | |
---|
278 | 304 | static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch, u32 value) |
---|
279 | 305 | { |
---|
280 | | - ch->cmt->info->write_count(ch->ioctrl, CMCOR, value); |
---|
| 306 | + u32 old_value = ch->cmt->info->read_count(ch->ioctrl, CMCOR); |
---|
| 307 | + |
---|
| 308 | + if (value != old_value) { |
---|
| 309 | + ch->cmt->info->write_count(ch->ioctrl, CMCOR, value); |
---|
| 310 | + udelay(ch->cmt->reg_delay); |
---|
| 311 | + } |
---|
281 | 312 | } |
---|
282 | 313 | |
---|
283 | 314 | static u32 sh_cmt_get_counter(struct sh_cmt_channel *ch, u32 *has_wrapped) |
---|
.. | .. |
---|
321 | 352 | |
---|
322 | 353 | static int sh_cmt_enable(struct sh_cmt_channel *ch) |
---|
323 | 354 | { |
---|
324 | | - int k, ret; |
---|
| 355 | + int ret; |
---|
325 | 356 | |
---|
326 | 357 | pm_runtime_get_sync(&ch->cmt->pdev->dev); |
---|
327 | 358 | dev_pm_syscore_device(&ch->cmt->pdev->dev, true); |
---|
.. | .. |
---|
349 | 380 | } |
---|
350 | 381 | |
---|
351 | 382 | sh_cmt_write_cmcor(ch, 0xffffffff); |
---|
352 | | - sh_cmt_write_cmcnt(ch, 0); |
---|
| 383 | + ret = sh_cmt_write_cmcnt(ch, 0); |
---|
353 | 384 | |
---|
354 | | - /* |
---|
355 | | - * According to the sh73a0 user's manual, as CMCNT can be operated |
---|
356 | | - * only by the RCLK (Pseudo 32 KHz), there's one restriction on |
---|
357 | | - * modifying CMCNT register; two RCLK cycles are necessary before |
---|
358 | | - * this register is either read or any modification of the value |
---|
359 | | - * it holds is reflected in the LSI's actual operation. |
---|
360 | | - * |
---|
361 | | - * While at it, we're supposed to clear out the CMCNT as of this |
---|
362 | | - * moment, so make sure it's processed properly here. This will |
---|
363 | | - * take RCLKx2 at maximum. |
---|
364 | | - */ |
---|
365 | | - for (k = 0; k < 100; k++) { |
---|
366 | | - if (!sh_cmt_read_cmcnt(ch)) |
---|
367 | | - break; |
---|
368 | | - udelay(1); |
---|
369 | | - } |
---|
370 | | - |
---|
371 | | - if (sh_cmt_read_cmcnt(ch)) { |
---|
| 385 | + if (ret || sh_cmt_read_cmcnt(ch)) { |
---|
372 | 386 | dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n", |
---|
373 | 387 | ch->index); |
---|
374 | 388 | ret = -ETIMEDOUT; |
---|
.. | .. |
---|
668 | 682 | return; |
---|
669 | 683 | |
---|
670 | 684 | sh_cmt_stop(ch, FLAG_CLOCKSOURCE); |
---|
671 | | - pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev); |
---|
| 685 | + dev_pm_genpd_suspend(&ch->cmt->pdev->dev); |
---|
672 | 686 | } |
---|
673 | 687 | |
---|
674 | 688 | static void sh_cmt_clocksource_resume(struct clocksource *cs) |
---|
.. | .. |
---|
678 | 692 | if (!ch->cs_enabled) |
---|
679 | 693 | return; |
---|
680 | 694 | |
---|
681 | | - pm_genpd_syscore_poweron(&ch->cmt->pdev->dev); |
---|
| 695 | + dev_pm_genpd_resume(&ch->cmt->pdev->dev); |
---|
682 | 696 | sh_cmt_start(ch, FLAG_CLOCKSOURCE); |
---|
683 | 697 | } |
---|
684 | 698 | |
---|
.. | .. |
---|
770 | 784 | { |
---|
771 | 785 | struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); |
---|
772 | 786 | |
---|
773 | | - pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev); |
---|
| 787 | + dev_pm_genpd_suspend(&ch->cmt->pdev->dev); |
---|
774 | 788 | clk_unprepare(ch->cmt->clk); |
---|
775 | 789 | } |
---|
776 | 790 | |
---|
.. | .. |
---|
779 | 793 | struct sh_cmt_channel *ch = ced_to_sh_cmt(ced); |
---|
780 | 794 | |
---|
781 | 795 | clk_prepare(ch->cmt->clk); |
---|
782 | | - pm_genpd_syscore_poweron(&ch->cmt->pdev->dev); |
---|
| 796 | + dev_pm_genpd_resume(&ch->cmt->pdev->dev); |
---|
783 | 797 | } |
---|
784 | 798 | |
---|
785 | 799 | static int sh_cmt_register_clockevent(struct sh_cmt_channel *ch, |
---|
.. | .. |
---|
790 | 804 | int ret; |
---|
791 | 805 | |
---|
792 | 806 | irq = platform_get_irq(ch->cmt->pdev, ch->index); |
---|
793 | | - if (irq < 0) { |
---|
794 | | - dev_err(&ch->cmt->pdev->dev, "ch%u: failed to get irq\n", |
---|
795 | | - ch->index); |
---|
| 807 | + if (irq < 0) |
---|
796 | 808 | return irq; |
---|
797 | | - } |
---|
798 | 809 | |
---|
799 | 810 | ret = request_irq(irq, sh_cmt_interrupt, |
---|
800 | 811 | IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, |
---|
.. | .. |
---|
856 | 867 | unsigned int hwidx, bool clockevent, |
---|
857 | 868 | bool clocksource, struct sh_cmt_device *cmt) |
---|
858 | 869 | { |
---|
| 870 | + u32 value; |
---|
859 | 871 | int ret; |
---|
860 | 872 | |
---|
861 | 873 | /* Skip unused channels. */ |
---|
.. | .. |
---|
885 | 897 | ch->iostart = cmt->mapbase + ch->hwidx * 0x100; |
---|
886 | 898 | ch->ioctrl = ch->iostart + 0x10; |
---|
887 | 899 | ch->timer_bit = 0; |
---|
| 900 | + |
---|
| 901 | + /* Enable the clock supply to the channel */ |
---|
| 902 | + value = ioread32(cmt->mapbase + CMCLKE); |
---|
| 903 | + value |= BIT(hwidx); |
---|
| 904 | + iowrite32(value, cmt->mapbase + CMCLKE); |
---|
888 | 905 | break; |
---|
889 | 906 | } |
---|
890 | 907 | |
---|
.. | .. |
---|
918 | 935 | return -ENXIO; |
---|
919 | 936 | } |
---|
920 | 937 | |
---|
921 | | - cmt->mapbase = ioremap_nocache(mem->start, resource_size(mem)); |
---|
| 938 | + cmt->mapbase = ioremap(mem->start, resource_size(mem)); |
---|
922 | 939 | if (cmt->mapbase == NULL) { |
---|
923 | 940 | dev_err(&cmt->pdev->dev, "failed to remap I/O memory\n"); |
---|
924 | 941 | return -ENXIO; |
---|
.. | .. |
---|
935 | 952 | MODULE_DEVICE_TABLE(platform, sh_cmt_id_table); |
---|
936 | 953 | |
---|
937 | 954 | static const struct of_device_id sh_cmt_of_table[] __maybe_unused = { |
---|
938 | | - { .compatible = "renesas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] }, |
---|
| 955 | + { |
---|
| 956 | + /* deprecated, preserved for backward compatibility */ |
---|
| 957 | + .compatible = "renesas,cmt-48", |
---|
| 958 | + .data = &sh_cmt_info[SH_CMT_48BIT] |
---|
| 959 | + }, |
---|
939 | 960 | { |
---|
940 | 961 | /* deprecated, preserved for backward compatibility */ |
---|
941 | 962 | .compatible = "renesas,cmt-48-gen2", |
---|
942 | 963 | .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] |
---|
943 | 964 | }, |
---|
944 | | - { .compatible = "renesas,rcar-gen2-cmt0", .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] }, |
---|
945 | | - { .compatible = "renesas,rcar-gen2-cmt1", .data = &sh_cmt_info[SH_CMT1_RCAR_GEN2] }, |
---|
| 965 | + { |
---|
| 966 | + .compatible = "renesas,r8a7740-cmt1", |
---|
| 967 | + .data = &sh_cmt_info[SH_CMT_48BIT] |
---|
| 968 | + }, |
---|
| 969 | + { |
---|
| 970 | + .compatible = "renesas,sh73a0-cmt1", |
---|
| 971 | + .data = &sh_cmt_info[SH_CMT_48BIT] |
---|
| 972 | + }, |
---|
| 973 | + { |
---|
| 974 | + .compatible = "renesas,rcar-gen2-cmt0", |
---|
| 975 | + .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] |
---|
| 976 | + }, |
---|
| 977 | + { |
---|
| 978 | + .compatible = "renesas,rcar-gen2-cmt1", |
---|
| 979 | + .data = &sh_cmt_info[SH_CMT1_RCAR_GEN2] |
---|
| 980 | + }, |
---|
| 981 | + { |
---|
| 982 | + .compatible = "renesas,rcar-gen3-cmt0", |
---|
| 983 | + .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2] |
---|
| 984 | + }, |
---|
| 985 | + { |
---|
| 986 | + .compatible = "renesas,rcar-gen3-cmt1", |
---|
| 987 | + .data = &sh_cmt_info[SH_CMT1_RCAR_GEN2] |
---|
| 988 | + }, |
---|
946 | 989 | { } |
---|
947 | 990 | }; |
---|
948 | 991 | MODULE_DEVICE_TABLE(of, sh_cmt_of_table); |
---|
949 | 992 | |
---|
950 | 993 | static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) |
---|
951 | 994 | { |
---|
952 | | - unsigned int mask; |
---|
953 | | - unsigned int i; |
---|
| 995 | + unsigned int mask, i; |
---|
| 996 | + unsigned long rate; |
---|
954 | 997 | int ret; |
---|
955 | 998 | |
---|
956 | 999 | cmt->pdev = pdev; |
---|
.. | .. |
---|
986 | 1029 | if (ret < 0) |
---|
987 | 1030 | goto err_clk_unprepare; |
---|
988 | 1031 | |
---|
989 | | - if (cmt->info->width == 16) |
---|
990 | | - cmt->rate = clk_get_rate(cmt->clk) / 512; |
---|
991 | | - else |
---|
992 | | - cmt->rate = clk_get_rate(cmt->clk) / 8; |
---|
| 1032 | + rate = clk_get_rate(cmt->clk); |
---|
| 1033 | + if (!rate) { |
---|
| 1034 | + ret = -EINVAL; |
---|
| 1035 | + goto err_clk_disable; |
---|
| 1036 | + } |
---|
993 | 1037 | |
---|
994 | | - clk_disable(cmt->clk); |
---|
| 1038 | + /* We shall wait 2 input clks after register writes */ |
---|
| 1039 | + if (cmt->info->model >= SH_CMT_48BIT) |
---|
| 1040 | + cmt->reg_delay = DIV_ROUND_UP(2UL * USEC_PER_SEC, rate); |
---|
| 1041 | + cmt->rate = rate / (cmt->info->width == 16 ? 512 : 8); |
---|
995 | 1042 | |
---|
996 | 1043 | /* Map the memory resource(s). */ |
---|
997 | 1044 | ret = sh_cmt_map_memory(cmt); |
---|
998 | 1045 | if (ret < 0) |
---|
999 | | - goto err_clk_unprepare; |
---|
| 1046 | + goto err_clk_disable; |
---|
1000 | 1047 | |
---|
1001 | 1048 | /* Allocate and setup the channels. */ |
---|
1002 | 1049 | cmt->num_channels = hweight8(cmt->hw_channels); |
---|
.. | .. |
---|
1024 | 1071 | mask &= ~(1 << hwidx); |
---|
1025 | 1072 | } |
---|
1026 | 1073 | |
---|
| 1074 | + clk_disable(cmt->clk); |
---|
| 1075 | + |
---|
1027 | 1076 | platform_set_drvdata(pdev, cmt); |
---|
1028 | 1077 | |
---|
1029 | 1078 | return 0; |
---|
.. | .. |
---|
1031 | 1080 | err_unmap: |
---|
1032 | 1081 | kfree(cmt->channels); |
---|
1033 | 1082 | iounmap(cmt->mapbase); |
---|
| 1083 | +err_clk_disable: |
---|
| 1084 | + clk_disable(cmt->clk); |
---|
1034 | 1085 | err_clk_unprepare: |
---|
1035 | 1086 | clk_unprepare(cmt->clk); |
---|
1036 | 1087 | err_clk_put: |
---|
.. | .. |
---|
1043 | 1094 | struct sh_cmt_device *cmt = platform_get_drvdata(pdev); |
---|
1044 | 1095 | int ret; |
---|
1045 | 1096 | |
---|
1046 | | - if (!is_early_platform_device(pdev)) { |
---|
| 1097 | + if (!is_sh_early_platform_device(pdev)) { |
---|
1047 | 1098 | pm_runtime_set_active(&pdev->dev); |
---|
1048 | 1099 | pm_runtime_enable(&pdev->dev); |
---|
1049 | 1100 | } |
---|
.. | .. |
---|
1063 | 1114 | pm_runtime_idle(&pdev->dev); |
---|
1064 | 1115 | return ret; |
---|
1065 | 1116 | } |
---|
1066 | | - if (is_early_platform_device(pdev)) |
---|
| 1117 | + if (is_sh_early_platform_device(pdev)) |
---|
1067 | 1118 | return 0; |
---|
1068 | 1119 | |
---|
1069 | 1120 | out: |
---|
.. | .. |
---|
1100 | 1151 | platform_driver_unregister(&sh_cmt_device_driver); |
---|
1101 | 1152 | } |
---|
1102 | 1153 | |
---|
1103 | | -early_platform_init("earlytimer", &sh_cmt_device_driver); |
---|
| 1154 | +#ifdef CONFIG_SUPERH |
---|
| 1155 | +sh_early_platform_init("earlytimer", &sh_cmt_device_driver); |
---|
| 1156 | +#endif |
---|
| 1157 | + |
---|
1104 | 1158 | subsys_initcall(sh_cmt_init); |
---|
1105 | 1159 | module_exit(sh_cmt_exit); |
---|
1106 | 1160 | |
---|