📄 via_i2c.c
字号:
/* * 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -