|
31 | 31 | #include <linux/platform_data/dmtimer-omap.h> |
32 | 32 |
|
33 | 33 | #include <clocksource/timer-ti-dm.h> |
| 34 | +#include <linux/delay.h> |
34 | 35 |
|
35 | 36 | /* |
36 | 37 | * timer errata flags |
@@ -836,6 +837,48 @@ static int omap_dm_timer_set_match(struct omap_dm_timer *cookie, int enable, |
836 | 837 | return 0; |
837 | 838 | } |
838 | 839 |
|
| 840 | +static int omap_dm_timer_set_cap(struct omap_dm_timer *cookie, |
| 841 | + int autoreload, bool config_period) |
| 842 | +{ |
| 843 | + struct dmtimer *timer; |
| 844 | + struct device *dev; |
| 845 | + int rc; |
| 846 | + u32 l; |
| 847 | + |
| 848 | + timer = to_dmtimer(cookie); |
| 849 | + if (unlikely(!timer)) |
| 850 | + return -EINVAL; |
| 851 | + |
| 852 | + dev = &timer->pdev->dev; |
| 853 | + rc = pm_runtime_resume_and_get(dev); |
| 854 | + if (rc) |
| 855 | + return rc; |
| 856 | + /* |
| 857 | + * 1. Select autoreload mode. TIMER_TCLR[1] AR bit. |
| 858 | + * 2. TIMER_TCLR[14]: Sets the functionality of the TIMER IO pin. |
| 859 | + * 3. TIMER_TCLR[13] : Capture mode select bit. |
| 860 | + * 3. TIMER_TCLR[9-8] : Select transition capture mode. |
| 861 | + */ |
| 862 | + |
| 863 | + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); |
| 864 | + |
| 865 | + if (autoreload) |
| 866 | + l |= OMAP_TIMER_CTRL_AR; |
| 867 | + |
| 868 | + l |= OMAP_TIMER_CTRL_CAPTMODE | OMAP_TIMER_CTRL_GPOCFG; |
| 869 | + |
| 870 | + if (config_period == true) |
| 871 | + l |= OMAP_TIMER_CTRL_TCM_LOWTOHIGH; /* Time Period config */ |
| 872 | + else |
| 873 | + l |= OMAP_TIMER_CTRL_TCM_BOTHEDGES; /* Duty Cycle config */ |
| 874 | + |
| 875 | + dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l); |
| 876 | + |
| 877 | + pm_runtime_put_sync(dev); |
| 878 | + |
| 879 | + return 0; |
| 880 | +} |
| 881 | + |
839 | 882 | static int omap_dm_timer_set_pwm(struct omap_dm_timer *cookie, int def_on, |
840 | 883 | int toggle, int trigger, int autoreload) |
841 | 884 | { |
@@ -1023,23 +1066,92 @@ static unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *cookie) |
1023 | 1066 | return __omap_dm_timer_read_counter(timer); |
1024 | 1067 | } |
1025 | 1068 |
|
| 1069 | +static inline unsigned int __omap_dm_timer_cap(struct dmtimer *timer, int idx) |
| 1070 | +{ |
| 1071 | + return idx == 0 ? dmtimer_read(timer, OMAP_TIMER_CAPTURE_REG) : |
| 1072 | + dmtimer_read(timer, OMAP_TIMER_CAPTURE2_REG); |
| 1073 | +} |
| 1074 | + |
1026 | 1075 | static int omap_dm_timer_write_counter(struct omap_dm_timer *cookie, unsigned int value) |
1027 | 1076 | { |
1028 | 1077 | struct dmtimer *timer; |
| 1078 | + struct device *dev; |
1029 | 1079 |
|
1030 | 1080 | timer = to_dmtimer(cookie); |
1031 | | - if (unlikely(!timer || !atomic_read(&timer->enabled))) { |
1032 | | - pr_err("%s: timer not available or enabled.\n", __func__); |
| 1081 | + if (unlikely(!timer)) { |
| 1082 | + pr_err("%s: timer not available.\n", __func__); |
1033 | 1083 | return -EINVAL; |
1034 | 1084 | } |
1035 | 1085 |
|
| 1086 | + dev = &timer->pdev->dev; |
| 1087 | + |
| 1088 | + pm_runtime_resume_and_get(dev); |
1036 | 1089 | dmtimer_write(timer, OMAP_TIMER_COUNTER_REG, value); |
| 1090 | + pm_runtime_put_sync(dev); |
1037 | 1091 |
|
1038 | 1092 | /* Save the context */ |
1039 | 1093 | timer->context.tcrr = value; |
1040 | 1094 | return 0; |
1041 | 1095 | } |
1042 | 1096 |
|
| 1097 | +/** |
| 1098 | + * omap_dm_timer_cap_counter() - Calculate the high count or period count depending on the |
| 1099 | + * configuration. |
| 1100 | + * @cookie:Pointer to OMAP DM timer |
| 1101 | + * @is_period:Whether to configure timer in period or duty cycle mode |
| 1102 | + * |
| 1103 | + * Return high count or period count if timer is enabled else appropriate error. |
| 1104 | + */ |
| 1105 | +static unsigned int omap_dm_timer_cap_counter(struct omap_dm_timer *cookie, bool is_period) |
| 1106 | +{ |
| 1107 | + struct dmtimer *timer; |
| 1108 | + unsigned int cap1 = 0; |
| 1109 | + unsigned int cap2 = 0; |
| 1110 | + u32 l, ret; |
| 1111 | + |
| 1112 | + timer = to_dmtimer(cookie); |
| 1113 | + if (unlikely(!timer || !atomic_read(&timer->enabled))) { |
| 1114 | + pr_err("%s:timer is not available or enabled.%p\n", __func__, (void *)timer); |
| 1115 | + return -EINVAL; |
| 1116 | + } |
| 1117 | + |
| 1118 | + /* Stop the timer */ |
| 1119 | + omap_dm_timer_stop(cookie); |
| 1120 | + |
| 1121 | + /* Clear the timer counter value to 0 */ |
| 1122 | + ret = omap_dm_timer_write_counter(cookie, 0); |
| 1123 | + if (ret) |
| 1124 | + return ret; |
| 1125 | + |
| 1126 | + /* Sets the timer capture configuration for period/duty cycle calculation */ |
| 1127 | + ret = omap_dm_timer_set_cap(cookie, true, is_period); |
| 1128 | + if (ret) { |
| 1129 | + pr_err("%s: Failed to set timer capture configuration.\n", __func__); |
| 1130 | + return ret; |
| 1131 | + } |
| 1132 | + /* Start the timer */ |
| 1133 | + omap_dm_timer_start(cookie); |
| 1134 | + |
| 1135 | + /* |
| 1136 | + * 1 sec delay is given so as to provide |
| 1137 | + * enough time to capture low frequency signals. |
| 1138 | + */ |
| 1139 | + msleep(1000); |
| 1140 | + |
| 1141 | + cap1 = __omap_dm_timer_cap(timer, 0); |
| 1142 | + cap2 = __omap_dm_timer_cap(timer, 1); |
| 1143 | + |
| 1144 | + /* |
| 1145 | + * Clears the TCLR configuration. |
| 1146 | + * The start bit must be set to 1 as the timer is already in start mode. |
| 1147 | + */ |
| 1148 | + l = dmtimer_read(timer, OMAP_TIMER_CTRL_REG); |
| 1149 | + l &= ~(0xffff) | 0x1; |
| 1150 | + dmtimer_write(timer, OMAP_TIMER_CTRL_REG, l); |
| 1151 | + |
| 1152 | + return (cap2-cap1); |
| 1153 | +} |
| 1154 | + |
1043 | 1155 | static int __maybe_unused omap_dm_timer_runtime_suspend(struct device *dev) |
1044 | 1156 | { |
1045 | 1157 | struct dmtimer *timer = dev_get_drvdata(dev); |
@@ -1246,6 +1358,9 @@ static const struct omap_dm_timer_ops dmtimer_ops = { |
1246 | 1358 | .write_counter = omap_dm_timer_write_counter, |
1247 | 1359 | .read_status = omap_dm_timer_read_status, |
1248 | 1360 | .write_status = omap_dm_timer_write_status, |
| 1361 | + .set_cap = omap_dm_timer_set_cap, |
| 1362 | + .get_cap_status = omap_dm_timer_get_pwm_status, |
| 1363 | + .read_cap = omap_dm_timer_cap_counter, |
1249 | 1364 | }; |
1250 | 1365 |
|
1251 | 1366 | static const struct dmtimer_platform_data omap3plus_pdata = { |
|
0 commit comments