Blame view

drivers/clocksource/h8300_tpu.c 3.23 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
618b902d8   Yoshinori Sato   h8300: clocksource
2
  /*
4633f4cac   Yoshinori Sato   clocksource/drive...
3
   *  H8S TPU Driver
618b902d8   Yoshinori Sato   h8300: clocksource
4
5
6
7
8
9
   *
   *  Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp>
   *
   */
  
  #include <linux/errno.h>
618b902d8   Yoshinori Sato   h8300: clocksource
10
  #include <linux/kernel.h>
618b902d8   Yoshinori Sato   h8300: clocksource
11
  #include <linux/init.h>
618b902d8   Yoshinori Sato   h8300: clocksource
12
  #include <linux/clocksource.h>
618b902d8   Yoshinori Sato   h8300: clocksource
13
14
15
  #include <linux/clk.h>
  #include <linux/io.h>
  #include <linux/of.h>
4633f4cac   Yoshinori Sato   clocksource/drive...
16
17
  #include <linux/of_address.h>
  #include <linux/of_irq.h>
618b902d8   Yoshinori Sato   h8300: clocksource
18

9471f1d95   Daniel Lezcano   clocksource/drive...
19
20
21
  #define TCR	0x0
  #define TSR	0x5
  #define TCNT	0x6
618b902d8   Yoshinori Sato   h8300: clocksource
22

d33f250af   Yoshinori Sato   clocksource/drive...
23
  #define TCFV	0x10
618b902d8   Yoshinori Sato   h8300: clocksource
24
  struct tpu_priv {
618b902d8   Yoshinori Sato   h8300: clocksource
25
  	struct clocksource cs;
751605152   Daniel Lezcano   h8300: Rename ctl...
26
27
  	void __iomem *mapbase1;
  	void __iomem *mapbase2;
618b902d8   Yoshinori Sato   h8300: clocksource
28
29
30
31
32
33
34
  	raw_spinlock_t lock;
  	unsigned int cs_enabled;
  };
  
  static inline unsigned long read_tcnt32(struct tpu_priv *p)
  {
  	unsigned long tcnt;
d33f250af   Yoshinori Sato   clocksource/drive...
35
36
  	tcnt = ioread16be(p->mapbase1 + TCNT) << 16;
  	tcnt |= ioread16be(p->mapbase2 + TCNT);
618b902d8   Yoshinori Sato   h8300: clocksource
37
38
39
40
41
42
43
  	return tcnt;
  }
  
  static int tpu_get_counter(struct tpu_priv *p, unsigned long long *val)
  {
  	unsigned long v1, v2, v3;
  	int o1, o2;
d33f250af   Yoshinori Sato   clocksource/drive...
44
  	o1 = ioread8(p->mapbase1 + TSR) & TCFV;
618b902d8   Yoshinori Sato   h8300: clocksource
45
46
47
48
49
50
51
  
  	/* Make sure the timer value is stable. Stolen from acpi_pm.c */
  	do {
  		o2 = o1;
  		v1 = read_tcnt32(p);
  		v2 = read_tcnt32(p);
  		v3 = read_tcnt32(p);
d33f250af   Yoshinori Sato   clocksource/drive...
52
  		o1 = ioread8(p->mapbase1 + TSR) & TCFV;
618b902d8   Yoshinori Sato   h8300: clocksource
53
54
55
56
57
58
59
60
61
62
63
  	} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
  			  || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
  
  	*val = v2;
  	return o1;
  }
  
  static inline struct tpu_priv *cs_to_priv(struct clocksource *cs)
  {
  	return container_of(cs, struct tpu_priv, cs);
  }
a5a1d1c29   Thomas Gleixner   clocksource: Use ...
64
  static u64 tpu_clocksource_read(struct clocksource *cs)
