X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=blobdiff_plain;f=drivers%2Fi2c%2Fsoft_i2c.c;h=dfea54ae73308c5f665bbe4606bc49c90e8b19cc;hp=19c364b136e5c196f5f70d15885ab7b23cf98927;hb=cb96a0a4c90e64b286d1b117374d16817b1c8521;hpb=98aed379586a155292efbf3209356836584b601c diff --git a/drivers/i2c/soft_i2c.c b/drivers/i2c/soft_i2c.c index 19c364b136..dfea54ae73 100644 --- a/drivers/i2c/soft_i2c.c +++ b/drivers/i2c/soft_i2c.c @@ -1,24 +1,12 @@ /* + * (C) Copyright 2009 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * Changes for multibus/multiadapter I2C support. + * * (C) Copyright 2001, 2002 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program 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 of - * the License, or (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ * * This has been changed substantially by Gerald Van Baren, Custom IDEAS, * vanbaren@cideas.com. It was heavily influenced by LiMon, written by @@ -28,60 +16,132 @@ #include #ifdef CONFIG_MPC8260 /* only valid for MPC8260 */ #include +#include #endif -#ifdef CONFIG_AT91RM9200 /* need this for the at91rm9200 */ +#if defined(CONFIG_AVR32) +#include +#endif +#if defined(CONFIG_AT91FAMILY) #include #include +#include +#ifdef CONFIG_ATMEL_LEGACY +#include +#endif #endif #ifdef CONFIG_IXP425 /* only valid for IXP425 */ #include #endif -#ifdef CONFIG_LPC2292 -#include +#if defined(CONFIG_MPC852T) || defined(CONFIG_MPC866) +#include #endif #include +#if defined(CONFIG_SOFT_I2C_GPIO_SCL) +# include + +# ifndef I2C_GPIO_SYNC +# define I2C_GPIO_SYNC +# endif + +# ifndef I2C_INIT +# define I2C_INIT \ + do { \ + gpio_request(CONFIG_SOFT_I2C_GPIO_SCL, "soft_i2c"); \ + gpio_request(CONFIG_SOFT_I2C_GPIO_SDA, "soft_i2c"); \ + } while (0) +# endif + +# ifndef I2C_ACTIVE +# define I2C_ACTIVE do { } while (0) +# endif + +# ifndef I2C_TRISTATE +# define I2C_TRISTATE do { } while (0) +# endif + +# ifndef I2C_READ +# define I2C_READ gpio_get_value(CONFIG_SOFT_I2C_GPIO_SDA) +# endif + +# ifndef I2C_SDA +# define I2C_SDA(bit) \ + do { \ + if (bit) \ + gpio_direction_input(CONFIG_SOFT_I2C_GPIO_SDA); \ + else \ + gpio_direction_output(CONFIG_SOFT_I2C_GPIO_SDA, 0); \ + I2C_GPIO_SYNC; \ + } while (0) +# endif + +# ifndef I2C_SCL +# define I2C_SCL(bit) \ + do { \ + gpio_direction_output(CONFIG_SOFT_I2C_GPIO_SCL, bit); \ + I2C_GPIO_SYNC; \ + } while (0) +# endif + +# ifndef I2C_DELAY +# define I2C_DELAY udelay(5) /* 1/4 I2C clock duration */ +# endif + +#endif + /* #define DEBUG_I2C */ -#ifdef DEBUG_I2C DECLARE_GLOBAL_DATA_PTR; + +#ifndef I2C_SOFT_DECLARATIONS +# if defined(CONFIG_MPC8260) +# define I2C_SOFT_DECLARATIONS volatile ioport_t *iop = \ + ioport_addr((immap_t *)CONFIG_SYS_IMMR, I2C_PORT); +# elif defined(CONFIG_8xx) +# define I2C_SOFT_DECLARATIONS volatile immap_t *immr = \ + (immap_t *)CONFIG_SYS_IMMR; +# else +# define I2C_SOFT_DECLARATIONS +# endif #endif +#if !defined(CONFIG_SYS_I2C_SOFT_SPEED) +#define CONFIG_SYS_I2C_SOFT_SPEED CONFIG_SYS_I2C_SPEED +#endif +#if !defined(CONFIG_SYS_I2C_SOFT_SLAVE) +#define CONFIG_SYS_I2C_SOFT_SLAVE CONFIG_SYS_I2C_SLAVE +#endif /*----------------------------------------------------------------------- * Definitions */ - #define RETRIES 0 - #define I2C_ACK 0 /* PD_SDA level to ack a byte */ #define I2C_NOACK 1 /* PD_SDA level to noack a byte */ #ifdef DEBUG_I2C #define PRINTD(fmt,args...) do { \ - if (gd->have_console) \ printf (fmt ,##args); \ } while (0) #else #define PRINTD(fmt,args...) #endif -#if defined(CONFIG_I2C_MULTI_BUS) -static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = 0; -#endif /* CONFIG_I2C_MULTI_BUS */ - /*----------------------------------------------------------------------- * Local functions */ +#if !defined(CONFIG_SYS_I2C_INIT_BOARD) static void send_reset (void); +#endif static void send_start (void); static void send_stop (void); static void send_ack (int); static int write_byte (uchar byte); static uchar read_byte (int); +#if !defined(CONFIG_SYS_I2C_INIT_BOARD) /*----------------------------------------------------------------------- * Send a reset sequence consisting of 9 clocks with the data signal high * to clock any confused device back into an idle state. Also send a @@ -109,6 +169,7 @@ static void send_reset(void) send_stop(); I2C_TRISTATE; } +#endif /*----------------------------------------------------------------------- * START: High -> Low on SDA while SCL is High @@ -146,7 +207,6 @@ static void send_stop(void) I2C_TRISTATE; } - /*----------------------------------------------------------------------- * ack should be I2C_ACK or I2C_NOACK */ @@ -166,7 +226,6 @@ static void send_ack(int ack) I2C_DELAY; } - /*----------------------------------------------------------------------- * Send 8 bits and look for an acknowledgement. */ @@ -208,39 +267,6 @@ static int write_byte(uchar data) return(nack); /* not a nack is an ack */ } -#if defined(CONFIG_I2C_MULTI_BUS) -/* - * Functions for multiple I2C bus handling - */ -unsigned int i2c_get_bus_num(void) -{ - return i2c_bus_num; -} - -int i2c_set_bus_num(unsigned int bus) -{ - if (bus >= CFG_MAX_I2C_BUS) - return -1; - i2c_bus_num = bus; - - return 0; -} - -/* TODO: add 100/400k switching */ -unsigned int i2c_get_bus_speed(void) -{ - return CFG_I2C_SPEED; -} - -int i2c_set_bus_speed(unsigned int speed) -{ - if (speed != CFG_I2C_SPEED) - return -1; - - return 0; -} -#endif - /*----------------------------------------------------------------------- * if ack == I2C_ACK, ACK the byte so can continue reading, else * send I2C_NOACK to end the read. @@ -271,15 +297,17 @@ static uchar read_byte(int ack) return(data); } -/*=====================================================================*/ -/* Public Functions */ -/*=====================================================================*/ - /*----------------------------------------------------------------------- * Initialization */ -void i2c_init (int speed, int slaveaddr) +static void soft_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr) { +#if defined(CONFIG_SYS_I2C_INIT_BOARD) + /* call board specific i2c bus reset routine before accessing the */ + /* environment, which might be in a chip on that bus. For details */ + /* about this problem see doc/I2C_Edge_Conditions. */ + i2c_init_board(); +#else /* * WARNING: Do NOT save speed in a static variable: if the * I2C routines are called before RAM is initialized (to read @@ -287,6 +315,7 @@ void i2c_init (int speed, int slaveaddr) * system will crash. */ send_reset (); +#endif } /*----------------------------------------------------------------------- @@ -294,7 +323,7 @@ void i2c_init (int speed, int slaveaddr) * completion of EEPROM writes since the chip stops responding until * the write completes (typically 10mSec). */ -int i2c_probe(uchar addr) +static int soft_i2c_probe(struct i2c_adapter *adap, uint8_t addr) { int rc; @@ -312,13 +341,14 @@ int i2c_probe(uchar addr) /*----------------------------------------------------------------------- * Read bytes */ -int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) +static int soft_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len) { int shift; PRINTD("i2c_read: chip %02X addr %02X alen %d buffer %p len %d\n", chip, addr, alen, buffer, len); -#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW +#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW /* * EEPROM chips that implement "address overflow" are ones * like Catalyst 24WC04/08/16 which has 9/10/11 bits of @@ -330,7 +360,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) * still be one byte because the extra address bits are * hidden in the chip address. */ - chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); + chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); PRINTD("i2c_read: fix addr_overflow: chip %02X addr %02X\n", chip, addr); @@ -357,8 +387,18 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) } shift -= 8; } - send_stop(); /* reportedly some chips need a full stop */ + + /* Some I2C chips need a stop/start sequence here, + * other chips don't work with a full stop and need + * only a start. Default behaviour is to send the + * stop/start sequence. + */ +#ifdef CONFIG_SOFT_I2C_READ_REPEATED_START + send_start(); +#else + send_stop(); send_start(); +#endif } /* * Send the chip address again, this time for a read cycle. @@ -376,7 +416,8 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) /*----------------------------------------------------------------------- * Write bytes */ -int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) +static int soft_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len) { int shift, failures = 0; @@ -407,22 +448,31 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) return(failures); } -/*----------------------------------------------------------------------- - * Read a register - */ -uchar i2c_reg_read(uchar i2c_addr, uchar reg) -{ - uchar buf; - - i2c_read(i2c_addr, reg, 1, &buf, 1); - - return(buf); -} - -/*----------------------------------------------------------------------- - * Write a register +/* + * Register soft i2c adapters */ -void i2c_reg_write(uchar i2c_addr, uchar reg, uchar val) -{ - i2c_write(i2c_addr, reg, 1, &val, 1); -} +U_BOOT_I2C_ADAP_COMPLETE(soft0, soft_i2c_init, soft_i2c_probe, + soft_i2c_read, soft_i2c_write, NULL, + CONFIG_SYS_I2C_SOFT_SPEED, CONFIG_SYS_I2C_SOFT_SLAVE, + 0) +#if defined(I2C_SOFT_DECLARATIONS2) +U_BOOT_I2C_ADAP_COMPLETE(soft1, soft_i2c_init, soft_i2c_probe, + soft_i2c_read, soft_i2c_write, NULL, + CONFIG_SYS_I2C_SOFT_SPEED_2, + CONFIG_SYS_I2C_SOFT_SLAVE_2, + 1) +#endif +#if defined(I2C_SOFT_DECLARATIONS3) +U_BOOT_I2C_ADAP_COMPLETE(soft2, soft_i2c_init, soft_i2c_probe, + soft_i2c_read, soft_i2c_write, NULL, + CONFIG_SYS_I2C_SOFT_SPEED_3, + CONFIG_SYS_I2C_SOFT_SLAVE_3, + 2) +#endif +#if defined(I2C_SOFT_DECLARATIONS4) +U_BOOT_I2C_ADAP_COMPLETE(soft3, soft_i2c_init, soft_i2c_probe, + soft_i2c_read, soft_i2c_write, NULL, + CONFIG_SYS_I2C_SOFT_SPEED_4, + CONFIG_SYS_I2C_SOFT_SLAVE_4, + 3) +#endif