Subject: mx27: gpio multiplexing support
From: Robert Schwebel <r.schwebel@pengutronix.de>

FIXME: split apart into generic function plus things which are special
to ADS.

Signed-off-by: Robert Schwebel <r.schwebel@pengutronix.de>
Signed-off-by: N.N. (FIXME: get a sign from freescale)

---
 arch/arm/mach-mx27/gpio.c |  146 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 110 insertions(+), 36 deletions(-)

Index: arch/arm/mach-mx27/gpio.c
===================================================================
--- arch/arm/mach-mx27/gpio.c.orig
+++ arch/arm/mach-mx27/gpio.c
@@ -1,43 +1,38 @@
 /*
- *  Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * linux/arch/arm/mach-mx27/gpio.c
+ *
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2007 Robert Schwebel <r.schwebel@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
  */
 
 /*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
+ * TODO
+ * - are the gpio_* functions generic? may be per arch
  */
 
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/device.h>
-#include <asm/io.h>
-#include <asm/hardware.h>
+
 #include <asm/arch/gpio.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
 
 #include "gpio_mux.h"
 #include "crm_regs.h"
 
 static int g_uart_activated[MXC_UART_NR] = { 0, 0, 0, 0, 0, 0 };
 
-/*!
- * @file mach-mx27/gpio.c
- *
- * @brief This file contains all the GPIO setup functions for the board.
- *
- * @ingroup GPIO_MX27
- */
-
-/*!
- * Setup GPIO for a UART port to be active
- *
- * @param  port         a UART port
- * @param  ir_mode      indicates if the port is used for SIR
+/*
+ * FIXME: pcm038: we have uart 0, 1, 2 -> ttymxc0..2
  */
