aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/comedi/drivers/comedi_8254.h
blob: d89f6d94f8aa623e5f628eecb65f764de38a11f4 (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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * comedi_8254.h
 * Generic 8254 timer/counter support
 * Copyright (C) 2014 H Hartley Sweeten <hsweeten@visionengravers.com>
 *
 * COMEDI - Linux Control and Measurement Device Interface
 * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
 *
 * 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 will 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.
 */

#ifndef _COMEDI_8254_H
#define _COMEDI_8254_H

/*
 * Common oscillator base values in nanoseconds
 */
#define I8254_OSC_BASE_10MHZ	100
#define I8254_OSC_BASE_5MHZ	200
#define I8254_OSC_BASE_4MHZ	250
#define I8254_OSC_BASE_2MHZ	500
#define I8254_OSC_BASE_1MHZ	1000
#define I8254_OSC_BASE_100KHZ	10000
#define I8254_OSC_BASE_10KHZ	100000
#define I8254_OSC_BASE_1KHZ	1000000

/*
 * I/O access size used to read/write registers
 */
#define I8254_IO8		1
#define I8254_IO16		2
#define I8254_IO32		4

/*
 * Register map for generic 8254 timer (I8254_IO8 with 0 regshift)
 */
#define I8254_COUNTER0_REG		0x00
#define I8254_COUNTER1_REG		0x01
#define I8254_COUNTER2_REG		0x02
#define I8254_CTRL_REG			0x03
#define I8254_CTRL_SEL_CTR(x)		((x) << 6)
#define I8254_CTRL_READBACK_COUNT	((3 << 6) | (1 << 4))
#define I8254_CTRL_READBACK_STATUS	((3 << 6) | (1 << 5))
#define I8254_CTRL_READBACK_SEL_CTR(x)	(2 << (x))
#define I8254_CTRL_LATCH		(0 << 4)
#define I8254_CTRL_LSB_ONLY		(1 << 4)
#define I8254_CTRL_MSB_ONLY		(2 << 4)
#define I8254_CTRL_LSB_MSB		(3 << 4)

/* counter maps zero to 0x10000 */
#define I8254_MAX_COUNT			0x10000

/**
 * struct comedi_8254 - private data used by this module
 * @iobase:		PIO base address of the registers (in/out)
 * @mmio:		MMIO base address of the registers (read/write)
 * @iosize:		I/O size used to access the registers (b/w/l)
 * @regshift:		register gap shift
 * @osc_base:		cascaded oscillator speed in ns
 * @divisor:		divisor for single counter
 * @divisor1:		divisor loaded into first cascaded counter
 * @divisor2:		divisor loaded into second cascaded counter
 * #next_div:		next divisor for single counter
 * @next_div1:		next divisor to use for first cascaded counter
 * @next_div2:		next divisor to use for second cascaded counter
 * @clock_src;		current clock source for each counter (driver specific)
 * @gate_src;		current gate source  for each counter (driver specific)
 * @busy:		flags used to indicate that a counter is "busy"
 * @insn_config:	driver specific (*insn_config) callback
 */
struct comedi_8254 {
	unsigned long iobase;
	void __iomem *mmio;
	unsigned int iosize;
	unsigned int regshift;
	unsigned int osc_base;
	unsigned int divisor;
	unsigned int divisor1;
	unsigned int divisor2;
	unsigned int next_div;
	unsigned int next_div1;
	unsigned int next_div2;
	unsigned int clock_src[3];
	unsigned int gate_src[3];
	bool busy[3];

	int (*insn_config)(struct comedi_device *, struct comedi_subdevice *s,
			   struct comedi_insn *, unsigned int *data);
};

unsigned int comedi_8254_status(struct comedi_8254 *, unsigned int counter);
unsigned int comedi_8254_read(struct comedi_8254 *, unsigned int counter);
void comedi_8254_write(struct comedi_8254 *,
		       unsigned int counter, unsigned int val);

int comedi_8254_set_mode(struct comedi_8254 *,
			 unsigned int counter, unsigned int mode);
int comedi_8254_load(struct comedi_8254 *,
		     unsigned int counter, unsigned int val, unsigned int mode);

void comedi_8254_pacer_enable(struct comedi_8254 *,
			      unsigned int counter1, unsigned int counter2,
			      bool enable);
void comedi_8254_update_divisors(struct comedi_8254 *);
void comedi_8254_cascade_ns_to_timer(struct comedi_8254 *,
				     unsigned int *nanosec, unsigned int flags);
void comedi_8254_ns_to_timer(struct comedi_8254 *,
			     unsigned int *nanosec, unsigned int flags);

void comedi_8254_set_busy(struct comedi_8254 *,
			  unsigned int counter, bool busy);

void comedi_8254_subdevice_init(struct comedi_subdevice *,
				struct comedi_8254 *);

struct comedi_8254 *comedi_8254_init(unsigned long iobase,
				     unsigned int osc_base,
				     unsigned int iosize,
				     unsigned int regshift);
struct comedi_8254 *comedi_8254_mm_init(void __iomem *mmio,
					unsigned int osc_base,
					unsigned int iosize,
					unsigned int regshift);

#endif	/* _COMEDI_8254_H */