8ba094cc31f4d9c0fdfbb9ef00c6cd2fc2b40aec
[pandora-kernel.git] / drivers / staging / comedi / drivers / addi-data / hwdrv_apci3501.c
1 /* Watchdog Related Defines */
2
3 #define ADDIDATA_TIMER                  0
4 #define ADDIDATA_WATCHDOG               2
5
6 /*
7  * (*insn_config) for the timer subdevice
8  *
9  * Configures The Timer, Counter or Watchdog
10  * Data Pointer contains configuration parameters as below
11  *      data[0] : 0 Configure As Timer
12  *                1 Configure As Counter
13  *                2 Configure As Watchdog
14  *      data[1] : 1 Enable  Interrupt
15  *                0 Disable Interrupt
16  *      data[2] : Time Unit
17  *      data[3] : Reload Value
18  */
19 static int apci3501_config_insn_timer(struct comedi_device *dev,
20                                       struct comedi_subdevice *s,
21                                       struct comedi_insn *insn,
22                                       unsigned int *data)
23 {
24         struct apci3501_private *devpriv = dev->private;
25         unsigned int ctrl;
26
27         if (data[0] != ADDIDATA_WATCHDOG &&
28             data[0] != ADDIDATA_TIMER)
29                 return -EINVAL;
30
31         devpriv->tsk_Current = current;
32
33         devpriv->timer_mode = data[0];
34
35         /* first, disable the watchdog or stop the timer */
36         if (devpriv->timer_mode == ADDIDATA_WATCHDOG) {
37                 ctrl = 0;
38         } else {
39                 ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
40                 ctrl &= 0xfffff9fe;
41         }
42         outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
43
44         /* enable/disable the timer interrupt */
45         ctrl = (data[1] == 1) ? 0x2 : 0;
46         outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
47
48         outl(data[2], devpriv->tcw + ADDI_TCW_TIMEBASE_REG);
49         outl(data[3], devpriv->tcw + ADDI_TCW_RELOAD_REG);
50
51         ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
52         if (devpriv->timer_mode == ADDIDATA_WATCHDOG) {
53                 /* Set the mode (e2->e0) NOTE: this doesn't look correct */
54                 ctrl |= 0xfff819e0;
55         } else {
56                 /* mode 2 */
57                 ctrl &= 0xfff719e2;
58                 ctrl |= (2 << 13) | 0x10;
59         }
60         outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
61
62         return insn->n;
63 }
64
65 /*
66  * (*insn_write) for the timer subdevice
67  *
68  * Start / Stop The Selected Timer , Counter or Watchdog
69  * Data Pointer contains configuration parameters as below
70  *      data[0] : 0 Timer
71  *                1 Counter
72  *                2 Watchdog
73  *      data[1] : 1 Start
74  *                0 Stop
75  *                2 Trigger
76  */
77 static int apci3501_write_insn_timer(struct comedi_device *dev,
78                                      struct comedi_subdevice *s,
79                                      struct comedi_insn *insn,
80                                      unsigned int *data)
81 {
82         struct apci3501_private *devpriv = dev->private;
83         unsigned int ctrl;
84
85         if (devpriv->timer_mode == ADDIDATA_WATCHDOG ||
86             devpriv->timer_mode == ADDIDATA_TIMER) {
87                 ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
88                 ctrl &= 0xfffff9ff;
89
90                 if (data[1] == 1) {             /* enable */
91                         ctrl |= 0x1;
92                 } else if (data[1] == 0) {      /* stop */
93                         if (devpriv->timer_mode == ADDIDATA_WATCHDOG)
94                                 ctrl = 0;
95                         else
96                                 ctrl &= ~0x1;
97                 } else if (data[1] == 2) {      /* trigger */
98                         ctrl |= 0x200;
99                 }
100                 outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
101         }
102
103         inl(devpriv->tcw + ADDI_TCW_STATUS_REG);
104         return insn->n;
105 }
106
107 /*
108  * (*insn_read) for the timer subdevice
109  *
110  * Read The Selected Timer, Counter or Watchdog
111  * Data Pointer contains configuration parameters as below
112  *      data[0] : 0 Timer
113  *                1 Counter
114  *                2 Watchdog
115  *      data[1] : Timer Counter Watchdog Number
116  */
117 static int apci3501_read_insn_timer(struct comedi_device *dev,
118                                     struct comedi_subdevice *s,
119                                     struct comedi_insn *insn,
120                                     unsigned int *data)
121 {
122         struct apci3501_private *devpriv = dev->private;
123
124         if (devpriv->timer_mode != ADDIDATA_TIMER &&
125             devpriv->timer_mode != ADDIDATA_WATCHDOG)
126                 return -EINVAL;
127
128         data[0] = inl(devpriv->tcw + ADDI_TCW_STATUS_REG) & 0x1;
129         data[1] = inl(devpriv->tcw + ADDI_TCW_VAL_REG);
130
131         return insn->n;
132 }