2 Mantis PCI bridge driver
4 Copyright (C) Manu Abraham (abraham.manu@gmail.com)
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <linux/ioport.h>
23 #include <linux/pci.h>
24 #include <linux/i2c.h>
28 #include "dvb_demux.h"
29 #include "dvb_frontend.h"
32 #include "mantis_common.h"
33 #include "mantis_reg.h"
34 #include "mantis_i2c.h"
38 static int mantis_i2c_read(struct mantis_pci
*mantis
, const struct i2c_msg
*msg
)
40 u32 rxd
, i
, stat
, trials
;
42 dprintk(MANTIS_INFO
, 0, " %s: Address=[0x%02x] <R>[ ",
45 for (i
= 0; i
< msg
->len
; i
++) {
46 rxd
= (msg
->addr
<< 25) | (1 << 24)
51 if (i
== (msg
->len
- 1))
52 rxd
&= ~MANTIS_I2C_STOP
;
54 mmwrite(MANTIS_INT_I2CDONE
, MANTIS_INT_STAT
);
55 mmwrite(rxd
, MANTIS_I2CDATA_CTL
);
57 /* wait for xfer completion */
58 for (trials
= 0; trials
< TRIALS
; trials
++) {
59 stat
= mmread(MANTIS_INT_STAT
);
60 if (stat
& MANTIS_INT_I2CDONE
)
64 dprintk(MANTIS_TMG
, 0, "I2CDONE: trials=%d\n", trials
);
66 /* wait for xfer completion */
67 for (trials
= 0; trials
< TRIALS
; trials
++) {
68 stat
= mmread(MANTIS_INT_STAT
);
69 if (stat
& MANTIS_INT_I2CRACK
)
73 dprintk(MANTIS_TMG
, 0, "I2CRACK: trials=%d\n", trials
);
75 rxd
= mmread(MANTIS_I2CDATA_CTL
);
76 msg
->buf
[i
] = (u8
)((rxd
>> 8) & 0xFF);
77 dprintk(MANTIS_INFO
, 0, "%02x ", msg
->buf
[i
]);
79 dprintk(MANTIS_INFO
, 0, "]\n");
84 static int mantis_i2c_write(struct mantis_pci
*mantis
, const struct i2c_msg
*msg
)
87 u32 txd
= 0, stat
, trials
;
89 dprintk(MANTIS_INFO
, 0, " %s: Address=[0x%02x] <W>[ ",
92 for (i
= 0; i
< msg
->len
; i
++) {
93 dprintk(MANTIS_INFO
, 0, "%02x ", msg
->buf
[i
]);
94 txd
= (msg
->addr
<< 25) | (msg
->buf
[i
] << 8)
99 if (i
== (msg
->len
- 1))
100 txd
&= ~MANTIS_I2C_STOP
;
102 mmwrite(MANTIS_INT_I2CDONE
, MANTIS_INT_STAT
);
103 mmwrite(txd
, MANTIS_I2CDATA_CTL
);
105 /* wait for xfer completion */
106 for (trials
= 0; trials
< TRIALS
; trials
++) {
107 stat
= mmread(MANTIS_INT_STAT
);
108 if (stat
& MANTIS_INT_I2CDONE
)
112 dprintk(MANTIS_TMG
, 0, "I2CDONE: trials=%d\n", trials
);
114 /* wait for xfer completion */
115 for (trials
= 0; trials
< TRIALS
; trials
++) {
116 stat
= mmread(MANTIS_INT_STAT
);
117 if (stat
& MANTIS_INT_I2CRACK
)
121 dprintk(MANTIS_TMG
, 0, "I2CRACK: trials=%d\n", trials
);
123 dprintk(MANTIS_INFO
, 0, "]\n");
128 static int mantis_i2c_xfer(struct i2c_adapter
*adapter
, struct i2c_msg
*msgs
, int num
)
130 int ret
= 0, i
= 0, trials
;
132 struct mantis_pci
*mantis
;
133 struct mantis_hwconfig
*config
;
135 mantis
= i2c_get_adapdata(adapter
);
137 config
= mantis
->hwconfig
;
140 dprintk(MANTIS_DEBUG
, 1, "Messages:%d", num
);
141 mutex_lock(&mantis
->i2c_lock
);
145 if ((config
->i2c_mode
& MANTIS_BYTE_MODE
) &&
148 (msgs
[i
+ 1].len
< 2) &&
149 (msgs
[i
+ 1].flags
& I2C_M_RD
)) {
151 dprintk(MANTIS_DEBUG
, 0, " Byte MODE:\n");
154 txd
= msgs
[i
].addr
<< 25 | (0x1 << 24)
155 | (msgs
[i
].buf
[0] << 16)
158 mmwrite(txd
, MANTIS_I2CDATA_CTL
);
159 /* wait for xfer completion */
160 for (trials
= 0; trials
< TRIALS
; trials
++) {
161 stat
= mmread(MANTIS_INT_STAT
);
162 if (stat
& MANTIS_INT_I2CDONE
)
166 /* check for xfer completion */
167 if (stat
& MANTIS_INT_I2CDONE
) {
168 /* check xfer was acknowledged */
169 if (stat
& MANTIS_INT_I2CRACK
) {
170 data
= mmread(MANTIS_I2CDATA_CTL
);
171 msgs
[i
+ 1].buf
[0] = (data
>> 8) & 0xff;
172 dprintk(MANTIS_DEBUG
, 0, " Byte <%d> RXD=0x%02x [%02x]\n", 0x0, data
, msgs
[i
+ 1].buf
[0]);
175 dprintk(MANTIS_ERROR
, 1, " I/O error, LINE:%d", __LINE__
);
181 dprintk(MANTIS_ERROR
, 1, " I/O error, LINE:%d", __LINE__
);
185 i
+= 2; /* Write/Read operation in one go */
189 if (msgs
[i
].flags
& I2C_M_RD
)
190 ret
= mantis_i2c_read(mantis
, &msgs
[i
]);
192 ret
= mantis_i2c_write(mantis
, &msgs
[i
]);
201 mutex_unlock(&mantis
->i2c_lock
);
206 mutex_unlock(&mantis
->i2c_lock
);
210 static u32
mantis_i2c_func(struct i2c_adapter
*adapter
)
212 return I2C_FUNC_SMBUS_EMUL
;
215 static struct i2c_algorithm mantis_algo
= {
216 .master_xfer
= mantis_i2c_xfer
,
217 .functionality
= mantis_i2c_func
,
220 int mantis_i2c_init(struct mantis_pci
*mantis
)
222 u32 intstat
, intmask
;
223 struct i2c_adapter
*i2c_adapter
= &mantis
->adapter
;
224 struct pci_dev
*pdev
= mantis
->pdev
;
226 init_waitqueue_head(&mantis
->i2c_wq
);
227 mutex_init(&mantis
->i2c_lock
);
228 strncpy(i2c_adapter
->name
, "Mantis I2C", sizeof(i2c_adapter
->name
));
229 i2c_set_adapdata(i2c_adapter
, mantis
);
231 i2c_adapter
->owner
= THIS_MODULE
;
232 i2c_adapter
->algo
= &mantis_algo
;
233 i2c_adapter
->algo_data
= NULL
;
234 i2c_adapter
->timeout
= 500;
235 i2c_adapter
->retries
= 3;
236 i2c_adapter
->dev
.parent
= &pdev
->dev
;
238 mantis
->i2c_rc
= i2c_add_adapter(i2c_adapter
);
239 if (mantis
->i2c_rc
< 0)
240 return mantis
->i2c_rc
;
242 dprintk(MANTIS_DEBUG
, 1, "Initializing I2C ..");
244 intstat
= mmread(MANTIS_INT_STAT
);
245 intmask
= mmread(MANTIS_INT_MASK
);
246 mmwrite(intstat
, MANTIS_INT_STAT
);
247 dprintk(MANTIS_DEBUG
, 1, "Disabling I2C interrupt");
248 intmask
= mmread(MANTIS_INT_MASK
);
249 mmwrite((intmask
& ~MANTIS_INT_I2CDONE
), MANTIS_INT_MASK
);
253 EXPORT_SYMBOL_GPL(mantis_i2c_init
);
255 int mantis_i2c_exit(struct mantis_pci
*mantis
)
259 dprintk(MANTIS_DEBUG
, 1, "Disabling I2C interrupt");
260 intmask
= mmread(MANTIS_INT_MASK
);
261 mmwrite((intmask
& ~MANTIS_INT_I2CDONE
), MANTIS_INT_MASK
);
263 dprintk(MANTIS_DEBUG
, 1, "Removing I2C adapter");
264 i2c_del_adapter(&mantis
->adapter
);
268 EXPORT_SYMBOL_GPL(mantis_i2c_exit
);