This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
PATCH::polling mode i2c driver for at91sam7x
- From: vibisreenivasan <vibi_sreenivasan at cms dot com>
- To: ecos-patches at ecos dot sourceware dot org
- Date: Sun, 05 Apr 2009 17:09:08 +0530
- Subject: PATCH::polling mode i2c driver for at91sam7x
- Reply-to: vibi_sreenivasan at cms dot com
Polling mode TWI driver for at91sam7x
Thanks & Regards
vibi
Index: packages/ecos.db
===================================================================
RCS file: /media/nfs/ecos-exp/cvsserver/packages/ecos.db,v
retrieving revision 1.1.1.1
diff -u -5 -p -r1.1.1.1 ecos.db
--- packages/ecos.db 5 Apr 2009 09:50:30 -0000 1.1.1.1
+++ packages/ecos.db 5 Apr 2009 11:02:37 -0000
@@ -2419,10 +2419,19 @@ package CYGPKG_DEVS_ADC_ARM_LPC24XX {
description "
This packages provides an ADC driver for the on-chip
ADC provided by the LPC24xx processor family."
}
+package CYGPKG_DEVS_I2C_ARM_AT91 {
+ alias { "AT91sam7x I2C driver" }
+ hardware
+ directory devs/i2c/arm/at91
+ script i2c_at91.cdl
+ description "This package provides a driver for the I2C unit of the AT91sam7x
+ controller family."
+}
+
package CYGPKG_DEVS_ADC_SYNTH {
alias { "Synthethic ADC driver" adc_synth }
hardware
directory devs/adc/synth
script adc_synth.cdl
@@ -4712,10 +4721,12 @@ target at91sam7xek {
CYGPKG_HAL_ARM_AT91SAM7XEK
CYGPKG_IO_SERIAL_ARM_AT91
CYGPKG_DEVS_FLASH_AT91
CYGPKG_IO_SPI
CYGPKG_DEVS_SPI_ARM_AT91
+ CYGPKG_IO_I2C
+ CYGPKG_DEVS_I2C_ARM_AT91
CYGPKG_DEVICES_WATCHDOG_ARM_AT91WDTC
CYGPKG_DEVS_USB_AT91
CYGPKG_DEVS_ETH_PHY
CYGPKG_DEVS_ETH_ARM_AT91
}
Index: packages/devs/i2c/arm/at91/current/cdl/i2c_at91.cdl
===================================================================
RCS file: /media/nfs/ecos-exp/cvsserver/packages/devs/i2c/arm/at91/current/cdl/i2c_at91.cdl,v
retrieving revision 1.1
diff -u -5 -p -r1.1 i2c_at91.cdl
--- packages/devs/i2c/arm/at91/current/cdl/i2c_at91.cdl 5 Apr 2009 10:50:28 -0000 1.1
+++ packages/devs/i2c/arm/at91/current/cdl/i2c_at91.cdl 1 Apr 2009 19:36:19 -0000
@@ -0,0 +1,58 @@
+# ====================================================================
+#
+# i2c_at91.cdl
+#
+# I2C driver for AT91SAM7x
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## eCos is free software; you can redistribute it and/or modify it under
+## the terms of the GNU General Public License as published by the Free
+## Software Foundation; either version 2 or (at your option) any later version.
+##
+## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+## WARRANTY; without even the implied warranty of MERCHANTABILITY or
+## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along
+## with eCos; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+##
+## As a special exception, if other files instantiate templates or use macros
+## or inline functions from this file, or you compile this file and link it
+## with other works to produce a work based on this file, this file does not
+## by itself cause the resulting work to be covered by the GNU General Public
+## License. However the source code for this file must still be made available
+## in accordance with section (3) of the GNU General Public License.
+##
+## This exception does not invalidate any other reasons why a work based on
+## this file might be covered by the GNU General Public License.
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): vibi sreenivasan <vibi_sreenivasan@cms.com>
+# Contributors:
+# Date: 2007-07-12
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_I2C_ARM_AT91 {
+ display "I2C driver for AT91 family of ARM controllers"
+ parent CYGPKG_IO_I2C
+ active_if CYGPKG_IO_I2C
+ active_if CYGPKG_HAL_ARM_AT91SAM7XEK
+ description "This package provides a driver for the I2C module found in
+ Atmel AT91SAM7X controllers."
+ hardware
+ include_dir cyg/io
+ compile i2c_at91.c
+}
\ No newline at end of file
Index: packages/devs/i2c/arm/at91/current/include/i2c_at91.h
===================================================================
RCS file: /media/nfs/ecos-exp/cvsserver/packages/devs/i2c/arm/at91/current/include/i2c_at91.h,v
retrieving revision 1.1
diff -u -5 -p -r1.1 i2c_at91.h
--- packages/devs/i2c/arm/at91/current/include/i2c_at91.h 5 Apr 2009 10:50:45 -0000 1.1
+++ packages/devs/i2c/arm/at91/current/include/i2c_at91.h 5 Apr 2009 11:30:36 -0000
@@ -0,0 +1,85 @@
+#ifndef CYGONCE_DEVS_I2C_ARM_AT91_H
+#define CYGONCE_DEVS_I2C_ARM_AT91_H
+//==========================================================================
+//
+// i2c_at91.h
+//
+// Atmel AT91 (ARM) I2C driver defines
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): vibi sreenivasan <vibi_sreenivasan@cms.com>
+// Date: 10-11-2008
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/hal.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/hal/drv_api.h>
+#include <cyg/io/i2c.h>
+
+#define I2C_AT91_TXR_START (1 << 7)
+#define I2C_AT91_TXR_END (1 << 6)
+#define I2C_AT91_RXR_START (1 << 5)
+#define I2C_AT91_RXR_END (1 << 4)
+
+
+typedef struct cyg_i2c_at91_dev_s
+{
+ // upper layer data (upper layer i2c device structure)
+ cyg_i2c_device i2c_device;
+ // lower layer data
+ cyg_uint8 int_addr_sz; // most chips do have internal address size
+} cyg_i2c_at91_dev_t;
+
+#define CYG_I2C_AT91_DEVICE(_name_, _bus_, _address_, _flags_, _delay_, _int_adr_sz_) \
+ cyg_i2c_at91_dev_t _name_ = { \
+ .i2c_device = { \
+ .i2c_bus = _bus_, \
+ .i2c_address = _address_, \
+ .i2c_flags = _flags_, \
+ .i2c_delay = _delay_, \
+ }, \
+ .int_addr_sz = _int_adr_sz_, \
+ }
+
+#define HAL_I2C_EXPORTED_DEVICES \
+ externC cyg_i2c_bus cyg_i2c_at91_bus; \
+#endif // CYGONCE_DEVS_I2C_ARM_AT91_H
+
Index: packages/devs/i2c/arm/at91/current/src/i2c_at91.c
===================================================================
RCS file: /media/nfs/ecos-exp/cvsserver/packages/devs/i2c/arm/at91/current/src/i2c_at91.c,v
retrieving revision 1.1
diff -u -5 -p -r1.1 i2c_at91.c
--- packages/devs/i2c/arm/at91/current/src/i2c_at91.c 5 Apr 2009 10:50:54 -0000 1.1
+++ packages/devs/i2c/arm/at91/current/src/i2c_at91.c 5 Apr 2009 11:32:14 -0000
@@ -0,0 +1,239 @@
+//==========================================================================
+//
+// i2c_at91.c
+//
+// I2C driver for AT91SAM7x
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): vibi sreenivasan <vibi_sreenivasan@cms.com>
+// Contributors:
+// Date: 2009-3-25
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <pkgconf/system.h>
+#include <pkgconf/devs_i2c_arm_at91.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/diag.h>
+#include <cyg/io/i2c.h>
+#include <cyg/io/i2c_at91.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/drv_api.h>
+
+#define I2C_BASE AT91_TWI
+#define I2C_TXCOMP AT91_TWI_SR_TXCOMP
+#define I2C_RXRDY AT91_TWI_SR_RXRDY
+#define I2C_TXRDY AT91_TWI_SR_TXRDY
+#define I2C_NACK AT91_TWI_SR_NACK
+
+#define I2C_W8(r,x) HAL_WRITE_UINT8(I2C_BASE + (r), (x))
+#define I2C_R8(r,x) HAL_READ_UINT8(I2C_BASE + (r), (x))
+#define I2C_W32(r, x) HAL_WRITE_UINT32(I2C_BASE + (r), (x))
+#define I2C_R32(r, x) HAL_READ_UINT32(I2C_BASE + (r), (x))
+
+#define TIMEOUT 1200
+static cyg_uint32 i2c_delay;
+
+// set up I2C bus timing
+static void
+i2c_at91_delay(cyg_uint32 delay)
+{
+ cyg_uint32 cdiv,ckdiv = 0;
+
+ if(delay == i2c_delay)
+ return;
+ // (delay / 10^9) for converting delay nsec to sec
+ // formula from datasheet => Tlow = ((CLDIV * 2^CKDIV) + 3) * Tmck
+ // CLDIV = CHDIV = CDIV
+ cdiv = (delay / 1000) * (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED / (2 * 1000000));
+ cdiv -= 3;
+ while (cdiv > 255) {
+ ckdiv++;
+ cdiv >>= 1;
+ }
+ I2C_W32(AT91_TWI_CWGR,ckdiv << AT91_TWI_CWGR_CKDIV_SHIFT |
+ cdiv << AT91_TWI_CWGR_CHDIV_SHIFT | cdiv << AT91_TWI_CWGR_CLDIV_SHIFT);
+ i2c_delay = delay;
+}
+
+// Initialize driver & hardware state
+static void
+i2c_at91_init(struct cyg_i2c_bus *bus)
+{
+ // enable multi-drain
+ HAL_WRITE_UINT32((AT91_PIOA + AT91_PIO_MDER),(AT91_PIO_PSR_TWD
+ |AT91_PIO_PSR_TWCK));
+ HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PA10,AT91_PIN_PULLUP_DISABLE);
+ HAL_ARM_AT91_GPIO_CFG_PULLUP(AT91_GPIO_PA11,AT91_PIN_PULLUP_DISABLE);
+ HAL_ARM_AT91_PIO_CFG(AT91_TWI_TWD);
+ HAL_ARM_AT91_PIO_CFG(AT91_TWI_TWCK);
+ // enable TWI clock
+ HAL_WRITE_UINT32((AT91_PMC + AT91_PMC_PCER), AT91_PMC_PCER_TWI);
+ // S/W reset
+ I2C_W32(AT91_TWI_CR, AT91_TWI_CR_SWRST);
+ // Works only as master
+ I2C_W32(AT91_TWI_CR, AT91_TWI_CR_MSEN);
+
+}
+
+
+// transmit a buffer to a device
+static cyg_uint32
+i2c_at91_tx(const cyg_i2c_device *dev,
+ cyg_bool send_start,
+ const cyg_uint8 *tx_data,
+ cyg_uint32 count,
+ cyg_bool send_stop)
+{
+ cyg_i2c_at91_dev_t *at91_i2c_dev = (cyg_i2c_at91_dev_t*)dev;
+ cyg_uint32 tmp = 0,timeout,i2c_count = count;
+ cyg_uint8 i = at91_i2c_dev->int_addr_sz;
+ volatile cyg_uint32 stat_reg;
+ const cyg_uint8 *i2c_txbuf = &tx_data[i];
+ if (!count)
+ return 0;
+ // set device specific speed
+ i2c_at91_delay(dev->i2c_delay);
+ // calculate internal address
+ while (i--)
+ tmp |= *tx_data++ << (i << 3);
+ // Load device address, direction & internal address size
+ I2C_W32(AT91_TWI_MMR,AT91_TWI_MMR_MWRITE |
+ ((dev->i2c_address << AT91_TWI_MMR_DADR_SHIFT) |
+ ((at91_i2c_dev->int_addr_sz << AT91_TWI_MMR_IADRZ_SHIFT) &
+ AT91_TWI_MMR_IADRZ_MASK)));
+ // Load internal address
+ I2C_W32(AT91_TWI_IADR,tmp);
+ // Load START condition if requested
+ if (send_start)
+ I2C_W32(AT91_TWI_CR, AT91_TWI_CR_START);
+ // use tmp to store flags to check
+ tmp = AT91_TWI_SR_TXRDY;
+ do
+ {
+ // Load STOP condition with the last transfer if requested
+ if (send_stop && i2c_count == 1) {
+ I2C_W32(AT91_TWI_CR, AT91_TWI_CR_STOP);
+ tmp = AT91_TWI_SR_TXCOMP;
+ }
+ // Load DATA to txmit
+ I2C_W8(AT91_TWI_THR,*i2c_txbuf++);
+ // Wait for txr completion flag || timeout
+ for ( timeout = TIMEOUT,stat_reg = 0;
+ timeout && !(stat_reg & tmp); timeout-- )
+ I2C_R32 (AT91_TWI_SR,stat_reg);
+ // error condition , return howmuch data was transferred
+ if (!timeout)
+ return (count - i2c_count);
+ } while (--i2c_count);
+ return (count - i2c_count);
+}
+
+
+// receive into a buffer from a device
+// there is no h/w specific way to send NACK
+static cyg_uint32
+i2c_at91_rx(const cyg_i2c_device *dev,
+ cyg_bool send_start,
+ cyg_uint8 *rx_data,
+ cyg_uint32 count,
+ cyg_bool send_nak,
+ cyg_bool send_stop)
+{
+ cyg_i2c_at91_dev_t *at91_i2c_dev = (cyg_i2c_at91_dev_t*)dev;
+ cyg_uint32 tmp = 0,timeout,i2c_count = count;
+ volatile cyg_uint32 stat_reg;
+ cyg_uint8 i = at91_i2c_dev->int_addr_sz;
+ if (!count)
+ return 0;
+ // set device specific speed
+ i2c_at91_delay(dev->i2c_delay);
+ // calculate internal address
+ while (i--)
+ tmp |= *rx_data++ << (i << 3);
+ // Load device address , direction & internal address size
+ I2C_W32(AT91_TWI_MMR,AT91_TWI_MMR_MREAD |
+ ((dev->i2c_address << AT91_TWI_MMR_DADR_SHIFT) |
+ ((at91_i2c_dev->int_addr_sz << AT91_TWI_MMR_IADRZ_SHIFT) &
+ AT91_TWI_MMR_IADRZ_MASK)));
+ I2C_W32(AT91_TWI_IADR,tmp);
+ I2C_W32(AT91_TWI_CR, AT91_TWI_CR_START);
+ // use tmp to store flags to check
+ tmp = AT91_TWI_SR_RXRDY;
+ do
+ {
+ // Load STOP condition with the last transfer if requested
+ if (send_stop && i2c_count == 1) {
+ I2C_W32(AT91_TWI_CR, AT91_TWI_CR_STOP);
+ tmp = AT91_TWI_SR_TXCOMP;
+ }
+ // Wait for txr completion flag || timeout
+ for ( timeout = TIMEOUT,stat_reg = 0;
+ timeout && !(stat_reg & tmp); timeout-- )
+ I2C_R32 (AT91_TWI_SR,stat_reg);
+ // error condition , return howmuch data was transferred
+ if (!timeout)
+ return (count - i2c_count);
+ // Read recived data
+ I2C_R8(AT91_TWI_RHR,*rx_data++);
+ } while (--i2c_count);
+ return (count - i2c_count);
+}
+
+
+
+// generate a STOP
+static void
+i2c_at91_stop(const cyg_i2c_device *dev)
+{
+ I2C_W32(AT91_TWI_CR, AT91_TWI_CR_STOP);
+}
+
+CYG_I2C_BUS(cyg_i2c_at91_bus,
+ &i2c_at91_init,
+ &i2c_at91_tx,
+ &i2c_at91_rx,
+ &i2c_at91_stop,
+ (void *) 0);
+
Index: packages/hal/arm/at91/var/current/include/var_io.h
===================================================================
RCS file: /media/nfs/ecos-exp/cvsserver/packages/hal/arm/at91/var/current/include/var_io.h,v
retrieving revision 1.1.1.1
diff -u -5 -p -r1.1.1.1 var_io.h
--- packages/hal/arm/at91/var/current/include/var_io.h 5 Apr 2009 09:50:34 -0000 1.1.1.1
+++ packages/hal/arm/at91/var/current/include/var_io.h 5 Apr 2009 10:59:49 -0000
@@ -2625,10 +2625,12 @@
#define AT91_TWI_CR_MSDIS (1 << 3) // Master Transfer Disable
#define AT91_TWI_CR_SVEN (1 << 4) // Slave Transfer Enable
#define AT91_TWI_CR_SDIS (1 << 5) // Slave Transfer Disable
#define AT91_TWI_CR_SWRST (1 << 7) // Software Reset
#define AT91_TWI_MMR 0x04 // Master Mode
+#define AT91_TWI_MMR_IADRZ_MASK (3 << 8) // Internal Device Address Size Mask
+#define AT91_TWI_MMR_IADRZ_SHIFT (8) // Internal Device Address Size Shift
#define AT91_TWI_MMR_IADRZ_NO (0 << 8) // Internal Device Address size 0Bytes
#define AT91_TWI_MMR_IADRZ_1 (1 << 8) // Internal Device Address size 1Byte
#define AT91_TWI_MMR_IADRZ_2 (2 << 8) // Internal Device Address size 2Bytes
#define AT91_TWI_MMR_IADRZ_3 (3 << 8) // Internal Device Address size 3Bytes
#define AT91_TWI_MMR_MWRITE (0 << 12) // Master Write