Subject: QUERY: How to handle SOC Configuration (Peripheral Multiplexing) in linux

From: [email-masked] (Viresh KUMAR)
Date: Mon, 15 Mar 2010 10:01:31 +0530

Hello everybody,

In our SOC's (SPEArxxx), we have many peripheral sharing PL_GPIO pins and so
only few peripherals can be selected in a configuration. This is configurable
using a set of registers. Now the problem is to make following work:

1. How to do this selection in kernel in a simple way?
2. Based on this selection hardware registers needs to be configured.

I propose following solution to solve this issue, but i am not sure if it is
acceptable by community.

Please see if it is fine. Or if there is any other way people may already be
following for similar issues.

I have provided this selection from "make menuconfig", based on selection I
configure hardware at initialization time. Basically these selections will
decide which device is present in the system when it boots.

There are modes in which SOC can be configured and in these modes
peripherals can be selected.

file: arch/arm/mach-spear3xx/Kconfig300

#
# SPEAr300 machine configuration file
#
if MACH_SPEAR300

choice
	prompt "SPEAr300 Boards"
	default BOARD_SPEAR300_EVB

config BOARD_SPEAR300_EVB
	bool "SPEAr300 Evaluation Board"
	help
	  Supports ST SPEAr300 Evaluation Board

endchoice

# SOC configuration for SPEAr 300 machine
menu "SPEAr300 SOC Configuration"

# Operation modes
choice
	prompt "Select Operation Mode"
	default PHOTO_FRAME_MODE

config NAND_MODE
	bool "NAND Mode"
	help
	  This mode will enable NAND Mode of SPEAr300 SOC.

config NOR_MODE
	bool "NOR Mode"
	help
	  This mode will enable NOR Mode of SPEAr300 SOC.

config PHOTO_FRAME_MODE
	bool "PHOTO FRAME Mode"
	help
	  This mode will enable PHOTO FRAME Mode of SPEAr300 SOC.

config LEND_IP_PHONE_MODE
	bool "LEND IP PHONE (LOW END IP PHONE mode)"
	help
	  This mode will enable LEND IP PHONE Mode of SPEAr300 SOC.

config HEND_IP_PHONE_MODE
	bool "HEND IP PHONE (HIGH END IP PHONE mode)"
	help
	  This mode will enable HEND IP PHONE Mode of SPEAr300 SOC.

config LEND_WIFI_PHONE_MODE
	bool "LEND WIFI PHONE (LOW END WI-FI PHONE mode)"
	help
	  This mode will enable LEND WIFI PHONE Mode of SPEAr300 SOC.

config HEND_WIFI_PHONE_MODE
	bool "HEND WIFI PHONE (HIGH END WI-FI PHONE mode)"
	help
	  This mode will enable HEND WIFI PHONE Mode of SPEAr300 SOC.

config ATA_PABX_wI2S_MODE
	bool "ATA PABX wI2S (ATA PABX without I2S) mode"
	help
	  This mode will enable ATA PABX wI2S Mode of SPEAr300 SOC.

config ATA_PABX_I2S_MODE
	bool "ATA PABX I2S (ATA PABX with I2S) Mode"
	help
	  This mode will enable ATA PABX I2S Mode of SPEAr300 SOC.

config CAMl_LCDw_MODE
	bool "CAMl LCDw (8 bit CAMERA without LCD) Mode"
	help
	  This mode will enable CAMl LCDw Mode of SPEAr300 SOC.

config CAMu_LCD_MODE
	bool "CAMu LCD (14 bit CAMERA with LCD) Mode"
	help
	  This mode will enable CAMu LCD Mode of SPEAr300 SOC.

config CAMu_wLCD_MODE
	bool "CAMu wLCD (14 bit CAMERA without LCD) Mode"
	help
	  This mode will enable CAMu wLCD Mode of SPEAr300 SOC.

config CAMl_LCD_MODE
	bool "CAMl LCD (8 bit CAMERA with LCD) Mode"
	help
	  This mode will enable CAMl LCD Mode of SPEAr300 SOC.

endchoice #Select Operation Mode

#mode specific peripherals
#FSMC
config FSMC_2_CHIPS
	bool "FSMC 2 CHIPS - Disables FIRDA"
	depends on NAND_MODE || NOR_MODE || PHOTO_FRAME_MODE || \
	ATA_PABX_wI2S_MODE || ATA_PABX_I2S_MODE
	depends on !FSMC_4_CHIPS
	default n