-void gpio_uart_active(int port, int ir_mode)
+void
+gpio_uart_active(int port, int ir_mode)
 {
 	if (port < 0 || port >= MXC_UART_NR) {
 		pr_info("Wrong port number: %d\n", port);
@@ -45,9 +40,11 @@ void gpio_uart_active(int port, int ir_m
 	}
 
 	if (g_uart_activated[port]) {
-		pr_info("UART %d has been activated multiple times\n", port + 1);
+		pr_info("UART %d has been activated multiple times\n",
+			port + 1);
 		return;
 	}
+
 	g_uart_activated[port] = 1;
 
 	switch (port) {
@@ -69,14 +66,18 @@ void gpio_uart_active(int port, int ir_m
 		gpio_request_mux(MX27_PIN_UART3_CTS, GPIO_MUX_PRIMARY);
 		gpio_request_mux(MX27_PIN_UART3_RTS, GPIO_MUX_PRIMARY);
 
-		/* enable or disable the IrDA transceiver based on ir_mode */
-/* FIXME refactor for generic boards */
-#ifdef CONFIG_MACH_MX27ADS
-		if (ir_mode == IRDA)
-			__raw_writew(PBC_BCTRL2_IRDA_EN, PBC_BCTRL2_CLEAR_REG);
-		else
-			__raw_writew(PBC_BCTRL2_IRDA_EN, PBC_BCTRL2_SET_REG);
-#endif
+		/*
+		 * on mx27ads we have to enable or disable the IrDA
+		 * transceiver based on ir_mode
+		 */
+		if (machine_is_mx27ads()) {
+			if (ir_mode == IRDA)
+				__raw_writew(PBC_BCTRL2_IRDA_EN,
+					     PBC_BCTRL2_CLEAR_REG);
+			else
+				__raw_writew(PBC_BCTRL2_IRDA_EN,
+					     PBC_BCTRL2_SET_REG);
+		}
 		break;
 	case 3:
 		gpio_request_mux(MX27_PIN_USBH1_TXDM, GPIO_MUX_ALT);
@@ -187,6 +188,7 @@ void config_uartdma_event(int port)
   *  PB25 - PB31  -- PRIMARY
       PB22  -- PRIMARY
  */
+/* FIXME pcm038: usbh1->non-otg with onboard transceiver; conflicts with spi interface */
 void gpio_usbh1_active(void)
 {
 	gpio_request_mux(MX27_PIN_USBH1_SUSP, GPIO_MUX_PRIMARY);
@@ -213,6 +215,10 @@ void gpio_usbh1_inactive(void)
 /*
  * conflicts with CSPI1 (MC13783) and CSPI2 (Connector)
  */
+/* FIXME pcm038:
+ * usbh2->non-otg with baseboard 1504 transceiver
+ * checked
+ */
 void gpio_usbh2_active(void)
 {
 	gpio_set_puen(MX27_PIN_USBH2_CLK, 0);
@@ -220,6 +226,7 @@ void gpio_usbh2_active(void)
 	gpio_set_puen(MX27_PIN_USBH2_DATA7, 0);
 	gpio_set_puen(MX27_PIN_USBH2_NXT, 0);
 	gpio_set_puen(MX27_PIN_USBH2_STP, 0);
+
 	gpio_set_puen(MX27_PIN_CSPI2_SS2, 0);
 	gpio_set_puen(MX27_PIN_CSPI2_SS1, 0);
 	gpio_set_puen(MX27_PIN_CSPI2_SS0, 0);
@@ -272,6 +279,9 @@ void gpio_usbh2_inactive(void)
 	gpio_set_puen(MX27_PIN_CSPI1_SS2, 1);
 }
 
+/*
+ * FIXME: pcm038: checked
+ */
 void gpio_usbotg_hs_active(void)
 {
 	gpio_request_mux(MX27_PIN_USBOTG_DATA5, GPIO_MUX_PRIMARY);
@@ -337,6 +347,9 @@ void gpio_usbotg_fs_inactive(void)
 *
 * @param  i2c_num         an I2C device
 */
+/*
+ * FIXME: pcm038: checked
+ */
 void gpio_i2c_active(int i2c_num)
 {
 	switch (i2c_num) {
@@ -380,21 +393,24 @@ void gpio_i2c_inactive(int i2c_num)
  *
  * @param  cspi_mod         an CSPI device
  */
+/*
+ * FIXME: pcm038: checked
+ */
 void gpio_spi_active(int cspi_mod)
 {
 	switch (cspi_mod) {
 	case 0:
-		/* SPI1 */
+		/* SPI1 */ /* pcm038: checked */
 		gpio_request_mux(MX27_PIN_CSPI1_MOSI, GPIO_MUX_PRIMARY);
 		gpio_request_mux(MX27_PIN_CSPI1_MISO, GPIO_MUX_PRIMARY);
 		gpio_request_mux(MX27_PIN_CSPI1_SCLK, GPIO_MUX_PRIMARY);
 		gpio_request_mux(MX27_PIN_CSPI1_RDY, GPIO_MUX_PRIMARY);
 		gpio_request_mux(MX27_PIN_CSPI1_SS0, GPIO_MUX_PRIMARY);
 		gpio_request_mux(MX27_PIN_CSPI1_SS1, GPIO_MUX_PRIMARY);
-		gpio_request_mux(MX27_PIN_CSPI1_SS2, GPIO_MUX_PRIMARY);
+		gpio_request_mux(MX27_PIN_CSPI1_SS2, GPIO_MUX_PRIMARY); /* pcm038: we don't have this one */
 		break;
 	case 1:
-		/*SPI2  */
+		/* SPI2  */ /* FIXME pcm038: not used on pcm038 */
 		gpio_request_mux(MX27_PIN_CSPI2_MOSI, GPIO_MUX_PRIMARY);
 		gpio_request_mux(MX27_PIN_CSPI2_MISO, GPIO_MUX_PRIMARY);
 		gpio_request_mux(MX27_PIN_CSPI2_SCLK, GPIO_MUX_PRIMARY);
@@ -403,7 +419,7 @@ void gpio_spi_active(int cspi_mod)
 		gpio_request_mux(MX27_PIN_CSPI2_SS2, GPIO_MUX_PRIMARY);
 		break;
 	case 2:
-		/*SPI3  */
+		/* SPI3  */ /* pcm038: checked */
 		gpio_request_mux(MX27_PIN_SD1_D0, GPIO_MUX_ALT);
 		gpio_request_mux(MX27_PIN_SD1_CMD, GPIO_MUX_ALT);
 		gpio_request_mux(MX27_PIN_SD1_CLK, GPIO_MUX_ALT);
@@ -459,6 +475,9 @@ void gpio_spi_inactive(int cspi_mod)
  * Setup GPIO for a nand flash device to be active
  *
  */
+/*
+ * FIXME: pcm038: checked
+ */
 void gpio_nand_active(void)
 {
 	unsigned long reg;
@@ -494,6 +513,9 @@ void gpio_nand_inactive(void)
  * Setup GPIO for CSI device to be active
  *
  */
+/*
+ * FIXME: pcm038: checked
+ */
 void gpio_sensor_active(void)
 {
 	gpio_request_mux(MX27_PIN_CSI_D0, GPIO_MUX_PRIMARY);
@@ -561,6 +583,9 @@ void gpio_sensor_reset(bool flag)
  * Setup GPIO for LCDC device to be active
  *
  */
+/*
+ * FIXME: pcm038: checked
+ */
 void gpio_lcdc_active(void)
 {
 	gpio_request_mux(MX27_PIN_LSCLK, GPIO_MUX_PRIMARY);
@@ -631,6 +656,9 @@ void gpio_lcdc_inactive(void)
  * Setup GPIO PA25 low to start hard reset FS453 TV encoder
  *
  */
+/*
+ * FIXME: pcm038: we don't have this one, put into ads code
+ */
 void gpio_fs453_reset_low(void)
 {
 	gpio_free_mux(MX27_PIN_CLS);
@@ -667,16 +695,32 @@ void gpio_fs453_reset_high(void)
  * This function configures the IOMux block for PMIC standard operations.
  *
  */
+/*
+ * FIXME: pcm038: re-check with ads schematic
+ */
 void gpio_pmic_active(void)
 {
+	/* FIXME This is board specific! Not generic! */
+#if 1
+/* This is for pcm038 */
+	gpio_config_mux(MX27_PIN_USB_PWR, GPIO_MUX_GPIO);
+	mxc_set_gpio_direction(MX27_PIN_USB_PWR, 1);
+#endif
+#if 0
+/* This is for ADS */
 	gpio_config_mux(MX27_PIN_TOUT, GPIO_MUX_GPIO);
 	mxc_set_gpio_direction(MX27_PIN_TOUT, 1);
+#endif
 }
 
 /*!
  * GPIO settings not required for keypad
  *
  */
+/*
+ * FIXME: pcm038: we have to do something here when a keypad is connected
+ * KP_COL...KP_ROW, don't have an alternate function, so maybe nothing to do here
+ */
 void gpio_keypad_active(void)
 {
 }
@@ -693,6 +737,9 @@ void gpio_keypad_inactive(void)
  * Setup GPIO for ATA device to be active
  *
  */
+/*
+ * FIXME: pcm038: we don't have ata
+ */
 void gpio_ata_active(void)
 {
 	gpio_request_mux(MX27_PIN_ATA_DATA0, GPIO_MUX_PRIMARY);
@@ -769,6 +816,9 @@ void gpio_ata_inactive(void)
  * Setup GPIO for FEC device to be active
  *
  */
+/*
+ * FIXME: pcm038: checked
+ */
 void gpio_fec_active(void)
 {
 	gpio_request_mux(MX27_PIN_ATA_DATA15, GPIO_MUX_OUTPUT1);
@@ -846,6 +896,9 @@ void gpio_fec_inactive(void)
  * Setup GPIO for SLCDC device to be active
  *
  */
+/*
+ * FIXME: pcm038: "smart lcd controller" not used
+ */
 void gpio_slcdc_active(int type)
 {
 	switch (type) {
@@ -936,6 +989,13 @@ void gpio_slcdc_inactive(int type)
 	return;
 }
 
+/*
+ * FIXME: pcm038:
+ * - SSI1 used
+ * - SSI2 not used, gpio
+ * - SSI3 not used, gpio
+ * - SSI4 -> PMIC
+ */
 void gpio_ssi_active(int ssi_num)
 {
 	switch (ssi_num) {
@@ -997,6 +1057,9 @@ void gpio_ssi_inactive(int ssi_num)
  *
  * @param module SDHC module number
  */
+/*
+ * FIXME: pcm038: we have SD2
+ */
 void gpio_sdhc_active(int module)
 {
 	u16 data;
@@ -1096,6 +1159,9 @@ int sdhc_get_card_det_status(struct devi
 /*
  * Return the card detect pin.
  */
+/*
+ * FIXME: pcm038: we need this information
+ */
 int sdhc_init_card_det(int id)
 {
 	int ret = 0;
@@ -1116,6 +1182,9 @@ int sdhc_init_card_det(int id)
 /*
  * Power on/off Sharp QVGA panel.
  */
+/*
+ * FIXME: pcm038: currently not used, but will be in the next board revision
+ */
 void board_power_lcd(int on)
 {
 /* FIXME refactor for generic boards */
@@ -1127,6 +1196,9 @@ void board_power_lcd(int on)
 #endif
 }
 
+/*
+ * FIXME: pcm038: checked
+ */
 void gpio_owire_active(void)
 {
 	gpio_request_mux(MX27_PIN_RTCK, GPIO_MUX_ALT);
@@ -1137,6 +1209,9 @@ void gpio_owire_inactive(void)
 	gpio_request_mux(MX27_PIN_RTCK, GPIO_MUX_PRIMARY);
 }
 
+/*
+ * FIXME: pcm038: we don't have irda
+ */
 void gpio_irda_active(void)
 {
 	gpio_uart_active(2, 0);
@@ -1149,6 +1224,14 @@ void gpio_irda_inactive(void)
 	gpio_uart_inactive(2, 0);
 }
 
+/*
+ * FIXME: pcm038: missing functions:
+ * - T_IN T_OUT (Timer In/Out)
+ * - PCMCIA
+ * - PWM output
+ * - PE19, PE20, PC28-31, GPT4_TIN/TOUT, GPT5_TIN/TOUT, PB23-24 -> gpio
+ */
+
 EXPORT_SYMBOL(gpio_uart_active);
 EXPORT_SYMBOL(gpio_uart_inactive);
 EXPORT_SYMBOL(config_uartdma_event);
