xref: /dflybsd-src/sys/dev/drm/linux_i2c.c (revision 9f4ca8679e7400b5656a8d177c172fdfaf205cb1)
1*9f4ca867SFrançois Tigeot /*
2*9f4ca867SFrançois Tigeot  * Copyright (c) 2016 François Tigeot
3*9f4ca867SFrançois Tigeot  * All rights reserved.
4*9f4ca867SFrançois Tigeot  *
5*9f4ca867SFrançois Tigeot  * Redistribution and use in source and binary forms, with or without
6*9f4ca867SFrançois Tigeot  * modification, are permitted provided that the following conditions
7*9f4ca867SFrançois Tigeot  * are met:
8*9f4ca867SFrançois Tigeot  * 1. Redistributions of source code must retain the above copyright
9*9f4ca867SFrançois Tigeot  *    notice unmodified, this list of conditions, and the following
10*9f4ca867SFrançois Tigeot  *    disclaimer.
11*9f4ca867SFrançois Tigeot  * 2. Redistributions in binary form must reproduce the above copyright
12*9f4ca867SFrançois Tigeot  *    notice, this list of conditions and the following disclaimer in the
13*9f4ca867SFrançois Tigeot  *    documentation and/or other materials provided with the distribution.
14*9f4ca867SFrançois Tigeot  *
15*9f4ca867SFrançois Tigeot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16*9f4ca867SFrançois Tigeot  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17*9f4ca867SFrançois Tigeot  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18*9f4ca867SFrançois Tigeot  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19*9f4ca867SFrançois Tigeot  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20*9f4ca867SFrançois Tigeot  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21*9f4ca867SFrançois Tigeot  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22*9f4ca867SFrançois Tigeot  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23*9f4ca867SFrançois Tigeot  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24*9f4ca867SFrançois Tigeot  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*9f4ca867SFrançois Tigeot  */
26*9f4ca867SFrançois Tigeot 
27*9f4ca867SFrançois Tigeot #include <linux/i2c.h>
28*9f4ca867SFrançois Tigeot #include <linux/i2c-algo-bit.h>
29*9f4ca867SFrançois Tigeot 
30*9f4ca867SFrançois Tigeot static struct lock i2c_lock;
31*9f4ca867SFrançois Tigeot LOCK_SYSINIT(i2c_lock, &i2c_lock, "i2cl", LK_CANRECURSE);
32*9f4ca867SFrançois Tigeot 
33*9f4ca867SFrançois Tigeot int
34*9f4ca867SFrançois Tigeot i2c_add_adapter(struct i2c_adapter *adapter)
35*9f4ca867SFrançois Tigeot {
36*9f4ca867SFrançois Tigeot 	/* Linux registers a unique bus number here */
37*9f4ca867SFrançois Tigeot 	return 0;
38*9f4ca867SFrançois Tigeot }
39*9f4ca867SFrançois Tigeot 
40*9f4ca867SFrançois Tigeot void
41*9f4ca867SFrançois Tigeot i2c_del_adapter(struct i2c_adapter *adapter)
42*9f4ca867SFrançois Tigeot {
43*9f4ca867SFrançois Tigeot 	/* Linux deletes a unique bus number here */
44*9f4ca867SFrançois Tigeot }
45*9f4ca867SFrançois Tigeot 
46*9f4ca867SFrançois Tigeot /*
47*9f4ca867SFrançois Tigeot  * i2c_transfer()
48*9f4ca867SFrançois Tigeot  * The original Linux implementation does:
49*9f4ca867SFrançois Tigeot  * 1. return -EOPNOTSUPP if adapter->algo->master_xfer is NULL
50*9f4ca867SFrançois Tigeot  * 2. try to transfer msgs by calling adapter->algo->master_xfer()
51*9f4ca867SFrançois Tigeot  * 3. if it took more ticks than adapter->timeout, fail
52*9f4ca867SFrançois Tigeot  * 4. if the transfer failed, retry up to adapter->retries times
53*9f4ca867SFrançois Tigeot  * 5. return the result of the last call of adapter->algo->master_xfer()
54*9f4ca867SFrançois Tigeot  */
55*9f4ca867SFrançois Tigeot int
56*9f4ca867SFrançois Tigeot i2c_transfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
57*9f4ca867SFrançois Tigeot {
58*9f4ca867SFrançois Tigeot 	uint64_t start_ticks;
59*9f4ca867SFrançois Tigeot 	int ret, tries = 0;
60*9f4ca867SFrançois Tigeot 
61*9f4ca867SFrançois Tigeot 	if (adapter->algo->master_xfer == NULL)
62*9f4ca867SFrançois Tigeot 		return -EOPNOTSUPP;
63*9f4ca867SFrançois Tigeot 
64*9f4ca867SFrançois Tigeot 	lockmgr(&i2c_lock, LK_EXCLUSIVE);
65*9f4ca867SFrançois Tigeot 	start_ticks = ticks;
66*9f4ca867SFrançois Tigeot 	do {
67*9f4ca867SFrançois Tigeot 		ret = adapter->algo->master_xfer(adapter, msgs, num);
68*9f4ca867SFrançois Tigeot 		if (ticks > start_ticks + adapter->timeout)
69*9f4ca867SFrançois Tigeot 			break;
70*9f4ca867SFrançois Tigeot 		if (ret != -EAGAIN)
71*9f4ca867SFrançois Tigeot 			break;
72*9f4ca867SFrançois Tigeot 		tries++;
73*9f4ca867SFrançois Tigeot 	} while (tries < adapter->retries);
74*9f4ca867SFrançois Tigeot 	lockmgr(&i2c_lock, LK_RELEASE);
75*9f4ca867SFrançois Tigeot 
76*9f4ca867SFrançois Tigeot 	return ret;
77*9f4ca867SFrançois Tigeot }
78*9f4ca867SFrançois Tigeot 
79*9f4ca867SFrançois Tigeot static int
80*9f4ca867SFrançois Tigeot bit_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
81*9f4ca867SFrançois Tigeot {
82*9f4ca867SFrançois Tigeot 	/* XXX Linux really does try to transfer some data here */
83*9f4ca867SFrançois Tigeot 	return 0;
84*9f4ca867SFrançois Tigeot }
85*9f4ca867SFrançois Tigeot 
86*9f4ca867SFrançois Tigeot static uint32_t
87*9f4ca867SFrançois Tigeot bit_func(struct i2c_adapter *adap)
88*9f4ca867SFrançois Tigeot {
89*9f4ca867SFrançois Tigeot 	return (I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL |
90*9f4ca867SFrançois Tigeot 		I2C_FUNC_SMBUS_READ_BLOCK_DATA |
91*9f4ca867SFrançois Tigeot 		I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
92*9f4ca867SFrançois Tigeot 		I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING);
93*9f4ca867SFrançois Tigeot }
94*9f4ca867SFrançois Tigeot 
95*9f4ca867SFrançois Tigeot const struct i2c_algorithm i2c_bit_algo = {
96*9f4ca867SFrançois Tigeot 	.master_xfer	= bit_xfer,
97*9f4ca867SFrançois Tigeot 	.functionality	= bit_func,
98*9f4ca867SFrançois Tigeot };
99