/*
 * linux/arch/arm/mach-argonplus/argonplusevb_gpio.c
 *
 * Copyright 2004 Freescale Semiconductor, Inc. All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <asm/arch/gpio.h>
#include <asm/io.h>
#include <asm/arch/board.h>
#include <asm/arch/clock.h>
#include <linux/delay.h>

/*!
 * @file argonplusevb_gpio.c
 * 
 * @brief This file contains all the GPIO setup functions for the board. 
 * 
 * @ingroup GPIO
 */

/*!
 * This system-wise GPIO function initializes the pins during system startup. 
 * All the statically linked device drivers should put the proper GPIO initialization 
 * code inside this function. It is called by \b fixup_argonplusevb() during
 * system startup. This function is board specific. 
 */
void argonplusevb_gpio_init(void) 
{
}

/*!
 * Setup GPIO for a UART port to be active
 *
 * @param  port         a UART port
 * @param  no_irda      indicates if the port is used for SIR
 */
void gpio_uart_active(int port, int no_irda)
{
        unsigned int pbc_bctrl1_set = 0;

        /*
         * Configure the IOMUX control registers for the UART signals 
         */
        switch (port) {
        /* UART 1 IOMUX Configs */
        case 0:
                if (no_irda == 1) {
                        iomux_config_mux(PIN_UART_TXD1, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        iomux_config_mux(PIN_UART_RXD1, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        iomux_config_mux(PIN_UART_RTS1_B, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        iomux_config_mux(PIN_UART_CTS1_B, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        /*
                         * Enable the UART 1 Transceiver
                         */
                        pbc_bctrl1_set |= PBC_BCTRL1_UENA;
                }
                break;
        /* UART 2 IOMUX Configs */
        case 1:
                if (no_irda == 1) {
                        iomux_config_mux(PIN_USB_VMOUT, OUTPUTCONFIG_ALT2, 
                                         INPUTCONFIG_ALT2); /* TXD */
                        iomux_config_mux(PIN_USB_VPOUT, OUTPUTCONFIG_ALT2, 
                                         INPUTCONFIG_ALT2); /* RXD */
                        iomux_config_mux(PIN_USB_XRXD, OUTPUTCONFIG_ALT1, 
                                         INPUTCONFIG_ALT1); /* RTS */
                        iomux_config_mux(PIN_UART_CTS2_B, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        iomux_config_mux(PIN_UART_DSR2_B, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        iomux_config_mux(PIN_UART_DTR2_B, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        iomux_config_mux(PIN_UART_RI2_B, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        iomux_config_mux(PIN_UART_DCD2_B, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        /*
                         * Enable the UART 2 Transceiver
                         */
                        pbc_bctrl1_set |= PBC_BCTRL1_UENCE;
                }
                break;
        /* UART 3 IOMUX Configs */
        case 2:
                if (no_irda == 1) {
                        iomux_config_mux(PIN_UART_TXD3, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        iomux_config_mux(PIN_UART_RXD3, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        iomux_config_mux(PIN_UART_RTS3_B, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        iomux_config_mux(PIN_UART_CTS3_B, OUTPUTCONFIG_FUNC, 
                                         INPUTCONFIG_FUNC);
                        /*
                         * Enable the UART 3 Transceiver
                         */
                        pbc_bctrl1_set |= PBC_BCTRL1_UENB;
                }
                break;
        /* 
         * UART 4 IOMUX Configs
         * UART 4 is used for Irda 
         */
        case 3:
                if (no_irda == 0) {
                        /* 
                         * IOMUX configs for Irda pins
                         */
                         iomux_config_mux(PIN_IRDA_TX4, OUTPUTCONFIG_FUNC, INPUTCONFIG_NONE);
                         iomux_config_mux(PIN_IRDA_RX4, INPUTCONFIG_NONE, INPUTCONFIG_FUNC);

                         iomux_config_mux(PIN_GPIO6,OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                         gpio_config(0, 6, true, GPIO_INT_NONE);
                         /* Clear the SD/Mode signal */
                         gpio_set_data(0, 6, 0);


                        /*
                         * Enable the Irda Transmitter
                         */
                        pbc_bctrl1_set |= PBC_BCTRL1_IREN;
                } 
                break;
        default:
                break;
        }
        writew(pbc_bctrl1_set, PBC_BASE_ADDRESS + PBC_BCTRL1_SET); 
        /*
         * TODO: Configure the Pad registers for the UART pins
         */
}

/*!
 * Setup GPIO for a UART port to be inactive
 *
 * @param  port         a UART port
 * @param  no_irda      indicates if the port is used for SIR
 */
void gpio_uart_inactive(int port, int no_irda)
{
        unsigned int pbc_bctrl1_clr = 0;

        /*
         * Disable the UART Transceiver by configuring the GPIO pin
         */
        switch (port) {
        case 0:
                /*
                 * Disable the UART 1 Transceiver
                 */
                pbc_bctrl1_clr |= PBC_BCTRL1_UENA;
                break;
        case 1:
                /*
                 * Disable the UART 2 Transceiver
                 * Note: Check this, currently modelled this way in Virtio
                 */
                pbc_bctrl1_clr |= PBC_BCTRL1_UENCE;
                break;
        case 2:
                /*
                 * Disable the UART 3 Transceiver
                 */
                pbc_bctrl1_clr |= PBC_BCTRL1_UENB;
                break;
        case 3:
                /*
                 * Disable the Irda Transmitter
                 */
                pbc_bctrl1_clr |= PBC_BCTRL1_IREN;
                break;
        default:
                break;
        }
        writew(pbc_bctrl1_clr, PBC_BASE_ADDRESS + PBC_BCTRL1_CLEAR);
}

/*!
 * Configure the IOMUX GPR register to receive shared SDMA UART events
 *
 * @param  port         a UART port
 */
void config_uartdma_event(int port) 
{
        switch (port) {
        case 3:
                /* Configure to receive UART 4 SDMA events */
                iomux_config_gpr(MUX_PGP_FIRI, false);
                break;
        default:
                break;
        }
}

/*!
 * Setup GPIO for a Keypad to be active
 */
void gpio_keypad_active(void)
{
        iomux_config_mux(PIN_KEY_COL0, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_COL1, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_COL2, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_COL3, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_COL4, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_COL5, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_COL6, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_COL7, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_ROW0, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_ROW1, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_ROW2, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_ROW3, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_ROW4, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_ROW5, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_ROW6, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        iomux_config_mux(PIN_KEY_ROW7, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
} 

/*!
 * Setup GPIO for a keypad to be inactive
 */
void gpio_keypad_inactive(void)
{
        iomux_config_mux(PIN_KEY_COL0, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_COL1, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_COL2, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_COL3, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_COL4, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_COL5, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_COL6, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_COL7, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_ROW0, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_ROW1, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_ROW2, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_ROW3, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_ROW4, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_ROW5, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_ROW6, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
        iomux_config_mux(PIN_KEY_ROW7, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE); 
}

/*!
 * Setup GPIO for a CSPI device to be active
 *
 * @param  cspi_mod         an CSPI device
 */
void gpio_spi_active(int cspi_mod)
{
        switch (cspi_mod) {
        case 0:
                /* SPI1_SS0 IOMux configuration */
                iomux_config_mux(PIN_CSPI1_CS_0, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                /* SPI1 MISO IOMux configuration */
                iomux_config_mux(PIN_CSPI1_DI, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                /* SPI1 MOSI IOMux configuration */
                iomux_config_mux(PIN_CSPI1_DO, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                /* SPI1_SS1 IOMux configuration */
                iomux_config_mux(PIN_CSPI1_CS_1, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                /* SPI1 CLK IOMux configuration */
                iomux_config_mux(PIN_CSPI1_CK, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                break;
        case 1:
                /* SPI2_SS0 IOMux configuration */
                iomux_config_mux(PIN_CSPI2_CS_0, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                /* SPI2 MISO IOMux configuration */
                iomux_config_mux(PIN_CSPI2_DI, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                /* SPI2 MOSI IOMux configuration */
                iomux_config_mux(PIN_CSPI2_DO, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                /* SPI2_SS1 IOMux configuration */
                iomux_config_mux(PIN_CSPI2_CS_1, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                /* SPI2 CLK IOMux configuration */
                iomux_config_mux(PIN_CSPI2_CK, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                break;
        default:
                break;
        }
}

/*!
 * Setup GPIO for a CSPI device to be inactive
 *
 * @param  cspi_mod         a CSPI device
 */
void gpio_spi_inactive(int cspi_mod)
{
        switch (cspi_mod) {
        case 0:
                /* SPI1_SS0 IOMux configuration */
                iomux_config_mux(PIN_CSPI1_CS_0, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                /* SPI1 MISO IOMux configuration */
                iomux_config_mux(PIN_CSPI1_DI, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                /* SPI1 MOSI IOMux configuration */
                iomux_config_mux(PIN_CSPI1_DO, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                /* SPI1_SS1 IOMux configuration */
                iomux_config_mux(PIN_CSPI1_CS_1, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                /* SPI1 CLK IOMux configuration */
                iomux_config_mux(PIN_CSPI1_CK, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                break;
        case 1:
                /* SPI2_SS0 IOMux configuration */
                iomux_config_mux(PIN_CSPI2_CS_0, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                /* SPI2 MISO IOMux configuration */
                iomux_config_mux(PIN_CSPI2_DI, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                /* SPI2 MOSI IOMux configuration */
                iomux_config_mux(PIN_CSPI2_DO, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                /* SPI2_SS1 IOMux configuration */
                iomux_config_mux(PIN_CSPI2_CS_1, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                /* SPI2 CLK IOMux configuration */
                iomux_config_mux(PIN_CSPI2_CK, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                break;
        default:
                break;
        }
}

/*!
 * Setup GPIO for an I2C device to be active
 *
 * @param  i2c_num         an I2C device
 */
void gpio_i2c_active(int i2c_num) 
{
        switch (i2c_num) {
        case 0:
                iomux_config_mux(PIN_I2C_CLK, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                iomux_config_mux(PIN_I2C_DAT, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                break;
        default:
                break;
        }
}

/*!
 * Setup GPIO for an I2C device to be inactive
 *
 * @param  i2c_num         an I2C device
 */
void gpio_i2c_inactive(int i2c_num) 
{
        switch (i2c_num) {
        case 0:
                iomux_config_mux(PIN_I2C_CLK, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                iomux_config_mux(PIN_I2C_DAT, OUTPUTCONFIG_GPIO, INPUTCONFIG_GPIO);
                break;
        default:
                break;
        }
}

/*!
 * This function configures the Atlas intrrupt operations.
 *
 */
void gpio_atlas_active(void* irq_handler) 
{
        iomux_config_mux(PIN_PM_INT, OUTPUTCONFIG_ALT2, 
                INPUTCONFIG_ALT2);
        edio_config(ED_INT1, 0, EDIO_INT_RISE_EDGE);
}

/*!
 * This function clears the Atlas intrrupt.
 *
 */
void gpio_atlas_clear_int(void) 
{
        edio_clear_int(ED_INT1);
        edio_get_int(ED_INT1);
}

/*!
 * This function return the SPI connected to Atlas.
 *
 */
int gpio_atlas_get_spi(void) 
{
        /* ARGON -> SPI2 = 1 */
        return 1;
}

/*!
 * This function return the SPI smave select for Atlas.
 *
 */
int gpio_atlas_get_ss(void) 
{
        /* ARGONEVB -> SS = 0 */
        return 0;
}

/*!
 * Setup GPIO for SDHC to be active
 *
 * @param module SDHC module number
 */
void gpio_sdhc_active(int module) 
{
        unsigned int pbc_bctrl1_set = 0;
        switch(module){
        case 0:
                iomux_config_mux(PIN_MMC1_CLK, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                iomux_config_mux(PIN_MMC1_CMD, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                iomux_config_mux(PIN_MMC1_DATA_0, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                iomux_config_mux(PIN_MMC1_DATA_1, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                iomux_config_mux(PIN_MMC1_DATA_2, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                iomux_config_mux(PIN_MMC1_DATA_3, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                pbc_bctrl1_set |= PBC_BCTRL1_MCP1;
                break;
        case 1:
                iomux_config_mux(PIN_MMC2_CLK, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                iomux_config_mux(PIN_MMC2_CMD, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                iomux_config_mux(PIN_MMC2_DATA_0, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                iomux_config_mux(PIN_MMC2_DATA_1, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                iomux_config_mux(PIN_MMC2_DATA_2, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                iomux_config_mux(PIN_MMC2_DATA_3, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
                pbc_bctrl1_set |= PBC_BCTRL1_MCP2;
                break;
        default:
                break;
        }
        writew(pbc_bctrl1_set, PBC_BASE_ADDRESS + PBC_BCTRL1_SET);
}

/*!
 * Setup GPIO for SDHC1 to be inactive
 *
 * @param module SDHC module number
 */
void gpio_sdhc_inactive(int module) 
{
        unsigned int pbc_bctrl1_set = 0;
        switch(module){
        case 0:
                iomux_config_mux(PIN_MMC1_CLK, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                iomux_config_mux(PIN_MMC1_CMD, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                iomux_config_mux(PIN_MMC1_DATA_0, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                iomux_config_mux(PIN_MMC1_DATA_1, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                iomux_config_mux(PIN_MMC1_DATA_2, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                iomux_config_mux(PIN_MMC1_DATA_3, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                pbc_bctrl1_set &= PBC_BCTRL1_MCP1;
                break;
        case 1:
                iomux_config_mux(PIN_MMC2_CLK, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                iomux_config_mux(PIN_MMC2_CMD, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                iomux_config_mux(PIN_MMC2_DATA_0, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                iomux_config_mux(PIN_MMC2_DATA_1, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                iomux_config_mux(PIN_MMC2_DATA_2, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                iomux_config_mux(PIN_MMC2_DATA_3, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                pbc_bctrl1_set &= PBC_BCTRL1_MCP2;
                break;
        default:
                break;
        }
        writew(pbc_bctrl1_set, PBC_BASE_ADDRESS + PBC_BCTRL1_SET);
}

/*!
 * Setup the IOMUX/GPIO for SDHC1 SD1_DET.
 * 
 * @param  host Pointer to MMC/SD host structure.
 * @param  handler      GPIO ISR function pointer for the GPIO signal.
 * @return The function returns 0 on success and -1 on failure.
 *
 **/
int sdhc_intr_setup(void *host, gpio_irq_handler handler) 
{
        int ret;

        /* MMC1_SDDET is connected to GPIO37 */
        iomux_config_mux(PIN_GPIO37, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        gpio_config(0, 24, false, GPIO_INT_FALL_EDGE);
        ret = gpio_request_irq(0, 24, GPIO_HIGH_PRIO, handler,
                        0, "MXCMMC", host);
        if (ret != 0) {
                gpio_free_irq(0, 24, GPIO_HIGH_PRIO);
        }
        return ret;
}

/*!
 * Clear the IOMUX/GPIO for SDHC1 SD1_DET.
 *
 * @param flag Flag represents whether the card is inserted/removed.
 *             Using this sensitive level of GPIO signal is changed.
 *
 **/
void sdhc_intr_clear(int *flag) 
{
        if(*flag) {
                gpio_config(0, 24, false, GPIO_INT_FALL_EDGE);
                *flag = 0;
        } else {
                gpio_config(0, 24, false, GPIO_INT_RISE_EDGE);
                *flag = 1;
        }
}

/*
 * Find the minimum clock for SDHC.
 *
 * @param clk SDHC module number.
 * @return Returns the minimum SDHC clock.
 */
unsigned int sdhc_get_min_clock(enum mxc_clocks clk)
{
        return (mxc_get_clocks(SDHC1_CLK) / 8) / 32;
}

/*
 * Find the maximum clock for SDHC.
 * @param clk SDHC module number.
 * @return Returns the maximum SDHC clock.
 */
unsigned int sdhc_get_max_clock(enum mxc_clocks clk)
{
        return mxc_get_clocks(SDHC1_CLK) / 4;
}

/*
 * Probe for the card. If present the GPIO data would be set.
 */
int sdhc_find_card(void)
{
        return gpio_get_data(0, 24);
}
              
/*!
 * Setup GPIO for LCD to be active
 *
 */
void gpio_lcd_active(void)
{
        u16 temp;

        temp = PBC_BCTRL1_LCDON; 
        writew(temp, PBC_BASE_ADDRESS + PBC_BCTRL1_SET); 
}

/*!
 * Setup GPIO for LCD to be inactive
 *
 */
void gpio_lcd_inactive(void)
{
        u16 pbc_bctrl1_set = 0;

        pbc_bctrl1_set = (u16) PBC_BCTRL1_LCDON; 
        writew(pbc_bctrl1_set, PBC_BASE_ADDRESS + PBC_BCTRL1_SET + 2); 
}

/*!
 * Setup GPIO for LCD to be active
 *
 */
void gpio_sensor_active(void)
{
        u16 temp;
     
        temp = PBC_BCTRL1_SENSORON; 

        writew(temp, PBC_BASE_ADDRESS + PBC_BCTRL1_SET); 
}

/*!
 * Setup EDIO/IOMUX for external UART.
 *
 * @param port UART port
 * @return    The function returns 0 if the interrupt pin is connected to 
 *            EDIO or 1 if the pin is connected to GPIO. For GPIO pin the return
 *            value is used to make gpio_request_irq() instead of request_irq().
 */
int extuart_intr_setup(int port)
{
        /*! 
         * 16C652 UART-A and UART-B interrupt pins are connected to
         * e_GPIO24 and e_GPIO25. They are routed to ED_INT6 and ED_INT7
         * by configuring the IOMUX and EDIO.
         */
        if (port == 0) {
                iomux_config_mux(PIN_GPIO24, OUTPUTCONFIG_ALT1, INPUTCONFIG_ALT1);
                edio_config(ED_INT6, 0, EDIO_INT_RISE_EDGE);
                return 0;
        } else if (port == 1) {
                iomux_config_mux(PIN_GPIO25, OUTPUTCONFIG_ALT1, INPUTCONFIG_ALT1);
                edio_config(ED_INT7, 0, EDIO_INT_RISE_EDGE);
                return 0;
        } else {
                printk("%s():Invalid port:%d\n", __FUNCTION__, port);
                return 0;
        }

}

/*!
 * Get the EDIO interrupt, clear if set. 
 *
 * @param port UART port
 */
void extuart_intr_clear(int port)
{
        if (port == 0) {
                if (edio_get_int(ED_INT6)) {
                        edio_clear_int(ED_INT6);
                }
        } else if (port == 1) {
                if (edio_get_int(ED_INT7))
                        edio_clear_int(ED_INT7);
        } else {
                printk("%s():Invalid port:%d\n", __FUNCTION__, port);
        }
}

/*!
 * Do IOMUX configs required to put the
 * pin back in low power mode.
 *
 * @param port UART port
 * @return  The function returns 0 if the interrupt pin is connected to 
 *          EDIO or 1 if the pin is connected to GPIO. For GPIO pin the 
 *          return value is used to make gpio_free_irq() instead of free_irq().
 */    
int extuart_intr_cleanup(int port)
{
        if (port == 0) {
                iomux_config_mux(PIN_GPIO24, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                edio_config(ED_INT6, 0, EDIO_INT_NONE);
        } else if (port == 1){
                iomux_config_mux(PIN_GPIO25, OUTPUTCONFIG_GPIO, INPUTCONFIG_NONE);
                edio_config(ED_INT7, 0, EDIO_INT_NONE);
        }
        return 0;
}

int enet_request_irq(unsigned int irq, 
        irqreturn_t (*handler)(int, void *, struct pt_regs *),
        unsigned long irq_flags, const char * devname, void *dev_id)
{
    int ret = 0;
    
    /*
     * Configure INT line as EDIO input
     */
    iomux_config_mux(PIN_GPIO23, OUTPUTCONFIG_ALT1, INPUTCONFIG_ALT1);
    edio_config(ED_INT5, 0 /*INPUT*/, EDIO_INT_LOW_LEV);

    ret = request_irq(irq, handler, irq_flags, devname, dev_id);
    return ret;
}

int enet_free_irq(unsigned int irq, void *dev_id)
{
    edio_config(ED_INT5, 0, EDIO_INT_NONE);
    edio_clear_int(ED_INT5);
    free_irq(irq, dev_id);
    return 0;
}

void slcd_gpio_config(void)
{
        // PIN_GPIO31 is actually bit 21 in in GPIO module!!!
        gpio_set_data(0, 21, 0);
        gpio_config( 0, 21, true, GPIO_INT_NONE);
        iomux_config_mux(PIN_GPIO31, OUTPUTCONFIG_FUNC, INPUTCONFIG_FUNC);
        msleep(1);

        gpio_set_data(0, 21, 1);
        msleep(1);
}
