| .. | .. |
|---|
| 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 | |
|---|