X-Git-Url: https://git.kernelconcepts.de/?a=blobdiff_plain;f=drivers%2Fi2c%2Fmxs_i2c.c;h=de3b19402b4af1c2f8a97283a77a0d92d034b0ed;hb=f7582ce8496f19edf845d1f62c4b7f385e4cd864;hp=b907f7b379bb6c6bb02aabffdff363f4560bc23c;hpb=a098cf41fdb2a6607c675f7fe4f3164617c9367e;p=karo-tx-uboot.git diff --git a/drivers/i2c/mxs_i2c.c b/drivers/i2c/mxs_i2c.c index b907f7b379..de3b19402b 100644 --- a/drivers/i2c/mxs_i2c.c +++ b/drivers/i2c/mxs_i2c.c @@ -10,20 +10,7 @@ * Which was based on a (non-working) driver which was: * Copyright (C) 2009-2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -37,7 +24,7 @@ #define MXS_I2C_MAX_TIMEOUT 1000000 -void mxs_i2c_reset(void) +static void mxs_i2c_reset(void) { struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; int ret; @@ -59,7 +46,7 @@ void mxs_i2c_reset(void) i2c_set_bus_speed(speed); } -void mxs_i2c_setup_read(uint8_t chip, int len) +static void mxs_i2c_setup_read(uint8_t chip, int len) { struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; @@ -77,16 +64,17 @@ void mxs_i2c_setup_read(uint8_t chip, int len) writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set); } -void mxs_i2c_write(uchar chip, uint addr, int alen, +static int mxs_i2c_write(uchar chip, uint addr, int alen, uchar *buf, int blen, int stop) { struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; - uint32_t data; + uint32_t data, tmp; int i, remain, off; + int timeout = MXS_I2C_MAX_TIMEOUT; if ((alen > 4) || (alen == 0)) { debug("MXS I2C: Invalid address length\n"); - return; + return -EINVAL; } if (stop) @@ -119,9 +107,22 @@ void mxs_i2c_write(uchar chip, uint addr, int alen, writel(data >> remain, &i2c_regs->hw_i2c_data); writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set); + + while (--timeout) { + tmp = readl(&i2c_regs->hw_i2c_queuestat); + if (tmp & I2C_QUEUESTAT_WR_QUEUE_EMPTY) + break; + } + + if (!timeout) { + debug("MXS I2C: Failed transmitting data!\n"); + return -EINVAL; + } + + return 0; } -int mxs_i2c_wait_for_ack(void) +static int mxs_i2c_wait_for_ack(void) { struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; uint32_t tmp; @@ -163,10 +164,16 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) { struct mxs_i2c_regs *i2c_regs = (struct mxs_i2c_regs *)MXS_I2C0_BASE; uint32_t tmp = 0; + int timeout = MXS_I2C_MAX_TIMEOUT; int ret; int i; - mxs_i2c_write(chip, addr, alen, NULL, 0, 0); + ret = mxs_i2c_write(chip, addr, alen, NULL, 0, 0); + if (ret) { + debug("MXS I2C: Failed writing address\n"); + return ret; + } + ret = mxs_i2c_wait_for_ack(); if (ret) { debug("MXS I2C: Failed writing address\n"); @@ -182,9 +189,17 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) for (i = 0; i < len; i++) { if (!(i & 3)) { - while (readl(&i2c_regs->hw_i2c_queuestat) & - I2C_QUEUESTAT_RD_QUEUE_EMPTY) - ; + while (--timeout) { + tmp = readl(&i2c_regs->hw_i2c_queuestat); + if (!(tmp & I2C_QUEUESTAT_RD_QUEUE_EMPTY)) + break; + } + + if (!timeout) { + debug("MXS I2C: Failed receiving data!\n"); + return -ETIMEDOUT; + } + tmp = readl(&i2c_regs->hw_i2c_queuedata); } buffer[i] = tmp & 0xff; @@ -197,7 +212,12 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) { int ret; - mxs_i2c_write(chip, addr, alen, buffer, len, 1); + ret = mxs_i2c_write(chip, addr, alen, buffer, len, 1); + if (ret) { + debug("MXS I2C: Failed writing address\n"); + return ret; + } + ret = mxs_i2c_wait_for_ack(); if (ret) debug("MXS I2C: Failed writing address\n"); @@ -208,8 +228,9 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) int i2c_probe(uchar chip) { int ret; - mxs_i2c_write(chip, 0, 1, NULL, 0, 1); - ret = mxs_i2c_wait_for_ack(); + ret = mxs_i2c_write(chip, 0, 1, NULL, 0, 1); + if (!ret) + ret = mxs_i2c_wait_for_ack(); mxs_i2c_reset(); return ret; }