config FSMC_4_CHIPS
	bool "FSMC 4 CHIPS - Disables UART and FIRDA"
	depends on NAND_MODE || NOR_MODE || PHOTO_FRAME_MODE || \
	ATA_PABX_wI2S_MODE || ATA_PABX_I2S_MODE
	default n

#Keyboard
config KEYBOARD
	bool "Keyboard"
	depends on LEND_IP_PHONE_MODE || HEND_IP_PHONE_MODE || \
	LEND_WIFI_PHONE_MODE || HEND_WIFI_PHONE_MODE || CAMl_LCDw_MODE || \
	CAMu_LCD_MODE || CAMu_wLCD_MODE || CAMl_LCD_MODE
	default y

#CLCD
config CLCD_1
	bool "CLCD - Disables TIMER 1-2 and TIMER 3-4"
	depends on PHOTO_FRAME_MODE
	default n

config CLCD_2
	bool "CLCD - Disables TIMER 3-4"
	depends on HEND_IP_PHONE_MODE || HEND_WIFI_PHONE_MODE || \
	CAMu_LCD_MODE || CAMl_LCD_MODE
	default n

#Telecom_GPIO Combinations
config TL_GPIO_1
	bool "Telecom GPIO - Disables GMAC"
	depends on PHOTO_FRAME_MODE || CAMu_LCD_MODE || CAMl_LCD_MODE
	default n

config TL_GPIO_2
	bool "Telecom GPIO - Disables TIMER 1-2, Timer 3-4 and GMAC"
	depends on LEND_IP_PHONE_MODE || LEND_WIFI_PHONE_MODE
	default n

config TL_GPIO_3
	bool "Telecom GPIO - Disables TIMER 3-4 and GMAC"
	depends on ATA_PABX_I2S_MODE || CAMl_LCDw_MODE || CAMu_wLCD_MODE
	default n

config TL_GPIO_4
	bool "Telecom GPIO - Disables TIMER 1-2 and GMAC"
	depends on HEND_IP_PHONE_MODE || HEND_WIFI_PHONE_MODE
	default n

config TL_GPIO_5
	bool "Telecom GPIO - Disables TIMER 1-2-3-4, UART MODEM and GMAC"
	depends on ATA_PABX_wI2S_MODE
	default n

#TL_TDM Combinations
config TL_TDM
	bool "Telecom TDM - Disables UART MODEM and SSP CHIP SELECTS"
	depends on PHOTO_FRAME_MODE || LEND_IP_PHONE_MODE || \
	HEND_IP_PHONE_MODE || LEND_WIFI_PHONE_MODE || HEND_WIFI_PHONE_MODE || \
	ATA_PABX_wI2S_MODE || ATA_PABX_I2S_MODE || CAMl_LCDw_MODE || \
	CAMu_LCD_MODE || CAMu_wLCD_MODE || CAMl_LCD_MODE
	default n

#TL_SPI_I2C Combinations
config TL_SPI_I2C
	bool "Telecom SPI-CS I2C-CLK - Disables TIMER 1-2 and TIMER 3-4"
	depends on LEND_IP_PHONE_MODE || HEND_IP_PHONE_MODE || \
	LEND_WIFI_PHONE_MODE || HEND_WIFI_PHONE_MODE || ATA_PABX_wI2S_MODE || \
	ATA_PABX_I2S_MODE || CAMl_LCDw_MODE || CAMl_LCD_MODE
	default n

#TL_CAMERA Combinations
config TL_CAMERA_1
	bool "Telecom CAMERA - Disables GMAC"
	depends on CAMl_LCDw_MODE || CAMl_LCD_MODE
	default n

config TL_CAMERA_2
	bool "Telecom CAMERA - Disables TIMER 1-2, TIMER 3-4 and GMAC"
	depends on CAMu_LCD_MODE || CAMu_wLCD_MODE
	default n

#TL_DAC Combinations
config TL_DAC
	bool "Telecom DAC - Disables Timer A"
	depends on ATA_PABX_I2S_MODE || CAMl_LCDw_MODE || \
	CAMu_LCD_MODE || CAMu_wLCD_MODE || CAMl_LCD_MODE
	default n

