1 /* $NetBSD: gxiic.c,v 1.4 2009/04/20 12:58:33 pgoyette Exp $ */
3 * Copyright (c) 2007 KIYOHARA Takashi
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: gxiic.c,v 1.4 2009/04/20 12:58:33 pgoyette Exp $");
30 #include <sys/param.h>
31 #include <sys/device.h>
32 #include <sys/errno.h>
33 #include <sys/mutex.h>
35 #include <arm/xscale/pxa2x0var.h>
36 #include <arm/xscale/pxa2x0_i2c.h>
38 #include <evbarm/gumstix/gumstixvar.h>
40 #include <dev/i2c/i2cvar.h>
44 struct pxa2x0_i2c_softc sc_pxa_i2c
;
46 struct i2c_controller sc_i2c
;
51 static int gxiicmatch(device_t
, cfdata_t
, void *);
52 static void gxiicattach(device_t
, device_t
, void *);
54 /* fuctions for i2c_controller */
55 static int gxiic_acquire_bus(void *, int);
56 static void gxiic_release_bus(void *, int);
57 static int gxiic_exec(void *cookie
, i2c_op_t
, i2c_addr_t
, const void *, size_t,
61 CFATTACH_DECL(gxiic
, sizeof(struct gxiic_softc
),
62 gxiicmatch
, gxiicattach
, NULL
, NULL
);
67 gxiicmatch(device_t parent
, cfdata_t match
, void *aux
)
69 struct pxaip_attach_args
*pxa
= aux
;
71 if (strcmp(pxa
->pxa_name
, match
->cf_name
) != 0)
74 pxa
->pxa_size
= PXA2X0_I2C_SIZE
;
80 gxiicattach(device_t parent
, device_t self
, void *aux
)
82 struct pxaip_attach_args
*pxa
= aux
;
83 struct gxiic_softc
*sc
= device_private(self
);
84 struct i2cbus_attach_args iba
;
89 sc
->sc_pxa_i2c
.sc_iot
= pxa
->pxa_iot
;
90 sc
->sc_pxa_i2c
.sc_size
= pxa
->pxa_size
;
91 if (pxa2x0_i2c_attach_sub(&sc
->sc_pxa_i2c
)) {
92 aprint_error_dev(self
, "unable to attach PXA I2C\n");
96 mutex_init(&sc
->sc_lock
, MUTEX_DEFAULT
, IPL_NONE
);
98 /* Initialize i2c_controller */
99 sc
->sc_i2c
.ic_cookie
= sc
;
100 sc
->sc_i2c
.ic_acquire_bus
= gxiic_acquire_bus
;
101 sc
->sc_i2c
.ic_release_bus
= gxiic_release_bus
;
102 sc
->sc_i2c
.ic_send_start
= NULL
;
103 sc
->sc_i2c
.ic_send_stop
= NULL
;
104 sc
->sc_i2c
.ic_initiate_xfer
= NULL
;
105 sc
->sc_i2c
.ic_read_byte
= NULL
;
106 sc
->sc_i2c
.ic_write_byte
= NULL
;
107 sc
->sc_i2c
.ic_exec
= gxiic_exec
;
109 iba
.iba_tag
= &sc
->sc_i2c
;
110 pxa2x0_i2c_open(&sc
->sc_pxa_i2c
);
111 config_found_ia(&sc
->sc_pxa_i2c
.sc_dev
, "i2cbus", &iba
, iicbus_print
);
112 pxa2x0_i2c_close(&sc
->sc_pxa_i2c
);
116 gxiic_acquire_bus(void *cookie
, int flags
)
118 struct gxiic_softc
*sc
= cookie
;
120 mutex_enter(&sc
->sc_lock
);
121 pxa2x0_i2c_open(&sc
->sc_pxa_i2c
);
127 gxiic_release_bus(void *cookie
, int flags
)
129 struct gxiic_softc
*sc
= cookie
;
131 pxa2x0_i2c_close(&sc
->sc_pxa_i2c
);
132 mutex_exit(&sc
->sc_lock
);
137 gxiic_exec(void *cookie
, i2c_op_t op
, i2c_addr_t addr
, const void *vcmd
,
138 size_t cmdlen
, void *vbuf
, size_t buflen
, int flags
)
140 struct gxiic_softc
*sc
= cookie
;
143 if (I2C_OP_READ_P(op
) && (cmdlen
== 0) && (buflen
== 1))
144 rv
= pxa2x0_i2c_read(&sc
->sc_pxa_i2c
, addr
, (u_char
*)vbuf
);
146 if ((I2C_OP_READ_P(op
)) && (cmdlen
== 1) && (buflen
== 1)) {
147 rv
= pxa2x0_i2c_write(&sc
->sc_pxa_i2c
, addr
, *(u_char
*)vbuf
);
149 rv
= pxa2x0_i2c_read(&sc
->sc_pxa_i2c
,
150 addr
, (u_char
*)vbuf
);
153 if ((I2C_OP_READ_P(op
)) && (cmdlen
== 1) && (buflen
== 2)) {
154 rv
= pxa2x0_i2c_write(&sc
->sc_pxa_i2c
, addr
, *(u_char
*)vbuf
);
156 rv
= pxa2x0_i2c_read(&sc
->sc_pxa_i2c
,
157 addr
, (u_char
*)vbuf
);
159 rv
= pxa2x0_i2c_read(&sc
->sc_pxa_i2c
,
160 addr
, (u_char
*)(vbuf
) + 1);
163 if ((I2C_OP_WRITE_P(op
)) && (cmdlen
== 0) && (buflen
== 1))
164 rv
= pxa2x0_i2c_write(&sc
->sc_pxa_i2c
, addr
, *(u_char
*)vbuf
);
166 if ((I2C_OP_WRITE_P(op
)) && (cmdlen
== 1) && (buflen
== 1)) {
167 rv
= pxa2x0_i2c_write(&sc
->sc_pxa_i2c
,
168 addr
, *(const u_char
*)vcmd
);
170 rv
= pxa2x0_i2c_write(&sc
->sc_pxa_i2c
,
171 addr
, *(u_char
*)vbuf
);
174 if ((I2C_OP_WRITE_P(op
)) && (cmdlen
== 1) && (buflen
== 2)) {
175 rv
= pxa2x0_i2c_write(&sc
->sc_pxa_i2c
,
176 addr
, *(const u_char
*)vcmd
);
178 rv
= pxa2x0_i2c_write_2(&sc
->sc_pxa_i2c
,
179 addr
, *(u_short
*)vbuf
);
182 /* Handle quick_read/quick_write ops - XXX Untested XXX */
183 if ((cmdlen
== 0) && (buflen
== 0))
184 rv
= pxa2x0_i2c_quick(&sc
->sc_pxa_i2c
, addr
,
185 I2C_OP_READ_P(op
)?1:0);