2 * Copyright 2015 Red Hat Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
22 * Authors: Ben Skeggs <bskeggs@redhat.com>
27 #include <core/option.h>
29 /*******************************************************************************
31 ******************************************************************************/
33 nvkm_i2c_bus_pre_xfer(struct i2c_adapter
*adap
)
35 struct nvkm_i2c_bus
*bus
= container_of(adap
, typeof(*bus
), i2c
);
36 return nvkm_i2c_bus_acquire(bus
);
40 nvkm_i2c_bus_post_xfer(struct i2c_adapter
*adap
)
42 struct nvkm_i2c_bus
*bus
= container_of(adap
, typeof(*bus
), i2c
);
43 return nvkm_i2c_bus_release(bus
);
47 nvkm_i2c_bus_setscl(void *data
, int state
)
49 struct nvkm_i2c_bus
*bus
= data
;
50 bus
->func
->drive_scl(bus
, state
);
54 nvkm_i2c_bus_setsda(void *data
, int state
)
56 struct nvkm_i2c_bus
*bus
= data
;
57 bus
->func
->drive_sda(bus
, state
);
61 nvkm_i2c_bus_getscl(void *data
)
63 struct nvkm_i2c_bus
*bus
= data
;
64 return bus
->func
->sense_scl(bus
);
68 nvkm_i2c_bus_getsda(void *data
)
70 struct nvkm_i2c_bus
*bus
= data
;
71 return bus
->func
->sense_sda(bus
);
74 /*******************************************************************************
75 * !i2c-algo-bit (off-chip i2c bus / hw i2c / internal bit-banging algo)
76 ******************************************************************************/
78 nvkm_i2c_bus_xfer(struct i2c_adapter
*adap
, struct i2c_msg
*msgs
, int num
)
80 struct nvkm_i2c_bus
*bus
= container_of(adap
, typeof(*bus
), i2c
);
83 ret
= nvkm_i2c_bus_acquire(bus
);
87 ret
= bus
->func
->xfer(bus
, msgs
, num
);
88 nvkm_i2c_bus_release(bus
);
93 nvkm_i2c_bus_func(struct i2c_adapter
*adap
)
95 return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_EMUL
;
98 static const struct i2c_algorithm
100 .master_xfer
= nvkm_i2c_bus_xfer
,
101 .functionality
= nvkm_i2c_bus_func
,
104 /*******************************************************************************
106 ******************************************************************************/
108 nvkm_i2c_bus_init(struct nvkm_i2c_bus
*bus
)
110 BUS_TRACE(bus
, "init");
112 bus
->func
->init(bus
);
114 mutex_lock(&bus
->mutex
);
116 mutex_unlock(&bus
->mutex
);
120 nvkm_i2c_bus_fini(struct nvkm_i2c_bus
*bus
)
122 BUS_TRACE(bus
, "fini");
123 mutex_lock(&bus
->mutex
);
124 bus
->enabled
= false;
125 mutex_unlock(&bus
->mutex
);
129 nvkm_i2c_bus_release(struct nvkm_i2c_bus
*bus
)
131 struct nvkm_i2c_pad
*pad
= bus
->pad
;
132 BUS_TRACE(bus
, "release");
133 nvkm_i2c_pad_release(pad
);
134 mutex_unlock(&bus
->mutex
);
138 nvkm_i2c_bus_acquire(struct nvkm_i2c_bus
*bus
)
140 struct nvkm_i2c_pad
*pad
= bus
->pad
;
143 BUS_TRACE(bus
, "acquire");
144 mutex_lock(&bus
->mutex
);
147 ret
= nvkm_i2c_pad_acquire(pad
, NVKM_I2C_PAD_I2C
);
152 mutex_unlock(&bus
->mutex
);
157 nvkm_i2c_bus_probe(struct nvkm_i2c_bus
*bus
, const char *what
,
158 struct nvkm_i2c_bus_probe
*info
,
159 bool (*match
)(struct nvkm_i2c_bus
*,
160 struct i2c_board_info
*, void *), void *data
)
164 BUS_DBG(bus
, "probing %ss", what
);
165 for (i
= 0; info
[i
].dev
.addr
; i
++) {
168 if ((bus
->i2c
.algo
== &i2c_bit_algo
) && (info
[i
].udelay
!= 0)) {
169 struct i2c_algo_bit_data
*algo
= bus
->i2c
.algo_data
;
170 BUS_DBG(bus
, "%dms delay instead of %dms",
171 info
[i
].udelay
, algo
->udelay
);
172 orig_udelay
= algo
->udelay
;
173 algo
->udelay
= info
[i
].udelay
;
176 if (nvkm_probe_i2c(&bus
->i2c
, info
[i
].dev
.addr
) &&
177 (!match
|| match(bus
, &info
[i
].dev
, data
))) {
178 BUS_DBG(bus
, "detected %s: %s",
179 what
, info
[i
].dev
.type
);
184 struct i2c_algo_bit_data
*algo
= bus
->i2c
.algo_data
;
185 algo
->udelay
= orig_udelay
;
189 BUS_DBG(bus
, "no devices found.");
194 nvkm_i2c_bus_del(struct nvkm_i2c_bus
**pbus
)
196 struct nvkm_i2c_bus
*bus
= *pbus
;
197 if (bus
&& !WARN_ON(!bus
->func
)) {
198 BUS_TRACE(bus
, "dtor");
199 list_del(&bus
->head
);
200 i2c_del_adapter(&bus
->i2c
);
201 kfree(bus
->i2c
.algo_data
);
208 nvkm_i2c_bus_ctor(const struct nvkm_i2c_bus_func
*func
,
209 struct nvkm_i2c_pad
*pad
, int id
,
210 struct nvkm_i2c_bus
*bus
)
212 struct nvkm_device
*device
= pad
->i2c
->subdev
.device
;
213 struct i2c_algo_bit_data
*bit
;
214 #ifndef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT
215 const bool internal
= false;
217 const bool internal
= true;
224 mutex_init(&bus
->mutex
);
225 list_add_tail(&bus
->head
, &pad
->i2c
->bus
);
226 BUS_TRACE(bus
, "ctor");
228 snprintf(bus
->i2c
.name
, sizeof(bus
->i2c
.name
), "nvkm-%s-bus-%04x",
229 dev_name(device
->dev
), id
);
230 bus
->i2c
.owner
= THIS_MODULE
;
231 bus
->i2c
.dev
.parent
= device
->dev
;
233 if ( bus
->func
->drive_scl
&&
234 !nvkm_boolopt(device
->cfgopt
, "NvI2C", internal
)) {
235 if (!(bit
= kzalloc(sizeof(*bit
), GFP_KERNEL
)))
238 bit
->timeout
= usecs_to_jiffies(2200);
240 bit
->pre_xfer
= nvkm_i2c_bus_pre_xfer
;
241 bit
->post_xfer
= nvkm_i2c_bus_post_xfer
;
242 bit
->setscl
= nvkm_i2c_bus_setscl
;
243 bit
->setsda
= nvkm_i2c_bus_setsda
;
244 bit
->getscl
= nvkm_i2c_bus_getscl
;
245 bit
->getsda
= nvkm_i2c_bus_getsda
;
246 bus
->i2c
.algo_data
= bit
;
247 ret
= i2c_bit_add_bus(&bus
->i2c
);
249 bus
->i2c
.algo
= &nvkm_i2c_bus_algo
;
250 ret
= i2c_add_adapter(&bus
->i2c
);
257 nvkm_i2c_bus_new_(const struct nvkm_i2c_bus_func
*func
,
258 struct nvkm_i2c_pad
*pad
, int id
,
259 struct nvkm_i2c_bus
**pbus
)
261 if (!(*pbus
= kzalloc(sizeof(**pbus
), GFP_KERNEL
)))
263 return nvkm_i2c_bus_ctor(func
, pad
, id
, *pbus
);