#TL_I2S Combinations
config TL_I2S
	bool "Telecom I2S - Disables UART MODEM and SDIO"
	depends on LEND_IP_PHONE_MODE || HEND_IP_PHONE_MODE || \
	LEND_WIFI_PHONE_MODE || HEND_WIFI_PHONE_MODE || \
	ATA_PABX_I2S_MODE || CAMl_LCDw_MODE || CAMu_LCD_MODE || \
	CAMu_wLCD_MODE || CAMl_LCD_MODE
	depends on !SDIO_1_4 && !SDIO_8
	default n

#Boot Pins Combinations
config BOOT_PINS
	bool "BOOT PINS - Disables UART MODEM, TIMER 1-2 and TIMER 3-4"
	depends on NAND_MODE || NOR_MODE
	default n

#SDIO Combinations
config SDIO_1_4
	bool "SDIO 1-4 Bit - Enable GPIO1 and Disables GPIO0 Pin 0 TO 5 and I2S"
	depends on PHOTO_FRAME_MODE || LEND_IP_PHONE_MODE || \
	HEND_IP_PHONE_MODE || LEND_WIFI_PHONE_MODE || \
	HEND_WIFI_PHONE_MODE || CAMl_LCDw_MODE || \
	CAMu_LCD_MODE || CAMu_wLCD_MODE || CAMl_LCD_MODE || \
	ATA_PABX_wI2S_MODE || ATA_PABX_I2S_MODE
	depends on !SDIO_8
	select GPIO1
	default n

config SDIO_8
	bool "SDIO 8 bit - Enable GPIO1 and Disables GPIO0 Pin 0 TO 5, GMAC and I2S"
	depends on PHOTO_FRAME_MODE || LEND_IP_PHONE_MODE || \
	HEND_IP_PHONE_MODE || LEND_WIFI_PHONE_MODE || \
	HEND_WIFI_PHONE_MODE || CAMl_LCDw_MODE || \
	CAMu_LCD_MODE || CAMu_wLCD_MODE || CAMl_LCD_MODE
	select GPIO1
	default n

#GPIO Combinations
config GPIO1
	bool "GPIO1 - Disables UART MODEM, TIMER 1-2 and TIMER 3-4"
	depends on PHOTO_FRAME_MODE
	default n

#peripherals available in all modes
config FIRDA
	bool "FIRDA"
	depends on !FSMC_4_CHIPS && !FSMC_2_CHIPS
	default y

config I2C
	bool "I2C"
	default y

config SSP
	bool "SSP"
	default y

config SSP_CHIP_SELECTS
	bool "SSP CHIP SELECTS"
	depends on !TL_TDM
	default y

config GMAC
	bool "GMAC"
	depends on !TL_GPIO_1 && !TL_GPIO_2 && !TL_GPIO_3 && !TL_GPIO_4 && \
	!TL_GPIO_5 && !TL_CAMERA_1 && !TL_CAMERA_2 && !SDIO_8
	default y

config GPIO0_PIN_0_TO_5
	bool "GPIO0 Pin 0 TO 5"
	depends on !SDIO_1_4 && !SDIO_8
	default y

config UART
	bool "UART"
	depends on !FSMC_4_CHIPS
	default y

config UART_MODEM
	bool "UART MODEM"
	depends on !TL_GPIO_5 && !TL_TDM && !TL_I2S && !BOOT_PINS && !GPIO1
	default y

config TIMER_1_2
	bool "TIMER 1-2"
	depends on !CLCD_1 && !TL_GPIO_2 && !TL_GPIO_4 && !TL_GPIO_5 && \
	!TL_SPI_I2C && !TL_CAMERA_2 && !TL_DAC && !BOOT_PINS && !GPIO1
	default y

config TIMER_3_4
	bool "TIMER 3-4"
	depends on !CLCD_1 && !CLCD_2 && !TL_GPIO_2 && !TL_GPIO_3 && \
	!TL_GPIO_5 && !TL_SPI_I2C && !BOOT_PINS && !GPIO1 && !TL_CAMERA_2
	default y

endmenu #SOC Configuration

endif	#MACH_SPEAR300

file: arch/arm/mach-spear3xx/spear300.c

