aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/rtc-v3020.h
blob: e55d82cebf80978ea6fc4b8a1b4528046ae88c3d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/*
 * v3020.h - Registers definition and platform data structure for the v3020 RTC.
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2006, 8D Technologies inc.
 */
#ifndef __LINUX_V3020_H
#define __LINUX_V3020_H

/* The v3020 has only one data pin but which one
 * is used depends on the board. */
struct v3020_platform_data {
	int leftshift; /* (1<<(leftshift)) & readl() */

	unsigned int use_gpio:1;
	unsigned int gpio_cs;
	unsigned int gpio_wr;
	unsigned int gpio_rd;
	unsigned int gpio_io;
};

#define V3020_STATUS_0	0x00
#define V3020_STATUS_1	0x01
#define V3020_SECONDS	0x02
#define V3020_MINUTES	0x03
#define V3020_HOURS		0x04
#define V3020_MONTH_DAY	0x05
#define V3020_MONTH		0x06
#define V3020_YEAR		0x07
#define V3020_WEEK_DAY	0x08
#define V3020_WEEK		0x09

#define V3020_IS_COMMAND(val) ((val)>=0x0E)

#define V3020_CMD_RAM2CLOCK	0x0E
#define V3020_CMD_CLOCK2RAM	0x0F

#endif /* __LINUX_V3020_H */
36 137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228








































































































































                                                                              





                                                                             








                                                                              




                                                                            
 
                         




                                         
                                        















                                                                         
                                













































                                                                            
/*
 * test_kprobes.c - simple sanity test for *probes
 *
 * Copyright IBM Corp. 2008
 *
 * This program is free software;  you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it would be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
 * the GNU General Public License for more details.
 */

#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/random.h>

#define div_factor 3

static u32 rand1, preh_val, posth_val, jph_val;
static int errors, handler_errors, num_tests;

static noinline u32 kprobe_target(u32 value)
{
	/*
	 * gcc ignores noinline on some architectures unless we stuff
	 * sufficient lard into the function. The get_kprobe() here is
	 * just for that.
	 *
	 * NOTE: We aren't concerned about the correctness of get_kprobe()
	 * here; hence, this call is neither under !preempt nor with the
	 * kprobe_mutex held. This is fine(tm)
	 */
	if (get_kprobe((void *)0xdeadbeef))
		printk(KERN_INFO "Kprobe smoke test: probe on 0xdeadbeef!\n");

	return (value / div_factor);
}

static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
	preh_val = (rand1 / div_factor);
	return 0;
}

static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
		unsigned long flags)
{
	if (preh_val != (rand1 / div_factor)) {
		handler_errors++;
		printk(KERN_ERR "Kprobe smoke test failed: "
				"incorrect value in post_handler\n");
	}
	posth_val = preh_val + div_factor;
}

static struct kprobe kp = {
	.symbol_name = "kprobe_target",
	.pre_handler = kp_pre_handler,
	.post_handler = kp_post_handler
};

static int test_kprobe(void)
{
	int ret;

	ret = register_kprobe(&kp);
	if (ret < 0) {
		printk(KERN_ERR "Kprobe smoke test failed: "
				"register_kprobe returned %d\n", ret);
		return ret;
	}

	ret = kprobe_target(rand1);
	unregister_kprobe(&kp);

	if (preh_val == 0) {
		printk(KERN_ERR "Kprobe smoke test failed: "
				"kprobe pre_handler not called\n");
		handler_errors++;
	}

	if (posth_val == 0) {
		printk(KERN_ERR "Kprobe smoke test failed: "
				"kprobe post_handler not called\n");
		handler_errors++;
	}

	return 0;
}

static u32 j_kprobe_target(u32 value)
{
	if (value != rand1) {
		handler_errors++;
		printk(KERN_ERR "Kprobe smoke test failed: "
				"incorrect value in jprobe handler\n");
	}

	jph_val = rand1;
	jprobe_return();
	return 0;
}

static struct jprobe jp = {
	.entry		= j_kprobe_target,
	.kp.symbol_name = "kprobe_target"
};

static int test_jprobe(void)
{
	int ret;

	ret = register_jprobe(&jp);
	if (ret < 0) {
		printk(KERN_ERR "Kprobe smoke test failed: "
				"register_jprobe returned %d\n", ret);
		return ret;
	}

	ret = kprobe_target(rand1);
	unregister_jprobe(&jp);
	if (jph_val == 0) {
		printk(KERN_ERR "Kprobe smoke test failed: "
				"jprobe handler not called\n");
		handler_errors++;
	}

	return 0;
}

#ifdef CONFIG_KRETPROBES
static u32 krph_val;

static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
	krph_val = (rand1 / div_factor);
	return 0;
}

static int return_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
	unsigned long ret = regs_return_value(regs);

	if (ret != (rand1 / div_factor)) {
		handler_errors++;
		printk(KERN_ERR "Kprobe smoke test failed: "
				"incorrect value in kretprobe handler\n");
	}
	if (krph_val == 0) {
		handler_errors++;
		printk(KERN_ERR "Kprobe smoke test failed: "
				"call to kretprobe entry handler failed\n");
	}

	krph_val = rand1;
	return 0;
}

static struct kretprobe rp = {
	.handler	= return_handler,
	.entry_handler  = entry_handler,
	.kp.symbol_name = "kprobe_target"
};

static int test_kretprobe(void)
{
	int ret;

	ret = register_kretprobe(&rp);
	if (ret < 0) {
		printk(KERN_ERR "Kprobe smoke test failed: "
				"register_kretprobe returned %d\n", ret);
		return ret;
	}

	ret = kprobe_target(rand1);
	unregister_kretprobe(&rp);
	if (krph_val != rand1) {
		printk(KERN_ERR "Kprobe smoke test failed: "
				"kretprobe handler not called\n");
		handler_errors++;
	}

	return 0;
}
#endif /* CONFIG_KRETPROBES */

int init_test_probes(void)
{
	int ret;

	do {
		rand1 = random32();
	} while (rand1 <= div_factor);

	printk(KERN_INFO "Kprobe smoke test started\n");
	num_tests++;
	ret = test_kprobe();
	if (ret < 0)
		errors++;

	num_tests++;
	ret = test_jprobe();
	if (ret < 0)
		errors++;

#ifdef CONFIG_KRETPROBES
	num_tests++;
	ret = test_kretprobe();
	if (ret < 0)
		errors++;
#endif /* CONFIG_KRETPROBES */

	if (errors)
		printk(KERN_ERR "BUG: Kprobe smoke test: %d out of "
				"%d tests failed\n", errors, num_tests);
	else if (handler_errors)
		printk(KERN_ERR "BUG: Kprobe smoke test: %d error(s) "
				"running handlers\n", handler_errors);
	else
		printk(KERN_INFO "Kprobe smoke test passed successfully\n");

	return 0;
}