From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:43904) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UYfiY-0006E6-TQ for qemu-devel@nongnu.org; Sat, 04 May 2013 12:53:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UYfiX-0002fI-Do for qemu-devel@nongnu.org; Sat, 04 May 2013 12:53:50 -0400 Received: from cantor2.suse.de ([195.135.220.15]:45039 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UYfiX-0002eK-11 for qemu-devel@nongnu.org; Sat, 04 May 2013 12:53:49 -0400 Message-ID: <51853D15.7040409@suse.de> Date: Sat, 04 May 2013 18:53:41 +0200 From: =?ISO-8859-15?Q?Andreas_F=E4rber?= MIME-Version: 1.0 References: In-Reply-To: Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v2 4/4] Add qtest support for i.MX I2C device emulation. List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Jean-Christophe DUBOIS Cc: peter.maydell@linaro.org, peter.crosthwaite@xilinx.com, peter.chubb@nicta.com.au, qemu-devel@nongnu.org Am 04.05.2013 16:09, schrieb Jean-Christophe DUBOIS: > This is using a ds1338 RTC chip on the i2c bus. This RTC > chip is nop present on the real board >=20 > Signed-off-by: Jean-Christophe DUBOIS > --- > tests/Makefile | 3 + > tests/ds1338-test.c | 64 ++++++++++++++ > tests/libqos/i2c-imx.c | 224 +++++++++++++++++++++++++++++++++++++++++= ++++++++ > tests/libqos/i2c.h | 3 + > 4 files changed, 294 insertions(+) > create mode 100644 tests/ds1338-test.c > create mode 100644 tests/libqos/i2c-imx.c [...] The qtest itself looks fine, thanks. > diff --git a/tests/libqos/i2c-imx.c b/tests/libqos/i2c-imx.c > new file mode 100644 > index 0000000..da7316f > --- /dev/null > +++ b/tests/libqos/i2c-imx.c > @@ -0,0 +1,224 @@ > +/* > + * QTest i.MX I2C driver > + * > + * Copyright (c) 2013 Jean-Christophe Dubois > + * > + * This work is licensed under the terms of the GNU GPL, version 2 or = later. > + * See the COPYING file in the top-level directory. > + */ > +#include "libqos/i2c.h" > + > +#include > +#include > + > +#include "qemu/osdep.h" > +#include "qemu/bswap.h" Is this one needed? > +#include "libqtest.h" > + > +enum IMXI2CRegisters { > + IMX_I2C_IADR =3D 0x00, > + IMX_I2C_IFDR =3D 0x04, > + IMX_I2C_I2CR =3D 0x08, > + IMX_I2C_I2SR =3D 0x0c, > + IMX_I2C_I2DR =3D 0x10, > +}; > + > +enum IMXI2CCRBits { > + IMX_I2C_I2CR_IEN =3D 1 << 7, > + IMX_I2C_I2CR_IIEN =3D 1 << 6, > + IMX_I2C_I2CR_MSTA =3D 1 << 5, > + IMX_I2C_I2CR_MTX =3D 1 << 4, > + IMX_I2C_I2CR_TXAK =3D 1 << 3, > + IMX_I2C_I2CR_RSTA =3D 1 << 2, > +}; > + > +enum IMXI2CSRBits { > + IMX_I2C_I2SR_ICF =3D 1 << 7, > + IMX_I2C_I2SR_IAAF =3D 1 << 6, > + IMX_I2C_I2SR_IBB =3D 1 << 5, > + IMX_I2C_I2SR_IAL =3D 1 << 4, > + IMX_I2C_I2SR_SRW =3D 1 << 2, > + IMX_I2C_I2SR_IIF =3D 1 << 1, > + IMX_I2C_I2SR_RXAK =3D 1 << 0, > +}; > + > +enum IMXI2CDirection { > + IMX_I2C_READ, > + IMX_I2C_WRITE, > +}; libqos/i2c-omap.c was a driver for an unmaintained legacy device. i.MX I2C however is being added by you in 2/4, so it would be better to put these constants in a header in 2/4 for reuse here (i2c/imx_regs.h?). Otherwise looking fine! Regards, Andreas > + > +typedef struct IMXI2C { > + I2CAdapter parent; > + > + uint64_t addr; > +} IMXI2C; > + > + > +static void imx_i2c_set_slave_addr(IMXI2C *s, uint8_t addr, > + enum IMXI2CDirection direction) > +{ > + writeb(s->addr + IMX_I2C_I2DR, (addr << 1) | > + (direction =3D=3D IMX_I2C_READ ? 1 : 0)); > +} > + > +static void imx_i2c_send(I2CAdapter *i2c, uint8_t addr, > + const uint8_t *buf, uint16_t len) > +{ > + IMXI2C *s =3D (IMXI2C *)i2c; > + uint8_t data; > + uint8_t status; > + uint16_t size =3D 0; > + > + if (!len) { > + return; > + } > + > + /* set the bus for write */ > + data =3D IMX_I2C_I2CR_IEN | > + IMX_I2C_I2CR_IIEN | > + IMX_I2C_I2CR_MSTA | > + IMX_I2C_I2CR_MTX | > + IMX_I2C_I2CR_TXAK; > + > + writeb(s->addr + IMX_I2C_I2CR, data); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IBB) !=3D 0); > + > + /* set the slave address */ > + imx_i2c_set_slave_addr(s, addr, IMX_I2C_WRITE); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IIF) !=3D 0); > + g_assert((status & IMX_I2C_I2SR_RXAK) =3D=3D 0); > + > + /* ack the interrupt */ > + writeb(s->addr + IMX_I2C_I2SR, 0); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IIF) =3D=3D 0); > + > + while (size < len) { > + /* check we are still busy */ > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IBB) !=3D 0); > + > + /* write the data */ > + writeb(s->addr + IMX_I2C_I2DR, buf[size]); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IIF) !=3D 0); > + g_assert((status & IMX_I2C_I2SR_RXAK) =3D=3D 0); > + > + /* ack the interrupt */ > + writeb(s->addr + IMX_I2C_I2SR, 0); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IIF) =3D=3D 0); > + > + size++; > + } > + > + /* release the bus */ > + data &=3D ~(IMX_I2C_I2CR_MSTA | IMX_I2C_I2CR_MTX); > + writeb(s->addr + IMX_I2C_I2CR, data); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IBB) =3D=3D 0); > +} > + > +static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr, > + uint8_t *buf, uint16_t len) > +{ > + IMXI2C *s =3D (IMXI2C *)i2c; > + uint8_t data; > + uint8_t status; > + uint16_t size =3D 0; > + > + if (!len) { > + return; > + } > + > + /* set the bus for write */ > + data =3D IMX_I2C_I2CR_IEN | > + IMX_I2C_I2CR_IIEN | > + IMX_I2C_I2CR_MSTA | > + IMX_I2C_I2CR_MTX | > + IMX_I2C_I2CR_TXAK; > + > + writeb(s->addr + IMX_I2C_I2CR, data); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IBB) !=3D 0); > + > + /* set the slave address */ > + imx_i2c_set_slave_addr(s, addr, IMX_I2C_READ); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IIF) !=3D 0); > + g_assert((status & IMX_I2C_I2SR_RXAK) =3D=3D 0); > + > + /* ack the interrupt */ > + writeb(s->addr + IMX_I2C_I2SR, 0); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IIF) =3D=3D 0); > + > + /* set the bus for read */ > + data &=3D ~IMX_I2C_I2CR_MTX; > + /* if only one byte don't ack */ > + if (len !=3D 1) { > + data &=3D ~IMX_I2C_I2CR_TXAK; > + } > + writeb(s->addr + IMX_I2C_I2CR, data); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IBB) !=3D 0); > + > + /* dummy read */ > + readb(s->addr + IMX_I2C_I2DR); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IIF) !=3D 0); > + > + /* ack the interrupt */ > + writeb(s->addr + IMX_I2C_I2SR, 0); > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IIF) =3D=3D 0); > + > + while (size < len) { > + /* check we are still busy */ > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IBB) !=3D 0); > + > + if (size =3D=3D (len - 1)) { > + /* stop the read transaction */ > + data &=3D ~(IMX_I2C_I2CR_MSTA | IMX_I2C_I2CR_MTX); > + } else { > + /* ack the data read */ > + data |=3D IMX_I2C_I2CR_TXAK; > + } > + writeb(s->addr + IMX_I2C_I2CR, data); > + > + /* read the data */ > + buf[size] =3D readb(s->addr + IMX_I2C_I2DR); > + > + if (size !=3D (len - 1)) { > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IIF) !=3D 0); > + > + /* ack the interrupt */ > + writeb(s->addr + IMX_I2C_I2SR, 0); > + } > + > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IIF) =3D=3D 0); > + > + size++; > + } > + > + status =3D readb(s->addr + IMX_I2C_I2SR); > + g_assert((status & IMX_I2C_I2SR_IBB) =3D=3D 0); > +} > + > +I2CAdapter *imx_i2c_create(uint64_t addr) > +{ > + IMXI2C *s =3D g_malloc0(sizeof(*s)); > + I2CAdapter *i2c =3D (I2CAdapter *)s; > + > + s->addr =3D addr; > + > + i2c->send =3D imx_i2c_send; > + i2c->recv =3D imx_i2c_recv; > + > + return i2c; > +} > diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h > index 1ce9af4..c21f1dc 100644 > --- a/tests/libqos/i2c.h > +++ b/tests/libqos/i2c.h > @@ -27,4 +27,7 @@ void i2c_recv(I2CAdapter *i2c, uint8_t addr, > /* libi2c-omap.c */ > I2CAdapter *omap_i2c_create(uint64_t addr); > =20 > +/* libi2c-imx.c */ > +I2CAdapter *imx_i2c_create(uint64_t addr); > + > #endif >=20 --=20 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 N=FCrnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imend=F6rffer; HRB 16746 AG N=FCrnbe= rg