[PATCH] sunxi:i2c: unify headers with name inification

104 views
Skip to first unread message

wing...@gmail.com

unread,
Mar 30, 2013, 2:29:02 PM3/30/13
to d...@linux-sunxi.org, Alexsey Shestacov
From: Alexsey Shestacov <wing...@gmail.com>

sun4i-i2c and sun5i-i2c now will have same sunxi-i2c name,
patch removes many #ifdef stuff for it
---
arch/arm/mach-sun4i/include/mach/i2c.h | 196 -------------------------------
arch/arm/mach-sun5i/include/mach/i2c.h | 200 --------------------------------
arch/arm/plat-sunxi/clocksrc.c | 2 +-
arch/arm/plat-sunxi/devices.c | 38 ++----
arch/arm/plat-sunxi/include/plat/i2c.h | 196 +++++++++++++++++++++++++++++++
drivers/i2c/busses/i2c-sunxi.c | 28 +----
6 files changed, 210 insertions(+), 450 deletions(-)
delete mode 100644 arch/arm/mach-sun4i/include/mach/i2c.h
delete mode 100644 arch/arm/mach-sun5i/include/mach/i2c.h
create mode 100644 arch/arm/plat-sunxi/include/plat/i2c.h

diff --git a/arch/arm/mach-sun4i/include/mach/i2c.h b/arch/arm/mach-sun4i/include/mach/i2c.h
deleted file mode 100644
index 6eae7af..0000000
--- a/arch/arm/mach-sun4i/include/mach/i2c.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * arch/arm/mach-sun4i/include/mach/i2c.h
- *
- * (C) Copyright 2007-2012
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- * Tom Cubie <tang...@allwinnertech.com>
- * Victor Wei <weiz...@allwinnertech.com>
- *
- * 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
- */
-
-#ifndef _SUN4I_I2C_PRIVATE_H_
-#define _SUN4I_I2C_PRIVATE_H_
-
-#define TWI_MODULE_NUM (3)
-
-/* TWI Register Offset */
-#define TWI_ADDR_REG (0x00) /* 31:8bit reserved,7-1bit for slave addr,0 bit for GCE */
-#define TWI_XADDR_REG (0x04) /* 31:8bit reserved,7-0bit for second addr in 10bit addr */
-#define TWI_DATA_REG (0x08) /* 31:8bit reserved, 7-0bit send or receive data byte */
-#define TWI_CTL_REG (0x0C) /* INT_EN,BUS_EN,M_STA,INT_FLAG,A_ACK */
-#define TWI_STAT_REG (0x10) /* 28 interrupt types + 0xF8 normal type = 29 */
-#define TWI_CLK_REG (0x14) /* 31:7bit reserved,6-3bit,CLK_M,2-0bit CLK_N */
-#define TWI_SRST_REG (0x18) /* 31:1bit reserved;0bit,write 1 to clear 0. */
-#define TWI_EFR_REG (0x1C) /* 31:2bit reserved,1:0 bit data byte follow read comand */
-#define TWI_LCR_REG (0x20) /* 31:6bits reserved 5:0bit for sda&scl control*/
-
-/* TWI address register */
-#define TWI_GCE_EN (0x1 <<0) /* general call address enable for slave mode */
-#define TWI_ADDR_MASK (0x7f<<1) /* 7:1bits */
-/* 31:8bits reserved */
-
-
-/* TWI extend address register */
-#define TWI_XADDR_MASK (0xff) /* 7:0bits for extend slave address */
-/* 31:8bits reserved */
-
-
-/* TWI Data register default is 0x0000_0000 */
-#define TWI_DATA_MASK (0xff) /* 7:0bits for send or received */
-
-/* TWI Control Register Bit Fields & Masks, default value: 0x0000_0000*/
-/* 1:0 bits reserved */
-#define TWI_CTL_ACK (0x1<<2) /* set 1 to send A_ACK,then low level on SDA */
-#define TWI_CTL_INTFLG (0x1<<3) /* INT_FLAG,interrupt status flag: set '1' when interrupt coming */
-#define TWI_CTL_STP (0x1<<4) /* M_STP,Automatic clear 0 */
-#define TWI_CTL_STA (0x1<<5) /* M_STA,atutomatic clear 0 */
-#define TWI_CTL_BUSEN (0x1<<6) /* BUS_EN, master mode should be set 1.*/
-#define TWI_CTL_INTEN (0x1<<7) /* INT_EN */
-/* 31:8 bit reserved */
-
-
-/* TWI Clock Register Bit Fields & Masks,default value:0x0000_0000 */
-/*
-Fin is APB CLOCK INPUT;
-Fsample = F0 = Fin/2^CLK_N;
- F1 = F0/(CLK_M+1);
-
-Foscl = F1/10 = Fin/(2^CLK_N * (CLK_M+1)*10);
-Foscl is clock SCL;standard mode:100KHz or fast mode:400KHz
-*/
-#define TWI_CLK_DIV_M (0xF<<3) /* 6:3bit */
-#define TWI_CLK_DIV_N (0x7<<0) /* 2:0bit */
-
-
-/* TWI Soft Reset Register Bit Fields & Masks */
-#define TWI_SRST_SRST (0x1<<0) /* write 1 to clear 0, when complete soft reset clear 0 */
-
-
-/* TWI Enhance Feature Register Bit Fields & Masks */
-/* default -- 0x0 */
-#define TWI_EFR_MASK (0x3<<0)/* 00:no,01: 1byte, 10:2 bytes, 11: 3bytes */
-#define TWI_EFR_WARC_0 (0x0<<0)
-#define TWI_EFR_WARC_1 (0x1<<0)
-#define TWI_EFR_WARC_2 (0x2<<0)
-#define TWI_EFR_WARC_3 (0x3<<0)
-
-
-/* twi line control register -default value: 0x0000_003a */
-#define TWI_LCR_SDA_EN (0x01<<0) /* SDA line state control enable ,1:enable;0:disable */
-#define TWI_LCR_SDA_CTL (0x01<<1) /* SDA line state control bit, 1:high level;0:low level */
-#define TWI_LCR_SCL_EN (0x01<<2) /* SCL line state control enable ,1:enable;0:disable */
-#define TWI_LCR_SCL_CTL (0x01<<3) /* SCL line state control bit, 1:high level;0:low level */
-#define TWI_LCR_SDA_STATE_MASK (0x01<<4) /* current state of SDA,readonly bit */
-#define TWI_LCR_SCL_STATE_MASK (0x01<<5) /* current state of SCL,readonly bit */
-/* 31:6bits reserved */
-#define TWI_LCR_IDLE_STATUS (0x3a)
-
-
-/* TWI Status Register Bit Fields & Masks */
-#define TWI_STAT_MASK (0xff)
-/* 7:0 bits use only,default is 0xF8 */
-#define TWI_STAT_BUS_ERR (0x00) /* BUS ERROR */
-/* Master mode use only */
-#define TWI_STAT_TX_STA (0x08) /* START condition transmitted */
-#define TWI_STAT_TX_RESTA (0x10) /* Repeated START condition transmitted */
-#define TWI_STAT_TX_AW_ACK (0x18) /* Address+Write bit transmitted, ACK received */
-#define TWI_STAT_TX_AW_NAK (0x20) /* Address+Write bit transmitted, ACK not received */
-#define TWI_STAT_TXD_ACK (0x28) /* data byte transmitted in master mode,ack received */
-#define TWI_STAT_TXD_NAK (0x30) /* data byte transmitted in master mode ,ack not received */
-#define TWI_STAT_ARBLOST (0x38) /* arbitration lost in address or data byte */
-#define TWI_STAT_TX_AR_ACK (0x40) /* Address+Read bit transmitted, ACK received */
-#define TWI_STAT_TX_AR_NAK (0x48) /* Address+Read bit transmitted, ACK not received */
-#define TWI_STAT_RXD_ACK (0x50) /* data byte received in master mode ,ack transmitted */
-#define TWI_STAT_RXD_NAK (0x58) /* date byte received in master mode,not ack transmitted */
-/* Slave mode use only */
-#define TWI_STAT_RXWS_ACK (0x60) /* Slave address+Write bit received, ACK transmitted */
-#define TWI_STAT_ARBLOST_RXWS_ACK (0x68)
-#define TWI_STAT_RXGCAS_ACK (0x70) /* General Call address received, ACK transmitted */
-#define TWI_STAT_ARBLOST_RXGCAS_ACK (0x78)
-#define TWI_STAT_RXDS_ACK (0x80)
-#define TWI_STAT_RXDS_NAK (0x88)
-#define TWI_STAT_RXDGCAS_ACK (0x90)
-#define TWI_STAT_RXDGCAS_NAK (0x98)
-#define TWI_STAT_RXSTPS_RXRESTAS (0xA0)
-#define TWI_STAT_RXRS_ACK (0xA8)
-
-#define TWI_STAT_ARBLOST_SLAR_ACK (0xB0)
-
-/* 10bit Address, second part of address */
-#define TWI_STAT_TX_SAW_ACK (0xD0) /* Second Address byte+Write bit transmitted,ACK received */
-#define TWI_STAT_TX_SAW_NAK (0xD8) /* Second Address byte+Write bit transmitted,ACK not received */
-
-#define TWI_STAT_IDLE (0xF8) /* No relevant status infomation,INT_FLAG = 0 */
-
-
-/* status or interrupt source */
-/*------------------------------------------------------------------------------
-* Code Status
-* 00h Bus error
-* 08h START condition transmitted
-* 10h Repeated START condition transmitted
-* 18h Address + Write bit transmitted, ACK received
-* 20h Address + Write bit transmitted, ACK not received
-* 28h Data byte transmitted in master mode, ACK received
-* 30h Data byte transmitted in master mode, ACK not received
-* 38h Arbitration lost in address or data byte
-* 40h Address + Read bit transmitted, ACK received
-* 48h Address + Read bit transmitted, ACK not received
-* 50h Data byte received in master mode, ACK transmitted
-* 58h Data byte received in master mode, not ACK transmitted
-* 60h Slave address + Write bit received, ACK transmitted
-* 68h Arbitration lost in address as master, slave address + Write bit received, ACK transmitted
-* 70h General Call address received, ACK transmitted
-* 78h Arbitration lost in address as master, General Call address received, ACK transmitted
-* 80h Data byte received after slave address received, ACK transmitted
-* 88h Data byte received after slave address received, not ACK transmitted
-* 90h Data byte received after General Call received, ACK transmitted
-* 98h Data byte received after General Call received, not ACK transmitted
-* A0h STOP or repeated START condition received in slave mode
-* A8h Slave address + Read bit received, ACK transmitted
-* B0h Arbitration lost in address as master, slave address + Read bit received, ACK transmitted
-* B8h Data byte transmitted in slave mode, ACK received
-* C0h Data byte transmitted in slave mode, ACK not received
-* C8h Last byte transmitted in slave mode, ACK received
-* D0h Second Address byte + Write bit transmitted, ACK received
-* D8h Second Address byte + Write bit transmitted, ACK not received
-* F8h No relevant status information or no interrupt
-*-----------------------------------------------------------------------------*/
-
-/* TWI mode select */
-#define TWI_MASTER_MODE (1)
-#define TWI_SLAVE_MODE (0) /* seldom use */
-
-#define AW_TWI_ADDR_SIZE 0x3ff
-
-#define TWI0_BASE_ADDR_START (0x01C2ac00)
-#define TWI0_BASE_ADDR_END (TWI0_BASE_ADDR_START + AW_TWI_ADDR_SIZE)
-#define TWI1_BASE_ADDR_START (0x01C2b000)
-#define TWI1_BASE_ADDR_END (TWI1_BASE_ADDR_START + AW_TWI_ADDR_SIZE)
-#define TWI2_BASE_ADDR_START (0x01C2b400)
-#define TWI2_BASE_ADDR_END (TWI2_BASE_ADDR_START + AW_TWI_ADDR_SIZE)
-
-#define I2C0_TRANSFER_SPEED (400000)
-#define I2C1_TRANSFER_SPEED (200000)
-#define I2C2_TRANSFER_SPEED (200000)
-
-struct sun4i_i2c_platform_data {
- int bus_num;
- unsigned int frequency;
-};
-
-#endif
diff --git a/arch/arm/mach-sun5i/include/mach/i2c.h b/arch/arm/mach-sun5i/include/mach/i2c.h
deleted file mode 100644
index 3dac290..0000000
--- a/arch/arm/mach-sun5i/include/mach/i2c.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * arch/arm/mach-sun5i/include/mach/i2c.h
- *
- * (C) Copyright 2007-2012
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- *
- * Tom Cubie <tang...@allwinnertech.com>
- * Victor Wei <weiz...@allwinnertech.com>
- *
- * SUN5I two wire interface reg definition
- *
- * 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
- */
-
-
-#ifndef _SUN5I_I2C_PRIVATE_H_
-#define _SUN5I_I2C_PRIVATE_H_
-
-#define TWI_MODULE_NUM (3)
-
-/* TWI Register Offset */
-#define TWI_ADDR_REG (0x00) /* 31:8bit reserved,7-1bit for slave addr,0 bit for GCE */
-#define TWI_XADDR_REG (0x04) /* 31:8bit reserved,7-0bit for second addr in 10bit addr */
-#define TWI_DATA_REG (0x08) /* 31:8bit reserved, 7-0bit send or receive data byte */
-#define TWI_CTL_REG (0x0C) /* INT_EN,BUS_EN,M_STA,INT_FLAG,A_ACK */
-#define TWI_STAT_REG (0x10) /* 28 interrupt types + 0xF8 normal type = 29 */
-#define TWI_CLK_REG (0x14) /* 31:7bit reserved,6-3bit,CLK_M,2-0bit CLK_N */
-#define TWI_SRST_REG (0x18) /* 31:1bit reserved;0bit,write 1 to clear 0. */
-#define TWI_EFR_REG (0x1C) /* 31:2bit reserved,1:0 bit data byte follow read comand */
-#define TWI_LCR_REG (0x20) /* 31:6bits reserved 5:0bit for sda&scl control*/
-
-/* TWI address register */
-#define TWI_GCE_EN (0x1 <<0) /* general call address enable for slave mode */
-#define TWI_ADDR_MASK (0x7f<<1) /* 7:1bits */
-/* 31:8bits reserved */
-
-
-/* TWI extend address register */
-#define TWI_XADDR_MASK (0xff) /* 7:0bits for extend slave address */
-/* 31:8bits reserved */
-
-
-/* TWI Data register default is 0x0000_0000 */
-#define TWI_DATA_MASK (0xff) /* 7:0bits for send or received */
-
-/* TWI Control Register Bit Fields & Masks, default value: 0x0000_0000*/
-/* 1:0 bits reserved */
-#define TWI_CTL_ACK (0x1<<2) /* set 1 to send A_ACK,then low level on SDA */
-#define TWI_CTL_INTFLG (0x1<<3) /* INT_FLAG,interrupt status flag: set '1' when interrupt coming */
-#define TWI_CTL_STP (0x1<<4) /* M_STP,Automatic clear 0 */
-#define TWI_CTL_STA (0x1<<5) /* M_STA,atutomatic clear 0 */
-#define TWI_CTL_BUSEN (0x1<<6) /* BUS_EN, master mode should be set 1.*/
-#define TWI_CTL_INTEN (0x1<<7) /* INT_EN */
-/* 31:8 bit reserved */
-
-
-/* TWI Clock Register Bit Fields & Masks,default value:0x0000_0000 */
-/*
-Fin is APB CLOCK INPUT;
-Fsample = F0 = Fin/2^CLK_N;
- F1 = F0/(CLK_M+1);
-
-Foscl = F1/10 = Fin/(2^CLK_N * (CLK_M+1)*10);
-Foscl is clock SCL;standard mode:100KHz or fast mode:400KHz
-*/
-#define TWI_CLK_DIV_M (0xF<<3) /* 6:3bit */
-#define TWI_CLK_DIV_N (0x7<<0) /* 2:0bit */
-
-
-/* TWI Soft Reset Register Bit Fields & Masks */
-#define TWI_SRST_SRST (0x1<<0) /* write 1 to clear 0, when complete soft reset clear 0 */
-
-
-/* TWI Enhance Feature Register Bit Fields & Masks */
-/* default -- 0x0 */
-#define TWI_EFR_MASK (0x3<<0)/* 00:no,01: 1byte, 10:2 bytes, 11: 3bytes */
-#define TWI_EFR_WARC_0 (0x0<<0)
-#define TWI_EFR_WARC_1 (0x1<<0)
-#define TWI_EFR_WARC_2 (0x2<<0)
-#define TWI_EFR_WARC_3 (0x3<<0)
-
-
-/* twi line control register -default value: 0x0000_003a */
-#define TWI_LCR_SDA_EN (0x01<<0) /* SDA line state control enable ,1:enable;0:disable */
-#define TWI_LCR_SDA_CTL (0x01<<1) /* SDA line state control bit, 1:high level;0:low level */
-#define TWI_LCR_SCL_EN (0x01<<2) /* SCL line state control enable ,1:enable;0:disable */
-#define TWI_LCR_SCL_CTL (0x01<<3) /* SCL line state control bit, 1:high level;0:low level */
-#define TWI_LCR_SDA_STATE_MASK (0x01<<4) /* current state of SDA,readonly bit */
-#define TWI_LCR_SCL_STATE_MASK (0x01<<5) /* current state of SCL,readonly bit */
-/* 31:6bits reserved */
-#define TWI_LCR_IDLE_STATUS (0x3a)
-
-
-/* TWI Status Register Bit Fields & Masks */
-#define TWI_STAT_MASK (0xff)
-/* 7:0 bits use only,default is 0xF8 */
-#define TWI_STAT_BUS_ERR (0x00) /* BUS ERROR */
-/* Master mode use only */
-#define TWI_STAT_TX_STA (0x08) /* START condition transmitted */
-#define TWI_STAT_TX_RESTA (0x10) /* Repeated START condition transmitted */
-#define TWI_STAT_TX_AW_ACK (0x18) /* Address+Write bit transmitted, ACK received */
-#define TWI_STAT_TX_AW_NAK (0x20) /* Address+Write bit transmitted, ACK not received */
-#define TWI_STAT_TXD_ACK (0x28) /* data byte transmitted in master mode,ack received */
-#define TWI_STAT_TXD_NAK (0x30) /* data byte transmitted in master mode ,ack not received */
-#define TWI_STAT_ARBLOST (0x38) /* arbitration lost in address or data byte */
-#define TWI_STAT_TX_AR_ACK (0x40) /* Address+Read bit transmitted, ACK received */
-#define TWI_STAT_TX_AR_NAK (0x48) /* Address+Read bit transmitted, ACK not received */
-#define TWI_STAT_RXD_ACK (0x50) /* data byte received in master mode ,ack transmitted */
-#define TWI_STAT_RXD_NAK (0x58) /* date byte received in master mode,not ack transmitted */
-/* Slave mode use only */
-#define TWI_STAT_RXWS_ACK (0x60) /* Slave address+Write bit received, ACK transmitted */
-#define TWI_STAT_ARBLOST_RXWS_ACK (0x68)
-#define TWI_STAT_RXGCAS_ACK (0x70) /* General Call address received, ACK transmitted */
-#define TWI_STAT_ARBLOST_RXGCAS_ACK (0x78)
-#define TWI_STAT_RXDS_ACK (0x80)
-#define TWI_STAT_RXDS_NAK (0x88)
-#define TWI_STAT_RXDGCAS_ACK (0x90)
-#define TWI_STAT_RXDGCAS_NAK (0x98)
-#define TWI_STAT_RXSTPS_RXRESTAS (0xA0)
-#define TWI_STAT_RXRS_ACK (0xA8)
-
-#define TWI_STAT_ARBLOST_SLAR_ACK (0xB0)
-
-/* 10bit Address, second part of address */
-#define TWI_STAT_TX_SAW_ACK (0xD0) /* Second Address byte+Write bit transmitted,ACK received */
-#define TWI_STAT_TX_SAW_NAK (0xD8) /* Second Address byte+Write bit transmitted,ACK not received */
-
-#define TWI_STAT_IDLE (0xF8) /* No relevant status infomation,INT_FLAG = 0 */
-
-
-/* status or interrupt source */
-/*------------------------------------------------------------------------------
-* Code Status
-* 00h Bus error
-* 08h START condition transmitted
-* 10h Repeated START condition transmitted
-* 18h Address + Write bit transmitted, ACK received
-* 20h Address + Write bit transmitted, ACK not received
-* 28h Data byte transmitted in master mode, ACK received
-* 30h Data byte transmitted in master mode, ACK not received
-* 38h Arbitration lost in address or data byte
-* 40h Address + Read bit transmitted, ACK received
-* 48h Address + Read bit transmitted, ACK not received
-* 50h Data byte received in master mode, ACK transmitted
-* 58h Data byte received in master mode, not ACK transmitted
-* 60h Slave address + Write bit received, ACK transmitted
-* 68h Arbitration lost in address as master, slave address + Write bit received, ACK transmitted
-* 70h General Call address received, ACK transmitted
-* 78h Arbitration lost in address as master, General Call address received, ACK transmitted
-* 80h Data byte received after slave address received, ACK transmitted
-* 88h Data byte received after slave address received, not ACK transmitted
-* 90h Data byte received after General Call received, ACK transmitted
-* 98h Data byte received after General Call received, not ACK transmitted
-* A0h STOP or repeated START condition received in slave mode
-* A8h Slave address + Read bit received, ACK transmitted
-* B0h Arbitration lost in address as master, slave address + Read bit received, ACK transmitted
-* B8h Data byte transmitted in slave mode, ACK received
-* C0h Data byte transmitted in slave mode, ACK not received
-* C8h Last byte transmitted in slave mode, ACK received
-* D0h Second Address byte + Write bit transmitted, ACK received
-* D8h Second Address byte + Write bit transmitted, ACK not received
-* F8h No relevant status information or no interrupt
-*-----------------------------------------------------------------------------*/
-
-/* TWI mode select */
-#define TWI_MASTER_MODE (1)
-#define TWI_SLAVE_MODE (0) /* seldom use */
-
-#define AW_TWI_ADDR_SIZE 0x3ff
-
-#define TWI0_BASE_ADDR_START (0x01C2ac00)
-#define TWI0_BASE_ADDR_END (TWI0_BASE_ADDR_START + AW_TWI_ADDR_SIZE)
-#define TWI1_BASE_ADDR_START (0x01C2b000)
-#define TWI1_BASE_ADDR_END (TWI1_BASE_ADDR_START + AW_TWI_ADDR_SIZE)
-#define TWI2_BASE_ADDR_START (0x01C2b400)
-#define TWI2_BASE_ADDR_END (TWI2_BASE_ADDR_START + AW_TWI_ADDR_SIZE)
-
-#define I2C0_TRANSFER_SPEED (400000)
-#define I2C1_TRANSFER_SPEED (200000)
-#define I2C2_TRANSFER_SPEED (200000)
-
-struct sun5i_i2c_platform_data {
- int bus_num;
- unsigned int frequency;
-};
-
-#endif
diff --git a/arch/arm/plat-sunxi/clocksrc.c b/arch/arm/plat-sunxi/clocksrc.c
index 6dcfff9..42f23f5 100644
--- a/arch/arm/plat-sunxi/clocksrc.c
+++ b/arch/arm/plat-sunxi/clocksrc.c
@@ -118,7 +118,7 @@ static cycle_t aw_clksrc_read(struct clocksource *cs)

