142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher#include <linux/i2c.h> 279fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher#include <linux/mutex.h> 37a707b89202f905bd9f9fbde326933c59a81214cPaul Gortmaker#include <linux/module.h> 442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher#include "dibx000_common.h" 642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstatic int debug; 842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettchermodule_param(debug, int, 0644); 942afd061700edb43bb082bc65a2ddde431151d6bPatrick BoettcherMODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); 1042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 1103245a5ee69a5faa99b020fe1aca9bafe10c46a9Olivier Grenie#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0) 1242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 1342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstatic int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) 1442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 1579fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher int ret; 1679fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 1779fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { 1879fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher dprintk("could not acquire lock"); 1979fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher return -EINVAL; 2079fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher } 2179fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 225a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->i2c_write_buffer[0] = (reg >> 8) & 0xff; 235a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->i2c_write_buffer[1] = reg & 0xff; 245a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->i2c_write_buffer[2] = (val >> 8) & 0xff; 255a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->i2c_write_buffer[3] = val & 0xff; 265a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie 275a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie memset(mst->msg, 0, sizeof(struct i2c_msg)); 285a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].addr = mst->i2c_addr; 295a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].flags = 0; 305a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].buf = mst->i2c_write_buffer; 315a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].len = 4; 325a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie 3379fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0; 3479fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher mutex_unlock(&mst->i2c_buffer_lock); 3579fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 3679fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher return ret; 3742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 3842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 39b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Greniestatic u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg) 40b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie{ 4179fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher u16 ret; 4279fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 4379fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { 4479fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher dprintk("could not acquire lock"); 4579fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher return 0; 4679fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher } 4779fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 485a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->i2c_write_buffer[0] = reg >> 8; 495a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->i2c_write_buffer[1] = reg & 0xff; 505a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie 515a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie memset(mst->msg, 0, 2 * sizeof(struct i2c_msg)); 525a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].addr = mst->i2c_addr; 535a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].flags = 0; 545a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].buf = mst->i2c_write_buffer; 555a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].len = 2; 565a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[1].addr = mst->i2c_addr; 575a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[1].flags = I2C_M_RD; 585a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[1].buf = mst->i2c_read_buffer; 595a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[1].len = 2; 605a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie 615a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2) 62b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie dprintk("i2c read error on %d", reg); 63b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 6479fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1]; 6579fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher mutex_unlock(&mst->i2c_buffer_lock); 6679fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 6779fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher return ret; 68b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie} 69b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 70b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Greniestatic int dibx000_is_i2c_done(struct dibx000_i2c_master *mst) 71b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie{ 72b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie int i = 100; 73b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie u16 status; 74b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 75b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie while (((status = dibx000_read_word(mst, mst->base_reg + 2)) & 0x0100) == 0 && --i > 0) 76b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie ; 77b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 78b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie /* i2c timed out */ 79b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (i == 0) 80b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return -EREMOTEIO; 81b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 82b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie /* no acknowledge */ 83b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if ((status & 0x0080) == 0) 84b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return -EREMOTEIO; 85b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 86b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return 0; 87b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie} 88b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 89b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Greniestatic int dibx000_master_i2c_write(struct dibx000_i2c_master *mst, struct i2c_msg *msg, u8 stop) 90b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie{ 91b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie u16 data; 92b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie u16 da; 93b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie u16 i; 94b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie u16 txlen = msg->len, len; 95b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie const u8 *b = msg->buf; 96b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 97b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie while (txlen) { 98b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie dibx000_read_word(mst, mst->base_reg + 2); 99b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 100b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie len = txlen > 8 ? 8 : txlen; 101b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie for (i = 0; i < len; i += 2) { 102b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie data = *b++ << 8; 103b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (i+1 < len) 104b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie data |= *b++; 105b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie dibx000_write_word(mst, mst->base_reg, data); 106b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie } 107b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie da = (((u8) (msg->addr)) << 9) | 108b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (1 << 8) | 109b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (1 << 7) | 110b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (0 << 6) | 111b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (0 << 5) | 112b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie ((len & 0x7) << 2) | 113b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (0 << 1) | 114b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (0 << 0); 115b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 116b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (txlen == msg->len) 117b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie da |= 1 << 5; /* start */ 118b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 119b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (txlen-len == 0 && stop) 120b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie da |= 1 << 6; /* stop */ 121b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 122b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie dibx000_write_word(mst, mst->base_reg+1, da); 123b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 124b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (dibx000_is_i2c_done(mst) != 0) 125b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return -EREMOTEIO; 126b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie txlen -= len; 127b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie } 128b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 129b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return 0; 130b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie} 131b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 132b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Greniestatic int dibx000_master_i2c_read(struct dibx000_i2c_master *mst, struct i2c_msg *msg) 133b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie{ 134b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie u16 da; 135b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie u8 *b = msg->buf; 136b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie u16 rxlen = msg->len, len; 137b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 138b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie while (rxlen) { 139b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie len = rxlen > 8 ? 8 : rxlen; 140b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie da = (((u8) (msg->addr)) << 9) | 141b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (1 << 8) | 142b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (1 << 7) | 143b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (0 << 6) | 144b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (0 << 5) | 145b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie ((len & 0x7) << 2) | 146b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (1 << 1) | 147b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie (0 << 0); 148b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 149b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (rxlen == msg->len) 150b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie da |= 1 << 5; /* start */ 151b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 152b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (rxlen-len == 0) 153b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie da |= 1 << 6; /* stop */ 154b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie dibx000_write_word(mst, mst->base_reg+1, da); 155b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 156b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (dibx000_is_i2c_done(mst) != 0) 157b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return -EREMOTEIO; 158b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 159b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie rxlen -= len; 160b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 161b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie while (len) { 162b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie da = dibx000_read_word(mst, mst->base_reg); 163b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie *b++ = (da >> 8) & 0xff; 164b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie len--; 165b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (len >= 1) { 166b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie *b++ = da & 0xff; 167b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie len--; 168b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie } 169b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie } 170b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie } 171b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 172b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return 0; 173b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie} 174b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 175b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenieint dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed) 176b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie{ 177b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); 178b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 179b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (mst->device_rev < DIB7000MC && speed < 235) 180b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie speed = 235; 181b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return dibx000_write_word(mst, mst->base_reg + 3, (u16)(60000 / speed)); 182b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 183b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie} 184b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier GrenieEXPORT_SYMBOL(dibx000_i2c_set_speed); 185b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 186b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Greniestatic u32 dibx000_i2c_func(struct i2c_adapter *adapter) 187b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie{ 188b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return I2C_FUNC_I2C; 189b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie} 19042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 19177e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcherstatic int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, 19277e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher enum dibx000_i2c_interface intf) 19342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 19442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { 19503245a5ee69a5faa99b020fe1aca9bafe10c46a9Olivier Grenie dprintk("selecting interface: %d", intf); 19642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher mst->selected_interface = intf; 19742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return dibx000_write_word(mst, mst->base_reg + 4, intf); 19842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher } 19942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return 0; 20042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 20142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 202b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Greniestatic int dibx000_i2c_master_xfer_gpio12(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num) 203b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie{ 204b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); 205b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie int msg_index; 206b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie int ret = 0; 207b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 208b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_1_2); 209b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie for (msg_index = 0; msg_index < num; msg_index++) { 210b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie if (msg[msg_index].flags & I2C_M_RD) { 211b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie ret = dibx000_master_i2c_read(mst, &msg[msg_index]); 212b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (ret != 0) 213b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return 0; 214b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie } else { 215b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1); 216b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (ret != 0) 217b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return 0; 218b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie } 219b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie } 220b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 221b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return num; 222b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie} 223b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 224b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Greniestatic int dibx000_i2c_master_xfer_gpio34(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num) 225b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie{ 226b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); 227b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie int msg_index; 228b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie int ret = 0; 229b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 230b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_3_4); 231b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie for (msg_index = 0; msg_index < num; msg_index++) { 232b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie if (msg[msg_index].flags & I2C_M_RD) { 233b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie ret = dibx000_master_i2c_read(mst, &msg[msg_index]); 234b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (ret != 0) 235b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return 0; 236b4d6046e841955be9cc49164b03b91c9524f9c2eOlivier Grenie } else { 237b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1); 238b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (ret != 0) 239b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return 0; 240b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie } 241b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie } 242b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 243b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return num; 244b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie} 245b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 246b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Greniestatic struct i2c_algorithm dibx000_i2c_master_gpio12_xfer_algo = { 247b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie .master_xfer = dibx000_i2c_master_xfer_gpio12, 248b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie .functionality = dibx000_i2c_func, 249b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie}; 250b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 251b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Greniestatic struct i2c_algorithm dibx000_i2c_master_gpio34_xfer_algo = { 252b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie .master_xfer = dibx000_i2c_master_xfer_gpio34, 253b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie .functionality = dibx000_i2c_func, 254b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie}; 255b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 25677e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcherstatic int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], 25777e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher u8 addr, int onoff) 25842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 25942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher u16 val; 26042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 26142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 26242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher if (onoff) 26377e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher val = addr << 8; // bit 7 = use master or not, if 0, the gate is open 26442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher else 26542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher val = 1 << 7; 26642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 26742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher if (mst->device_rev > DIB7000) 26842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher val <<= 1; 26942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 27042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher tx[0] = (((mst->base_reg + 1) >> 8) & 0xff); 27177e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher tx[1] = ((mst->base_reg + 1) & 0xff); 27242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher tx[2] = val >> 8; 27342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher tx[3] = val & 0xff; 27442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 27542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return 0; 27642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 27742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 278b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Greniestatic int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap, 279b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie struct i2c_msg msg[], int num) 28042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 281b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); 28279fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher int ret; 283b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 2845a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie if (num > 32) { 2855a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie dprintk("%s: too much I2C message to be transmitted (%i).\ 2865a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie Maximum is 32", __func__, num); 2875a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie return -ENOMEM; 2885a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie } 2895a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie 290b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7); 291b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 29279fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { 29379fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher dprintk("could not acquire lock"); 29479fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher return -EINVAL; 29579fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher } 29679fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 29779fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); 29879fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 2995a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie /* open the gate */ 3005a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); 3015a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].addr = mst->i2c_addr; 3025a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].buf = &mst->i2c_write_buffer[0]; 3035a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].len = 4; 304b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 3055a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num); 306b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 3075a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie /* close the gate */ 3085a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0); 3095a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[num + 1].addr = mst->i2c_addr; 3105a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; 3115a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[num + 1].len = 4; 312b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 31379fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? 31479fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher num : -EIO); 31579fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 31679fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher mutex_unlock(&mst->i2c_buffer_lock); 31779fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher return ret; 31842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 31942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 320b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Greniestatic struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = { 321b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie .master_xfer = dibx000_i2c_gated_gpio67_xfer, 322b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie .functionality = dibx000_i2c_func, 323b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie}; 324b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 32577e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcherstatic int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, 32677e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher struct i2c_msg msg[], int num) 32742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 32842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); 32979fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher int ret; 33042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 3315a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie if (num > 32) { 3325a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie dprintk("%s: too much I2C message to be transmitted (%i).\ 3335a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie Maximum is 32", __func__, num); 3345a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie return -ENOMEM; 3355a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie } 3365a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie 33742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); 33842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 33979fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { 34079fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher dprintk("could not acquire lock"); 34179fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher return -EINVAL; 34279fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher } 34379fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num)); 34479fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 3455a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie /* open the gate */ 3465a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1); 3475a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].addr = mst->i2c_addr; 3485a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].buf = &mst->i2c_write_buffer[0]; 3495a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[0].len = 4; 35042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 3515a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num); 35242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 3535a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie /* close the gate */ 3545a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0); 3555a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[num + 1].addr = mst->i2c_addr; 3565a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[num + 1].buf = &mst->i2c_write_buffer[4]; 3575a0deeed5741117ee8625d6305d0034e219f102cOlivier Grenie mst->msg[num + 1].len = 4; 35842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 35979fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ? 36079fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher num : -EIO); 36179fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher mutex_unlock(&mst->i2c_buffer_lock); 36279fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher return ret; 36342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 36442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 36542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstatic struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { 36677e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher .master_xfer = dibx000_i2c_gated_tuner_xfer, 36742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher .functionality = dibx000_i2c_func, 36842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher}; 36942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 37077e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcherstruct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, 371b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie enum dibx000_i2c_interface intf, 372b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie int gating) 37342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 37442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher struct i2c_adapter *i2c = NULL; 37542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 37642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher switch (intf) { 37777e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher case DIBX000_I2C_INTERFACE_TUNER: 37877e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher if (gating) 37977e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher i2c = &mst->gated_tuner_i2c_adap; 38077e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher break; 381b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie case DIBX000_I2C_INTERFACE_GPIO_1_2: 382b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (!gating) 383b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie i2c = &mst->master_i2c_adap_gpio12; 384b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie break; 385b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie case DIBX000_I2C_INTERFACE_GPIO_3_4: 386b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (!gating) 387b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie i2c = &mst->master_i2c_adap_gpio34; 388b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie break; 389b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie case DIBX000_I2C_INTERFACE_GPIO_6_7: 390b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (gating) 391b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie i2c = &mst->master_i2c_adap_gpio67; 392b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie break; 39377e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher default: 39477e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n"); 39577e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher break; 39642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher } 39742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 39842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return i2c; 39942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 40077e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher 40142afd061700edb43bb082bc65a2ddde431151d6bPatrick BoettcherEXPORT_SYMBOL(dibx000_get_i2c_adapter); 40242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 40377e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettchervoid dibx000_reset_i2c_master(struct dibx000_i2c_master *mst) 40477e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher{ 40577e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher /* initialize the i2c-master by closing the gate */ 40677e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher u8 tx[4]; 40777e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher struct i2c_msg m = {.addr = mst->i2c_addr,.buf = tx,.len = 4 }; 40877e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher 40977e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher dibx000_i2c_gate_ctrl(mst, tx, 0, 0); 41077e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher i2c_transfer(mst->i2c_adap, &m, 1); 41177e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher mst->selected_interface = 0xff; // the first time force a select of the I2C 41277e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); 41377e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher} 41477e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher 41577e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick BoettcherEXPORT_SYMBOL(dibx000_reset_i2c_master); 41677e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher 41777e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcherstatic int i2c_adapter_init(struct i2c_adapter *i2c_adap, 418b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie struct i2c_algorithm *algo, const char *name, 419b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie struct dibx000_i2c_master *mst) 42042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 4212096b956d24c4b5950b808fc23b218425d79ebb1David Brownell strncpy(i2c_adap->name, name, sizeof(i2c_adap->name)); 4222c2742da1e590f426e8d85ce4e33b69142245fb8Jean Delvare i2c_adap->algo = algo; 42342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher i2c_adap->algo_data = NULL; 42442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher i2c_set_adapdata(i2c_adap, mst); 42542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher if (i2c_add_adapter(i2c_adap) < 0) 42642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return -ENODEV; 42742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return 0; 42842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 42942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 43077e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcherint dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, 431b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie struct i2c_adapter *i2c_adap, u8 i2c_addr) 43242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 43379fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher int ret; 43479fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 43579fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher mutex_init(&mst->i2c_buffer_lock); 43679fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) { 43779fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher dprintk("could not acquire lock"); 43879fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher return -EINVAL; 43979fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher } 44079fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher memset(mst->msg, 0, sizeof(struct i2c_msg)); 44179fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher mst->msg[0].addr = i2c_addr >> 1; 44279fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher mst->msg[0].flags = 0; 44379fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher mst->msg[0].buf = mst->i2c_write_buffer; 44479fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher mst->msg[0].len = 4; 44542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 44642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher mst->device_rev = device_rev; 44777e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher mst->i2c_adap = i2c_adap; 44877e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher mst->i2c_addr = i2c_addr >> 1; 44942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 45077e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher if (device_rev == DIB7000P || device_rev == DIB8000) 45142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher mst->base_reg = 1024; 45242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher else 45342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher mst->base_reg = 768; 45442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 455b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie mst->gated_tuner_i2c_adap.dev.parent = mst->i2c_adap->dev.parent; 456b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (i2c_adapter_init 457b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie (&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo, 458b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie "DiBX000 tuner I2C bus", mst) != 0) 459b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie printk(KERN_ERR 460b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie "DiBX000: could not initialize the tuner i2c_adapter\n"); 461b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 462b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie mst->master_i2c_adap_gpio12.dev.parent = mst->i2c_adap->dev.parent; 463b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (i2c_adapter_init 464b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie (&mst->master_i2c_adap_gpio12, &dibx000_i2c_master_gpio12_xfer_algo, 465b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie "DiBX000 master GPIO12 I2C bus", mst) != 0) 466b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie printk(KERN_ERR 467b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie "DiBX000: could not initialize the master i2c_adapter\n"); 468b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 469b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie mst->master_i2c_adap_gpio34.dev.parent = mst->i2c_adap->dev.parent; 470b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie if (i2c_adapter_init 471b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie (&mst->master_i2c_adap_gpio34, &dibx000_i2c_master_gpio34_xfer_algo, 472b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie "DiBX000 master GPIO34 I2C bus", mst) != 0) 473b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie printk(KERN_ERR 474b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie "DiBX000: could not initialize the master i2c_adapter\n"); 475b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie 476b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie mst->master_i2c_adap_gpio67.dev.parent = mst->i2c_adap->dev.parent; 47777e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher if (i2c_adapter_init 478b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie (&mst->master_i2c_adap_gpio67, &dibx000_i2c_gated_gpio67_algo, 479b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie "DiBX000 master GPIO67 I2C bus", mst) != 0) 48077e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher printk(KERN_ERR 481b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie "DiBX000: could not initialize the master i2c_adapter\n"); 48242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 48342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher /* initialize the i2c-master by closing the gate */ 48479fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0); 48579fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher 48679fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1); 48779fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher mutex_unlock(&mst->i2c_buffer_lock); 48842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 48979fcce3230b140f7675f8529ee53fe2f9644f902Patrick Boettcher return ret; 49042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 49177e2c0f5d471e2b14140f0695a1b6a718f318dd7Patrick Boettcher 49242afd061700edb43bb082bc65a2ddde431151d6bPatrick BoettcherEXPORT_SYMBOL(dibx000_init_i2c_master); 49342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 49442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettchervoid dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) 49542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 49642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher i2c_del_adapter(&mst->gated_tuner_i2c_adap); 497b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie i2c_del_adapter(&mst->master_i2c_adap_gpio12); 498b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie i2c_del_adapter(&mst->master_i2c_adap_gpio34); 499b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie i2c_del_adapter(&mst->master_i2c_adap_gpio67); 50042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 50142afd061700edb43bb082bc65a2ddde431151d6bPatrick BoettcherEXPORT_SYMBOL(dibx000_exit_i2c_master); 502c6d74c2ce86a80c9859010eb65e622214a6993edPatrick Boettcher 50303245a5ee69a5faa99b020fe1aca9bafe10c46a9Olivier Grenie 5047ccf1eea972177064b4df9d5ba68958604781db6Randy Dunlapu32 systime(void) 50503245a5ee69a5faa99b020fe1aca9bafe10c46a9Olivier Grenie{ 506b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie struct timespec t; 50703245a5ee69a5faa99b020fe1aca9bafe10c46a9Olivier Grenie 508b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie t = current_kernel_time(); 509b994d19268756b640ccc76f0b0d47ee13c0f8af9Olivier Grenie return (t.tv_sec * 10000) + (t.tv_nsec / 100000); 51003245a5ee69a5faa99b020fe1aca9bafe10c46a9Olivier Grenie} 51103245a5ee69a5faa99b020fe1aca9bafe10c46a9Olivier GrenieEXPORT_SYMBOL(systime); 51203245a5ee69a5faa99b020fe1aca9bafe10c46a9Olivier Grenie 513c6d74c2ce86a80c9859010eb65e622214a6993edPatrick BoettcherMODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); 514c6d74c2ce86a80c9859010eb65e622214a6993edPatrick BoettcherMODULE_DESCRIPTION("Common function the DiBcom demodulator family"); 515c6d74c2ce86a80c9859010eb65e622214a6993edPatrick BoettcherMODULE_LICENSE("GPL"); 516