Skip to content

Commit 22627c6

Browse files
Sergei Shtylyovdlezcano
authored andcommitted
clocksource/drivers/sh_cmt: Fixup for 64-bit machines
When trying to use CMT for clockevents on R-Car gen3 SoCs, I noticed that 'max_delta_ns' for the broadcast timer (CMT) was shown as 1000 in /proc/timer_list. It turned out that when calculating it, the driver did 1 << 32 (causing what I think was undefined behavior) resulting in a zero delta, later clamped to 1000 by cev_delta2ns(). The root cause turned out to be that the driver abused *unsigned long* for the CMT register values (which are 16/32-bit), so that the calculation of 'ch->max_match_value' in sh_cmt_setup_channel() used the wrong branch. Using more proper 'u32' instead fixed 'max_delta_ns' and even fixed the switching an active clocksource to CMT (which caused the system to turn non-interactive before). Signed-off-by: Sergei Shtylyov <[email protected]> Reviewed-by: Geert Uytterhoeven <[email protected]> Signed-off-by: Daniel Lezcano <[email protected]>
1 parent 0b9294f commit 22627c6

File tree

1 file changed

+33
-39
lines changed

1 file changed

+33
-39
lines changed

drivers/clocksource/sh_cmt.c

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,17 @@ struct sh_cmt_info {
7070
unsigned int channels_mask;
7171

7272
unsigned long width; /* 16 or 32 bit version of hardware block */
73-
unsigned long overflow_bit;
74-
unsigned long clear_bits;
73+
u32 overflow_bit;
74+
u32 clear_bits;
7575

7676
/* callbacks for CMSTR and CMCSR access */
77-
unsigned long (*read_control)(void __iomem *base, unsigned long offs);
77+
u32 (*read_control)(void __iomem *base, unsigned long offs);
7878
void (*write_control)(void __iomem *base, unsigned long offs,
79-
unsigned long value);
79+
u32 value);
8080

8181
/* callbacks for CMCNT and CMCOR access */
82-
unsigned long (*read_count)(void __iomem *base, unsigned long offs);
83-
void (*write_count)(void __iomem *base, unsigned long offs,
84-
unsigned long value);
82+
u32 (*read_count)(void __iomem *base, unsigned long offs);
83+
void (*write_count)(void __iomem *base, unsigned long offs, u32 value);
8584
};
8685

8786
struct sh_cmt_channel {
@@ -95,9 +94,9 @@ struct sh_cmt_channel {
9594

9695
unsigned int timer_bit;
9796
unsigned long flags;
98-
unsigned long match_value;
99-
unsigned long next_match_value;
100-
unsigned long max_match_value;
97+
u32 match_value;
98+
u32 next_match_value;
99+
u32 max_match_value;
101100
raw_spinlock_t lock;
102101
struct clock_event_device ced;
103102
struct clocksource cs;
@@ -152,24 +151,22 @@ struct sh_cmt_device {
152151
#define SH_CMT32_CMCSR_CKS_RCLK1 (7 << 0)
153152
#define SH_CMT32_CMCSR_CKS_MASK (7 << 0)
154153

155-
static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
154+
static u32 sh_cmt_read16(void __iomem *base, unsigned long offs)
156155
{
157156
return ioread16(base + (offs << 1));
158157
}
159158

160-
static unsigned long sh_cmt_read32(void __iomem *base, unsigned long offs)
159+
static u32 sh_cmt_read32(void __iomem *base, unsigned long offs)
161160
{
162161
return ioread32(base + (offs << 2));
163162
}
164163

165-
static void sh_cmt_write16(void __iomem *base, unsigned long offs,
166-
unsigned long value)
164+
static void sh_cmt_write16(void __iomem *base, unsigned long offs, u32 value)
167165
{
168166
iowrite16(value, base + (offs << 1));
169167
}
170168

171-
static void sh_cmt_write32(void __iomem *base, unsigned long offs,
172-
unsigned long value)
169+
static void sh_cmt_write32(void __iomem *base, unsigned long offs, u32 value)
173170
{
174171
iowrite32(value, base + (offs << 2));
175172
}
@@ -234,56 +231,51 @@ static const struct sh_cmt_info sh_cmt_info[] = {
234231
#define CMCNT 1 /* channel register */
235232
#define CMCOR 2 /* channel register */
236233

237-
static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
234+
static inline u32 sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
238235
{
239236
if (ch->iostart)
240237
return ch->cmt->info->read_control(ch->iostart, 0);
241238
else
242239
return ch->cmt->info->read_control(ch->cmt->mapbase, 0);
243240
}
244241

245-
static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
246-
unsigned long value)
242+
static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, u32 value)
247243
{
248244
if (ch->iostart)
249245
ch->cmt->info->write_control(ch->iostart, 0, value);
250246
else
251247
ch->cmt->info->write_control(ch->cmt->mapbase, 0, value);
252248
}
253249

254-
static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
250+
static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
255251
{
256252
return ch->cmt->info->read_control(ch->ioctrl, CMCSR);
257253
}
258254

259-
static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch,
260-
unsigned long value)
255+
static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch, u32 value)
261256
{
262257
ch->cmt->info->write_control(ch->ioctrl, CMCSR, value);
263258
}
264259