618b902d8   Yoshinori Sato   h8300: clocksource
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  {
  	struct tpu_priv *p = cs_to_priv(cs);
  	unsigned long flags;
  	unsigned long long value;
  
  	raw_spin_lock_irqsave(&p->lock, flags);
  	if (tpu_get_counter(p, &value))
  		value += 0x100000000;
  	raw_spin_unlock_irqrestore(&p->lock, flags);
  
  	return value;
  }
  
  static int tpu_clocksource_enable(struct clocksource *cs)
  {
  	struct tpu_priv *p = cs_to_priv(cs);
  
  	WARN_ON(p->cs_enabled);
d33f250af   Yoshinori Sato   clocksource/drive...
83
84
85
86
  	iowrite16be(0, p->mapbase1 + TCNT);
  	iowrite16be(0, p->mapbase2 + TCNT);
  	iowrite8(0x0f, p->mapbase1 + TCR);
  	iowrite8(0x03, p->mapbase2 + TCR);
618b902d8   Yoshinori Sato   h8300: clocksource
87
88
89
90
91
92
93
94
95
96
  
  	p->cs_enabled = true;
  	return 0;
  }
  
  static void tpu_clocksource_disable(struct clocksource *cs)
  {
  	struct tpu_priv *p = cs_to_priv(cs);
  
  	WARN_ON(!p->cs_enabled);
d33f250af   Yoshinori Sato   clocksource/drive...
97
98
  	iowrite8(0, p->mapbase1 + TCR);
  	iowrite8(0, p->mapbase2 + TCR);
618b902d8   Yoshinori Sato   h8300: clocksource
99
100
  	p->cs_enabled = false;
  }
4633f4cac   Yoshinori Sato   clocksource/drive...
101
102
103
104
105
106
107
108
109
110
111
  static struct tpu_priv tpu_priv = {
  	.cs = {
  		.name = "H8S_TPU",
  		.rating = 200,
  		.read = tpu_clocksource_read,
  		.enable = tpu_clocksource_enable,
  		.disable = tpu_clocksource_disable,
  		.mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8),
  		.flags = CLOCK_SOURCE_IS_CONTINUOUS,
  	},
  };
618b902d8   Yoshinori Sato   h8300: clocksource
112
113
  #define CH_L 0
  #define CH_H 1
f2f9900ca   Daniel Lezcano   clocksource/drive...
114
  static int __init h8300_tpu_init(struct device_node *node)
618b902d8   Yoshinori Sato   h8300: clocksource
115
  {
4633f4cac   Yoshinori Sato   clocksource/drive...
116
117
  	void __iomem *base[2];
  	struct clk *clk;
f2f9900ca   Daniel Lezcano   clocksource/drive...
118
  	int ret = -ENXIO;
618b902d8   Yoshinori Sato   h8300: clocksource
119

4633f4cac   Yoshinori Sato   clocksource/drive...
120
121
122
123
  	clk = of_clk_get(node, 0);
  	if (IS_ERR(clk)) {
  		pr_err("failed to get clock for clocksource
  ");
f2f9900ca   Daniel Lezcano   clocksource/drive...
124
  		return PTR_ERR(clk);
618b902d8   Yoshinori Sato   h8300: clocksource
125
  	}
4633f4cac   Yoshinori Sato   clocksource/drive...
126
127
128
129
130
  	base[CH_L] = of_iomap(node, CH_L);
  	if (!base[CH_L]) {
  		pr_err("failed to map registers for clocksource
  ");
  		goto free_clk;
618b902d8   Yoshinori Sato   h8300: clocksource
131
  	}
4633f4cac   Yoshinori Sato   clocksource/drive...
132
133
134
135
136
  	base[CH_H] = of_iomap(node, CH_H);
  	if (!base[CH_H]) {
  		pr_err("failed to map registers for clocksource
  ");
  		goto unmap_L;
618b902d8   Yoshinori Sato   h8300: clocksource
137
  	}
751605152   Daniel Lezcano   h8300: Rename ctl...
138
139
  	tpu_priv.mapbase1 = base[CH_L];
  	tpu_priv.mapbase2 = base[CH_H];
618b902d8   Yoshinori Sato   h8300: clocksource
140

f2f9900ca   Daniel Lezcano   clocksource/drive...
141
  	return clocksource_register_hz(&tpu_priv.cs, clk_get_rate(clk) / 64);
618b902d8   Yoshinori Sato   h8300: clocksource
142

4633f4cac   Yoshinori Sato   clocksource/drive...
143
144
145
146
  unmap_L:
  	iounmap(base[CH_H]);
  free_clk:
  	clk_put(clk);
f2f9900ca   Daniel Lezcano   clocksource/drive...
147
  	return ret;
618b902d8   Yoshinori Sato   h8300: clocksource
148
  }
172733959   Daniel Lezcano   clocksource/drive...
149
  TIMER_OF_DECLARE(h8300_tpu, "renesas,tpu", h8300_tpu_init);