SoC base drivers: ASIC3 SoC hardware definitions
RFC PATCH 2/4 SoC base drivers: ASIC3 SoC hardware definitions
Hello linux-kernel,
Intro: This is a header with hardware definitions for ASIC3 chip, contributed by HP/Compaq. It is provided as-is, as a vendor-originated header.
---------
ipaq-asic3.h: Hardware definitions for ASIC3 chip, found in ~12 handheld devices from HP/Compaq and HTC.
include/asm-arm/hardware/ipaq-asic3.h | 609 +++++++++++++++++++++++++++++++++ 1 files changed, 609 insertions(+), 0 deletions(-)
include/asm-arm/hardware/ipaq-asic3.h new file +609 -0
@@ -0,0 +1,609 @@ +/* +* +* Definitions for the HTC ASIC3 chip found in several handheld devices +* +* Copyright 2001 Compaq Computer Corporation. +* +* Use consistent with the GNU GPL is permitted, +* provided that this copyright notice is +* preserved in its entirety in all copies and derived works. +* +* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, +* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS +* FITNESS FOR ANY PARTICULAR PURPOSE. +* +* Author: Andrew Christian +* +*/ + +#ifndef IPAQ_ASIC3_H +#define IPAQ_ASIC3_H + +/****************************************************/ +/* IPAQ, ASIC #3, replaces ASIC #1 */ + +#define IPAQ_ASIC3 (_b,s,x,y) \ + (*((volatile s *) (_b + _IPAQ_ASIC3_ ## x ## _Base + (_IPAQ_ASIC3_ ## x ## _ ## y)))) +#define IPAQ_ASIC3_N (_b,s,x,y,z) \ + (*((volatile s *) (_b + _IPAQ_ASIC3_ ## x ## _ ## y ## _Base + (_IPAQ_ASIC3_ ## x ## _ ## z)))) + +#define IPAQ_ASIC3_GPIO (_b,s,x,y) \ + (*((volatile s *) (_b + _IPAQ_ASIC3_GPIO_ ## x ## _Base + (_IPAQ_ASIC3_GPIO_ ## y)))) + +#define IPAQ_ASIC3_OFFSET (x,y) (_IPAQ_ASIC3_ ## x ## _Base + _IPAQ_ASIC3_ ## x ## _ ## y) +#define IPAQ_ASIC3_GPIO_OFFSET (x,y) (_IPAQ_ASIC3_GPIO_ ## x ## _Base + _IPAQ_ASIC3_GPIO_ ## y) + + +/* All offsets below are specified with this address bus shift */ +#define ASIC3_DEFAULT_ADDR_SHIFT 2 + +#define _IPAQ_ASIC3_GPIO_A_Base 0x0000 +#define _IPAQ_ASIC3_GPIO_B_Base 0x0100 +#define _IPAQ_ASIC3_GPIO_C_Base 0x0200 +#define _IPAQ_ASIC3_GPIO_D_Base 0x0300 + +#define _IPAQ_ASIC3_GPIO_Mask 0x00/* R/W 0:don't mask, 1:mask interrupt */ +#define _IPAQ_ASIC3_GPIO_Direction 0x04/* R/W 0:input, 1:output */ +#define _IPAQ_ASIC3_GPIO_Out 0x08/* R/W 0:output low, 1:output high */ +#define _IPAQ_ASIC3_GPIO_TriggerType 0x0c/* R/W 0:level, 1:edge */ +#define _IPAQ_ASIC3_GPIO_EdgeTrigger 0x10/* R/W 0:falling, 1:rising */ +#define _IPAQ_ASIC3_GPIO_LevelTrigger 0x14/* R/W 0:low, 1:high level detect */ +#define _IPAQ_ASIC3_GPIO_SleepMask 0x18/* R/W 0:don't mask, 1:mask trigger in sleep mode */ +#define _IPAQ_ASIC3_GPIO_SleepOut 0x1c/* R/W level 0:low, 1:high in sleep mode */ +#define _IPAQ_ASIC3_GPIO_BattFaultOut 0x20/* R/W level 0:low, 1:high in batt_fault */ +#define _IPAQ_ASIC3_GPIO_IntStatus 0x24/* R/W 0:none, 1:detect */ +#define _IPAQ_ASIC3_GPIO_AltFunction 0x28/* R/W 0:normal control 1:LED register control */ +#define _IPAQ_ASIC3_GPIO_SleepConf 0x2c/* R/W bit 1: autosleep 0: disable gposlpout in normal mode, enable gposlpout in sleep mode */ +#define _IPAQ_ASIC3_GPIO_Status 0x30/* R Pin status */ + +#define IPAQ_ASIC3_GPIO_A_MASK (_b) IPAQ_ASIC3_GPIO( _b, u16, A, Mask ) +#define IPAQ_ASIC3_GPIO_A_DIR (_b) IPAQ_ASIC3_GPIO( _b, u16, A, Direction ) +#define IPAQ_ASIC3_GPIO_A_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, A, Out ) +#define IPAQ_ASIC3_GPIO_A_LEVELTRI (_b) IPAQ_ASIC3_GPIO( _b, u16, A, TriggerType ) +#define IPAQ_ASIC3_GPIO_A_RISING (_b) IPAQ_ASIC3_GPIO( _b, u16, A, EdgeTrigger ) +#define IPAQ_ASIC3_GPIO_A_LEVEL (_b) IPAQ_ASIC3_GPIO( _b, u16, A, LevelTrigger ) +#define IPAQ_ASIC3_GPIO_A_SLEEP_MASK (_b) IPAQ_ASIC3_GPIO( _b, u16, A, SleepMask ) +#define IPAQ_ASIC3_GPIO_A_SLEEP_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, A, SleepOut ) +#define IPAQ_ASIC3_GPIO_A_BATT_FAULT_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, A, BattFaultOut ) +#define IPAQ_ASIC3_GPIO_A_INT_STATUS (_b) IPAQ_ASIC3_GPIO( _b, u16, A, IntStatus ) +#define IPAQ_ASIC3_GPIO_A_ALT_FUNCTION (_b) IPAQ_ASIC3_GPIO( _b, u16, A, AltFunction ) +#define IPAQ_ASIC3_GPIO_A_SLEEP_CONF (_b) IPAQ_ASIC3_GPIO( _b, u16, A, SleepConf ) +#define IPAQ_ASIC3_GPIO_A_STATUS (_b) IPAQ_ASIC3_GPIO( _b, u16, A, Status ) + +#define IPAQ_ASIC3_GPIO_B_MASK (_b) IPAQ_ASIC3_GPIO( _b, u16, B, Mask ) +#define IPAQ_ASIC3_GPIO_B_DIR (_b) IPAQ_ASIC3_GPIO( _b, u16, B, Direction ) +#define IPAQ_ASIC3_GPIO_B_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, B, Out ) +#define IPAQ_ASIC3_GPIO_B_LEVELTRI (_b) IPAQ_ASIC3_GPIO( _b, u16, B, TriggerType ) +#define IPAQ_ASIC3_GPIO_B_RISING (_b) IPAQ_ASIC3_GPIO( _b, u16, B, EdgeTrigger ) +#define IPAQ_ASIC3_GPIO_B_LEVEL (_b) IPAQ_ASIC3_GPIO( _b, u16, B, LevelTrigger ) +#define IPAQ_ASIC3_GPIO_B_SLEEP_MASK (_b) IPAQ_ASIC3_GPIO( _b, u16, B, SleepMask ) +#define IPAQ_ASIC3_GPIO_B_SLEEP_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, B, SleepOut ) +#define IPAQ_ASIC3_GPIO_B_BATT_FAULT_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, B, BattFaultOut ) +#define IPAQ_ASIC3_GPIO_B_INT_STATUS (_b) IPAQ_ASIC3_GPIO( _b, u16, B, IntStatus ) +#define IPAQ_ASIC3_GPIO_B_ALT_FUNCTION (_b) IPAQ_ASIC3_GPIO( _b, u16, B, AltFunction ) +#define IPAQ_ASIC3_GPIO_B_SLEEP_CONF (_b) IPAQ_ASIC3_GPIO( _b, u16, B, SleepConf ) +#define IPAQ_ASIC3_GPIO_B_STATUS (_b) IPAQ_ASIC3_GPIO( _b, u16, B, Status ) + +#define IPAQ_ASIC3_GPIO_C_MASK (_b) IPAQ_ASIC3_GPIO( _b, u16, C, Mask ) +#define IPAQ_ASIC3_GPIO_C_DIR (_b) IPAQ_ASIC3_GPIO( _b, u16, C, Direction ) +#define IPAQ_ASIC3_GPIO_C_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, C, Out ) +#define IPAQ_ASIC3_GPIO_C_LEVELTRI (_b) IPAQ_ASIC3_GPIO( _b, u16, C, TriggerType ) +#define IPAQ_ASIC3_GPIO_C_RISING (_b) IPAQ_ASIC3_GPIO( _b, u16, C, EdgeTrigger ) +#define IPAQ_ASIC3_GPIO_C_LEVEL (_b) IPAQ_ASIC3_GPIO( _b, u16, C, LevelTrigger ) +#define IPAQ_ASIC3_GPIO_C_SLEEP_MASK (_b) IPAQ_ASIC3_GPIO( _b, u16, C, SleepMask ) +#define IPAQ_ASIC3_GPIO_C_SLEEP_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, C, SleepOut ) +#define IPAQ_ASIC3_GPIO_C_BATT_FAULT_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, C, BattFaultOut ) +#define IPAQ_ASIC3_GPIO_C_INT_STATUS (_b) IPAQ_ASIC3_GPIO( _b, u16, C, IntStatus ) +#define IPAQ_ASIC3_GPIO_C_ALT_FUNCTION (_b) IPAQ_ASIC3_GPIO( _b, u16, C, AltFunction ) +#define IPAQ_ASIC3_GPIO_C_SLEEP_CONF (_b) IPAQ_ASIC3_GPIO( _b, u16, C, SleepConf ) +#define IPAQ_ASIC3_GPIO_C_STATUS (_b) IPAQ_ASIC3_GPIO( _b, u16, C, Status ) + +#define IPAQ_ASIC3_GPIO_D_MASK (_b) IPAQ_ASIC3_GPIO( _b, u16, D, Mask ) +#define IPAQ_ASIC3_GPIO_D_DIR (_b) IPAQ_ASIC3_GPIO( _b, u16, D, Direction ) +#define IPAQ_ASIC3_GPIO_D_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, D, Out ) +#define IPAQ_ASIC3_GPIO_D_LEVELTRI (_b) IPAQ_ASIC3_GPIO( _b, u16, D, TriggerType ) +#define IPAQ_ASIC3_GPIO_D_RISING (_b) IPAQ_ASIC3_GPIO( _b, u16, D, EdgeTrigger ) +#define IPAQ_ASIC3_GPIO_D_LEVEL (_b) IPAQ_ASIC3_GPIO( _b, u16, D, LevelTrigger ) +#define IPAQ_ASIC3_GPIO_D_SLEEP_MASK (_b) IPAQ_ASIC3_GPIO( _b, u16, D, SleepMask ) +#define IPAQ_ASIC3_GPIO_D_SLEEP_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, D, SleepOut ) +#define IPAQ_ASIC3_GPIO_D_BATT_FAULT_OUT (_b) IPAQ_ASIC3_GPIO( _b, u16, D, BattFaultOut ) +#define IPAQ_ASIC3_GPIO_D_INT_STATUS (_b) IPAQ_ASIC3_GPIO( _b, u16, D, IntStatus ) +#define IPAQ_ASIC3_GPIO_D_ALT_FUNCTION (_b) IPAQ_ASIC3_GPIO( _b, u16, D, AltFunction ) +#define IPAQ_ASIC3_GPIO_D_SLEEP_CONF (_b) IPAQ_ASIC3_GPIO( _b, u16, D, SleepConf ) +#define IPAQ_ASIC3_GPIO_D_STATUS (_b) IPAQ_ASIC3_GPIO( _b, u16, D, Status ) + +#define _IPAQ_ASIC3_SPI_Base 0x0400 +#define _IPAQ_ASIC3_SPI_Control 0x0000 +#define _IPAQ_ASIC3_SPI_TxData 0x0004 +#define _IPAQ_ASIC3_SPI_RxData 0x0008 +#define _IPAQ_ASIC3_SPI_Int 0x000c +#define _IPAQ_ASIC3_SPI_Status 0x0010 + +#define IPAQ_ASIC3_SPI_Control (_b) IPAQ_ASIC3( _b, u16, SPI, Control ) +#define IPAQ_ASIC3_SPI_TxData (_b) IPAQ_ASIC3( _b, u16, SPI, TxData ) +#define IPAQ_ASIC3_SPI_RxData (_b) IPAQ_ASIC3( _b, u16, SPI, RxData ) +#define IPAQ_ASIC3_SPI_Int (_b) IPAQ_ASIC3( _b, u16, SPI, Int ) +#define IPAQ_ASIC3_SPI_Status (_b) IPAQ_ASIC3( _b, u16, SPI, Status ) + +#define SPI_CONTROL_SPR (clk) ((clk) & 0x0f)/* Clock rate */ + +#define _IPAQ_ASIC3_PWM_0_Base 0x0500 +#define _IPAQ_ASIC3_PWM_1_Base 0x0600 +#define _IPAQ_ASIC3_PWM_TimeBase 0x0000 +#define _IPAQ_ASIC3_PWM_PeriodTime 0x0004 +#define _IPAQ_ASIC3_PWM_DutyTime 0x0008 + +#define IPAQ_ASIC3_PWM_TimeBase (_b, x) IPAQ_ASIC3_N( _b, u16, PWM, x, TimeBase ) +#define IPAQ_ASIC3_PWM_PeriodTime (_b, x) IPAQ_ASIC3_N( _b, u16, PWM, x, PeriodTime ) +#define IPAQ_ASIC3_PWM_DutyTime (_b, x) IPAQ_ASIC3_N( _b, u16, PWM, x, DutyTime ) + +#define PWM_TIMEBASE_VALUE (x) ((x)&0xf)/* Low 4 bits sets time base */ +#define PWM_TIMEBASE_ENABLE (1 << 4)/* Enable clock */ + +#define _IPAQ_ASIC3_LED_0_Base 0x0700 +#define _IPAQ_ASIC3_LED_1_Base 0x0800 +#define _IPAQ_ASIC3_LED_2_Base 0x0900 +#define _IPAQ_ASIC3_LED_TimeBase 0x0000/* R/W 7 bits */ +#define _IPAQ_ASIC3_LED_PeriodTime 0x0004/* R/W 12 bits */ +#define _IPAQ_ASIC3_LED_DutyTime 0x0008/* R/W 12 bits */ +#define _IPAQ_ASIC3_LED_AutoStopCount 0x000c/* R/W 16 bits */ + +#define IPAQ_ASIC3_LED_TimeBase (_b, x) IPAQ_ASIC3_N( _b, u8, LED, x, TimeBase ) +#define IPAQ_ASIC3_LED_PeriodTime (_b, x) IPAQ_ASIC3_N( _b, u16, LED, x, PeriodTime ) +#define IPAQ_ASIC3_LED_DutyTime (_b, x) IPAQ_ASIC3_N( _b, u16, LED, x, DutyTime ) +#define IPAQ_ASIC3_LED_AutoStopCount (_b, x) IPAQ_ASIC3_N( _b, u16, LED, x, AutoStopCount ) + +/* LED TimeBase bits - match ASIC2 */ +#define LED_TBS 0x0f/* Low 4 bits sets time base, max = 13 */ +/* Note: max = 5 on hx4700 */ +/* 0: maximum time base */ +/* 1: maximum time base / 2 */ +/* n: maximum time base / 2^n */ + +#define LED_EN (1 << 4)/* LED ON/OFF 0:off, 1:on */ +#define LED_AUTOSTOP (1 << 5)/* LED ON/OFF auto stop set 0:disable, 1:enable */ +#define LED_ALWAYS (1 << 6)/* LED Interrupt Mask 0:No mask, 1:mask */ + +#define _IPAQ_ASIC3_CLOCK_Base 0x0A00 +#define _IPAQ_ASIC3_CLOCK_CDEX 0x00 +#define _IPAQ_ASIC3_CLOCK_SEL 0x04 + +#define IPAQ_ASIC3_CLOCK_CDEX (_b) IPAQ_ASIC3( _b, u16, CLOCK, CDEX ) +#define IPAQ_ASIC3_CLOCK_SEL (_b) IPAQ_ASIC3( _b, u16, CLOCK, SEL ) + +#define CLOCK_CDEX_SOURCE (1 << 0)/* 2 bits */ +#define CLOCK_CDEX_SOURCE0 (1 << 0) +#define CLOCK_CDEX_SOURCE1 (1 << 1) +#define CLOCK_CDEX_SPI (1 << 2) +#define CLOCK_CDEX_OWM (1 << 3) +#define CLOCK_CDEX_PWM0 (1 << 4) +#define CLOCK_CDEX_PWM1 (1 << 5) +#define CLOCK_CDEX_LED0 (1 << 6) +#define CLOCK_CDEX_LED1 (1 << 7) +#define CLOCK_CDEX_LED2 (1 << 8) + +#define CLOCK_CDEX_SD_HOST (1 << 9)/* R/W: SD host clock source 24.576M/12.288M */ +#define CLOCK_CDEX_SD_BUS (1 << 10)/* R/W: SD bus clock source control 24.576M/12.288M */ +#define CLOCK_CDEX_SMBUS (1 << 11) +#define CLOCK_CDEX_CONTROL_CX (1 << 12) + +#define CLOCK_CDEX_EX0 (1 << 13)/* R/W: 32.768 kHz crystal */ +#define CLOCK_CDEX_EX1 (1 << 14)/* R/W: 24.576 MHz crystal */ + +#define CLOCK_SEL_SD_HCLK_SEL (1 << 0)/* R/W: SDIO host clock select - 1: 24.576 Mhz, 0: 12.288 MHz */ +#define CLOCK_SEL_SD_BCLK_SEL (1 << 1)/* R/W: SDIO bus clock select - 1: 24.576 MHz, 0: 12.288 MHz */ +#define CLOCK_SEL_CX (1 << 2)/* R/W: INT clock source control (32.768 kHz) */ + + +#define _IPAQ_ASIC3_INTR_Base 0x0B00 + +#define _IPAQ_ASIC3_INTR_IntMask 0x00/* Interrupt mask control */ +#define _IPAQ_ASIC3_INTR_PIntStat 0x04/* Peripheral interrupt status */ +#define _IPAQ_ASIC3_INTR_IntCPS 0x08/* Interrupt timer clock pre-scale */ +#define _IPAQ_ASIC3_INTR_IntTBS 0x0c/* Interrupt timer set */ + +#define IPAQ_ASIC3_INTR_IntMask (_b) IPAQ_ASIC3( _b, u8, INTR, IntMask ) +#define IPAQ_ASIC3_INTR_PIntStat (_b) IPAQ_ASIC3( _b, u8, INTR, PIntStat ) +#define IPAQ_ASIC3_INTR_IntCPS (_b) IPAQ_ASIC3( _b, u8, INTR, IntCPS ) +#define IPAQ_ASIC3_INTR_IntTBS (_b) IPAQ_ASIC3( _b, u16, INTR, IntTBS ) + +#define ASIC3_INTMASK_GINTMASK (1 << 0)/* Global interrupt mask 1:enable */ +#define ASIC3_INTMASK_GINTEL (1 << 1)/* 1: rising edge, 0: hi level */ +#define ASIC3_INTMASK_MASK0 (1 << 2) +#define ASIC3_INTMASK_MASK1 (1 << 3) +#define ASIC3_INTMASK_MASK2 (1 << 4) +#define ASIC3_INTMASK_MASK3 (1 << 5) +#define ASIC3_INTMASK_MASK4 (1 << 6) +#define ASIC3_INTMASK_MASK5 (1 << 7) + +#define ASIC3_INTR_PERIPHERAL_A (1 << 0) +#define ASIC3_INTR_PERIPHERAL_B (1 << 1) +#define ASIC3_INTR_PERIPHERAL_C (1 << 2) +#define ASIC3_INTR_PERIPHERAL_D (1 << 3) +#define ASIC3_INTR_LED0 (1 << 4) +#define ASIC3_INTR_LED1 (1 << 5) +#define ASIC3_INTR_LED2 (1 << 6) +#define ASIC3_INTR_SPI (1 << 7) +#define ASIC3_INTR_SMBUS (1 << 8) +#define ASIC3_INTR_OWM (1 << 9) + +#define ASIC3_INTR_CPS (x) ((x)&0x0f)/* 4 bits, max 14 */ +#define ASIC3_INTR_CPS_SET ( 1 << 4 )/* Time base enable */ + + +/* Basic control of the SD ASIC */ +#define _IPAQ_ASIC3_SDHWCTRL_Base 0x0E00 + +#define _IPAQ_ASIC3_SDHWCTRL_SDConf 0x00 +#define IPAQ_ASIC3_SDHWCTRL_SDConf (_b) IPAQ_ASIC3( _b, u8, SDHWCTRL, SDConf ) + +#define ASIC3_SDHWCTRL_SUSPEND (1 << 0)/* 1=suspend all SD operations */ +#define ASIC3_SDHWCTRL_CLKSEL (1 << 1)/* 1=SDICK, 0=HCLK */ +#define ASIC3_SDHWCTRL_PCLR (1 << 2)/* All registers of SDIO cleared */ +#define ASIC3_SDHWCTRL_LEVCD (1 << 3)/* Level of SD card detection: 1:high, 0:low */ +#define ASIC3_SDHWCTRL_LEVWP (1 << 4)/* Level of SD card write protection: 1=low, 0=high */ +#define ASIC3_SDHWCTRL_SDLED (1 << 5)/* SD card LED signal 1=enable, 0=disable */ +#define ASIC3_SDHWCTRL_SDPWR (1 << 6)/* SD card power supply control 1=enable */ + + +/* This is a pointer to an array of 12 u32 values - but only the lower 2 bytes matter */ +/* Use it as "IPAQ_ASIC3_HWPROTECT_ARRAY[x]" */ + +#define _IPAQ_ASIC3_HWPROTECT_Base 0x1000 +#define IPAQ_ASIC3_HWPROTECT_ARRAY ((volatile u32*)(_IPAQ_ASIC3_Base + _IPAQ_ASIC3_HWPROTECT_Base)) +#define HWPROTECT_ARRAY_LEN 12 +#define HWPROTECT_ARRAY_VALUES {0x4854,0x432d,0x5344,0x494f,0x2050,0x2f4e,0x3a33,0x3048,0x3830,0x3032,0x382d,0x3030} + + +#define _IPAQ_ASIC3_EXTCF_Base 0x1100 + +#define _IPAQ_ASIC3_EXTCF_Select 0x00 +#define _IPAQ_ASIC3_EXTCF_Reset 0x04 + +#define IPAQ_ASIC3_EXTCF_Select (_b) IPAQ_ASIC3( _b, u16, EXTCF, Select ) +#define IPAQ_ASIC3_EXTCF_Reset (_b) IPAQ_ASIC3( _b, u16, EXTCF, Reset ) + +#define ASIC3_EXTCF_SMOD0 (1 << 0)/* slot number of mode 0 */ +#define ASIC3_EXTCF_SMOD1 (1 << 1)/* slot number of mode 1 */ +#define ASIC3_EXTCF_SMOD2 (1 << 2)/* slot number of mode 2 */ +#define ASIC3_EXTCF_OWM_EN (1 << 4)/* enable onewire module */ +#define ASIC3_EXTCF_OWM_SMB (1 << 5)/* OWM bus selection */ +#define ASIC3_EXTCF_OWM_RESET (1 << 6)/* undocumented, used by OWM and CF */ +#define ASIC3_EXTCF_CF0_SLEEP_MODE (1 << 7)/* CF0 sleep state control */ +#define ASIC3_EXTCF_CF1_SLEEP_MODE (1 << 8)/* CF1 sleep state control */ +#define ASIC3_EXTCF_CF0_PWAIT_EN (1 << 10)/* CF0 PWAIT_n control */ +#define ASIC3_EXTCF_CF1_PWAIT_EN (1 << 11)/* CF1 PWAIT_n control */ +#define ASIC3_EXTCF_CF0_BUF_EN (1 << 12)/* CF0 buffer control */ +#define ASIC3_EXTCF_CF1_BUF_EN (1 << 13)/* CF1 buffer control */ +#define ASIC3_EXTCF_SD_MEM_ENABLE (1 << 14) +#define ASIC3_EXTCF_CF_SLEEP (1 << 15)/* CF sleep mode control */ + +/***************************************************************************** +* The Onewire interface registers +* +* OWM_CMD +* OWM_DAT +* OWM_INTR +* OWM_INTEN +* OWM_CLKDIV +* +*****************************************************************************/ + +#define _IPAQ_ASIC3_OWM_Base 0xC00 + +#define _IPAQ_ASIC3_OWM_CMD 0x00 +#define _IPAQ_ASIC3_OWM_DAT 0x04 +#define _IPAQ_ASIC3_OWM_INTR 0x08 +#define _IPAQ_ASIC3_OWM_INTEN 0x0C +#define _IPAQ_ASIC3_OWM_CLKDIV 0x10 + +#define ASIC3_OWM_CMD_ONEWR (1 << 0) +#define ASIC3_OWM_CMD_SRA (1 << 1) +#define ASIC3_OWM_CMD_DQO (1 << 2) +#define ASIC3_OWM_CMD_DQI (1 << 3) + +#define ASIC3_OWM_INTR_PD (1 << 0) +#define ASIC3_OWM_INTR_PDR (1 << 1) +#define ASIC3_OWM_INTR_TBE (1 << 2) +#define ASIC3_OWM_INTR_TEMP (1 << 3) +#define ASIC3_OWM_INTR_RBF (1 << 4) + +#define ASIC3_OWM_INTEN_EPD (1 << 0) +#define ASIC3_OWM_INTEN_IAS (1 << 1) +#define ASIC3_OWM_INTEN_ETBE (1 << 2) +#define ASIC3_OWM_INTEN_ETMT (1 << 3) +#define ASIC3_OWM_INTEN_ERBF (1 << 4) + +#define ASIC3_OWM_CLKDIV_PRE (3 << 0)/* two bits wide at bit position 0 */ +#define ASIC3_OWM_CLKDIV_DIV (7 << 2)/* 3 bits wide at bit position 2 */ + + +/***************************************************************************** +* The SD configuration registers are at a completely different location +* in memory. They are divided into three sets of registers: +* +* SD_CONFIG Core configuration register +* SD_CTRL Control registers for SD operations +* SDIO_CTRL Control registers for SDIO operations +* +*****************************************************************************/ + +#define IPAQ_ASIC3_SD_CONFIG (_b, s,x) \ + (*((volatile s *) ((_b) + _IPAQ_ASIC3_SD_CONFIG_Base + (_IPAQ_ASIC3_SD_CONFIG_ ## x)))) + +#define _IPAQ_ASIC3_SD_CONFIG_Base 0x0400 // Assumes 32 bit addressing + +#define _IPAQ_ASIC3_SD_CONFIG_Command 0x08/* R/W: Command */ +#define _IPAQ_ASIC3_SD_CONFIG_Addr0 0x20/* [9:31] SD Control Register Base Address */ +#define _IPAQ_ASIC3_SD_CONFIG_Addr1 0x24/* [9:31] SD Control Register Base Address */ +#define _IPAQ_ASIC3_SD_CONFIG_IntPin 0x78/* R/O: interrupt assigned to pin */ +#define _IPAQ_ASIC3_SD_CONFIG_ClkStop 0x80/* Set to 0x1f to clock SD controller, 0 otherwise. */ +/* at 0x82 - Gated Clock Control */ +#define _IPAQ_ASIC3_SD_CONFIG_ClockMode 0x84/* Control clock of SD controller */ +#define _IPAQ_ASIC3_SD_CONFIG_SDHC_PinStatus 0x88/* R/0: read status of SD pins */ +#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Power1 0x90/* Power1 - manual power control */ +/* Power2 is at 0x92 - auto power up after card inserted */ +#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Power3 0x94/* auto power down when card removed */ +#define _IPAQ_ASIC3_SD_CONFIG_SDHC_CardDetect 0x98/* */ +#define _IPAQ_ASIC3_SD_CONFIG_SDHC_Slot 0xA0/* R/O: define support slot number */ +#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk1 0x1E0/* Could be used for gated clock (don't use) */ +#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk2 0x1E2/* Could be used for gated clock (don't use) */ +#define _IPAQ_ASIC3_SD_CONFIG_SDHC_GPIO_OutAndEnable 0x1E8/* GPIO Output Reg. , at 0x1EA - GPIO Output Enable Reg. */ +#define _IPAQ_ASIC3_SD_CONFIG_SDHC_GPIO_Status 0x1EC/* GPIO Status Reg. */ +#define _IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk3 0x1F0/* Bit 1: double buffer/single buffer */ + +#define IPAQ_ASIC3_SD_CONFIG_Command (_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, Command ) +#define IPAQ_ASIC3_SD_CONFIG_Addr0 (_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, Addr0 ) +#define IPAQ_ASIC3_SD_CONFIG_Addr1 (_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, Addr1 ) +#define IPAQ_ASIC3_SD_CONFIG_IntPin (_b) IPAQ_ASIC3_SD_CONFIG(_b, u8, IntPin ) +#define IPAQ_ASIC3_SD_CONFIG_ClkStop (_b) IPAQ_ASIC3_SD_CONFIG(_b, u8, ClkStop ) +#define IPAQ_ASIC3_SD_CONFIG_ClockMode (_b) IPAQ_ASIC3_SD_CONFIG(_b, u8, ClockMode ) +#define IPAQ_ASIC3_SD_CONFIG_SDHC_PinStatus (_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_PinStatus ) +#define IPAQ_ASIC3_SD_CONFIG_SDHC_Power1 (_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Power1 ) +#define IPAQ_ASIC3_SD_CONFIG_SDHC_Power3 (_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Power3 ) +#define IPAQ_ASIC3_SD_CONFIG_SDHC_CardDetect (_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_CardDetect ) +#define IPAQ_ASIC3_SD_CONFIG_SDHC_Slot (_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_Slot ) +#define IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk1 (_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_ExtGateClk1 ) +#define IPAQ_ASIC3_SD_CONFIG_SDHC_ExtGateClk3 (_b) IPAQ_ASIC3_SD_CONFIG(_b, u16, SDHC_ExtGateClk3 ) + +#define SD_CONFIG_ + +#define SD_CONFIG_COMMAND_MAE (1<<1)/* Memory access enable (set to 1 to access SD Controller) */ + +#define SD_CONFIG_CLK_ENABLE_ALL 0x1f + +#define SD_CONFIG_POWER1_PC_33V 0x0200/* Set for 3.3 volts */ +#define SD_CONFIG_POWER1_PC_OFF 0x0000/* Turn off power */ + +#define SD_CONFIG_CARDDETECTMODE_CLK ((x)&0x3)/* two bits - number of cycles for card detection */ + + +#define _IPAQ_ASIC3_SD_CTRL_Base 0x1000 + +#define IPAQ_ASIC3_SD (_b, s,x) \ + (*((volatile s *) ((_b) + _IPAQ_ASIC3_SD_CTRL_Base + (_IPAQ_ASIC3_SD_CTRL_ ## x)))) + +#define _IPAQ_ASIC3_SD_CTRL_Cmd 0x00 +#define _IPAQ_ASIC3_SD_CTRL_Arg0 0x08 +#define _IPAQ_ASIC3_SD_CTRL_Arg1 0x0C +#define _IPAQ_ASIC3_SD_CTRL_StopInternal 0x10 +#define _IPAQ_ASIC3_SD_CTRL_TransferSectorCount 0x14 +#define _IPAQ_ASIC3_SD_CTRL_Response0 0x18 +#define _IPAQ_ASIC3_SD_CTRL_Response1 0x1C +#define _IPAQ_ASIC3_SD_CTRL_Response2 0x20 +#define _IPAQ_ASIC3_SD_CTRL_Response3 0x24 +#define _IPAQ_ASIC3_SD_CTRL_Response4 0x28 +#define _IPAQ_ASIC3_SD_CTRL_Response5 0x2C +#define _IPAQ_ASIC3_SD_CTRL_Response6 0x30 +#define _IPAQ_ASIC3_SD_CTRL_Response7 0x34 +#define _IPAQ_ASIC3_SD_CTRL_CardStatus 0x38 +#define _IPAQ_ASIC3_SD_CTRL_BufferCtrl 0x3C +#define _IPAQ_ASIC3_SD_CTRL_IntMaskCard 0x40 +#define _IPAQ_ASIC3_SD_CTRL_IntMaskBuffer 0x44 +#define _IPAQ_ASIC3_SD_CTRL_CardClockCtrl 0x48 +#define _IPAQ_ASIC3_SD_CTRL_MemCardXferDataLen 0x4C +#define _IPAQ_ASIC3_SD_CTRL_MemCardOptionSetup 0x50 +#define _IPAQ_ASIC3_SD_CTRL_ErrorStatus0 0x58 +#define _IPAQ_ASIC3_SD_CTRL_ErrorStatus1 0x5C +#define _IPAQ_ASIC3_SD_CTRL_DataPort 0x60 +#define _IPAQ_ASIC3_SD_CTRL_TransactionCtrl 0x68 +#define _IPAQ_ASIC3_SD_CTRL_SoftwareReset 0x1C0 + +#define IPAQ_ASIC3_SD_CTRL_Cmd (_b) IPAQ_ASIC3_SD( _b, u16, Cmd )/* */ +#define IPAQ_ASIC3_SD_CTRL_Arg0 (_b) IPAQ_ASIC3_SD( _b, u16, Arg0 )/* */ +#define IPAQ_ASIC3_SD_CTRL_Arg1 (_b) IPAQ_ASIC3_SD( _b, u16, Arg1 )/* */ +#define IPAQ_ASIC3_SD_CTRL_StopInternal (_b) IPAQ_ASIC3_SD( _b, u16, StopInternal )/* */ +#define IPAQ_ASIC3_SD_CTRL_TransferSectorCount (_b) IPAQ_ASIC3_SD( _b, u16, TransferSectorCount )/* */ +#define IPAQ_ASIC3_SD_CTRL_Response0 (_b) IPAQ_ASIC3_SD( _b, u16, Response0 )/* */ +#define IPAQ_ASIC3_SD_CTRL_Response1 (_b) IPAQ_ASIC3_SD( _b, u16, Response1 )/* */ +#define IPAQ_ASIC3_SD_CTRL_Response2 (_b) IPAQ_ASIC3_SD( _b, u16, Response2 )/* */ +#define IPAQ_ASIC3_SD_CTRL_Response3 (_b) IPAQ_ASIC3_SD( _b, u16, Response3 )/* */ +#define IPAQ_ASIC3_SD_CTRL_Response4 (_b) IPAQ_ASIC3_SD( _b, u16, Response4 )/* */ +#define IPAQ_ASIC3_SD_CTRL_Response5 (_b) IPAQ_ASIC3_SD( _b, u16, Response5 )/* */ +#define IPAQ_ASIC3_SD_CTRL_Response6 (_b) IPAQ_ASIC3_SD( _b, u16, Response6 )/* */ +#define IPAQ_ASIC3_SD_CTRL_Response7 (_b) IPAQ_ASIC3_SD( _b, u16, Response7 )/* */ +#define IPAQ_ASIC3_SD_CTRL_CardStatus (_b) IPAQ_ASIC3_SD( _b, u16, CardStatus )/* */ +#define IPAQ_ASIC3_SD_CTRL_BufferCtrl (_b) IPAQ_ASIC3_SD( _b, u16, BufferCtrl )/* and error status*/ +#define IPAQ_ASIC3_SD_CTRL_IntMaskCard (_b) IPAQ_ASIC3_SD( _b, u16, IntMaskCard )/* */ +#define IPAQ_ASIC3_SD_CTRL_IntMaskBuffer (_b) IPAQ_ASIC3_SD( _b, u16, IntMaskBuffer )/* */ +#define IPAQ_ASIC3_SD_CTRL_CardClockCtrl (_b) IPAQ_ASIC3_SD( _b, u16, CardClockCtrl )/* */ +#define IPAQ_ASIC3_SD_CTRL_MemCardXferDataLen (_b) IPAQ_ASIC3_SD( _b, u16, MemCardXferDataLen )/* */ +#define IPAQ_ASIC3_SD_CTRL_MemCardOptionSetup (_b) IPAQ_ASIC3_SD( _b, u16, MemCardOptionSetup )/* */ +#define IPAQ_ASIC3_SD_CTRL_ErrorStatus0 (_b) IPAQ_ASIC3_SD( _b, u16, ErrorStatus0 )/* */ +#define IPAQ_ASIC3_SD_CTRL_ErrorStatus1 (_b) IPAQ_ASIC3_SD( _b, u16, ErrorStatus1 )/* */ +#define IPAQ_ASIC3_SD_CTRL_DataPort (_b) IPAQ_ASIC3_SD( _b, u16, DataPort )/* */ +#define IPAQ_ASIC3_SD_CTRL_TransactionCtrl (_b) IPAQ_ASIC3_SD( _b, u16, TransactionCtrl )/* */ +#define IPAQ_ASIC3_SD_CTRL_SoftwareReset (_b) IPAQ_ASIC3_SD( _b, u16, SoftwareReset )/* */ + +#define SD_CTRL_SOFTWARE_RESET_CLEAR (1<<0) + +#define SD_CTRL_TRANSACTIONCONTROL_SET (1<<8) // 0x0100 + +#define SD_CTRL_CARDCLOCKCONTROL_FOR_SD_CARD (1<<15)// 0x8000 +#define SD_CTRL_CARDCLOCKCONTROL_ENABLE_CLOCK (1<<8) // 0x0100 +#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_512 (1<<7) // 0x0080 +#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_256 (1<<6) // 0x0040 +#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_128 (1<<5) // 0x0020 +#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_64 (1<<4) // 0x0010 +#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_32 (1<<3) // 0x0008 +#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_16 (1<<2) // 0x0004 +#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_8 (1<<1) // 0x0002 +#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_4 (1<<0) // 0x0001 +#define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_2 (0<<0) // 0x0000 + +#define MEM_CARD_OPTION_REQUIRED 0x000e +#define MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT (x) (((x)&0x0f)<<4)/* Four bits */ +#define MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT (1<<14) // 0x4000 +#define MEM_CARD_OPTION_DATA_XFR_WIDTH_1 (1<<15) // 0x8000 +#define MEM_CARD_OPTION_DATA_XFR_WIDTH_4 (0<<15) //~0x8000 + +#define SD_CTRL_COMMAND_INDEX (x) ((x)&0x3f)/* 0=CMD0, 1=CMD1, ..., 63=CMD63 */ +#define SD_CTRL_COMMAND_TYPE_CMD (0 << 6) +#define SD_CTRL_COMMAND_TYPE_ACMD (1 << 6) +#define SD_CTRL_COMMAND_TYPE_AUTHENTICATION (2 << 6) +#define SD_CTRL_COMMAND_RESPONSE_TYPE_NORMAL (0 << 8) +#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1 (4 << 8) +#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1B (5 << 8) +#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R2 (6 << 8) +#define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R3 (7 << 8) +#define SD_CTRL_COMMAND_DATA_PRESENT (1 << 11) +#define SD_CTRL_COMMAND_TRANSFER_READ (1 << 12) +#define SD_CTRL_COMMAND_TRANSFER_WRITE (0 << 12) +#define SD_CTRL_COMMAND_MULTI_BLOCK (1 << 13) +#define SD_CTRL_COMMAND_SECURITY_CMD (1 << 14) + +#define SD_CTRL_STOP_INTERNAL_ISSSUE_CMD12 (1 << 0) +#define SD_CTRL_STOP_INTERNAL_AUTO_ISSUE_CMD12 (1 << 8) + +#define SD_CTRL_CARDSTATUS_RESPONSE_END (1 << 0) +#define SD_CTRL_CARDSTATUS_RW_END (1 << 2) +#define SD_CTRL_CARDSTATUS_CARD_REMOVED_0 (1 << 3) +#define SD_CTRL_CARDSTATUS_CARD_INSERTED_0 (1 << 4) +#define SD_CTRL_CARDSTATUS_SIGNAL_STATE_PRESENT_0 (1 << 5) +#define SD_CTRL_CARDSTATUS_WRITE_PROTECT (1 << 7) +#define SD_CTRL_CARDSTATUS_CARD_REMOVED_3 (1 << 8) +#define SD_CTRL_CARDSTATUS_CARD_INSERTED_3 (1 << 9) +#define SD_CTRL_CARDSTATUS_SIGNAL_STATE_PRESENT_3 (1 << 10) + +#define SD_CTRL_BUFFERSTATUS_CMD_INDEX_ERROR (1 << 0) // 0x0001 +#define SD_CTRL_BUFFERSTATUS_CRC_ERROR (1 << 1) // 0x0002 +#define SD_CTRL_BUFFERSTATUS_STOP_BIT_END_ERROR (1 << 2) // 0x0004 +#define SD_CTRL_BUFFERSTATUS_DATA_TIMEOUT (1 << 3) // 0x0008 +#define SD_CTRL_BUFFERSTATUS_BUFFER_OVERFLOW (1 << 4) // 0x0010 +#define SD_CTRL_BUFFERSTATUS_BUFFER_UNDERFLOW (1 << 5) // 0x0020 +#define SD_CTRL_BUFFERSTATUS_CMD_TIMEOUT (1 << 6) // 0x0040 +#define SD_CTRL_BUFFERSTATUS_UNK7 (1 << 7) // 0x0080 +#define SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE (1 << 8) // 0x0100 +#define SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE (1 << 9) // 0x0200 +#define SD_CTRL_BUFFERSTATUS_ILLEGAL_FUNCTION (1 << 13)// 0x2000 +#define SD_CTRL_BUFFERSTATUS_CMD_BUSY (1 << 14)// 0x4000 +#define SD_CTRL_BUFFERSTATUS_ILLEGAL_ACCESS (1 << 15)// 0x8000 + +#define SD_CTRL_INTMASKCARD_RESPONSE_END (1 << 0) // 0x0001 +#define SD_CTRL_INTMASKCARD_RW_END (1 << 2) // 0x0004 +#define SD_CTRL_INTMASKCARD_CARD_REMOVED_0 (1 << 3) // 0x0008 +#define SD_CTRL_INTMASKCARD_CARD_INSERTED_0 (1 << 4) // 0x0010 +#define SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_0 (1 << 5) // 0x0020 +#define SD_CTRL_INTMASKCARD_UNK6 (1 << 6) // 0x0040 +#define SD_CTRL_INTMASKCARD_WRITE_PROTECT (1 << 7) // 0x0080 +#define SD_CTRL_INTMASKCARD_CARD_REMOVED_3 (1 << 8) // 0x0100 +#define SD_CTRL_INTMASKCARD_CARD_INSERTED_3 (1 << 9) // 0x0200 +#define SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_3 (1 << 10)// 0x0400 + +#define SD_CTRL_INTMASKBUFFER_CMD_INDEX_ERROR (1 << 0) // 0x0001 +#define SD_CTRL_INTMASKBUFFER_CRC_ERROR (1 << 1) // 0x0002 +#define SD_CTRL_INTMASKBUFFER_STOP_BIT_END_ERROR (1 << 2) // 0x0004 +#define SD_CTRL_INTMASKBUFFER_DATA_TIMEOUT (1 << 3) // 0x0008 +#define SD_CTRL_INTMASKBUFFER_BUFFER_OVERFLOW (1 << 4) // 0x0010 +#define SD_CTRL_INTMASKBUFFER_BUFFER_UNDERFLOW (1 << 5) // 0x0020 +#define SD_CTRL_INTMASKBUFFER_CMD_TIMEOUT (1 << 6) // 0x0040 +#define SD_CTRL_INTMASKBUFFER_UNK7 (1 << 7) // 0x0080 +#define SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE (1 << 8) // 0x0100 +#define SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE (1 << 9) // 0x0200 +#define SD_CTRL_INTMASKBUFFER_ILLEGAL_FUNCTION (1 << 13)// 0x2000 +#define SD_CTRL_INTMASKBUFFER_CMD_BUSY (1 << 14)// 0x4000 +#define SD_CTRL_INTMASKBUFFER_ILLEGAL_ACCESS (1 << 15)// 0x8000 + +#define SD_CTRL_DETAIL0_RESPONSE_CMD_ERROR (1 << 0) // 0x0001 +#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_RESPONSE_NON_CMD12 (1 << 2) // 0x0004 +#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_RESPONSE_CMD12 (1 << 3) // 0x0008 +#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_READ_DATA (1 << 4) // 0x0010 +#define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_WRITE_CRC_STATUS (1 << 5) // 0x0020 +#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_RESPONSE_NON_CMD12 (1 << 8) // 0x0100 +#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_RESPONSE_CMD12 (1 << 9) // 0x0200 +#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_READ_DATA (1 << 10)// 0x0400 +#define SD_CTRL_DETAIL0_CRC_ERROR_FOR_WRITE_CMD (1 << 11)// 0x0800 + +#define SD_CTRL_DETAIL1_NO_CMD_RESPONSE (1 << 0) // 0x0001 +#define SD_CTRL_DETAIL1_TIMEOUT_READ_DATA (1 << 4) // 0x0010 +#define SD_CTRL_DETAIL1_TIMEOUT_CRS_STATUS (1 << 5) // 0x0020 +#define SD_CTRL_DETAIL1_TIMEOUT_CRC_BUSY (1 << 6) // 0x0040 + +#define _IPAQ_ASIC3_SDIO_CTRL_Base 0x1200 + +#define IPAQ_ASIC3_SDIO (_b, s,x) \ + (*((volatile s *) ((_b) + _IPAQ_ASIC3_SDIO_CTRL_Base + (_IPAQ_ASIC3_SDIO_CTRL_ ## x)))) + +#define _IPAQ_ASIC3_SDIO_CTRL_Cmd 0x00 +#define _IPAQ_ASIC3_SDIO_CTRL_CardPortSel 0x04 +#define _IPAQ_ASIC3_SDIO_CTRL_Arg0 0x08 +#define _IPAQ_ASIC3_SDIO_CTRL_Arg1 0x0C +#define _IPAQ_ASIC3_SDIO_CTRL_TransferBlockCount 0x14 +#define _IPAQ_ASIC3_SDIO_CTRL_Response0 0x18 +#define _IPAQ_ASIC3_SDIO_CTRL_Response1 0x1C +#define _IPAQ_ASIC3_SDIO_CTRL_Response2 0x20 +#define _IPAQ_ASIC3_SDIO_CTRL_Response3 0x24 +#define _IPAQ_ASIC3_SDIO_CTRL_Response4 0x28 +#define _IPAQ_ASIC3_SDIO_CTRL_Response5 0x2C +#define _IPAQ_ASIC3_SDIO_CTRL_Response6 0x30 +#define _IPAQ_ASIC3_SDIO_CTRL_Response7 0x34 +#define _IPAQ_ASIC3_SDIO_CTRL_CardStatus 0x38 +#define _IPAQ_ASIC3_SDIO_CTRL_BufferCtrl 0x3C +#define _IPAQ_ASIC3_SDIO_CTRL_IntMaskCard 0x40 +#define _IPAQ_ASIC3_SDIO_CTRL_IntMaskBuffer 0x44 +#define _IPAQ_ASIC3_SDIO_CTRL_CardXferDataLen 0x4C +#define _IPAQ_ASIC3_SDIO_CTRL_CardOptionSetup 0x50 +#define _IPAQ_ASIC3_SDIO_CTRL_ErrorStatus0 0x54 +#define _IPAQ_ASIC3_SDIO_CTRL_ErrorStatus1 0x58 +#define _IPAQ_ASIC3_SDIO_CTRL_DataPort 0x60 +#define _IPAQ_ASIC3_SDIO_CTRL_TransactionCtrl 0x68 +#define _IPAQ_ASIC3_SDIO_CTRL_CardIntCtrl 0x6C +#define _IPAQ_ASIC3_SDIO_CTRL_ClocknWaitCtrl 0x70 +#define _IPAQ_ASIC3_SDIO_CTRL_HostInformation 0x74 +#define _IPAQ_ASIC3_SDIO_CTRL_ErrorCtrl 0x78 +#define _IPAQ_ASIC3_SDIO_CTRL_LEDCtrl 0x7C +#define _IPAQ_ASIC3_SDIO_CTRL_SoftwareReset 0x1C0 + +#define IPAQ_ASIC3_SDIO_CTRL_Cmd (_b) IPAQ_ASIC3_SDIO( _b, u16, Cmd )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_CardPortSel (_b) IPAQ_ASIC3_SDIO( _b, u16, CardPortSel )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_Arg0 (_b) IPAQ_ASIC3_SDIO( _b, u16, Arg0 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_Arg1 (_b) IPAQ_ASIC3_SDIO( _b, u16, Arg1 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_TransferBlockCount (_b) IPAQ_ASIC3_SDIO( _b, u16, TransferBlockCount )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_Response0 (_b) IPAQ_ASIC3_SDIO( _b, u16, Response0 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_Response1 (_b) IPAQ_ASIC3_SDIO( _b, u16, Response1 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_Response2 (_b) IPAQ_ASIC3_SDIO( _b, u16, Response2 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_Response3 (_b) IPAQ_ASIC3_SDIO( _b, u16, Response3 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_Response4 (_b) IPAQ_ASIC3_SDIO( _b, u16, Response4 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_Response5 (_b) IPAQ_ASIC3_SDIO( _b, u16, Response5 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_Response6 (_b) IPAQ_ASIC3_SDIO( _b, u16, Response6 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_Response7 (_b) IPAQ_ASIC3_SDIO( _b, u16, Response7 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_CardStatus (_b) IPAQ_ASIC3_SDIO( _b, u16, CardStatus )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_BufferCtrl (_b) IPAQ_ASIC3_SDIO( _b, u16, BufferCtrl )/* and error status*/ +#define IPAQ_ASIC3_SDIO_CTRL_IntMaskCard (_b) IPAQ_ASIC3_SDIO( _b, u16, IntMaskCard )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_IntMaskBuffer (_b) IPAQ_ASIC3_SDIO( _b, u16, IntMaskBuffer )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_CardXferDataLen (_b) IPAQ_ASIC3_SDIO( _b, u16, CardXferDataLen )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_CardOptionSetup (_b) IPAQ_ASIC3_SDIO( _b, u16, CardOptionSetup )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_ErrorStatus0 (_b) IPAQ_ASIC3_SDIO( _b, u16, ErrorStatus0 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_ErrorStatus1 (_b) IPAQ_ASIC3_SDIO( _b, u16, ErrorStatus1 )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_DataPort (_b) IPAQ_ASIC3_SDIO( _b, u16, DataPort )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_TransactionCtrl (_b) IPAQ_ASIC3_SDIO( _b, u16, TransactionCtrl )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_CardIntCtrl (_b) IPAQ_ASIC3_SDIO( _b, u16, CardIntCtrl )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_ClocknWaitCtrl (_b) IPAQ_ASIC3_SDIO( _b, u16, ClocknWaitCtrl )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_HostInformation (_b) IPAQ_ASIC3_SDIO( _b, u16, HostInformation )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_ErrorCtrl (_b) IPAQ_ASIC3_SDIO( _b, u16, ErrorCtrl )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_LEDCtrl (_b) IPAQ_ASIC3_SDIO( _b, u16, LEDCtrl )/* */ +#define IPAQ_ASIC3_SDIO_CTRL_SoftwareReset (_b) IPAQ_ASIC3_SDIO( _b, u16, SoftwareReset )/* */ + +#define IPAQ_ASIC3_MAP_SIZE 0x2000 + +#endif
Signature · 2 lines
Best regards, Paul mailto:[email protected]
Quoted 46 lines · On Tue, 1 May 2007 08:08:39 +0300 Paul Sokolovsky <[email protected]> wrote:
Hello linux-kernel,
Intro: This is a header with hardware definitions for ASIC3 chip, contributed by HP/Compaq. It is provided as-is, as a vendor-originated header.
---------
ipaq-asic3.h: Hardware definitions for ASIC3 chip, found in ~12 handheld devices from HP/Compaq and HTC.Signed-off-by Paul Sokolovsky <[email protected]>include/asm-arm/hardware/ipaq-asic3.h | 609 +++++++++++++++++++++++++++++++++ 1 files changed, 609 insertions(+), 0 deletions(-)include/asm-arm/hardware/ipaq-asic3.h new file +24
-0@@ -0,0 +1,609 @@ +/* +* +* Definitions for the HTC ASIC3 chip found in several handheld devices +* +* Copyright 2001 Compaq Computer Corporation. +* +* Use consistent with the GNU GPL is permitted, +* provided that this copyright notice is +* preserved in its entirety in all copies and derived works. +* +* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, +* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS +* FITNESS FOR ANY PARTICULAR PURPOSE. +* +* Author: Andrew Christian +* +*/ + +#ifndef IPAQ_ASIC3_H +#define IPAQ_ASIC3_H + +/****************************************************/ +/* IPAQ, ASIC #3, replaces ASIC #1 */ +
include/asm-arm/hardware/ipaq-asic3.h line 34
Quoted 10 lines
include/asm-arm/hardware/ipaq-asic3.h new file +10
-0+#define IPAQ_ASIC3 (_b,s,x,y) \ + (*((volatile s *) (_b + _IPAQ_ASIC3_ ## x ## _Base + (_IPAQ_ASIC3_ ## x ## _ ## y)))) +#define IPAQ_ASIC3_N (_b,s,x,y,z) \ + (*((volatile s *) (_b + _IPAQ_ASIC3_ ## x ## _ ## y ## _Base + (_IPAQ_ASIC3_ ## x ## _ ## z)))) + +#define IPAQ_ASIC3_GPIO (_b,s,x,y) \ + (*((volatile s *) (_b + _IPAQ_ASIC3_GPIO_ ## x ## _Base + (_IPAQ_ASIC3_GPIO_ ## y)))) + +#define IPAQ_ASIC3_OFFSET (x,y) (_IPAQ_ASIC3_ ## x ## _Base + _IPAQ_ASIC3_ ## x ## _ ## y) +#define IPAQ_ASIC3_GPIO_OFFSET (x,y) (_IPAQ_ASIC3_GPIO_ ## x ## _Base + _IPAQ_ASIC3_GPIO_ ## y)
Oh my eyes. What are these doing?
The volatiles are a worry - volatile is said to be basically-always-wrong in-kernel, although we've never managed to document why, and i386 cheerfully uses it in readb() and friends.
Perhaps if you can describe presisely what's going on here, alternatives might be suggested.
Quoted 9 lines
Quoted 9 lines
+ * Copyright 2001 Compaq Computer Corporation.
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
This doesn't appear to be self consistent or GPL compatible. Any binary will be a derivative work and will not contain the copyright notice.
Alan
Hello Alan,
Quoted 10 lines · you
Quoted 9 lines
Quoted 9 lines
+ * Copyright 2001 Compaq Computer Corporation.
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
Quoted 2 lines
This doesn't appear to be self consistent or GPL compatible. Any binary will be a derivative work and will not contain the copyright notice.
Well, this is one of those hard questions... Fortunately,
people who worked on this and were Compaq employees are reachable, so I contacted Jamie Hicks, who is one of the authors of iPaq ports, regarding solution for this. Jamie, would it be possible to leave Compaq and other copyright notices, and Compaq disclaimer intact, but replace following paragraph:
Quoted 3 lines
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
With more common wording as appears in kernel sources:
Quoted 4 lines
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.
(or GPL2 wording, or verbose wording, whatever you see fit)
Thanks!
Quoted 1 line
Alan
Signature · 2 lines
Best regards, Paul mailto:[email protected]
Quoted 43 lines · Paul Sokolovsky
Hello Alan,
Quoted 12 lines · you
Quoted 10 lines
Quoted 10 lines
+ * Copyright 2001 Compaq Computer Corporation.
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.Quoted 3 lines
This doesn't appear to be self consistent or GPL compatible. Any binary will be a derivative work and will not contain the copyright notice.
Well, this is one of those hard questions... Fortunately,
people who worked on this and were Compaq employees are reachable, so I contacted Jamie Hicks, who is one of the authors of iPaq ports, regarding solution for this. Jamie, would it be possible to leave Compaq and other copyright notices, and Compaq disclaimer intact, but replace following paragraph:Quoted 4 lines
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.With more common wording as appears in kernel sources:
Quoted 5 lines
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.
Quoted 4 lines
(or GPL2 wording, or verbose wording, whatever you see fit)
Thanks!
The intent of the vague wording was to have the copyright notice and Compaq disclaimer of warranties preserved in the source code, not in binaries, but it is definitely ambiguous. As I understand it, copyright law says the copyright notices need to be preserved in source code, so that part of the statement is redundant, and GPL has its own warrantee disclaimer, so I think the standard wording is just fine. I approve changing to the more standard GPL wording used in the kernel sources in order to make this acceptable into the kernel.org tree.
Jamey Hicks
[RFC/PATCH] doc: volatile considered evil
In reply to Andrew MortonQuoted 8 lines · On Mon, 30 Apr 2007 23:56:42 -0700 Andrew Morton wrote:
Oh my eyes. What are these doing?
The volatiles are a worry - volatile is said to be basically-always-wrong in-kernel, although we've never managed to document why, and i386 cheerfully uses it in
readb()and friends.Perhaps if you can describe presisely what's going on here, alternatives might be suggested.
[well, can be turned into a patch]
Here are some 'volatile' comments from Linus, extracted from several emails in at least 2 threads.
If this is close to useful, we can add it to Documentation/.
===============================================================
***** "volatile" considered useless and evil: Just Say NO! *****
Do not use the C-language "volatile" keyword
(extracted from lkml emails from Linus)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[Comment about a patch:]
Quoted 1 line
Also made all the relevant
mce_logfields volatile for further safety.
I refuse to apply this part.
If the memory barriers are right, then the "volatile" doesn't matter.
And if the memory barriers aren't right, then "volatile" doesn't help.
Using "volatile" in data structures is basically _always_ a bug.
The only acceptable uses for "volatile" are:
- in _code_, i.e., for things like the definition of "readb()" etc, where we use it to force a particular access.
- with inline asms
- on "jiffies", for stupid legacy reasons
Basically, a volatile on a data structure can NEVER be right. If it makes a difference, it's a sign of improper locking.
And the reason I refuse to apply that part of the patch is that anybody who even _thinks_ that they make a difference is horribly and utterly confused, and doesn't understand locking.
So please _never_ use them like this.
Quoted 6 lines
mce_logis fully lockless - it deals with machine checks which act like NMIs. That is it's problem.In theory the memory barriers should be sufficient, the volatiles are just an additional safety net to make it clear to humans/compiler these memory areas can change any time.
If the memory barriers aren't sufficient, the volatiles are useless. If the memory barriers _are_ sufficient, the volatiles are useless.
See? They're useless.
The only thing they do is
- potentially make the compiler generate worse code for no reason (the "no reason" being that if there aren't any barriers in between, the compiler _should_ merge accesses)
- make some people _believe_ that that compiler does something "right".
The first point doesn't much matter. The second point matters a LOT.
Anybody who thinks "volatile" matters is WRONG. As such, a "volatile" is anti-documentation - it makes people think that something is true that is NOT true.
In other words, volatile on data structures is _evil_, because it instills the wrong kind of beliefs in people. "volatility" is not a data structure issue. It's a matter of the _code_ working on the data structure.
"volatile" really _is_ misdesigned. The semantics of it are so unclear as to be totally useless. The only thing "volatile" can ever do is generate worse code, WITH NO UPSIDES.
Historically (and from the standpoint of the C standard), the definition of "volatile" is that any access is "visible" in the machine, and it really kind of makes sense for hardware accesses, except these days hardware accesses have other rules that are _not_ covered by "volatile", so you can't actually use them for that.
And for accesses that have some software rules (i.e., not IO devices etc), the rules for "volatile" are too vague to be useful.
So if you actually have rules about how to access a particular piece of memory, just make those rules _explicit_. Use the real rules. Not volatile, because volatile will always do the wrong thing.
Also, more importantly, "volatile" is on the wrong _part_ of the whole system. In C, it's "data" that is volatile, but that is insane. Data isn't volatile - _accesses_ are volatile. So it may make sense to say "make this particular _access_ be careful", but not "make all accesses to this data use some random strategy".
So the only thing "volatile" is potentially useful for is:
- actual accessor functions can use it in a _cast_ to make one particular access follow the rules of "don't cache this one dereference". That is useful as part of a _bigger_ set of rules about that access (i.e., it might be the internal implementation of a "readb()", for example).
- for "random number generation" data locations, where you literally don't _have_ any rules except "it's a random number". The only really valid example of this is the "jiffy" timer tick.
Any other use of "volatile" is almost certainly a bug, or just useless.
Side note: it's also totally possible that a volatiles _hides_ a bug, i.e., removing the volatile ends up having bad effects, but that's because the software itself isn't actually following the rules (or, more commonly, the rules are broken, and somebody added "volatile" to hide the problem).
It's a bug if the volatile means that you don't follow the proper protocol for accessing the data, and it's useless (and generally generates worse code) if you already do.
So just say NO! to volatile except under the above circumstances.
[from another email thread:]
I suspect we should just face up to the fact that:
(a) "volatile" on kernel data is basically always a bug, and you should use locking. "volatile" doesn't help anything at all with memory ordering and friends, so it's insane to think it "solves" anything on its own.
(b) on "iomem" pointers it does make sense, but those need special accessor functions _anyway_, so things like test_bit() wouldn't work on them.
(c) if you spin on a value [that's] changing, you should use "cpu_relax()" or "barrier()" anyway, which will force gcc to re-load any values from memory over the loop.
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 7 lines · Randy Dunlap
[well, can be turned into a patch]
Here are some 'volatile' comments from Linus, extracted from several emails in at least 2 threads.
If this is close to useful, we can add it to
Documentation/.
Quoted 8 lines
===============================================================
***** "volatile" considered useless and evil: Just Say NO! *****
Do not use the C-language "volatile" keyword
(extracted from lkml emails from Linus)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Since 'volatile' has two different semantics depending on the context in which it is used, this warning should be appended to include the fact that it is legitimate to use for inline assembly.
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 3 lines · David Rientjes
Since 'volatile' has two different semantics depending on the context in which it is used, this warning should be appended to include the fact that it is legitimate to use for inline assembly.
I think it hasn't two semantics, it's like arguing that char has two semantics.
Volatile does one thing - prohibits C compiler from optimizing accesses to the variable. Either with (volatile *) casts and with volatile var;
Linus is right in that volatile != direct access to the hardware and direct sync between all CPUs. Yes, most uses in high level code are probably bugs. OTOH, there are other uses where optimizing must be prohibited. It doesn't matter which form
is used, in fact
volatile type name; name is equivalent to: type name; *(volatile type *)&name;
At least as long as "volatile" keyword is concerned.
Signature · 1 line
Krzysztof Halasa
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 11 lines · Krzysztof Halasa
Quoted 3 lines
Since 'volatile' has two different semantics depending on the context in which it is used, this warning should be appended to include the fact that it is legitimate to use for inline assembly.
I think it hasn't two semantics, it's like arguing that char has two semantics.
Volatile does one thing - prohibits C compiler from optimizing accesses to the variable. Either with (volatile *) casts and with volatile var;
What the meaning of an "access" to a volatile memory-mapped I/O port or a variable that can be asynchronously interrupted is implementation-defined.
You're only citing qualified versions of objects.
In an asm construct, if all your input operands are modified and specified as output operands as well, volatile must be added so that the entire construct is not optimized away. Additionally, it must be added if your construct modifies memory that is neither listed in inputs nor outputs to the construct so that it is known to have at least one side-effect. Then, the compiler cannot delete your construct if it is reachable because it may produce such side-effects.
Thus, the warning that was proposed for addition to CodingStyle should be modified to explicitly state that the use of 'volatile' for asm constructs is perfectly legitimate and its use as a type qualifier for objects in code is inappropriate.
David
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 27 lines · On Tue, 8 May 2007 13:20:31 -0700 (PDT) David Rientjes wrote:
Quoted 11 lines · Krzysztof Halasa
Quoted 3 lines
Since 'volatile' has two different semantics depending on the context in which it is used, this warning should be appended to include the fact that it is legitimate to use for inline assembly.
I think it hasn't two semantics, it's like arguing that char has two semantics.
Volatile does one thing - prohibits C compiler from optimizing accesses to the variable. Either with (volatile *) casts and with volatile var;
What the meaning of an "access" to a volatile memory-mapped I/O port or a variable that can be asynchronously interrupted is implementation-defined.
You're only citing qualified versions of objects.
In an asm construct, if all your input operands are modified and specified as output operands as well, volatile must be added so that the entire construct is not optimized away. Additionally, it must be added if your construct modifies memory that is neither listed in inputs nor outputs to the construct so that it is known to have at least one side-effect. Then, the compiler cannot delete your construct if it is reachable because it may produce such side-effects.
Quoted 4 lines
Thus, the warning that was proposed for addition to CodingStyle should be modified to explicitly state that the use of 'volatile' for asm constructs is perfectly legitimate and its use as a type qualifier for objects in code is inappropriate.
It's already there, isn't it? <quote from original:>
The only acceptable uses for "volatile" are:
- in _code_, i.e., for things like the definition of "readb()" etc, where we use it to force a particular access.
- with inline asms
- on "jiffies", for stupid legacy reasons
</quote>
or are you saying that you want to subject/header/title modified also?
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 4 lines · Randy Dunlap
It's already there, isn't it? <quote from original:>
The only acceptable uses for "volatile" are:
Quoted 9 lines
- in _code_, i.e., for things like the definition of "
readb()" etc, where we use it to force a particular access.
- with inline asms
- on "jiffies", for stupid legacy reasons</quote>
or are you saying that you want to subject/header/title modified also?
I wasn't aware that you were considering the inclusion of Linus' entire email in the document. There exists a point where CodingStyle becomes so large that people choose not to read it in its entirety, so I was expecting only an addition that would explicit document the acceptable and unacceptable uses of 'volatile' in kernel code with perhaps a link to his email.
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 11 lines · David Rientjes
Quoted 9 lines · Randy Dunlap
It's already there, isn't it? <quote from original:>
The only acceptable uses for "volatile" are:
- in _code_, i.e., for things like the definition of "
readb()" etc, where we use it to force a particular access.
- with inline asms
- on "jiffies", for stupid legacy reasons
Quoted 7 lines
Quoted 4 lines
</quote>
or are you saying that you want to subject/header/title modified also?
I wasn't aware that you were considering the inclusion of Linus' entire email in the document. There exists a point where CodingStyle becomes so large that people choose not to read it in its entirety, so I was expecting only an addition that would explicit document the acceptable and unacceptable uses of 'volatile' in kernel code with perhaps a link to his email.
but I wouldn't put it into CodingStyle.
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [RFC/PATCH] doc: volatile considered evil
In reply to Krzysztof HalasaQuoted 11 lines · Krzysztof Halasa
Quoted 4 lines · David Rientjes
Since 'volatile' has two different semantics depending on the context in which it is used, this warning should be appended to include the fact that it is legitimate to use for inline assembly.
I think it hasn't two semantics, it's like arguing that char has two semantics.
No, David means that "asm volatile (...)" is meaningful and OK to use.
J
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 1 line · Jeremy Fitzhardinge
No, David means that "asm volatile (...)" is meaningful and OK to use.
Ok, I mistook that.
Signature · 1 line
Krzysztof Halasa
Re: [RFC/PATCH] doc: volatile considered evil
In reply to Jeremy FitzhardingeQuoted 1 line · Jeremy Fitzhardinge
No, David means that "asm volatile (...)" is meaningful and OK to use.
In a driver? Highly unlikey it is OK. In a filesystem? Even more unlikely it is OK to use.
The set of circumstances where 'volatile' is acceptable is very limited.
You will see it used properly in the definitions of writel(), for example. But most drivers using 'volatile' are likely bugs.
Jeff
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 2 lines · Jeff Garzik
Quoted 1 line · Jeremy Fitzhardinge
No, David means that "asm volatile (...)" is meaningful and OK to use.
I thought it was OK in readl(), writel(), etc... (and in asm), but that's it. (and jiffies)
Quoted 5 lines
In a driver? Highly unlikey it is OK. In a filesystem? Even more unlikely it is OK to use.
The set of circumstances where 'volatile' is acceptable is very limited.
You will see it used properly in the definitions of
writel(), for example. But most drivers using 'volatile' are likely bugs.
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 12 lines · Randy Dunlap
Quoted 2 lines · Jeff Garzik
Quoted 1 line · Jeremy Fitzhardinge
No, David means that "asm volatile (...)" is meaningful and OK to use.
I thought it was OK in
readl(),writel(), etc... (and in asm), but that's it. (and jiffies)Quoted 5 lines
In a driver? Highly unlikey it is OK. In a filesystem? Even more unlikely it is OK to use.
The set of circumstances where 'volatile' is acceptable is very limited.
You will see it used properly in the definitions of
writel(), for example. But most drivers using 'volatile' are likely bugs.
Not sure how to interpret your top-posted response :)
It is normal in the definition of writel(), in arch code, but inappropriate in drivers when they _use_ writel().
If I may generalize, arch code generally knows what it's doing, when it uses volatile. OTOH, driver authors that use volatile generally do /not/ know what they are doing.
Jeff
Re: [RFC/PATCH] doc: volatile considered evil
In reply to David RientjesQuoted 4 lines · David Rientjes
Since 'volatile' has two different semantics depending on the context in which it is used, this warning should be appended to include the fact that it is legitimate to use for inline assembly.
It's probably worth noting that "asm volatile (...)" doesn't mean what many people think it means: specifically, it *does not* prevent the asm from being reordered with respect to the surrounding code. It may not even prevent it from being reordered with respect to other asm volatiles. *All* it means is that the asm code will be emitted even if the compiler doesn't think its results will be used. Note that an "asm()" with no outputs is implicitly "asm volatile()" - on the grounds that it would be otherwise useless as far as gcc can tell.
If you need to guarantee ordering of asm statements, you must do it explicitly, with either a "memory" clobber, or some finer-grain serialization variable (like the _proxy_pda stuff). It would be useful if you could tell gcc "I'm passing this variable to the asm for serialization purposes, but there's no need to generate any explicit references to it", but as far as I know there's no support for that.
J
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 14 lines · Jeremy Fitzhardinge
Quoted 2 lines · David Rientjes
Since 'volatile' has two different semantics depending on the context in which it is used, this warning should be appended to include the fact that it is legitimate to use for inline assembly.
It's probably worth noting that "asm volatile (...)" doesn't mean what many people think it means: specifically, it *does not* prevent the asm from being reordered with respect to the surrounding code. It may not even prevent it from being reordered with respect to other asm volatiles. *All* it means is that the asm code will be emitted even if the compiler doesn't think its results will be used. Note that an "
asm()" with no outputs is implicitly "asmvolatile()" - on the grounds that it would be otherwise useless as far as gcc can tell.
Quoted 8 lines
If you need to guarantee ordering of asm statements, you must do it explicitly, with either a "memory" clobber, or some finer-grain serialization variable (like the
_proxy_pdastuff). It would be useful if you could tell gcc "I'm passing this variable to the asm for serialization purposes, but there's no need to generate any explicit references to it", but as far as I know there's no support for that.J
The doc. should just be talking about "volatile" in C mostly. Any asm volatile comments are "extra".
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [RFC/PATCH] doc: volatile considered evil
In reply to Jeremy FitzhardingeQuoted 9 lines · Jeremy Fitzhardinge
It's probably worth noting that "asm volatile (...)" doesn't mean what many people think it means: specifically, it *does not* prevent the asm from being reordered with respect to the surrounding code. It may not even prevent it from being reordered with respect to other asm volatiles. *All* it means is that the asm code will be emitted even if the compiler doesn't think its results will be used. Note that an "
asm()" with no outputs is implicitly "asmvolatile()" - on the grounds that it would be otherwise useless as far as gcc can tell.
Quoted 7 lines
If you need to guarantee ordering of asm statements, you must do it explicitly, with either a "memory" clobber, or some finer-grain serialization variable (like the
_proxy_pdastuff). It would be useful if you could tell gcc "I'm passing this variable to the asm for serialization purposes, but there's no need to generate any explicit references to it", but as far as I know there's no support for that.
Ok, so let's take your second paragraph and my email of an hour ago:
In an asm construct, if all your input operands are modified and specified as output operands as well, volatile must be added so that the entire construct is not optimized away. Additionally, it must be added if your construct modifies memory that is neither listed in inputs nor outputs to the construct so that it is known to have at least one side-effect. Then, the compiler cannot delete your construct if it is reachable because it may produce such side-effects.
and add it to any proposed change to CodingStyle that suggests against the 'volatile' keyword since there exists a distinct difference in behavior between using the keyword as a type qualifier for an object and as a qualifier for an asm construct.
David
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 8 lines · David Rientjes
Ok, so let's take your second paragraph and my email of an hour ago:
In an asm construct, if all your input operands are modified and specified as output operands as well, volatile must be added so that the entire construct is not optimized away. Additionally, it must be added if your construct modifies memory that is neither listed in inputs nor outputs to the construct so that it is known to have at least one side-effect.
Hm. Is "asm volatile" necessary if you have a "memory" clobber? Would probably be the safest thing, I guess.
Quoted 5 lines
and add it to any proposed change to CodingStyle that suggests against the 'volatile' keyword since there exists a distinct difference in behavior between using the keyword as a type qualifier for an object and as a qualifier for an asm construct.
Yeah, they're completely different. They're not even analogous, really, which was my point. People confer more meaning to "asm volatile" than it actually has, because of the analogy with volatile variables/types. They would have been better off with something like "asm static", which isn't much more meaningful, but at least it doesn't mislead the reader into thinking it has anything to do with the other volatile.
But yes, seems like a worthwhile thing to point out. Or just point to the gcc manual, which is pretty clear about all this stuff.
J
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 10 lines · Jeremy Fitzhardinge
Quoted 6 lines
In an asm construct, if all your input operands are modified and specified as output operands as well, volatile must be added so that the entire construct is not optimized away. Additionally, it must be added if your construct modifies memory that is neither listed in inputs nor outputs to the construct so that it is known to have at least one side-effect.
Hm. Is "asm volatile" necessary if you have a "memory" clobber? Would probably be the safest thing, I guess.
No, because the first requirement for 'volatile' in my paragraph above is restricted to clobbering specific hard registers and an operand cannot describe a hard register for a member when that register appears in the clobber list. If an input operand is modified (i.e. not "accessed", rather "modified" inclusive of the case where the previous value is the same as the original value) then it must also be specified as an output operand.
Now if all such output operands are to specify that the input operands were "modified", 'volatile' is required to ensure the side-effects are preserved or, otherwise, gcc is free optimize the entire asm construct away since it appears to be unused.
Quoted 7 lines
Yeah, they're completely different. They're not even analogous, really, which was my point. People confer more meaning to "asm volatile" than it actually has, because of the analogy with volatile variables/types. They would have been better off with something like "asm static", which isn't much more meaningful, but at least it doesn't mislead the reader into thinking it has anything to do with the other volatile.
You're point about reordering "asm volatile" constructs differs depending on -mvolatile-asm-stop or -mno-volatile-asm-stop, however.
David
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 5 lines · David Rientjes
Now if all such output operands are to specify that the input operands were "modified", 'volatile' is required to ensure the side-effects are preserved or, otherwise, gcc is free optimize the entire asm construct away since it appears to be unused.
Yup.
Quoted 9 lines
Quoted 8 lines
Yeah, they're completely different. They're not even analogous, really, which was my point. People confer more meaning to "asm volatile" than it actually has, because of the analogy with volatile variables/types. They would have been better off with something like "asm static", which isn't much more meaningful, but at least it doesn't mislead the reader into thinking it has anything to do with the other volatile.
Quoted 3 lines
You're point about reordering "asm volatile" constructs differs depending on -mvolatile-asm-stop or -mno-volatile-asm-stop, however.
Erm, that seems to be ia64 specific, and I have no idea what adding a "stop bit" implies. Can you set even or odd parity too?
J
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 7 lines · Jeremy Fitzhardinge
Quoted 3 lines
You're point about reordering "asm volatile" constructs differs depending on -mvolatile-asm-stop or -mno-volatile-asm-stop, however.
Erm, that seems to be ia64 specific, and I have no idea what adding a "stop bit" implies. Can you set even or odd parity too?
It is analogous with a sequence point for ia64. But, as you mentioned, it is ia64 specific so your comment about "asm volatile" constructs not being reordered is always appropriate outside of ia64 specific code but may not apply to ia64 if we ever compiled with -mvolatile-asm-stop. If we do not compile with that option, the behavior is unspecified. I don't think we'll be adding -mvolatile-asm-stop support any time soon so your warning certainly is appropriate for all code at this time.
David
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 8 lines · David Rientjes
It is analogous with a sequence point for ia64. But, as you mentioned, it is ia64 specific so your comment about "asm volatile" constructs not being reordered is always appropriate outside of ia64 specific code but may not apply to ia64 if we ever compiled with -mvolatile-asm-stop. If we do not compile with that option, the behavior is unspecified. I don't think we'll be adding -mvolatile-asm-stop support any time soon so your warning certainly is appropriate for all code at this time.
Sounds like it's referring to micro-architectural reordering, which is distinct from compiler reordering. In other words, even if you specified "-mvolatile-asm-stop" I would assume that the compiler could still reorder the asm statements. Am I right, or should I read more into the manual description than it actually says?
J
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 6 lines · Jeremy Fitzhardinge
Sounds like it's referring to micro-architectural reordering, which is distinct from compiler reordering. In other words, even if you specified "-mvolatile-asm-stop" I would assume that the compiler could still reorder the asm statements. Am I right, or should I read more into the manual description than it actually says?
The ia64 architecture does not include any interlocks for asm constructs and allow them to be executed in parallel without stop bits (although it should emit a diagnostic message from gcc, although that is not a constraint that was introduced in C99). Adding -mvolatile-asm-stops will add these stop bits for any asm volatile construct that does not already have them so that gcc is aware that it is unsafe to execute such constructs in parallel.
[ This is a tangent because we currently don't have -mvolatile-asm-stop
support and it's ia64-specific. If they ever request such support, then this will simply alter your warning about reordering asm volatile constructs to exclude the ia64 case. ]
David
Re: [RFC/PATCH] doc: volatile considered evil
In reply to David RientjesQuoted 11 lines · On Tue, 8 May 2007 14:27:33 -0700 (PDT) David Rientjes wrote:
Quoted 9 lines · Jeremy Fitzhardinge
It's probably worth noting that "asm volatile (...)" doesn't mean what many people think it means: specifically, it *does not* prevent the asm from being reordered with respect to the surrounding code. It may not even prevent it from being reordered with respect to other asm volatiles. *All* it means is that the asm code will be emitted even if the compiler doesn't think its results will be used. Note that an "
asm()" with no outputs is implicitly "asmvolatile()" - on the grounds that it would be otherwise useless as far as gcc can tell.
Quoted 7 lines
Quoted 7 lines
If you need to guarantee ordering of asm statements, you must do it explicitly, with either a "memory" clobber, or some finer-grain serialization variable (like the
_proxy_pdastuff). It would be useful if you could tell gcc "I'm passing this variable to the asm for serialization purposes, but there's no need to generate any explicit references to it", but as far as I know there's no support for that.
Well, the document is really about "volatile" in C, not in gcc asm extensions.
But if you want to add paragraphs(s) to the file, that's OK too.
Quoted 11 lines
Ok, so let's take your second paragraph and my email of an hour ago:
In an asm construct, if all your input operands are modified and specified as output operands as well, volatile must be added so that the entire construct is not optimized away. Additionally, it must be added if your construct modifies memory that is neither listed in inputs nor outputs to the construct so that it is known to have at least one side-effect. Then, the compiler cannot delete your construct if it is reachable because it may produce such side-effects.
Quoted 4 lines
and add it to any proposed change to CodingStyle that suggests against the 'volatile' keyword since there exists a distinct difference in behavior between using the keyword as a type qualifier for an object and as a qualifier for an asm construct.
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [RFC/PATCH] doc: volatile considered evil
In reply to Randy DunlapQuoted 11 lines · Randy Dunlap
Quoted 8 lines · On Mon, 30 Apr 2007 23:56:42 -0700 Andrew Morton wrote:
Oh my eyes. What are these doing?
The volatiles are a worry - volatile is said to be basically-always-wrong in-kernel, although we've never managed to document why, and i386 cheerfully uses it in
readb()and friends.Perhaps if you can describe presisely what's going on here, alternatives might be suggested.
Quoted 6 lines
[well, can be turned into a patch]
Here are some 'volatile' comments from Linus, extracted from several emails in at least 2 threads.
If this is close to useful, we can add it to
Documentation/.
Yes, definitely. Say Documentation/volatile-usage.txt -- this raw version could be touched a little bit, to have sections that clearly explain (1) how volatile makes the compiler generate trashy code, (2) why volatile doesn't even do what people _think_ it does, considering code is executed out-of-order by _hardware_ these days and not due to compilers like was the case 20 years back, (3) and so volatile ends up _hiding_ bugs from people and thus should be consigned to the trash can of history, (4) _except_ for _really special_ usage cases like reading IO mapped as memory.
PATCH 1/1 doc: volatile considered evil
Quoted 9 lines · On Tue, 8 May 2007 13:07:51 -0700 Satyam Sharma wrote:
Yes, definitely. Say
Documentation/volatile-usage.txt-- this raw version could be touched a little bit, to have sections that clearly explain (1) how volatile makes the compiler generate trashy code, (2) why volatile doesn't even do what people _think_ it does, considering code is executed out-of-order by _hardware_ these days and not due to compilers like was the case 20 years back, (3) and so volatile ends up _hiding_ bugs from people and thus should be consigned to the trash can of history, (4) _except_ for_reallyspecial_usage cases like reading IO mapped as memory.
Hi Satyam,
If you would like to organize it like that, I'd be happy to turn it over to you.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
From: Randy Dunlap <[email protected]>
Add information on the problems with the C-language "volatile" keyword and why it should not be used (most of the time).
--- Documentation/volatile-usage.txt | 129 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+)
Documentation/volatile-usage.txt new file +129 -0
@@ -0,0 +1,129 @@ +***** "volatile" considered useless and evil: Just Say NO! ***** + +Do not use the C-language "volatile" keyword +(extracted from lkml emails from Linus) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +[Comment about a patch:] + +> Also made all the relevant mce_log fields volatile for further safety. + +I refuse to apply this part. + +If the memory barriers are right, then the "volatile" doesn't matter. + +And if the memory barriers aren't right, then "volatile" doesn't help. + +Using "volatile" in data structures is basically _always_ a bug. + +The only acceptable uses for "volatile" are: + + - in _code_, i.e., for things like the definition of "readb()" etc, where we + use it to force a particular access. + - with inline asms + - on "jiffies", for stupid legacy reasons + +Basically, a volatile on a data structure can NEVER be right. If it makes +a difference, it's a sign of improper locking. + +And the reason I refuse to apply that part of the patch is that anybody +who even _thinks_ that they make a difference is horribly and utterly +confused, and doesn't understand locking. + +So please _never_ use them like this. + + +> mce_log is fully lockless - it deals with machine checks which act like NMIs. +> That is it's problem. +> +> In theory the memory barriers should be sufficient, the volatiles are +> just an additional safety net to make it clear to humans/compiler these memory +> areas can change any time. + +If the memory barriers aren't sufficient, the volatiles are useless. If +the memory barriers _are_ sufficient, the volatiles are useless. + +See? They're useless. + +The only thing they do is + + - potentially make the compiler generate worse code for no reason (the + "no reason" being that if there aren't any barriers in between, the + compiler _should_ merge accesses) + + - make some people _believe_ that that compiler does something "right". + +The first point doesn't much matter. The second point matters a LOT. + +Anybody who thinks "volatile" matters is WRONG. As such, a "volatile" is +anti-documentation - it makes people think that something is true that is +NOT true. + +In other words, volatile on data structures is _evil_, because it instills +the wrong kind of beliefs in people. "volatility" is not a data structure +issue. It's a matter of the _code_ working on the data structure. + + +"volatile" really _is_ misdesigned. The semantics of it are so unclear as +to be totally useless. The only thing "volatile" can ever do is generate +worse code, WITH NO UPSIDES. + +Historically (and from the standpoint of the C standard), the definition +of "volatile" is that any access is "visible" in the machine, and it +really kind of makes sense for hardware accesses, except these days +hardware accesses have other rules that are _not_ covered by "volatile", +so you can't actually use them for that. + +And for accesses that have some software rules (i.e., not IO devices etc), +the rules for "volatile" are too vague to be useful. + +So if you actually have rules about how to access a particular piece of +memory, just make those rules _explicit_. Use the real rules. Not +volatile, because volatile will always do the wrong thing. + +Also, more importantly, "volatile" is on the wrong _part_ of the whole +system. In C, it's "data" that is volatile, but that is insane. Data +isn't volatile - _accesses_ are volatile. So it may make sense to say +"make this particular _access_ be careful", but not "make all accesses to +this data use some random strategy". + +So the only thing "volatile" is potentially useful for is: + + - actual accessor functions can use it in a _cast_ to make one particular + access follow the rules of "don't cache this one dereference". That is + useful as part of a _bigger_ set of rules about that access (i.e., it + might be the internal implementation of a "readb()", for example). + + - for "random number generation" data locations, where you literally + don't _have_ any rules except "it's a random number". The only really + valid example of this is the "jiffy" timer tick. + +Any other use of "volatile" is almost certainly a bug, or just useless. + +Side note: it's also totally possible that a volatiles _hides_ a bug, i.e., +removing the volatile ends up having bad effects, but that's because the +software itself isn't actually following the rules (or, more commonly, the +rules are broken, and somebody added "volatile" to hide the problem). + +It's a bug if the volatile means that you don't follow the proper protocol +for accessing the data, and it's useless (and generally generates worse +code) if you already do. + +So just say NO! to volatile except under the above circumstances. + + + +[from another email thread:] + +I suspect we should just face up to the fact that: + + (a) "volatile" on kernel data is basically always a bug, and you should + use locking. "volatile" doesn't help anything at all with memory + ordering and friends, so it's insane to think it "solves" anything on + its own. + (b) on "iomem" pointers it does make sense, but those need special + accessor functions _anyway_, so things like test_bit() wouldn't work + on them. + (c) if you spin on a value [that's] changing, you should use "cpu_relax()" or + "barrier()" anyway, which will force gcc to re-load any values from + memory over the loop.
Re: [PATCH] doc: volatile considered evil
Quoted 13 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add information on the problems with the C-language "volatile" keyword and why it should not be used (most of the time).
Signed-off-by Randy Dunlap <[email protected]>--- Documentation/volatile-usage.txt | 129 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+)
Documentation/volatile-usage.txt line 6
Quoted 6 lines
Documentation/volatile-usage.txt new file +6
-0@@ -0,0 +1,129 @@ +***** "volatile" considered useless and evil: Just Say NO! ***** + +Do not use the C-language "volatile" keyword +(extracted from lkml emails from Linus) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
Again, please change this sweeping introduction to explicitly state that Linus' emails were a criticism of using 'volatile' for objects (he refers to them as "data structures") and can be appropriate for asm constructs.
Re: [PATCH] doc: volatile considered evil
Quoted 12 lines · On Tue, 8 May 2007 17:06:23 -0700 (PDT) David Rientjes wrote:
Quoted 10 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add information on the problems with the C-language "volatile" keyword and why it should not be used (most of the time).
Signed-off-by Randy Dunlap <[email protected]>--- Documentation/volatile-usage.txt | 129 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+)
Quoted 13 lines
Documentation/volatile-usage.txt line 6
Quoted 9 lines
Documentation/volatile-usage.txt new file +6
-0@@ -0,0 +1,129 @@ +***** "volatile" considered useless and evil: Just Say NO! ***** + +Do not use the C-language "volatile" keyword +(extracted from lkml emails from Linus) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Again, please change this sweeping introduction to explicitly state that Linus' emails were a criticism of using 'volatile' for objects (he refers to them as "data structures") and can be appropriate for asm constructs.
You haven't replied to my other emails...
"volatile" used on a gcc asm extension is different, granted. It's not even a C-language "volatile" keyword AFAICT, so it doesn't apply in this context.
Anyway, how is this slightly modified title?
+***** "volatile" considered useless and evil: Just Say NO! ***** +
+Do not use the C-language "volatile" keyword on kernel data +(extracted from lkml emails from Linus)
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH] doc: volatile considered evil
Quoted 4 lines · Randy Dunlap
"volatile" used on a gcc asm extension is different, granted. It's not even a C-language "volatile" keyword AFAICT, so it doesn't apply in this context.
Using 'volatile' for an asm construct certainly is a keyword; in fact, C99 defines 'volatile' as a token which is reserved for use as a keyword.
Documentation/volatile-usage.txt line 4
Quoted 7 lines
Anyway, how is this slightly modified title?
Documentation/volatile-usage.txt new file +4
-0+***** "volatile" considered useless and evil: Just Say NO! ***** + +Do not use the C-language "volatile" keyword on kernel data +(extracted from lkml emails from Linus)
It's still ambiguous. A much more explicit title that nobody could argue with would be "do not use the 'volatile' keyword as a type qualifier for an object."
David
Re: [PATCH] doc: volatile considered evil
Quoted 9 lines · On Tue, 8 May 2007 19:38:56 -0700 (PDT) David Rientjes wrote:
Quoted 4 lines · Randy Dunlap
"volatile" used on a gcc asm extension is different, granted. It's not even a C-language "volatile" keyword AFAICT, so it doesn't apply in this context.
Using 'volatile' for an asm construct certainly is a keyword; in fact, C99 defines 'volatile' as a token which is reserved for use as a keyword.
touche'
Quoted 11 lines
Documentation/volatile-usage.txt line 4
Quoted 7 lines
Anyway, how is this slightly modified title?
Documentation/volatile-usage.txt new file +4
-0+***** "volatile" considered useless and evil: Just Say NO! ***** + +Do not use the C-language "volatile" keyword on kernel data +(extracted from lkml emails from Linus)It's still ambiguous. A much more explicit title that nobody could argue with would be "do not use the 'volatile' keyword as a type qualifier for an object."
OK, I can accept that.
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH] doc: volatile considered evil
In reply to David RientjesQuoted 3 lines
It's still ambiguous. A much more explicit title that nobody could argue with would be "do not use the 'volatile' keyword as a type qualifier for an object."
Except when you do. The kernel uses the C volatile in various places itself for specific good reasons (and some for historical bad ones)
Perhaps a closer summary would be
Do Not Use Volatile
-------------------
1. volatile is not a locking mechanism
Volatile does not define sufficiently sane or strong semantics for locking. The kernel has proper locking mechanisms which also act as compiler fetch/store barriers and where neccessary hardware barriers for SMP systems. The kernel knows about all the corner cases, you probably don't.
2. volatile is not needed for mmio space
I/O memory access are done via readb/writeb and friends. They deal with volatility themselves so you don't have to. They may nor may not use volatile internally to their implementation, but that is none of your business.
3. volatile is not atomic
Using volatile does not guarantee atomic behaviour. This often requires special instructions or code sequences too. We have atomic_t and the atomic_* operators for this.
4. volatile is not a store or read barrier
Using volatile is not always sufficient to order accesses on SMP or to ensure things execute in the order expected. Instead the kernel provides a set of barrier operations which have clearly defined semantics on all systems. Make use of rmb, wmb, barrier, smp_wmb etc instead
When Might You Need volatile ?
------------------------------
When you are implementing the locking primitives on a new platform. When you are implementing the I/O and atomic prmitives on a new platform. Also in inline gcc assembler where "volatile" is used for subtly different purposes.
Possibly very special cases we haven't thought about yet. However if you find one remember the need for portability and ask whether it should be using volatile or there is a gap in the existing hardware abstraction.
Re: [PATCH] doc: volatile considered evil
Quoted 39 lines · Alan Cox
Quoted 1 line
It's still ambiguous. A much more explicit title that nobody could argue with would be "do not use the 'volatile' keyword as a type qualifier for an object."
Except when you do. The kernel uses the C volatile in various places itself for specific good reasons (and some for historical bad ones)
Perhaps a closer summary would be
Do Not Use Volatile
-------------------1. volatile is not a locking mechanism
Volatile does not define sufficiently sane or strong semantics for locking. The kernel has proper locking mechanisms which also act as compiler fetch/store barriers and where neccessary hardware barriers for SMP systems. The kernel knows about all the corner cases, you probably don't.
2. volatile is not needed for mmio space
I/O memory access are done via readb/writeb and friends. They deal with volatility themselves so you don't have to. They may nor may not use volatile internally to their implementation, but that is none of your business.
3. volatile is not atomic
Using volatile does not guarantee atomic behaviour. This often requires special instructions or code sequences too. We have
atomic_tand the atomic_* operators for this.4. volatile is not a store or read barrier
Using volatile is not always sufficient to order accesses on SMP or to ensure things execute in the order expected. Instead the kernel provides a set of barrier operations which have clearly defined semantics on all systems. Make use of rmb, wmb, barrier,
smp_wmbetc instead
Quoted 7 lines
When Might You Need volatile ?
------------------------------When you are implementing the locking primitives on a new platform. When you are implementing the I/O and atomic prmitives on a new platform. Also in inline gcc assembler where "volatile" is used for subtly different purposes.
Is there a good reason for using volatile in atomic/locking primitives? AFAIKS there is not.
Signature · 1 line
SUSE Labs, Novell Inc.
Re: [PATCH] doc: volatile considered evil
Quoted 7 lines
Quoted 4 lines
When you are implementing the locking primitives on a new platform. When you are implementing the I/O and atomic prmitives on a new platform. Also in inline gcc assembler where "volatile" is used for subtly different purposes.
Is there a good reason for using volatile in atomic/locking primitives? AFAIKS there is not.
Depends on the platform. If you are writing a new architecture then who knows what you will need to get the barriers right - you may want to use volatile, you may want to use asm.
Re: [PATCH] doc: volatile considered evil
In reply to Alan CoxQuoted 8 lines · Alan Cox
When Might You Need volatile ?
------------------------------When you are implementing the locking primitives on a new platform. When you are implementing the I/O and atomic prmitives on a new platform. Also in inline gcc assembler where "volatile" is used for subtly different purposes.
What is determined to be an "access" (read or modify) to an object such as a locking primitive that is type-qualified with the keyword 'volatile' is implementation defined.
You cannot guarantee that the value in such an object would agree with the evaluation thus far as specified by the semantics of the code even at sequence points because such an object can be modified without knowledge to the implementation. The only thing you _can_ guarantee at these sequence points is that their previous accesses are complete and later accesses, as specified by the semantics of the code, have not yet occurred. This does not exclude the possibility that they were modified without knowledge to the implementation. In this case, the actual and abstract semantics of the text may not agree.
Thus, any reliance on type-qualifying an object that represents an atomic or locking primitive on the keyword 'volatile' is misplaced.
David
Re: [PATCH] doc: volatile considered evil
Quoted 2 lines
Thus, any reliance on type-qualifying an object that represents an atomic or locking primitive on the keyword 'volatile' is misplaced.
arch/foo is generally implementation specific code.
Re: [PATCH] doc: volatile considered evil
Quoted 5 lines · Alan Cox
Quoted 2 lines
Thus, any reliance on type-qualifying an object that represents an atomic or locking primitive on the keyword 'volatile' is misplaced.
arch/foois generally implementation specific code.
That's true, but what qualifies as an "access" to an object that is type qualified with the 'volatile' keyword is _implementation_ defined, meaning the behavior is defined by the compiler and not this new architecture you're proposing 'volatile' is appropriate for. That's pure C99.
Re: [PATCH] doc: volatile considered evil
Quoted 5 lines · On Wed, 9 May 2007 11:41:27 -0700 (PDT) David Rientjes <[email protected]>…
Quoted 3 lines · Alan Cox
Quoted 2 lines
Thus, any reliance on type-qualifying an object that represents an atomic or locking primitive on the keyword 'volatile' is misplaced.
Quoted 8 lines
Quoted 2 lines
arch/foois generally implementation specific code.That's true, but what qualifies as an "access" to an object that is type qualified with the 'volatile' keyword is _implementation_ defined, meaning the behavior is defined by the compiler and not this new architecture you're proposing 'volatile' is appropriate for. That's pure C99.
arch/foo almost always supports a single compiler too - gcc. We simply don't support anything else. We use gcc inlines and features extensively.
And who cares about such fine detail of C99, did they fix the struct copy bug in ANSI C even ? [1]
Alan
[1] ANSI C says access to the padding fields of a struct is undefined. ANSI C also says that struct assignment is a memcpy. Therefore struct assignment in ANSI C is a violation of ANSI C...
At this point its a lot simpler not to care about other compilers pet insanities or areas of the spec like volatile that are vaguer and less credible than the output of the US congress.
Re: [PATCH] doc: volatile considered evil
Quoted 3 lines · Alan Cox
arch/fooalmost always supports a single compiler too - gcc. We simply don't support anything else. We use gcc inlines and features extensively.
Ok, so your "acceptable use clause" of your addition should include that fact. That the volatile type qualifier is legitimate when developing a new architecture and the only implementation you support for compilation of such text has a one-to-one correspondence between actual and abstract machine semantics.
Quoted 4 lines
[1] ANSI C says access to the padding fields of a struct is undefined. ANSI C also says that struct assignment is a memcpy. Therefore struct assignment in ANSI C is a violation of ANSI C...
Padding bytes are unspecified, not undefined. I doubt ANSI C says padding bytes are undefined because then any implementation that pads members of a struct object would not be strictly conforming.
David
Re: [PATCH] doc: volatile considered evil
In reply to Alan CoxQuoted 5 lines · Alan Cox
arch/fooalmost always supports a single compiler too - gcc. We simply don't support anything else. We use gcc inlines and features extensively.And who cares about such fine detail of C99, did they fix the struct copy bug in ANSI C even ? [1]
Um, I've picked up the tinycc baton (in my copious free time) and am slowly trying to get it to build a bootable linux kernel. There's a ways to go, and I really have no idea what I'm doing, but I have help and even made a release recently (which is already significantly out of date, largely thanks to David Wheeler):
http://landley.net/code/tinycc/
Admittedly, a lot of this involves implementing gcc extensions, but gratuitous use of them when there's a perfectly good c99 way of doing it isn't necessarily a plus. Fabrice got it as far as tccboot before QEMU ate his life, we've improved a bit since then, and there's presumably a finite amount of work left to be done...
Rob
Re: [PATCH] doc: volatile considered evil
In reply to Randy DunlapQuoted 2 lines · Randy Dunlap
Add information on the problems with the C-language "volatile" keyword and why it should not be used (most of the time).
I like Jonathan's article http://lwn.net/Articles/233479/ a lot. It puts as much emphasis on the DOs as on the DON'Ts, which I find helpful.
Signature · 3 lines
Stefan Richter -=====-=-=== -=-= -=--= http://arcgraph.de/sr/
Re: [PATCH] doc: volatile considered evil
Quoted 6 lines · On Wed, 09 May 2007 10:50:21 +0200 Stefan Richter wrote:
Quoted 2 lines · Randy Dunlap
Add information on the problems with the C-language "volatile" keyword and why it should not be used (most of the time).
I like Jonathan's article http://lwn.net/Articles/233479/ a lot. It puts as much emphasis on the DOs as on the DON'Ts, which I find helpful.
Yep. I expect to drop my patch in favor of Jon's writeup.
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
Re: [PATCH] doc: volatile considered evil
Quoted 10 lines · Randy Dunlap
Quoted 6 lines · On Wed, 09 May 2007 10:50:21 +0200 Stefan Richter wrote:
Quoted 2 lines · Randy Dunlap
Add information on the problems with the C-language "volatile" keyword and why it should not be used (most of the time).
I like Jonathan's article http://lwn.net/Articles/233479/ a lot. It puts as much emphasis on the DOs as on the DON'Ts, which I find helpful.
Yep. I expect to drop my patch in favor of Jon's writeup.
Yeah, that article was both comprehensive and to-the-point indeed. I was trying my hand at re-organizing your original mail, but Jon's version is nicer.
Jonathan Corbet
maintainerRe: [RFC/PATCH] doc: volatile considered evil
In reply to Randy DunlapQuoted 4 lines · Randy Dunlap
Here are some 'volatile' comments from Linus, extracted from several emails in at least 2 threads.
If this is close to useful, we can add it to
Documentation/.
I just took a shot at turning this into something more like a normal document:
http://lwn.net/Articles/233479/
Comments welcome. If people think it suits the need I'll happily make a version which moves from the LWN style to Documentation/ and send it in.
Thanks,
jon
Jonathan Corbet / LWN.net / [email protected]
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 5 lines · Jonathan Corbet
I just took a shot at turning this into something more like a normal document:
http://lwn.net/Articles/233479/
I think the "jiffies variable is special" part misses the "for stupid legacy reasons" explanation.
According to the other volatile rules one should use something like that:
extern unsigned long __jiffies;
static inline unsigned long read_ulong(unsigned long *addr)
{
return *(volatile unsigned long *)addr;
}
static inline unsigned long get_jiffies(void)
{
return read_ulong(&__jiffies);
}But of course changing all references to jiffies in the kernel would be insane, thus jiffies is special "for stupid legacy reasons".
Right?
Johannes
Re: [RFC/PATCH] doc: volatile considered evil
Quoted 23 lines · Johannes Stezenbach
Quoted 5 lines · Jonathan Corbet
I just took a shot at turning this into something more like a normal document:
http://lwn.net/Articles/233479/I think the "jiffies variable is special" part misses the "for stupid legacy reasons" explanation.
According to the other volatile rules one should use something like that:
extern unsigned long
__jiffies;
static inline unsigned longread_ulong(unsigned long *addr){ return *(volatile unsigned long *)addr; } static inline unsigned long get_jiffies(void) { return read_ulong(&__jiffies); }
Quoted 4 lines
But of course changing all references to jiffies in the kernel would be insane, thus jiffies is special "for stupid legacy reasons".
Right?
Right. jiffies comes with no locking protection by default (and adding one today in a patch that is not invasive / disruptive could be difficult). If it had a spinlock or something for itself then the above discussion would have been void, everybody would've just grabbed the lock before accessing jiffies, and the spinlock implementation would have done the Right Thing by itself (using barriers, obviously, and so "volatile" would've been unnecessary even then).
Anyway, as things stand, jiffies comes without locks for itself. But using a volatile "access cast" to read jiffies whenever you might need it is _still_ not what I would personally prefer. IMO, it's *much* better to use something like barrier() if / where you're sitting in a tight loop comparing jiffies to whatever (a timeout expiry for example).
So, if you _really_ need / want to do something of this sort, I'd much rather see:
while (time_before(jiffies, expiry))
barrier();
in code instead of:
while (time_before((*(volatile unsigned long *)&jiffies), expiry))
;
But of course,
while (time_before(jiffies, expiry))
cpu_relax();
would be better still.
A last word from Linus himself here would be obviously best, but I'm not so sure it makes sense to allow the "volatile" type qualifier _even_ for the jiffies case.