265-
static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
260+
static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
266261
{
267262
return ch->cmt->info->read_count(ch->ioctrl, CMCNT);
268263
}
269264

270-
static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch,
271-
unsigned long value)
265+
static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value)
272266
{
273267
ch->cmt->info->write_count(ch->ioctrl, CMCNT, value);
274268
}
275269

276-
static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch,
277-
unsigned long value)
270+
static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch, u32 value)
278271
{
279272
ch->cmt->info->write_count(ch->ioctrl, CMCOR, value);
280273
}
281274

282-
static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
283-
int *has_wrapped)
275+
static u32 sh_cmt_get_counter(struct sh_cmt_channel *ch, u32 *has_wrapped)
284276
{
285-
unsigned long v1, v2, v3;
286-
int o1, o2;
277+
u32 v1, v2, v3;
278+
u32 o1, o2;
287279

288280
o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit;
289281

@@ -303,7 +295,8 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
303295

304296
static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
305297
{
306-
unsigned long flags, value;
298+
unsigned long flags;
299+
u32 value;
307300

308301
/* start stop register shared by multiple timer channels */
309302
raw_spin_lock_irqsave(&ch->cmt->lock, flags);
@@ -410,11 +403,11 @@ static void sh_cmt_disable(struct sh_cmt_channel *ch)
410403
static void sh_cmt_clock_event_program_verify(struct sh_cmt_channel *ch,
411404
int absolute)
412405
{
413-
unsigned long new_match;
414-
unsigned long value = ch->next_match_value;
415-
unsigned long delay = 0;
416-
unsigned long now = 0;
417-
int has_wrapped;
406+
u32 value = ch->next_match_value;
407+
u32 new_match;
408+
u32 delay = 0;
409+
u32 now = 0;
410+
u32 has_wrapped;
418411

419412
now = sh_cmt_get_counter(ch, &has_wrapped);
420413
ch->flags |= FLAG_REPROGRAM; /* force reprogram */
@@ -611,9 +604,10 @@ static struct sh_cmt_channel *cs_to_sh_cmt(struct clocksource *cs)
611604
static u64 sh_cmt_clocksource_read(struct clocksource *cs)
612605
{
613606
struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
614-
unsigned long flags, raw;
607+
unsigned long flags;
615608
unsigned long value;
616-
int has_wrapped;
609+
u32 has_wrapped;
610+
u32 raw;
617611

618612
raw_spin_lock_irqsave(&ch->lock, flags);
619613
value = ch->total_cycles;

0 commit comments

Comments
 (0)