[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20080630154348.GF21835@fluff.org.uk>
Date: Mon, 30 Jun 2008 16:43:48 +0100
From: Ben Dooks <ben-linux@...ff.org>
To: JosephChan@....com.tw
Cc: linux-fbdev-devel@...ts.sourceforge.net,
linux-kernel@...r.kernel.org, akpm@...ux-foundation.org,
geert@...ux-m68k.org
Subject: Re: [PATCH 12/13] viafb: via_i2c.c, via_i2c.h, viamode.c, viamode.c
On Mon, Jun 30, 2008 at 03:51:19PM +0800, JosephChan@....com.tw wrote:
> via_i2c.c, via_i2c.h: Implement i2c specification.
> viamode.c, viamode.c: all support modes information.
>
>
> Signed-off-by: Joseph Chan <josephchan@....com.tw>
>
> diff -Nur a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
> --- a/drivers/video/via/via_i2c.c 1970-01-01 08:00:00.000000000 +0800
> +++ b/drivers/video/via/via_i2c.c 2008-06-30 08:53:33.000000000 +0800
> @@ -0,0 +1,377 @@
> +/*
> + * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
> + * Copyright 2001-2008 S3 Graphics, 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, or (at your option) any later version.
> +
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; 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 "global.h"
> +
> +/* i2c delay for microsecond*/
> +void viafb_delays(int count)
> +{
> + u8 data;
> + while (count--) {
> + /* delay 1 us */
> + data = inb(DELAYPORT);
> + data = inb(DELAYPORT);
> + data = inb(DELAYPORT);
> + data = inb(DELAYPORT);
> + data = inb(DELAYPORT);
> + }
> +
> +}
> +
> +/* Write I2C BUS SDA And SCL*/
> +static void i2cWriteSdaScl(u8 sda, u8 scl)
> +{
> + u8 data;
> + u16 port_addr;
> +
> + if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AMR) {
> +
> + data = ((scl << 1) | sda) << 4;
> + /* enable I2C port */
> + data = data | BIT0;
> +
> + port_addr = I2CPORT;
> + /* Write Register Value */
> + viafb_write_reg(I2CPORTINDEX, port_addr, data);
> + } else {
> + if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP) {
> + data = ((scl << 1) | sda) << 4;
> + /* enable GPIO write port */
> + data = data | (BIT6 + BIT7);
> + port_addr = GPIOPORT;
> + /* Write Register Value */
> + viafb_write_reg(GPIOPORTINDEX, port_addr, data);
> + }
> + }
> +}
> +
> +static void i2cReadSdaScl(u8 *pSda, u8 *pScl)
> +{
> + u8 data;
> + u16 port_addr;
> +
> + if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AMR) {
> + port_addr = I2CPORT;
> + data = viafb_read_reg(port_addr, I2CPORTINDEX);
> + *pSda = (data >> 2) & BIT0; /* get sda */
> + *pScl = (data >> 3) & BIT0; /* get scl */
> + } else {
> + if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP) {
> + port_addr = GPIOPORT;
> + data = viafb_read_reg(port_addr, GPIOPORTINDEX);
> + *pSda = (data >> 2) & BIT0; /* get sda */
> + *pScl = (data >> 3) & BIT0; /* get scl */
> + }
> + }
> +}
> +
> +static void i2cWriteSdaSclDelay(u8 sda, u8 scl)
> +{
> + i2cWriteSdaScl(sda, scl);
> + viafb_delays(16); /* Wait 16 uS */
> +}
> +
> +static void i2cStartSignal(void)
> +{
> + i2cWriteSdaSclDelay(1, 1);
> + i2cWriteSdaSclDelay(0, 1);
> + i2cWriteSdaSclDelay(0, 0);
> +}
> +
> +static void i2cStopSignal(void)
> +{
> + u8 data;
> + u16 port_addr;
> +
> + i2cWriteSdaSclDelay(0, 0);
> + i2cWriteSdaSclDelay(0, 1);
> + i2cWriteSdaSclDelay(1, 1);
> +
> + if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP) {
> + /* disable GPIO write port */
> + data = 0x3c;
> + port_addr = GPIOPORT;
> + /* Write Register Value */
> + viafb_write_reg(GPIOPORTINDEX, port_addr, data);
> + }
> + viafb_delays(2);
> +
> +}
> +
> +static void disableSdaGPIO(void)
> +{
> + u8 data;
> + u16 port_addr;
> +
> + if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP) {
> + port_addr = GPIOPORT;
> + data = viafb_read_reg(port_addr, GPIOPORTINDEX);
> + /* disable GPIO write port */
> + data = data & (~BIT6);
> + /* Write Register Value */
> + viafb_write_reg(GPIOPORTINDEX, port_addr, data);
> + }
> +}
> +
> +static void writeSclGPIO(u8 scl)
> +{
> + u8 data;
> + u16 port_addr;
> +
> + if (viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP) {
> + port_addr = GPIOPORT;
> + data = viafb_read_reg(port_addr, GPIOPORTINDEX);
> + data = data & (~BIT5);
> + /* write data to clock */
> + data = (data | (scl << 5)) & (~BIT6);
> + /* Write Register Value */
> + viafb_write_reg(GPIOPORTINDEX, port_addr, data);
> + }
> +}
> +
> +static int i2CWaitForSlave(void)
> +{
> + int time_out = 20000;
> + u8 sda, scl;
> +
> + while (time_out--) {
> + i2cReadSdaScl(&sda, &scl);
> + if (scl)
> + return OK; /* Successful stall */
> + viafb_delays(1); /* wait 1 uS */
> + }
> + return FAIL; /* Slave fail */
> +}
> +
> +static int i2cOutByte(u8 data)
> +{
> + u8 sda, scl;
> + u8 out_byte;
> + int bit_count = 8;
> + int status;
> +
> + out_byte = data;
> + while (bit_count--) {
> + sda = (out_byte >> 7) & 1; /* Load MSB */
> + out_byte = out_byte << 1; /* next bit. */
> + i2cWriteSdaSclDelay(sda, 0);
> + i2cWriteSdaSclDelay(sda, 1);
> +
> + status = i2CWaitForSlave();
> + if (status == FAIL)
> + return status;
> + i2cWriteSdaSclDelay(sda, 0);
> +
> + }
> +
> + if ((viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP)) {
> +
> + writeSclGPIO(0);
> + disableSdaGPIO();
> + viafb_delays(2);
> + writeSclGPIO(1);
> + viafb_delays(2);
> + i2cReadSdaScl(&sda, &scl);
> + writeSclGPIO(0);
> + viafb_delays(2);
> + if (sda == 0)
> + status = OK;
> + else
> + status = FAIL;
> + } else {
> + i2cWriteSdaSclDelay(1, 0);
> + i2cWriteSdaSclDelay(1, 1);
> + status = i2CWaitForSlave();
> + if (status == FAIL)
> + return status;
> +
> + i2cReadSdaScl(&sda, &scl);
> + if (sda == 0) {
> + i2cWriteSdaSclDelay(1, 0);
> + status = OK;
> + } else {
> +
> + i2cWriteSdaSclDelay(1, 0);
> + status = FAIL;
> + }
> + }
> + return status;
> +}
> +
> +static int i2cInputByte(u8 *pInByte, int ack)
> +{
> +
> + int bit_count = 8;
> + u8 sda, scl;
> + u8 data = 0;
> + int status;
> +
> + disableSdaGPIO();
> +
> + while (bit_count--) {
> + if ((viaparinfo->chip_info->chip_on_slot == PORT_ON_AGP)) {
> +
> + writeSclGPIO(1);
> + viafb_delays(2);
> + status = i2CWaitForSlave();
> + if (status == FAIL)
> + return FAIL;
> + i2cReadSdaScl(&sda, &scl);
> + data = data << 1;
> + data |= sda;
> + writeSclGPIO(0);
> + viafb_delays(2);
> +
> + } else {
> + i2cWriteSdaSclDelay(1, 1);
> + status = i2CWaitForSlave();
> + if (status == FAIL)
> + return FAIL;
> + i2cReadSdaScl(&sda, &scl);
> + data = data << 1;
> + data |= sda;
> + i2cWriteSdaSclDelay(1, 0);
> + }
> + }
> + *pInByte = data;
> +
> + if (ack) {
> + i2cWriteSdaSclDelay(0, 0);
> + i2cWriteSdaSclDelay(0, 1);
> + status = i2CWaitForSlave();
> + if (status == FAIL)
> + return status;
> + i2cWriteSdaSclDelay(0, 0);
> + } else {
> + i2cWriteSdaSclDelay(1, 0);
> + i2cWriteSdaSclDelay(1, 1);
> + status = i2CWaitForSlave();
> + if (status == FAIL)
> + return status;
> + }
> + i2cWriteSdaSclDelay(1, 0);
> +
> + return OK;
> +}
> +
> +int viafb_i2cReadByte(u8 slave_addr, u8 index, u8 *pData)
> +{
> +
> + int status;
> +
> + i2cStartSignal();
> +
> + status = i2cOutByte(slave_addr);
> + if (status == FAIL) {
> + i2cStopSignal();
> + return FAIL;
> + }
> + status = i2cOutByte(index);
> +
> + if (status == FAIL) {
> + i2cStopSignal();
> + return FAIL;
> + }
> +
> + i2cStartSignal();
> + status = i2cOutByte(slave_addr | BIT0);
> + if (status == FAIL) {
> + i2cStopSignal();
> + return FAIL;
> + }
> + status = i2cInputByte(pData, 0);
> + if (status == FAIL) {
> + i2cStopSignal();
> + return FAIL;
> + }
> +
> + i2cStopSignal();
> + return OK;
> +}
> +
> +int viafb_i2cWriteByte(u8 slave_addr, u8 index, u8 data)
> +{
> +
> + int status;
> +
> + i2cStartSignal();
> + status = i2cOutByte(slave_addr);
> + if (status == FAIL) {
> + i2cStopSignal();
> + return FAIL;
> + }
> + status = i2cOutByte(index);
> + if (status == FAIL) {
> + i2cStopSignal();
> + return FAIL;
> + }
> + status = i2cOutByte(data);
> + if (status == FAIL) {
> + i2cStopSignal();
> + return FAIL;
> + }
> + i2cStopSignal();
> + return OK;
> +}
> +
> +int viafb_i2cReadBytes(u8 slave_addr, u8 index, u8 *buff, int buff_len)
> +{
> +
> + int status, i;
> +
> + i2cStartSignal();
> +
> + status = i2cOutByte(slave_addr);
> + if (status == FAIL) {
> + i2cStopSignal();
> + return FAIL;
> + }
> +
> + status = i2cOutByte(index);
> + if (status == FAIL) {
> + i2cStopSignal();
> + return FAIL;
> + }
> +
> + i2cStartSignal();
> + status = i2cOutByte(slave_addr | BIT0);
> + if (status == FAIL) {
> + i2cStopSignal();
> + return FAIL;
> + }
> +
> + for (i = 0; i < buff_len; i++) {
> + if (buff_len == 1)
> + status = i2cInputByte(buff, 0); /* send NACK */
> + else if (i < buff_len - 1)
> + status = i2cInputByte(buff, 1); /* send ACK */
> + else
> + status = i2cInputByte(buff, 0); /* send NACK */
> + if (status == FAIL) {
> + i2cStopSignal();
> + return (FAIL);
> + }
> + buff++;
> + }
> +
> + i2cStopSignal();
> + return OK;
> +}
This looks like an attempt at re-doing the already extant i2c gpio
algorithm. Either export via gpiolib and use the i2c-gpio adapter or
use the i2c bit-banging algorithm.
--
Ben
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists