Merge branch 'pm-cpufreq'
[linux-2.6-block.git] / drivers / staging / comedi / drivers / addi-data / hwdrv_apci1564.c
CommitLineData
0658d6de
HS
1static int apci1564_timer_insn_config(struct comedi_device *dev,
2 struct comedi_subdevice *s,
3 struct comedi_insn *insn,
4 unsigned int *data)
c995fe94 5{
4c95a2b6 6 struct apci1564_private *devpriv = dev->private;
0658d6de 7 unsigned int ctrl;
843690b7 8
4c95a2b6 9 devpriv->tsk_current = current;
0658d6de 10
d9fca73c 11 /* Stop the timer */
e23337dc 12 ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
d9fca73c
HS
13 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
14 ADDI_TCW_CTRL_ENA);
e23337dc 15 outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
0658d6de
HS
16
17 if (data[1] == 1) {
18 /* Enable timer int & disable all the other int sources */
d9fca73c
HS
19 outl(ADDI_TCW_CTRL_IRQ_ENA,
20 devpriv->timer + ADDI_TCW_CTRL_REG);
0658d6de
HS
21 outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
22 outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG);
23 outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG);
24 if (devpriv->counters) {
7d6156ed
HS
25 unsigned long iobase;
26
27 iobase = devpriv->counters + ADDI_TCW_IRQ_REG;
28 outl(0x0, iobase + APCI1564_COUNTER(0));
29 outl(0x0, iobase + APCI1564_COUNTER(1));
30 outl(0x0, iobase + APCI1564_COUNTER(2));
11975225 31 }
988bcffd 32 } else {
0658d6de 33 /* disable Timer interrupt */
e23337dc 34 outl(0x0, devpriv->timer + ADDI_TCW_CTRL_REG);
11975225 35 }
0658d6de
HS
36
37 /* Loading Timebase */
e23337dc 38 outl(data[2], devpriv->timer + ADDI_TCW_TIMEBASE_REG);
0658d6de
HS
39
40 /* Loading the Reload value */
e23337dc 41 outl(data[3], devpriv->timer + ADDI_TCW_RELOAD_REG);
0658d6de 42
e23337dc 43 ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
d9fca73c
HS
44 ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK |
45 ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
46 ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
47 ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA);
48 ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA;
e23337dc 49 outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
0658d6de 50
c995fe94
ADG
51 return insn->n;
52}
53
0658d6de
HS
54static int apci1564_timer_insn_write(struct comedi_device *dev,
55 struct comedi_subdevice *s,
56 struct comedi_insn *insn,
57 unsigned int *data)
c995fe94 58{
4c95a2b6 59 struct apci1564_private *devpriv = dev->private;
0658d6de
HS
60 unsigned int ctrl;
61
e23337dc 62 ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
9a2d58c7 63 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
0658d6de
HS
64 switch (data[1]) {
65 case 0: /* Stop The Timer */
9a2d58c7 66 ctrl &= ~ADDI_TCW_CTRL_ENA;
0658d6de
HS
67 break;
68 case 1: /* Enable the Timer */
d9fca73c 69 ctrl |= ADDI_TCW_CTRL_ENA;
0658d6de 70 break;
11899188 71 }
e23337dc 72 outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
0658d6de 73
c995fe94
ADG
74 return insn->n;
75}
76
0658d6de
HS
77static int apci1564_timer_insn_read(struct comedi_device *dev,
78 struct comedi_subdevice *s,
79 struct comedi_insn *insn,
80 unsigned int *data)
c995fe94 81{
4c95a2b6 82 struct apci1564_private *devpriv = dev->private;
c995fe94 83
0658d6de 84 /* Stores the status of the Timer */
18543b13
HS
85 data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) &
86 ADDI_TCW_STATUS_OVERFLOW;
c995fe94 87
0658d6de 88 /* Stores the Actual value of the Timer */
e23337dc 89 data[1] = inl(devpriv->timer + ADDI_TCW_VAL_REG);
c995fe94 90
0658d6de
HS
91 return insn->n;
92}
c995fe94 93
0658d6de
HS
94static int apci1564_counter_insn_config(struct comedi_device *dev,
95 struct comedi_subdevice *s,
96 struct comedi_insn *insn,
97 unsigned int *data)
98{
99 struct apci1564_private *devpriv = dev->private;
100 unsigned int chan = CR_CHAN(insn->chanspec);
7d6156ed 101 unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
0658d6de 102 unsigned int ctrl;
c995fe94 103
0658d6de 104 devpriv->tsk_current = current;
c995fe94 105
0658d6de 106 /* Stop The Timer */
d9fca73c
HS
107 ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
108 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
109 ADDI_TCW_CTRL_ENA);
7d6156ed 110 outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
0658d6de
HS
111
112 /* Set the reload value */
7d6156ed 113 outl(data[3], iobase + ADDI_TCW_RELOAD_REG);
0658d6de 114
d9fca73c
HS
115 /* Set the mode */
116 ctrl &= ~(ADDI_TCW_CTRL_EXT_CLK_MASK | ADDI_TCW_CTRL_MODE_MASK |
d9fca73c 117 ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
835f8fe9 118 ADDI_TCW_CTRL_WARN_ENA);
1f5d767f 119 ctrl |= ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE(data[4]);
7d6156ed 120 outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
0658d6de
HS
121
122 /* Enable or Disable Interrupt */
d9fca73c
HS
123 if (data[1])
124 ctrl |= ADDI_TCW_CTRL_IRQ_ENA;
835f8fe9
HS
125 else
126 ctrl &= ~ADDI_TCW_CTRL_IRQ_ENA;
7d6156ed 127 outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
0658d6de
HS
128
129 /* Set the Up/Down selection */
d9fca73c
HS
130 if (data[6])
131 ctrl |= ADDI_TCW_CTRL_CNT_UP;
835f8fe9
HS
132 else
133 ctrl &= ~ADDI_TCW_CTRL_CNT_UP;
7d6156ed 134 outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
0658d6de
HS
135
136 return insn->n;
137}
138
139static int apci1564_counter_insn_write(struct comedi_device *dev,
140 struct comedi_subdevice *s,
141 struct comedi_insn *insn,
142 unsigned int *data)
143{
144 struct apci1564_private *devpriv = dev->private;
145 unsigned int chan = CR_CHAN(insn->chanspec);
7d6156ed 146 unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
0658d6de
HS
147 unsigned int ctrl;
148
7d6156ed 149 ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
c6288a3b 150 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
0658d6de
HS
151 switch (data[1]) {
152 case 0: /* Stops the Counter subdevice */
153 ctrl = 0;
154 break;
155 case 1: /* Start the Counter subdevice */
d9fca73c 156 ctrl |= ADDI_TCW_CTRL_ENA;
0658d6de
HS
157 break;
158 case 2: /* Clears the Counter subdevice */
d9fca73c 159 ctrl |= ADDI_TCW_CTRL_GATE;
0658d6de 160 break;
11975225 161 }
7d6156ed 162 outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
0658d6de
HS
163
164 return insn->n;
165}
166
167static int apci1564_counter_insn_read(struct comedi_device *dev,
168 struct comedi_subdevice *s,
169 struct comedi_insn *insn,
170 unsigned int *data)
171{
172 struct apci1564_private *devpriv = dev->private;
173 unsigned int chan = CR_CHAN(insn->chanspec);
7d6156ed 174 unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
0658d6de
HS
175 unsigned int status;
176
177 /* Read the Counter Actual Value. */
7d6156ed 178 data[0] = inl(iobase + ADDI_TCW_VAL_REG);
0658d6de 179
7d6156ed 180 status = inl(iobase + ADDI_TCW_STATUS_REG);
5babc1bc
HS
181 data[1] = (status & ADDI_TCW_STATUS_SOFT_TRIG) ? 1 : 0;
182 data[2] = (status & ADDI_TCW_STATUS_HARDWARE_TRIG) ? 1 : 0;
183 data[3] = (status & ADDI_TCW_STATUS_SOFT_CLR) ? 1 : 0;
184 data[4] = (status & ADDI_TCW_STATUS_OVERFLOW) ? 1 : 0;
0658d6de 185
c995fe94
ADG
186 return insn->n;
187}