/* macros with configuration values for modes */
#define S300_NAND_MODE			1
#define S300_NOR_MODE			2
#define S300_PHOTO_FRAME_MODE		3
#define S300_LEND_IP_PHONE_MODE		4
#define S300_HEND_IP_PHONE_MODE		5
#define S300_LEND_WIFI_PHONE_MODE	6
#define S300_HEND_WIFI_PHONE_MODE	7
#define S300_ATA_PABX_wI2S_MODE		8
#define S300_ATA_PABX_I2S_MODE		9
#define S300_CAMl_LCDw_MODE		10
#define S300_CAMu_LCD_MODE		11
#define S300_CAMu_LCDw_MODE		12
#define S300_CAMl_LCD_MOD		13

/* macros with configuration values for peripherals */
#define S300_FIRDA 		~0x00004000
#define S300_I2C		~0x00002000
#define S300_SSP_ENHANCED	~0x00001000
#define S300_SSP_BASIC		~0x00000800
#define S300_MII		~0x00000400
#define S300_LEG_GPIO		~0x000003f0
#define S300_UART_ENHANCED	~0x00000008
#define S300_UART_BASIC		~0x00000004
#define S300_TIMER_B		~0x00000002
#define S300_TIMER_A		~0x00000000

void spear300_configure(void)
{
	/* two variables to temporarily store values of two registers */
	volatile unsigned int *config_reg1;
	volatile unsigned int *config_reg2;

#ifndef CONFIG_FIRDA
	*config_reg1 &= FIRDA;
#endif
#ifndef CONFIG_I2C
	*config_reg1 &= I2C;
#endif
#ifndef CONFIG_SSP_CHIP_SELECTS
	*config_reg1 &= SSP_CHIP_SELECTS;
#endif
#ifndef CONFIG_SSP
	*config_reg1 &= SSP;
#endif
#ifndef CONFIG_GMAC
	*config_reg1 &= GMAC;
#endif
#ifndef CONFIG_GPIO0_PIN_0_TO_5
	*config_reg1 &= GPIO0_PIN_0_TO_5;
#endif
#ifndef CONFIG_UART_MODEM
	*config_reg1 &= UART_MODEM;
#endif
#ifndef CONFIG_UART
	*config_reg1 &= UART;
#endif
#ifndef CONFIG_TIMER_3_4
	*config_reg1 &= TIMER_3_4;
#endif
#ifndef CONFIG_TIMER_1_2
	*config_reg1 &= TIMER_1_2;
#endif

#ifdef CONFIG_NAND_MODE
	*config_reg2 = NAND_MODE;
#endif
#ifdef CONFIG_NOR_MODE
	*config_reg2 = NOR_MODE;
#endif
#ifdef CONFIG_PHOTO_FRAME_MODE
	*config_reg2 = PHOTO_FRAME_MODE;
#endif
#ifdef CONFIG_LEND_IP_PHONE_MODE
	*config_reg2 = LEND_IP_PHONE_MODE;
#endif
#ifdef CONFIG_HEND_IP_PHONE_MODE
	*config_reg2 = HEND_IP_PHONE_MODE;
#endif
#ifdef CONFIG_LEND_WIFI_PHONE_MODE
	*config_reg2 = LEND_WIFI_PHONE_MODE;
#endif
#ifdef CONFIG_HEND_WIFI_PHONE_MODE
	*config_reg2 = HEND_WIFI_PHONE_MODE;
#endif
#ifdef CONFIG_ATA_PABX_wI2S_MODE
	*config_reg2 = ATA_PABX_wI2S_MODE;
#endif
#ifdef CONFIG_ATA_PABX_I2S_MODE
	*config_reg2 = ATA_PABX_I2S_MODE;
#endif
#ifdef CONFIG_CAMl_LCDw_MODE
	*config_reg2 = CAMl_LCDw_MODE;
#endif
#ifdef CONFIG_CAMu_LCD_MODE
	*config_reg2 = CAMu_LCD_MODE;
#endif
#ifdef CONFIG_CAMu_wLCD_MODE
	*config_reg2 = CAMu_LCDw_MODE;
#endif
#ifdef CONFIG_CAMl_LCD_MODE
	*config_reg2 = CAMl_LCD_MODE;
#endif

	/* At the end we can write these values to actual registers */
}

regards,
viresh kumar.