1 /* $NetBSD: gti2c.c,v 1.11 2009/05/12 12:18:45 cegger Exp $ */
4 * Copyright (c) 2005 Brocade Communcations, inc.
7 * Written by Matt Thomas for Brocade Communcations, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of Brocade Communications, Inc. may not be used to endorse
18 * or promote products derived from this software without specific prior
21 * THIS SOFTWARE IS PROVIDED BY BROCADE COMMUNICATIONS, INC. ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL EITHER BROCADE COMMUNICATIONS, INC. BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: gti2c.c,v 1.11 2009/05/12 12:18:45 cegger Exp $");
37 #include <sys/param.h>
38 #include <sys/device.h>
41 #include <sys/mutex.h>
45 #include <dev/marvell/gtintrreg.h>
46 #include <dev/marvell/gti2creg.h>
48 #include <dev/marvell/gtvar.h>
50 #include <dev/i2c/i2cvar.h>
54 struct evcnt sc_ev_intr
;
55 struct i2c_controller sc_i2c
;
56 struct gt_softc
*sc_gt
;
60 static int gt_i2c_match(device_t
, cfdata_t
, void *);
61 static void gt_i2c_attach(device_t
, device_t
, void *);
63 CFATTACH_DECL(gtiic
, sizeof(struct gti2c_softc
),
64 gt_i2c_match
, gt_i2c_attach
, NULL
, NULL
);
66 extern struct cfdriver gtiic_cd
;
69 gt_i2c_wait(struct gti2c_softc
*sc
, uint32_t control
,
70 uint32_t desired_status
, int flags
)
76 if (flags
& I2C_F_POLL
)
77 control
|= I2C_Control_IntEn
;
78 if (desired_status
!= I2C_Status_MasterReadAck
)
79 gt_write(sc
->sc_gt
, I2C_REG_Control
, control
);
82 control
= gt_read(sc
->sc_gt
, I2C_REG_Control
);
83 if (control
& I2C_Control_IFlg
)
85 error
= tsleep(sc
, PZERO
, "gti2cwait",
86 (flags
& I2C_F_POLL
) ? 1 : 0);
87 if (error
&& (error
!= ETIMEDOUT
|| !(flags
& I2C_F_POLL
)))
91 status
= gt_read(sc
->sc_gt
, I2C_REG_Status
);
92 if (status
!= desired_status
)
95 if ((flags
& I2C_F_LAST
) &&
96 desired_status
!= I2C_Status_MasterReadAck
) {
97 control
= I2C_Control_Stop
;
105 gt_i2c_acquire_bus(void *cookie
, int flags
)
107 struct gti2c_softc
* const sc
= cookie
;
110 if (flags
& I2C_F_POLL
)
113 mutex_enter(&sc
->sc_lock
);
114 status
= gt_read(sc
->sc_gt
, I2C_REG_Status
);
115 if (status
!= I2C_Status_Idle
) {
116 gt_write(sc
->sc_gt
, I2C_REG_SoftReset
, 1);
123 gt_i2c_release_bus(void *cookie
, int flags
)
125 struct gti2c_softc
* const sc
= cookie
;
127 mutex_exit(&sc
->sc_lock
);
131 gt_i2c_send_start(void *cookie
, int flags
)
133 struct gti2c_softc
* const sc
= cookie
;
135 return gt_i2c_wait(sc
, I2C_Control_Start
, I2C_Status_Started
, flags
);
139 gt_i2c_send_stop(void *cookie
, int flags
)
141 struct gti2c_softc
* const sc
= cookie
;
143 return gt_i2c_wait(sc
, I2C_Control_Stop
, I2C_Status_Idle
, flags
);
147 gt_i2c_initiate_xfer(void *cookie
, i2c_addr_t addr
, int flags
)
149 struct gti2c_softc
* const sc
= cookie
;
150 uint32_t data
, wanted_status
;
151 uint8_t read_mask
= (flags
& I2C_F_READ
) != 0;
155 wanted_status
= I2C_Status_AddrReadAck
;
157 wanted_status
= I2C_Status_AddrWriteAck
;
160 * First byte contains whether this xfer is a read or write.
165 * If this is a 10bit request, the first address byte is
166 * 0b11110<b9><b8><r/w>.
168 data
|= 0xf0 | ((addr
& 0x30) >> 7);
169 gt_write(sc
->sc_gt
, I2C_REG_Data
, data
);
170 error
= gt_i2c_wait(sc
, 0, wanted_status
, flags
);
174 * The first address byte has been sent, now to send
178 wanted_status
= I2C_Status_2ndAddrReadAck
;
180 wanted_status
= I2C_Status_2ndAddrWriteAck
;
182 data
= (uint8_t) addr
;
187 gt_write(sc
->sc_gt
, I2C_REG_Data
, data
);
188 return gt_i2c_wait(sc
, 0, wanted_status
, flags
);
192 gt_i2c_read_byte(void *cookie
, uint8_t *dp
, int flags
)
194 struct gti2c_softc
* const sc
= cookie
;
197 gt_write(sc
->sc_gt
, I2C_REG_Data
, *dp
);
198 error
= gt_i2c_wait(sc
, 0, I2C_Status_MasterReadAck
, flags
);
200 *dp
= gt_read(sc
->sc_gt
, I2C_REG_Data
);
202 if (flags
& I2C_F_LAST
)
203 gt_write(sc
->sc_gt
, I2C_REG_Control
, 0);
208 gt_i2c_write_byte(void *cookie
, uint8_t v
, int flags
)
210 struct gti2c_softc
* const sc
= cookie
;
212 gt_write(sc
->sc_gt
, I2C_REG_Data
, v
);
213 return gt_i2c_wait(sc
, 0, I2C_Status_MasterWriteAck
, flags
);
217 gt_i2c_intr(void *aux
)
219 struct gti2c_softc
* const sc
= aux
;
222 v
= gt_read(sc
->sc_gt
, I2C_REG_Control
);
223 if ((v
& I2C_Control_IFlg
) == 0)
225 gt_write(sc
->sc_gt
, I2C_REG_Control
, v
& ~I2C_Control_IntEn
);
227 sc
->sc_ev_intr
.ev_count
++;
234 gt_i2c_match(device_t parent
, cfdata_t cfdata
, void *aux
)
236 struct gt_softc
* const gt
= device_private(parent
);
237 struct gt_attach_args
* const ga
= aux
;
239 return GT_I2COK(gt
, ga
, >iic_cd
);
243 gt_i2c_attach(device_t parent
, device_t self
, void *aux
)
245 struct gt_softc
* const gt
= device_private(parent
);
246 struct gti2c_softc
* const sc
= device_private(self
);
247 struct gt_attach_args
* const ga
= aux
;
248 struct i2cbus_attach_args iba
;
254 mutex_init(&sc
->sc_lock
, MUTEX_DEFAULT
, IPL_NONE
);
256 sc
->sc_i2c
.ic_cookie
= sc
;
257 sc
->sc_i2c
.ic_acquire_bus
= gt_i2c_acquire_bus
;
258 sc
->sc_i2c
.ic_release_bus
= gt_i2c_release_bus
;
259 sc
->sc_i2c
.ic_release_bus
= gt_i2c_release_bus
;
260 sc
->sc_i2c
.ic_send_start
= gt_i2c_send_start
;
261 sc
->sc_i2c
.ic_send_stop
= gt_i2c_send_stop
;
262 sc
->sc_i2c
.ic_initiate_xfer
= gt_i2c_initiate_xfer
;
263 sc
->sc_i2c
.ic_read_byte
= gt_i2c_read_byte
;
264 sc
->sc_i2c
.ic_write_byte
= gt_i2c_write_byte
;
266 intr_establish(IRQ_I2C
, IST_LEVEL
, IPL_VM
, gt_i2c_intr
, sc
);
268 evcnt_attach_dynamic(&sc
->sc_ev_intr
, EVCNT_TYPE_INTR
, NULL
,
269 device_xname(&sc
->sc_dev
), "intr");
271 iba
.iba_tag
= &sc
->sc_i2c
;
272 config_found_ia(self
, "i2cbus", &iba
, iicbus_print
);