lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