/* latch 64bit counter and wait ready for read */
TMR_REG_CNT64_CTL |= (1<<1);
- while(TMR_REG_CNT64_CTL & (1<<1));
+ // while(TMR_REG_CNT64_CTL & (1<<1));

/* read the 64bits counter */
lower = TMR_REG_CNT64_LO;
diff --git a/arch/arm/plat-sunxi/devices.c b/arch/arm/plat-sunxi/devices.c
index 03fc080..16b86b9 100644
--- a/arch/arm/plat-sunxi/devices.c
+++ b/arch/arm/plat-sunxi/devices.c
@@ -37,7 +37,7 @@
#include <asm/setup.h>
#include <asm/pmu.h>
#include <mach/hardware.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>

#if 0
/* uart */
@@ -86,11 +86,7 @@ struct platform_device sw_pdev_nand =
};

/* twi0 */
-#if defined CONFIG_ARCH_SUN4I
-static struct sun4i_i2c_platform_data sunxi_twi0_pdata[] = {
-#elif defined CONFIG_ARCH_SUN5I
-static struct sun5i_i2c_platform_data sunxi_twi0_pdata[] = {
-#endif
+static struct sunxi_i2c_platform_data sunxi_twi0_pdata[] = {
{
.bus_num = 0,
.frequency = I2C0_TRANSFER_SPEED,
@@ -110,11 +106,7 @@ static struct resource sunxi_twi0_resources[] = {
};

struct platform_device sunxi_twi0_device = {
-#if defined CONFIG_ARCH_SUN4I
- .name = "sun4i-i2c",
-#elif defined CONFIG_ARCH_SUN5I
- .name = "sun5i-i2c",
-#endif
+ .name = "sunxi-i2c",
.id = 0,
.resource = sunxi_twi0_resources,
.num_resources = ARRAY_SIZE(sunxi_twi0_resources),
@@ -124,11 +116,7 @@ struct platform_device sunxi_twi0_device = {
};

/* twi1 */
-#if defined CONFIG_ARCH_SUN4I
-static struct sun4i_i2c_platform_data sunxi_twi1_pdata[] = {
-#elif defined CONFIG_ARCH_SUN5I
-static struct sun5i_i2c_platform_data sunxi_twi1_pdata[] = {
-#endif
+static struct sunxi_i2c_platform_data sunxi_twi1_pdata[] = {
{
.bus_num = 1,
.frequency = I2C1_TRANSFER_SPEED,
@@ -148,11 +136,7 @@ static struct resource sunxi_twi1_resources[] = {
};

struct platform_device sunxi_twi1_device = {
-#if defined CONFIG_ARCH_SUN4I
- .name = "sun4i-i2c",
-#elif defined CONFIG_ARCH_SUN5I
- .name = "sun5i-i2c",
-#endif
+ .name = "sunxi-i2c",
.id = 1,
.resource = sunxi_twi1_resources,
.num_resources = ARRAY_SIZE(sunxi_twi1_resources),
@@ -162,11 +146,7 @@ struct platform_device sunxi_twi1_device = {
};

/* twi2 */
-#if defined CONFIG_ARCH_SUN4I
-static struct sun4i_i2c_platform_data sunxi_twi2_pdata[] = {
-#elif defined CONFIG_ARCH_SUN5I
-static struct sun5i_i2c_platform_data sunxi_twi2_pdata[] = {
-#endif
+static struct sunxi_i2c_platform_data sunxi_twi2_pdata[] = {
{
.bus_num = 2,
.frequency = I2C2_TRANSFER_SPEED,
@@ -186,11 +166,7 @@ static struct resource sunxi_twi2_resources[] = {
};

struct platform_device sunxi_twi2_device = {
-#if defined CONFIG_ARCH_SUN4I
- .name = "sun4i-i2c",
-#elif defined CONFIG_ARCH_SUN5I
- .name = "sun5i-i2c",
-#endif
+ .name = "sunxi-i2c",
.id = 2,
.resource = sunxi_twi2_resources,
.num_resources = ARRAY_SIZE(sunxi_twi2_resources),
diff --git a/arch/arm/plat-sunxi/include/plat/i2c.h b/arch/arm/plat-sunxi/include/plat/i2c.h
new file mode 100644
index 0000000..d56b017
--- /dev/null
+++ b/arch/arm/plat-sunxi/include/plat/i2c.h
@@ -0,0 +1,196 @@
+/*
+ * arch/arm/mach-sunxi/include/plat/i2c.h
+ *
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tang...@allwinnertech.com>
+ * Victor Wei <weiz...@allwinnertech.com>
+ *
+ * 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
+ */
+
+#ifndef _SUNXI_I2C_PRIVATE_H_
+#define _SUNXI_I2C_PRIVATE_H_
+
+#define TWI_MODULE_NUM (3)
+
+/* TWI Register Offset */
+#define TWI_ADDR_REG (0x00) /* 31:8bit reserved,7-1bit for slave addr,0 bit for GCE */
+#define TWI_XADDR_REG (0x04) /* 31:8bit reserved,7-0bit for second addr in 10bit addr */
+#define TWI_DATA_REG (0x08) /* 31:8bit reserved, 7-0bit send or receive data byte */
+#define TWI_CTL_REG (0x0C) /* INT_EN,BUS_EN,M_STA,INT_FLAG,A_ACK */
+#define TWI_STAT_REG (0x10) /* 28 interrupt types + 0xF8 normal type = 29 */
+#define TWI_CLK_REG (0x14) /* 31:7bit reserved,6-3bit,CLK_M,2-0bit CLK_N */
+#define TWI_SRST_REG (0x18) /* 31:1bit reserved;0bit,write 1 to clear 0. */
+#define TWI_EFR_REG (0x1C) /* 31:2bit reserved,1:0 bit data byte follow read comand */
+#define TWI_LCR_REG (0x20) /* 31:6bits reserved 5:0bit for sda&scl control*/
+
+/* TWI address register */
+#define TWI_GCE_EN (0x1 <<0) /* general call address enable for slave mode */
+#define TWI_ADDR_MASK (0x7f<<1) /* 7:1bits */
+/* 31:8bits reserved */
+
+
+/* TWI extend address register */
+#define TWI_XADDR_MASK (0xff) /* 7:0bits for extend slave address */
+/* 31:8bits reserved */
+
+
+/* TWI Data register default is 0x0000_0000 */
+#define TWI_DATA_MASK (0xff) /* 7:0bits for send or received */
+
+/* TWI Control Register Bit Fields & Masks, default value: 0x0000_0000*/
+/* 1:0 bits reserved */
+#define TWI_CTL_ACK (0x1<<2) /* set 1 to send A_ACK,then low level on SDA */
+#define TWI_CTL_INTFLG (0x1<<3) /* INT_FLAG,interrupt status flag: set '1' when interrupt coming */
+#define TWI_CTL_STP (0x1<<4) /* M_STP,Automatic clear 0 */
+#define TWI_CTL_STA (0x1<<5) /* M_STA,atutomatic clear 0 */
+#define TWI_CTL_BUSEN (0x1<<6) /* BUS_EN, master mode should be set 1.*/
+#define TWI_CTL_INTEN (0x1<<7) /* INT_EN */
+/* 31:8 bit reserved */
+
+
+/* TWI Clock Register Bit Fields & Masks,default value:0x0000_0000 */
+/*
+Fin is APB CLOCK INPUT;
+Fsample = F0 = Fin/2^CLK_N;
+ F1 = F0/(CLK_M+1);
+
+Foscl = F1/10 = Fin/(2^CLK_N * (CLK_M+1)*10);
+Foscl is clock SCL;standard mode:100KHz or fast mode:400KHz
+*/
+#define TWI_CLK_DIV_M (0xF<<3) /* 6:3bit */
+#define TWI_CLK_DIV_N (0x7<<0) /* 2:0bit */
+
+
+/* TWI Soft Reset Register Bit Fields & Masks */
+#define TWI_SRST_SRST (0x1<<0) /* write 1 to clear 0, when complete soft reset clear 0 */
+
+
+/* TWI Enhance Feature Register Bit Fields & Masks */
+/* default -- 0x0 */
+#define TWI_EFR_MASK (0x3<<0)/* 00:no,01: 1byte, 10:2 bytes, 11: 3bytes */
+#define TWI_EFR_WARC_0 (0x0<<0)
+#define TWI_EFR_WARC_1 (0x1<<0)
+#define TWI_EFR_WARC_2 (0x2<<0)
+#define TWI_EFR_WARC_3 (0x3<<0)
+
+
+/* twi line control register -default value: 0x0000_003a */
+#define TWI_LCR_SDA_EN (0x01<<0) /* SDA line state control enable ,1:enable;0:disable */
+#define TWI_LCR_SDA_CTL (0x01<<1) /* SDA line state control bit, 1:high level;0:low level */
+#define TWI_LCR_SCL_EN (0x01<<2) /* SCL line state control enable ,1:enable;0:disable */
+#define TWI_LCR_SCL_CTL (0x01<<3) /* SCL line state control bit, 1:high level;0:low level */
+#define TWI_LCR_SDA_STATE_MASK (0x01<<4) /* current state of SDA,readonly bit */
+#define TWI_LCR_SCL_STATE_MASK (0x01<<5) /* current state of SCL,readonly bit */
+/* 31:6bits reserved */
+#define TWI_LCR_IDLE_STATUS (0x3a)
+
+
+/* TWI Status Register Bit Fields & Masks */
+#define TWI_STAT_MASK (0xff)
+/* 7:0 bits use only,default is 0xF8 */
+#define TWI_STAT_BUS_ERR (0x00) /* BUS ERROR */
+/* Master mode use only */
+#define TWI_STAT_TX_STA (0x08) /* START condition transmitted */
+#define TWI_STAT_TX_RESTA (0x10) /* Repeated START condition transmitted */
+#define TWI_STAT_TX_AW_ACK (0x18) /* Address+Write bit transmitted, ACK received */
+#define TWI_STAT_TX_AW_NAK (0x20) /* Address+Write bit transmitted, ACK not received */
+#define TWI_STAT_TXD_ACK (0x28) /* data byte transmitted in master mode,ack received */
+#define TWI_STAT_TXD_NAK (0x30) /* data byte transmitted in master mode ,ack not received */
+#define TWI_STAT_ARBLOST (0x38) /* arbitration lost in address or data byte */
+#define TWI_STAT_TX_AR_ACK (0x40) /* Address+Read bit transmitted, ACK received */
+#define TWI_STAT_TX_AR_NAK (0x48) /* Address+Read bit transmitted, ACK not received */
+#define TWI_STAT_RXD_ACK (0x50) /* data byte received in master mode ,ack transmitted */
+#define TWI_STAT_RXD_NAK (0x58) /* date byte received in master mode,not ack transmitted */
+/* Slave mode use only */
+#define TWI_STAT_RXWS_ACK (0x60) /* Slave address+Write bit received, ACK transmitted */
+#define TWI_STAT_ARBLOST_RXWS_ACK (0x68)
+#define TWI_STAT_RXGCAS_ACK (0x70) /* General Call address received, ACK transmitted */
+#define TWI_STAT_ARBLOST_RXGCAS_ACK (0x78)
+#define TWI_STAT_RXDS_ACK (0x80)
+#define TWI_STAT_RXDS_NAK (0x88)
+#define TWI_STAT_RXDGCAS_ACK (0x90)
+#define TWI_STAT_RXDGCAS_NAK (0x98)
+#define TWI_STAT_RXSTPS_RXRESTAS (0xA0)
+#define TWI_STAT_RXRS_ACK (0xA8)
+
+#define TWI_STAT_ARBLOST_SLAR_ACK (0xB0)
+
+/* 10bit Address, second part of address */
+#define TWI_STAT_TX_SAW_ACK (0xD0) /* Second Address byte+Write bit transmitted,ACK received */
+#define TWI_STAT_TX_SAW_NAK (0xD8) /* Second Address byte+Write bit transmitted,ACK not received */
+
+#define TWI_STAT_IDLE (0xF8) /* No relevant status infomation,INT_FLAG = 0 */
+
+
+/* status or interrupt source */
+/*------------------------------------------------------------------------------
+* Code Status
+* 00h Bus error
+* 08h START condition transmitted
+* 10h Repeated START condition transmitted
+* 18h Address + Write bit transmitted, ACK received
+* 20h Address + Write bit transmitted, ACK not received
+* 28h Data byte transmitted in master mode, ACK received
+* 30h Data byte transmitted in master mode, ACK not received
+* 38h Arbitration lost in address or data byte
+* 40h Address + Read bit transmitted, ACK received
+* 48h Address + Read bit transmitted, ACK not received
+* 50h Data byte received in master mode, ACK transmitted
+* 58h Data byte received in master mode, not ACK transmitted
+* 60h Slave address + Write bit received, ACK transmitted
+* 68h Arbitration lost in address as master, slave address + Write bit received, ACK transmitted
+* 70h General Call address received, ACK transmitted
+* 78h Arbitration lost in address as master, General Call address received, ACK transmitted
+* 80h Data byte received after slave address received, ACK transmitted
+* 88h Data byte received after slave address received, not ACK transmitted
+* 90h Data byte received after General Call received, ACK transmitted
+* 98h Data byte received after General Call received, not ACK transmitted
+* A0h STOP or repeated START condition received in slave mode
+* A8h Slave address + Read bit received, ACK transmitted
+* B0h Arbitration lost in address as master, slave address + Read bit received, ACK transmitted
+* B8h Data byte transmitted in slave mode, ACK received
+* C0h Data byte transmitted in slave mode, ACK not received
+* C8h Last byte transmitted in slave mode, ACK received
+* D0h Second Address byte + Write bit transmitted, ACK received
+* D8h Second Address byte + Write bit transmitted, ACK not received
+* F8h No relevant status information or no interrupt
+*-----------------------------------------------------------------------------*/
+
+/* TWI mode select */
+#define TWI_MASTER_MODE (1)
+#define TWI_SLAVE_MODE (0) /* seldom use */
+
+#define AW_TWI_ADDR_SIZE 0x3ff
+
+#define TWI0_BASE_ADDR_START (0x01C2ac00)
+#define TWI0_BASE_ADDR_END (TWI0_BASE_ADDR_START + AW_TWI_ADDR_SIZE)
+#define TWI1_BASE_ADDR_START (0x01C2b000)
+#define TWI1_BASE_ADDR_END (TWI1_BASE_ADDR_START + AW_TWI_ADDR_SIZE)
+#define TWI2_BASE_ADDR_START (0x01C2b400)
+#define TWI2_BASE_ADDR_END (TWI2_BASE_ADDR_START + AW_TWI_ADDR_SIZE)
+
+#define I2C0_TRANSFER_SPEED (400000)
+#define I2C1_TRANSFER_SPEED (200000)
+#define I2C2_TRANSFER_SPEED (200000)
+
+struct sunxi_i2c_platform_data {
+ int bus_num;
+ unsigned int frequency;
+};
+
+#endif
diff --git a/drivers/i2c/busses/i2c-sunxi.c b/drivers/i2c/busses/i2c-sunxi.c
index 1426800..2f2bd8e 100644
--- a/drivers/i2c/busses/i2c-sunxi.c
+++ b/drivers/i2c/busses/i2c-sunxi.c
@@ -34,7 +34,7 @@

#include <plat/sys_config.h>
#include <mach/irqs.h>
-#include <mach/i2c.h>
+#include <plat/i2c.h>



@@ -900,11 +900,7 @@ static int i2c_sunxi_probe(struct platform_device *dev)
{
struct sunxi_i2c *i2c = NULL;
struct resource *res = NULL;
-#if defined CONFIG_ARCH_SUN4I
- struct sun4i_i2c_platform_data *pdata = NULL;
-#elif defined CONFIG_ARCH_SUN5I
- struct sun5i_i2c_platform_data *pdata = NULL;
-#endif
+ struct sunxi_i2c_platform_data *pdata = NULL;
char *i2c_clk[] ={"twi0","twi1","twi2"};
char *i2c_pclk[] ={"apb_twi0","apb_twi1","apb_twi2"};
int ret;
@@ -930,11 +926,7 @@ static int i2c_sunxi_probe(struct platform_device *dev)
ret = -ENOMEM;
goto emalloc;
}
-#if defined CONFIG_ARCH_SUN4I
- strlcpy(i2c->adap.name, "sun4i-i2c", sizeof(i2c->adap.name));
-#elif defined CONFIG_ARCH_SUN5I
- strlcpy(i2c->adap.name, "sun5i-i2c", sizeof(i2c->adap.name));
-#endif
+ strlcpy(i2c->adap.name, "sunxi-i2c", sizeof(i2c->adap.name));
i2c->adap.owner = THIS_MODULE;
i2c->adap.nr = pdata->bus_num;
i2c->adap.retries = 2;
@@ -963,12 +955,8 @@ static int i2c_sunxi_probe(struct platform_device *dev)
goto eremap;
}

-#if defined CONFIG_ARCH_SUN4I
- snprintf(i2c->adap.name, sizeof(i2c->adap.name), "sun4i-i2c.%u", i2c->adap.nr);
-#elif defined CONFIG_ARCH_SUN5I
- snprintf(i2c->adap.name, sizeof(i2c->adap.name), "sun5i-i2c.%u", i2c->adap.nr);
-#endif
-
+ snprintf(i2c->adap.name, sizeof(i2c->adap.name),\
+ "sunxi-i2c.%u", i2c->adap.nr);
i2c->base_addr = ioremap(res->start, resource_size(res));
if (!i2c->base_addr) {
ret = -EIO;
@@ -1133,11 +1121,7 @@ static struct platform_driver i2c_sunxi_driver = {
.suspend = i2c_sunxi_suspend,
.resume = i2c_sunxi_resume,
.driver = {
-#if defined CONFIG_ARCH_SUN4I
- .name = "sun4i-i2c",
-#elif defined CONFIG_ARCH_SUN5I
- .name = "sun5i-i2c",
-#endif
+ .name = "sunxi-i2c",
.owner = THIS_MODULE,
},
};
--
1.7.10.4

Alejandro Mery

unread,
Apr 1, 2013, 4:39:17 AM4/1/13
to linux...@googlegroups.com, wing...@gmail.com, d...@linux-sunxi.org
thank you. applied on both stage branches. please `git commit -s` in future.

cheers,
Alejandro Mery

Siarhei Siamashka

unread,
Apr 1, 2013, 1:27:55 PM4/1/13
to linux...@googlegroups.com
On Sun, 31 Mar 2013 00:29:02 +0600
wing...@gmail.com wrote:

> From: Alexsey Shestacov <wing...@gmail.com>
>
> sun4i-i2c and sun5i-i2c now will have same sunxi-i2c name,
> patch removes many #ifdef stuff for it
> ---
> arch/arm/mach-sun4i/include/mach/i2c.h | 196 -------------------------------
> arch/arm/mach-sun5i/include/mach/i2c.h | 200 --------------------------------
> arch/arm/plat-sunxi/clocksrc.c | 2 +-
> arch/arm/plat-sunxi/devices.c | 38 ++----
> arch/arm/plat-sunxi/include/plat/i2c.h | 196 +++++++++++++++++++++++++++++++
> drivers/i2c/busses/i2c-sunxi.c | 28 +----
> 6 files changed, 210 insertions(+), 450 deletions(-)
> delete mode 100644 arch/arm/mach-sun4i/include/mach/i2c.h
> delete mode 100644 arch/arm/mach-sun5i/include/mach/i2c.h
> create mode 100644 arch/arm/plat-sunxi/include/plat/i2c.h

[...]

> diff --git a/arch/arm/plat-sunxi/clocksrc.c b/arch/arm/plat-sunxi/clocksrc.c
> index 6dcfff9..42f23f5 100644
> --- a/arch/arm/plat-sunxi/clocksrc.c
> +++ b/arch/arm/plat-sunxi/clocksrc.c
> @@ -118,7 +118,7 @@ static cycle_t aw_clksrc_read(struct clocksource *cs)
>
> /* latch 64bit counter and wait ready for read */
> TMR_REG_CNT64_CTL |= (1<<1);
> - while(TMR_REG_CNT64_CTL & (1<<1));
> + // while(TMR_REG_CNT64_CTL & (1<<1));


Was this change introduced on purpose or by mistake? The commit message
does not seem to say anything about it.

And if it was done on purpose, then the "wait ready for read" part of
the comment above probably also needs to be updated (explaining why we
don't actually need to wait).

>
> /* read the 64bits counter */
> lower = TMR_REG_CNT64_LO;


--
Best regards,
Siarhei Siamashka

alex allss

unread,
Apr 1, 2013, 3:18:06 PM4/1/13
to linux...@googlegroups.com
A sorry , this is mistakly added


2013/4/1 Siarhei Siamashka <siarhei....@gmail.com>
--
You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



Siarhei Siamashka

unread,
Apr 1, 2013, 4:26:40 PM4/1/13
to linux...@googlegroups.com
On Tue, 2 Apr 2013 01:18:06 +0600
alex allss <wing...@gmail.com> wrote:

> 2013/4/1 Siarhei Siamashka <siarhei....@gmail.com>
> > > diff --git a/arch/arm/plat-sunxi/clocksrc.c
> > b/arch/arm/plat-sunxi/clocksrc.c
> > > index 6dcfff9..42f23f5 100644
> > > --- a/arch/arm/plat-sunxi/clocksrc.c
> > > +++ b/arch/arm/plat-sunxi/clocksrc.c
> > > @@ -118,7 +118,7 @@ static cycle_t aw_clksrc_read(struct clocksource *cs)
> > >
> > > /* latch 64bit counter and wait ready for read */
> > > TMR_REG_CNT64_CTL |= (1<<1);
> > > - while(TMR_REG_CNT64_CTL & (1<<1));
> > > + // while(TMR_REG_CNT64_CTL & (1<<1));
> >
> >
> > Was this change introduced on purpose or by mistake? The commit message
> > does not seem to say anything about it.
> >
> > And if it was done on purpose, then the "wait ready for read" part of
> > the comment above probably also needs to be updated (explaining why we
> > don't actually need to wait).
> >
> > >
> > > /* read the 64bits counter */
> > > lower = TMR_REG_CNT64_LO;

> A sorry , this is mistakly added

OK, now I see that it was indeed an unrelated timer optimization.
Which might deserve its own separate patch.

Using the following test program we can see that indeed a lot
of time can be spent in aw_clksrc_read() function:

/****************************/
#include <sys/time.h>
#include <stdlib.h>
int main()
{
int i;
struct timeval tv;
for (i = 0; i < 1000000; i++)
gettimeofday (&tv, NULL);
return 0;
}
/****************************/

# gcc -O2 benchgettime.c && time ./a.out

real 0m1.166s
user 0m0.070s
sys 0m1.090s

# perf record ./a.out && perf report

67.16% a.out [kernel.kallsyms] [k] aw_clksrc_read
12.30% a.out [kernel.kallsyms] [k] vector_swi
6.17% a.out [kernel.kallsyms] [k] getnstimeofday
5.15% a.out libc-2.15.so [.] __gettimeofday
2.61% a.out [kernel.kallsyms] [k] __copy_to_user_std
2.09% a.out a.out [.] main
1.66% a.out [kernel.kallsyms] [k] do_gettimeofday
1.49% a.out [kernel.kallsyms] [k] sys_gettimeofday
0.81% a.out [kernel.kallsyms] [k] ret_fast_syscall
0.17% a.out [kernel.kallsyms] [k] __do_softirq
0.04% a.out [kernel.kallsyms] [k] gpio_read_one_pin_value
0.04% a.out [kernel.kallsyms] [k] strcmp

Removing the "while(TMR_REG_CNT64_CTL & (1<<1));" loop really speeds
up this test a bit:

# gcc -O2 benchgettime.c && time ./a.out

real 0m0.927s
user 0m0.110s
sys 0m0.820s

Adding statistics collection debug code shows that the loop
"while(TMR_REG_CNT64_CTL & (1<<1));" actually runs at most one
iteration (first reads the value with the bit set, then reads
the value with the bit clear and exits the loop). So we don't
really have to wait too much and the delay is minimal. Moreover,
removing the loop and doing two back to back reads from
TMR_REG_CNT64_LO shows that both values seem to be always
the same, so the loop removal seems not to cause any immediate
failures in practice,

Trying to optimize aw_clksrc_read() code even more, we can even
replace "TMR_REG_CNT64_CTL |= (1<<1);" with something like
"TMR_REG_CNT64_CTL = default_tmr_reg_cnt64_ctl | (1<<1);"
and avoid expensive read of the hardware register. This provides
an additional speedup:

# gcc -O2 benchgettime.c && time ./a.out

real 0m0.806s
user 0m0.090s
sys 0m0.720s


But removing the loop is still a bit fishy because we can't be
totally sure that it is always safe (in the worst case we probably
might get an old stale value of TMR_REG_CNT64 register just before
it gets updated).

Alejandro Mery

unread,
Apr 1, 2013, 5:52:31 PM4/1/13
to linux...@googlegroups.com, Siarhei Siamashka
great catch. thank you! I've reverted this part. will squash them when
merging to the stable branch.

cheers,
Alejandro Mery

alex allss

unread,
Apr 2, 2013, 1:00:07 AM4/2/13
to linux...@googlegroups.com
May be we need lower timer rating?


2013/4/2 Siarhei Siamashka <siarhei....@gmail.com>

Michal Suchanek

unread,
Apr 2, 2013, 11:18:57 AM4/2/13
to linux-sunxi
On 1 April 2013 22:26, Siarhei Siamashka <siarhei....@gmail.com> wrote:
>

> But removing the loop is still a bit fishy because we can't be
> totally sure that it is always safe (in the worst case we probably
> might get an old stale value of TMR_REG_CNT64 register just before
> it gets updated).

Presumably the register is being updated after the write so if the
read happens at unfortunate time it could possibly read some
completely bogus value while the register is being written.

How bogus the value can be and what is the longest time the update can
take obviously depends on the hardware for which the only doc is this
loop :-(

It might be that if you read during tick (eg. while the counter value
is being increased) it takes longer than the two register reads to get
the right value but hitting that would be very unlikely.

Thanks

Michal

Siarhei Siamashka

unread,
Apr 2, 2013, 6:21:06 PM4/2/13
to linux...@googlegroups.com
Right. That's why I don't like this loop removal even though I could not
reproduce any obvious problem in my limited tests.

For comparison, the same benchmark program doing 1 million gettimeofday
calls on ARM Chromebook (dual-core ARM Cortex-A15 @1.7GHz):

# time ./a.out

real 0m0.829s
user 0m0.055s
sys 0m0.770s

# perf record ./a.out && perf report

57.70% a.out [kernel.kallsyms] [k] exynos4_frc_read
14.70% a.out [kernel.kallsyms] [k] vector_swi
8.02% a.out [kernel.kallsyms] [k] __aeabi_idiv
6.67% a.out [kernel.kallsyms] [k] getnstimeofday
6.58% a.out libc-2.15.so [.] __gettimeofday
1.98% a.out [kernel.kallsyms] [k] sys_gettimeofday
1.08% a.out [kernel.kallsyms] [k] ret_fast_syscall
0.96% a.out a.out [.] main
0.84% a.out [kernel.kallsyms] [k] do_gettimeofday
0.72% a.out a.out [.] 0x00000318
0.60% a.out [kernel.kallsyms] [k] __copy_to_user_std
0.12% a.out [kernel.kallsyms] [k] __aeabi_llsr
0.04% a.out [kernel.kallsyms] [k] mutex_unlock
0.00% a.out [kernel.kallsyms] [k] sys_read
0.00% a.out [kernel.kallsyms] [k] _raw_spin_unlock_irq

static cycle_t exynos4_frc_read(struct clocksource *cs)
{
u32 lo, hi;
static u32 __suspend_volatile_bss hi2;

do {
hi = hi2;
lo = __raw_readl(EXYNOS4_MCT_G_CNT_L);
hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
} while (hi != hi2);

return ((cycle_t)hi << 32) | lo;
}

So the performance of gettimeofday() is only a little bit better
compared to Allwinner A10 (0.829s vs. 1.166s).

However, appears that aw_clksrc_read() is somehow a performance
bottleneck for xbmc as reported on #linux-sunxi irc channel.
So we still might want to do something about it:

http://irclog.whitequark.org/linux-sunxi/2013-04-02#3430815

Hans de Goede

unread,
Apr 3, 2013, 3:18:18 AM4/3/13
to linux...@googlegroups.com, Siarhei Siamashka
Hi,
This looks like a lot better solution to the counter latching
problem, why don't we copy this over into the sunxi sources ?

This should be much faster then our current code in most scenarios
while still being wrap-safe.

Regards,

Hans

Siarhei Siamashka

unread,
Apr 7, 2013, 1:26:21 PM4/7/13
to linux...@googlegroups.com
Maybe because Exynos only needs to ensure wrap-safe 64-bit read and
the 32-bit reads of EXYNOS4_MCT_G_CNT_L and EXYNOS4_MCT_G_CNT_U
registers are already atomic?

Michal Suchanek mentioned that we can't be even sure that reading
TMR_REG_CNT64 is allowed without first waiting for the bit 1 in
TMR_REG_CNT64_CTL to clear. Getting a partially updated value might
be really bad (if it's ever possible of course).

> This should be much faster then our current code in most scenarios
> while still being wrap-safe.

In any case, the benchmark numbers show that the performance of
Exynos5250 and Allwiner A10 doing clock polling is roughly the
same (~1 million gettimeofday calls per second). So looks like
this level of performance is pretty "normal" for ARM hardware.

But Intel Atom is in a totally different league. It is more than 10x
faster on this gettimeofday benchmark because it uses vdso and
apparently rdtsc as the clock source (the counter, which is built
in the CPU itself and not in the SoC):

http://lwn.net/Articles/446528/
http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/plain/arch/x86/vdso/vclock_gettime.c

The vdso optimized gettimeofday on x86 unfortunately encourages
clock polling abusers (XBMC and maybe some other applications?).

ARM also has a 32-bit cycle counter built into the CPU core, and
kernel user helpers (poor man's wannabe vdso):

http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/plain/Documentation/arm/kernel_user_helpers.txt

But just 32-bit counter might be not very useful. And also all this
stuff belongs to the core ARM support code in the kernel (probably
well outside of the scope of linux-sunxi project).

Hans de Goede

unread,
Apr 7, 2013, 4:30:59 PM4/7/13
to linux...@googlegroups.com, Siarhei Siamashka
Hi,
I would expect it to not be wrap safe, since we do 2 32 bit reads,
but that other then that it would be fine. The tests people
have run where they removed the polling loop and things still
worked fine seem to confirm that.

>
>> This should be much faster then our current code in most scenarios
>> while still being wrap-safe.
>
> In any case, the benchmark numbers show that the performance of
> Exynos5250 and Allwiner A10 doing clock polling is roughly the
> same (~1 million gettimeofday calls per second). So looks like
> this level of performance is pretty "normal" for ARM hardware.

The current A10 code disables interrupts which is really quite
bad, dropping the polling and switching to the exynos method
would allow us to drop that, and I would also like to see benchmarks
on the A10 using the exonys method as a comparison.

>
> But Intel Atom is in a totally different league. It is more than 10x
> faster on this gettimeofday benchmark because it uses vdso and
> apparently rdtsc as the clock source (the counter, which is built
> in the CPU itself and not in the SoC):
>
> http://lwn.net/Articles/446528/
> http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/plain/arch/x86/vdso/vclock_gettime.c
>
> The vdso optimized gettimeofday on x86 unfortunately encourages
> clock polling abusers (XBMC and maybe some other applications?).
>
> ARM also has a 32-bit cycle counter built into the CPU core, and
> kernel user helpers (poor man's wannabe vdso):
>
> http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/plain/Documentation/arm/kernel_user_helpers.txt
>
> But just 32-bit counter might be not very useful.

Actually, they are. One frequent caller of the clocksource is
the scheduler, and there is a special scheduler clocksource
function an arch dependent platform can install, and the arm
code has wrappers in place for using a 32 bit counter for this.

Likewise the main clocksource can be 32 bit too, we just need
to make sure that gettimeofday gets called atleast once between
wraps, which we can do by setting a simple low-frequency timer
which calls gettimeofday. For this we really want a slower
counter then one running at cpu speed though, and cpu buildin
counters also suffer from clock scaling. But the A10 soc
has plenty of unused timers, and if we set the auto-reload
value to 0xffffffff we could use one of these as a simple slower
32 bit counter, giving us a possible better clocksource.

> And also all this
> stuff belongs to the core ARM support code in the kernel (probably
> well outside of the scope of linux-sunxi project).

If the 32 bit cpu counters run at core speed then they are both
too fast (need relatively high freq timer to work around wraps)
and not stable since they are influenced by clockscaling, which
is likely why this is not solved in the core.

Regards,

Hans

Oliver Schinagl

unread,
Apr 7, 2013, 12:34:14 PM4/7/13
to linux...@googlegroups.com
I'm just reading the LWN article and while I know nothing about vdso and
even less what A10 does; I understand it's a 'smart' way to keep some
syscalls in userspace memory to make things faster? I guess it's not so
easy and thus it's not something that could be done on A10?

Sorry for sounding stupid ;) but just really curious as to why hardware
support is needed for this.
Reply all
Reply to author
Forward
0 new messages