
Signed-off-by: Troy Kisky troy.kisky@boundarydevices.com --- arch/arm/cpu/armv7/imx-common/Makefile | 4 +- arch/arm/cpu/armv7/imx-common/i2c.c | 79 +++++++++++++++++++++++++++++ arch/arm/cpu/armv7/mx5/clock.c | 19 +++++++ arch/arm/cpu/armv7/mx6/clock.c | 19 +++++++ arch/arm/include/asm/arch-mx5/clock.h | 1 + arch/arm/include/asm/arch-mx6/clock.h | 1 + arch/arm/include/asm/imx-common/mxc_i2c.h | 46 +++++++++++++++++ 7 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/imx-common/i2c.c create mode 100644 arch/arm/include/asm/imx-common/mxc_i2c.h
diff --git a/arch/arm/cpu/armv7/imx-common/Makefile b/arch/arm/cpu/armv7/imx-common/Makefile index 53296fa..bf36be5 100644 --- a/arch/arm/cpu/armv7/imx-common/Makefile +++ b/arch/arm/cpu/armv7/imx-common/Makefile @@ -27,7 +27,9 @@ include $(TOPDIR)/config.mk
LIB = $(obj)libimx-common.o
-COBJS = iomux-v3.o timer.o cpu.o speed.o +COBJS-y = iomux-v3.o timer.o cpu.o speed.o +COBJS-$(CONFIG_I2C_MXC) += i2c.o +COBJS := $(sort $(COBJS-y))
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/arch/arm/cpu/armv7/imx-common/i2c.c b/arch/arm/cpu/armv7/imx-common/i2c.c new file mode 100644 index 0000000..a57d393 --- /dev/null +++ b/arch/arm/cpu/armv7/imx-common/i2c.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2012 Boundary Devices Inc. + * + * 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 + */ +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/errno.h> +#include <asm/gpio.h> +#include <asm/imx-common/mxc_i2c.h> +#include <asm/io.h> +#include <i2c.h> + +static void toggle_scl(void *priv) +{ + struct i2c_pads_info *p = (struct i2c_pads_info *)priv; + int i; + gpio_direction_input(p->sda.gp); + gpio_direction_input(p->scl.gp); + + imx_iomux_v3_setup_pad(p->sda.gpio_mode); + imx_iomux_v3_setup_pad(p->scl.gpio_mode); + + printf("%s sda=%i scl=%i sda.gp=0x%x scl.gp=0x%x\n", __func__, + gpio_get_value(p->sda.gp), gpio_get_value(p->scl.gp), + p->sda.gp, p->scl.gp); + /* Send high and low on the SCL line */ + for (i = 0; i < 9; i++) { + gpio_direction_output(p->scl.gp, 0); + udelay(50); + gpio_direction_input(p->scl.gp); + udelay(50); + printf("%s sda=%i scl=%i\n", __func__, + gpio_get_value(p->sda.gp), gpio_get_value(p->scl.gp)); + udelay(50); + } + imx_iomux_v3_setup_pad(p->sda.i2c_mode); + imx_iomux_v3_setup_pad(p->scl.i2c_mode); +} + +static const unsigned i2c_bases[] = { + I2C1_BASE_ADDR, + I2C2_BASE_ADDR, +#ifdef I2C3_BASE_ADDR + I2C3_BASE_ADDR, +#endif +}; + +/* i2c_index can be from 0 - 2 */ +void setup_i2c(unsigned i2c_index, int speed, int slave_addr, + struct i2c_pads_info *p) +{ + unsigned reg; + + if (i2c_index >= ARRAY_SIZE(i2c_bases)) + return; + imx_iomux_v3_setup_pad(p->sda.i2c_mode); + imx_iomux_v3_setup_pad(p->scl.i2c_mode); + /* Enable i2c clock */ + enable_i2c_clock(1, i2c_index); + bus_i2c_init(i2c_bases[i2c_index], speed, slave_addr, toggle_scl, p); +} diff --git a/arch/arm/cpu/armv7/mx5/clock.c b/arch/arm/cpu/armv7/mx5/clock.c index e92f106..b5d2794 100644 --- a/arch/arm/cpu/armv7/mx5/clock.c +++ b/arch/arm/cpu/armv7/mx5/clock.c @@ -80,6 +80,25 @@ void enable_usboh3_clk(unsigned char enable) writel(reg, &mxc_ccm->CCGR2); }
+#ifdef CONFIG_I2C_MXC +/* i2c_num can be from 0 - 2 */ +int enable_i2c_clock(unsigned char enable, unsigned i2c_num) +{ + u32 reg; + u32 mask; + + if (i2c_num > 2) + return; + mask = MXC_CCM_CCGR_CG_MASK << ((i2c_num + 9) << 1); + reg = __raw_readl(&mxc_ccm->CCGR1); + if (enable) + reg |= mask; + else + reg &= ~mask; + __raw_writel(reg, &mxc_ccm->CCGR1); +} +#endif + void set_usb_phy1_clk(void) { unsigned int reg; diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index ef98563..d31777b 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -49,6 +49,25 @@ void enable_usboh3_clk(unsigned char enable)
}
+#ifdef CONFIG_I2C_MXC +/* i2c_num can be from 0 - 2 */ +int enable_i2c_clock(unsigned char enable, unsigned i2c_num) +{ + u32 reg; + u32 mask; + + if (i2c_num > 2) + return; + mask = MXC_CCM_CCGR_CG_MASK << ((i2c_num + 3) << 1); + reg = __raw_readl(&imx_ccm->CCGR2); + if (enable) + reg |= mask; + else + reg &= ~mask; + __raw_writel(reg, &imx_ccm->CCGR2); +} +#endif + static u32 decode_pll(enum pll_clocks pll, u32 infreq) { u32 div; diff --git a/arch/arm/include/asm/arch-mx5/clock.h b/arch/arm/include/asm/arch-mx5/clock.h index ea972a3..da604bf 100644 --- a/arch/arm/include/asm/arch-mx5/clock.h +++ b/arch/arm/include/asm/arch-mx5/clock.h @@ -44,5 +44,6 @@ void set_usb_phy2_clk(void); void enable_usb_phy2_clk(unsigned char enable); void set_usboh3_clk(void); void enable_usboh3_clk(unsigned char enable); +int enable_i2c_clk(unsigned char enable, unsigned i2c_num);
#endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h index 613809b..04daf36 100644 --- a/arch/arm/include/asm/arch-mx6/clock.h +++ b/arch/arm/include/asm/arch-mx6/clock.h @@ -47,5 +47,6 @@ u32 imx_get_uartclk(void); u32 imx_get_fecclk(void); unsigned int mxc_get_clock(enum mxc_clock clk); void enable_usboh3_clk(unsigned char enable); +int enable_i2c_clk(unsigned char enable, unsigned i2c_num);
#endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/include/asm/imx-common/mxc_i2c.h b/arch/arm/include/asm/imx-common/mxc_i2c.h new file mode 100644 index 0000000..2a8f729 --- /dev/null +++ b/arch/arm/include/asm/imx-common/mxc_i2c.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef __ASM_ARCH_MXC_MXC_I2C_H__ +#define __ASM_ARCH_MXC_MXC_I2C_H__ +#include <asm/imx-common/iomux-v3.h> + +typedef void (*toggle_i2c_fn)(void *p); +struct mxc_i2c_regs; + + +struct i2c_pin_ctrl { + iomux_v3_cfg_t i2c_mode; + iomux_v3_cfg_t gpio_mode; + unsigned char gp; + unsigned char spare; +}; + +struct i2c_pads_info { + struct i2c_pin_ctrl scl; + struct i2c_pin_ctrl sda; +}; + +void setup_i2c(unsigned i2c_index, int speed, int slave_addr, + struct i2c_pads_info *p); +void bus_i2c_init(void *base, int speed, int slave_addr, toggle_i2c_fn tog, + void *p); +int bus_i2c_read(void *base, uchar chip, uint addr, int alen, uchar *buf, + int len); +int bus_i2c_write(void *base, uchar chip, uint addr, int alen, uchar *buf, + int len); +#endif