s5pc1xx: gpio: use C structure and GPIO API functions
authorMinkyu Kang <mk7.kang@samsung.com>
Tue, 13 Oct 2009 05:05:16 +0000 (14:05 +0900)
committerMinkyu Kang <mk7.kang@samsung.com>
Tue, 13 Oct 2009 05:05:16 +0000 (14:05 +0900)
Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
board/samsung/universal/i2c-gpio.c
board/samsung/universal/lowlevel_init.S
board/samsung/universal/modem_boot.c
board/samsung/universal/universal.c
cpu/arm_cortexa8/s5pc1xx/Makefile
cpu/arm_cortexa8/s5pc1xx/gpio.c [new file with mode: 0644]
include/asm-arm/arch-s5pc1xx/cpu.h
include/asm-arm/arch-s5pc1xx/gpio.h

index 06bb737..3f02293 100644 (file)
@@ -27,6 +27,7 @@
 #include <i2c-gpio.h>
 
 static unsigned int bus_index;
+static struct s5pc110_gpio *gpio = (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
 
 /*
  * i2c gpio3
@@ -34,7 +35,6 @@ static unsigned int bus_index;
  * SCL: GPJ3[7]
  */
 static struct i2c_gpio_bus_data i2c_gpio3 = {
-       .gpio_base      = S5PC110_GPIO_BASE(S5PC110_GPIO_J3_OFFSET),
        .sda_pin        = 6,
        .scl_pin        = 7,
 };
@@ -45,7 +45,6 @@ static struct i2c_gpio_bus_data i2c_gpio3 = {
  * SCL: GPJ4[3]
  */
 static struct i2c_gpio_bus_data i2c_pmic = {
-       .gpio_base      = S5PC110_GPIO_BASE(S5PC110_GPIO_J4_OFFSET),
        .sda_pin        = 0,
        .scl_pin        = 3,
 };
@@ -56,7 +55,6 @@ static struct i2c_gpio_bus_data i2c_pmic = {
  * SCL: MP05[2]
  */
 static struct i2c_gpio_bus_data i2c_gpio5 = {
-       .gpio_base      = S5PC110_GPIO_BASE(S5PC110_GPIO_MP0_5_OFFSET),
        .sda_pin        = 3,
        .scl_pin        = 2,
 };
@@ -79,23 +77,23 @@ void i2c_gpio_set_bus(int bus)
 void i2c_gpio_init(void)
 {
        int i;
-       unsigned int pin, reg;
+       struct s5pc1xx_gpio_bank *bank;
+
+       i2c_gpio[0].bus->gpio_base = (unsigned int)&gpio->gpio_j3;
+       i2c_gpio[1].bus->gpio_base = (unsigned int)&gpio->gpio_j4;
+       i2c_gpio[2].bus->gpio_base = (unsigned int)&gpio->gpio_mp0_5;
 
        /* set to output */
        for (i = 0; i < ARRAY_SIZE(i2c_gpio); i++) {
-               pin = i2c_gpio[i].bus->gpio_base;
+               bank = (struct s5pc1xx_gpio_bank *)i2c_gpio[i].bus->gpio_base;
 
                /* SDA */
-               reg = readl(pin + S5PC1XX_GPIO_CON_OFFSET);
-               reg &= ~(0xf << (i2c_gpio[i].bus->sda_pin * 4));
-               reg |= (1 << (i2c_gpio[i].bus->sda_pin * 4));
-               writel(reg, pin + S5PC1XX_GPIO_CON_OFFSET);
+               gpio_direction_output(bank,
+                               i2c_gpio[i].bus->sda_pin, 1);
 
                /* SCL */
-               reg = readl(pin + S5PC1XX_GPIO_CON_OFFSET);
-               reg &= ~(0xf << (i2c_gpio[i].bus->scl_pin * 4));
-               reg |= (1 << (i2c_gpio[i].bus->scl_pin * 4));
-               writel(reg, pin + S5PC1XX_GPIO_CON_OFFSET);
+               gpio_direction_output(bank,
+                               i2c_gpio[i].bus->scl_pin, 1);
        }
 }
 
@@ -113,41 +111,38 @@ void i2c_init_board(void)
 
 void i2c_gpio_set(int line, int value)
 {
-       unsigned int pin, reg;
+       struct s5pc1xx_gpio_bank *bank;
 
-       pin = i2c_gpio[bus_index].bus->gpio_base;
+       bank = (struct s5pc1xx_gpio_bank *)i2c_gpio[bus_index].bus->gpio_base;
 
        if (line)
                line = i2c_gpio[bus_index].bus->sda_pin;
        else
                line = i2c_gpio[bus_index].bus->scl_pin;
 
-       reg = readl(pin + S5PC1XX_GPIO_DAT_OFFSET);
-       if (value)
-               reg |= (1 << line);
-       else
-               reg &= ~(1 << line);
-       writel(reg, pin + S5PC1XX_GPIO_DAT_OFFSET);
+       gpio_set_value(bank, line, value);
 }
 
 int i2c_gpio_get(void)
 {
-       unsigned int pin, reg;
+       struct s5pc1xx_gpio_bank *bank;
 
-       pin = i2c_gpio[bus_index].bus->gpio_base;
-       reg = readl(pin + S5PC1XX_GPIO_DAT_OFFSET);
-       return reg & (1 << i2c_gpio[bus_index].bus->sda_pin);
+       bank = (struct s5pc1xx_gpio_bank *)i2c_gpio[bus_index].bus->gpio_base;
+
+       return gpio_get_value(bank, i2c_gpio[bus_index].bus->sda_pin);
 }
 
 void i2c_gpio_dir(int dir)
 {
-       unsigned int pin, reg;
+       struct s5pc1xx_gpio_bank *bank;
 
-       pin = i2c_gpio[bus_index].bus->gpio_base;
+       bank = (struct s5pc1xx_gpio_bank *)i2c_gpio[bus_index].bus->gpio_base;
 
-       reg = readl(pin + S5PC1XX_GPIO_CON_OFFSET);
-       reg &= ~(0xf << (i2c_gpio[bus_index].bus->sda_pin * 4));
-       if (dir)
-               reg |= (1 << (i2c_gpio[bus_index].bus->sda_pin * 4));
-       writel(reg, pin + S5PC1XX_GPIO_CON_OFFSET);
+       if (dir) {
+               gpio_direction_output(bank,
+                               i2c_gpio[bus_index].bus->sda_pin, 0);
+       } else {
+               gpio_direction_input(bank,
+                               i2c_gpio[bus_index].bus->sda_pin);
+       }
 }
index 7d5ab74..daaf383 100644 (file)
@@ -27,7 +27,6 @@
 #include <version.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/mem.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/power.h>
 #include <asm/arch/watchdog.h>
@@ -54,8 +53,8 @@ lowlevel_init:
        /* r5 has always zero */
        mov     r5, #0
 
-       ldr     r7, =S5PC100_GPIO_BASE(0)
-       ldr     r8, =S5PC100_GPIO_BASE(0)
+       ldr     r7, =S5PC100_GPIO_BASE
+       ldr     r8, =S5PC100_GPIO_BASE
        /* Read CPU ID */
        ldr     r2, =S5PC1XX_PRO_ID
        ldr     r0, [r2]
@@ -63,25 +62,25 @@ lowlevel_init:
        and     r0, r0, r1
        cmp     r0, r5
        beq     100f
-       ldr     r8, =S5PC110_GPIO_BASE(0)
+       ldr     r8, =S5PC110_GPIO_BASE
 100:
        /* Turn on KEY_LED_ON [GPJ4(1)] XMSMWEN */
        cmp     r7, r8
 #ifndef DEBUG_PM_C110
-       addeq   r0, r8, #S5PC100_GPIO_J4_OFFSET
-       addne   r0, r8, #S5PC110_GPIO_J4_OFFSET
-       ldr     r1, [r0, #S5PC1XX_GPIO_CON_OFFSET]
+       addeq   r0, r8, #0x280                          @S5PC100_GPIO_J4_OFFSET
+       addne   r0, r8, #0x2C0                          @S5PC110_GPIO_J4_OFFSET
+       ldr     r1, [r0, #0x0]                          @S5PC1XX_GPIO_CON_OFFSET
        bic     r1, r1, #(0xf << 4)                     @ 1 * 4-bit
        orr     r1, r1, #(0x1 << 4)
-       str     r1, [r0, #S5PC1XX_GPIO_CON_OFFSET]
+       str     r1, [r0, #0x0]                          @S5PC1XX_GPIO_CON_OFFSET
 
-       ldr     r1, [r0, #S5PC1XX_GPIO_DAT_OFFSET]
+       ldr     r1, [r0, #0x4]                          @S5PC1XX_GPIO_DAT_OFFSET
 #ifdef CONFIG_ONENAND_IPL
        orr     r1, r1, #(1 << 1)                       @ 1 * 1-bit
 #else
        bic     r1, r1, #(1 << 1)
 #endif
-       str     r1, [r0, #S5PC1XX_GPIO_DAT_OFFSET]
+       str     r1, [r0, #0x4]                          @S5PC1XX_GPIO_DAT_OFFSET
 #endif
 
        /* IO retension release */
@@ -179,25 +178,25 @@ wakeup:
 #ifdef DEBUG_PM_C110
        mov     r0, r8
        ldr     r1, =0x22222222
-       str     r1, [r0, #S5PC100_GPIO_A0_OFFSET]               @ GPA0_CON
+       str     r1, [r0, #0x0]                  @S5PC100_GPIO_A0_OFFSET
        ldr     r1, =0x00002222
-       str     r1, [r0, #S5PC100_GPIO_A1_OFFSET]               @ GPA1_CON
+       str     r1, [r0, #0x20]                 @S5PC100_GPIO_A1_OFFSET
 
        /* UART_SEL MP0_5[7] at S5PC110 */
-       add     r0, r8, #S5PC110_GPIO_MP0_5_OFFSET
-       ldr     r1, [r0, #S5PC1XX_GPIO_CON_OFFSET]
+       add     r0, r8, #0x360                  @S5PC110_GPIO_MP0_5_OFFSET
+       ldr     r1, [r0, #0x0]                  @S5PC1XX_GPIO_CON_OFFSET
        bic     r1, r1, #(0xf << 28)            @ 28 = 7 * 4-bit
        orr     r1, r1, #(0x1 << 28)            @ Output
-       str     r1, [r0, #S5PC1XX_GPIO_CON_OFFSET]
+       str     r1, [r0, #0x0]                  @S5PC1XX_GPIO_CON_OFFSET
 
-       ldr     r1, [r0, #S5PC1XX_GPIO_PULL_OFFSET]
+       ldr     r1, [r0, #0x8]                  @S5PC1XX_GPIO_PULL_OFFSET
        bic     r1, r1, #(0x3 << 14)            @ 14 = 7 * 2-bit
        orr     r1, r1, #(0x2 << 14)            @ Pull-up enabled
-       str     r1, [r0, #S5PC1XX_GPIO_PULL_OFFSET]
+       str     r1, [r0, #0x8]                  @S5PC1XX_GPIO_PULL_OFFSET
 
-       ldr     r1, [r0, #S5PC1XX_GPIO_DAT_OFFSET]
+       ldr     r1, [r0, #0x4]                  @S5PC1XX_GPIO_DAT_OFFSET
        orr     r1, r1, #(1 << 7)               @ 7 = 7 * 1-bit
-       str     r1, [r0, #S5PC1XX_GPIO_DAT_OFFSET]
+       str     r1, [r0, #0x4]                  @S5PC1XX_GPIO_DAT_OFFSET
 
        ldr     r0, =0xE2900000                 @ S5PC110_PA_UART
        orr     r0, r0, #0x800
@@ -394,9 +393,9 @@ uart_asm_init:
        /* set GPIO to enable UART0-UART4 */
        mov     r0, r8
        ldr     r1, =0x22222222
-       str     r1, [r0, #S5PC100_GPIO_A0_OFFSET]               @ GPA0_CON
+       str     r1, [r0, #0x0]                  @S5PC100_GPIO_A0_OFFSET
        ldr     r1, =0x00002222
-       str     r1, [r0, #S5PC100_GPIO_A1_OFFSET]               @ GPA1_CON
+       str     r1, [r0, #0x20]                 @S5PC100_GPIO_A1_OFFSET
 
        /* Check S5PC100 */
        cmp     r7, r8
@@ -404,20 +403,20 @@ uart_asm_init:
 
 #ifndef DEBUG_PM_C110
        /* UART_SEL GPK0[5] at S5PC100 */
-       add     r0, r8, #S5PC100_GPIO_K0_OFFSET
-       ldr     r1, [r0, #S5PC1XX_GPIO_CON_OFFSET]
+       add     r0, r8, #0x2A0                  @S5PC100_GPIO_K0_OFFSET
+       ldr     r1, [r0, #0x0]                  @S5PC1XX_GPIO_CON_OFFSET
        bic     r1, r1, #(0xf << 20)            @ 20 = 5 * 4-bit
        orr     r1, r1, #(0x1 << 20)            @ Output
-       str     r1, [r0, #S5PC1XX_GPIO_CON_OFFSET]
+       str     r1, [r0, #0x0]                  @S5PC1XX_GPIO_CON_OFFSET
 
-       ldr     r1, [r0, #S5PC1XX_GPIO_PULL_OFFSET]
+       ldr     r1, [r0, #0x8]                  @S5PC1XX_GPIO_PULL_OFFSET
        bic     r1, r1, #(0x3 << 10)            @ 10 = 5 * 2-bit
        orr     r1, r1, #(0x2 << 10)            @ Pull-up enabled
-       str     r1, [r0, #S5PC1XX_GPIO_PULL_OFFSET]
+       str     r1, [r0, #0x8]                  @S5PC1XX_GPIO_PULL_OFFSET
 
-       ldr     r1, [r0, #S5PC1XX_GPIO_DAT_OFFSET]
+       ldr     r1, [r0, #0x4]                  @S5PC1XX_GPIO_DAT_OFFSET
        orr     r1, r1, #(1 << 5)               @ 5 = 5 * 1-bit
-       str     r1, [r0, #S5PC1XX_GPIO_DAT_OFFSET]
+       str     r1, [r0, #0x4]                  @S5PC1XX_GPIO_DAT_OFFSET
 #endif
        b       200f
 110:
@@ -426,20 +425,20 @@ uart_asm_init:
         * 0xE020'0360 is reserved address at S5PC100
         */
        /* UART_SEL MP0_5[7] at S5PC110 */
-       add     r0, r8, #S5PC110_GPIO_MP0_5_OFFSET
-       ldr     r1, [r0, #S5PC1XX_GPIO_CON_OFFSET]
+       add     r0, r8, #0x360                  @S5PC110_GPIO_MP0_5_OFFSET
+       ldr     r1, [r0, #0x0]                  @S5PC1XX_GPIO_CON_OFFSET
        bic     r1, r1, #(0xf << 28)            @ 28 = 7 * 4-bit
        orr     r1, r1, #(0x1 << 28)            @ Output
-       str     r1, [r0, #S5PC1XX_GPIO_CON_OFFSET]
+       str     r1, [r0, #0x0]                  @S5PC1XX_GPIO_CON_OFFSET
 
-       ldr     r1, [r0, #S5PC1XX_GPIO_PULL_OFFSET]
+       ldr     r1, [r0, #0x8]                  @S5PC1XX_GPIO_PULL_OFFSET
        bic     r1, r1, #(0x3 << 14)            @ 14 = 7 * 2-bit
        orr     r1, r1, #(0x2 << 14)            @ Pull-up enabled
-       str     r1, [r0, #S5PC1XX_GPIO_PULL_OFFSET]
+       str     r1, [r0, #0x8]                  @S5PC1XX_GPIO_PULL_OFFSET
 
-       ldr     r1, [r0, #S5PC1XX_GPIO_DAT_OFFSET]
+       ldr     r1, [r0, #0x4]                  @S5PC1XX_GPIO_DAT_OFFSET
        orr     r1, r1, #(1 << 7)               @ 7 = 7 * 1-bit
-       str     r1, [r0, #S5PC1XX_GPIO_DAT_OFFSET]
+       str     r1, [r0, #0x4]                  @S5PC1XX_GPIO_DAT_OFFSET
 200:
        mov     pc, lr
 #endif
index 30dba4a..3ee35c1 100644 (file)
 #define CRC_OK                         0x01
 #define CRC_ERR                                0xff
 
-#define GPIO_CON_MASK                  0xF
-#define GPIO_DAT_MASK                  0x1
-#define GPIO_PUL_MASK                  0x3
-
 extern struct serial_device s5pc1xx_serial3_device;
+static struct s5pc110_gpio *gpio = (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
 
 int uart_serial_pollc(struct serial_device *uart, int retry)
 {
@@ -89,8 +86,7 @@ static int machine_is_tickertape(void)
 
 static int aquila_infineon_modem_on(void)
 {
-       unsigned int con, dat, pud, exit = 0;
-       unsigned int pin;
+       unsigned int dat, exit = 0;
        unsigned int nInfoSize;
        unsigned char *pDataPSI;
        int nCnt;
@@ -101,60 +97,22 @@ static int aquila_infineon_modem_on(void)
        /* Infineon modem */
        /* 1. Modem gpio init */
        /* Phone_on */
-       pin = S5PC110_GPIO_BASE(S5PC110_GPIO_J1_OFFSET);
-
-       con = readl(pin + S5PC1XX_GPIO_CON_OFFSET);
-       con &= ~(0xf << 0); /* 0 = 0 * 4 */
-       con |= (0x1 << 0); /* Set to output (0x1) */
-       writel(con, pin + S5PC1XX_GPIO_CON_OFFSET);
-
-       pud = readl(pin + S5PC1XX_GPIO_PULL_OFFSET);
-       pud &= ~(0x3 << 0); /* 0 = 0 * 2 */
-       pud |= (0x0 << 0); /* Pull-up/down disabled */
-       writel(pud, pin + S5PC1XX_GPIO_PULL_OFFSET);
+       gpio_direction_output(&gpio->gpio_j1, 0, 1);
+       gpio_set_pull(&gpio->gpio_j1, 0, GPIO_PULL_NONE);
 
        /* CP_Reset */
-       pin = S5PC110_GPIO_BASE(S5PC110_GPIO_H3_OFFSET);
-
-       con = readl(pin + S5PC1XX_GPIO_CON_OFFSET);
-       con &= ~(0xf << 28); /* 28 = 7 * 4 */
-       con |= (0x1 << 28); /* Set to output (0x1) */
-       writel(con, pin + S5PC1XX_GPIO_CON_OFFSET);
-
-       pud = readl(pin + S5PC1XX_GPIO_PULL_OFFSET);
-       pud &= ~(0x3 << 14); /* 14 = 7 * 2 */
-       pud |= (0x0 << 14); /* Pull-up/down disabled */
-       writel(pud, pin + S5PC1XX_GPIO_PULL_OFFSET);
+       gpio_direction_output(&gpio->gpio_h3, 7, 1);
+       gpio_set_pull(&gpio->gpio_h3, 7, GPIO_PULL_NONE);
 
        /* nINT_ONEDRAN_AP */
-       pin = S5PC110_GPIO_BASE(S5PC110_GPIO_H1_OFFSET);
-
-       con = readl(pin + S5PC1XX_GPIO_CON_OFFSET);
-       con &= ~(0xf << 12); /* 12 = 3 * 4 */
-       con |= (0x0 << 12); /* Set to input (0x0) */
-       writel(con, pin + S5PC1XX_GPIO_CON_OFFSET);
-
-       pud = readl(pin + S5PC1XX_GPIO_PULL_OFFSET);
-       pud &= ~(0x3 << 6); /* 6 = 3 * 2 */
-       pud |= (0x0 << 6); /* Pull-up/down disabled */
-       writel(pud, pin + S5PC1XX_GPIO_PULL_OFFSET);
+       gpio_direction_output(&gpio->gpio_h1, 3, 1);
+       gpio_set_pull(&gpio->gpio_h1, 3, GPIO_PULL_NONE);
 
        /* 2. Uart3 init */
-       pin = S5PC110_GPIO_BASE(S5PC110_GPIO_A1_OFFSET);
-
-       con = readl(pin + S5PC1XX_GPIO_CON_OFFSET);
-       con &= ~(0xf << 8); /* 8 = 2 * 4 */
-       con |= (0x2 << 8); /* Set to UART3_RXD */
-       con &= ~(0xf << 12); /* 12 = 3 * 4 */
-       con |= (0x2 << 12); /* Set to UART3_TXD */
-       writel(con, pin + S5PC1XX_GPIO_CON_OFFSET);
-
-       pud = readl(pin + S5PC1XX_GPIO_PULL_OFFSET);
-       pud &= ~(0x3 << 4); /* 4 = 2 * 2 */
-       pud |= (0x0 << 4); /* Pull-up/down disabled */
-       pud &= ~(0x3 << 6); /* 6 = 3 * 2 */
-       pud |= (0x0 << 6); /* Pull-up/down disabled */
-       writel(pud, pin + S5PC1XX_GPIO_PULL_OFFSET);
+       gpio_cfg_pin(&gpio->gpio_a1, 2, 0x2);
+       gpio_cfg_pin(&gpio->gpio_a1, 3, 0x2);
+       gpio_set_pull(&gpio->gpio_a1, 2, GPIO_PULL_NONE);
+       gpio_set_pull(&gpio->gpio_a1, 3, GPIO_PULL_NONE);
 
        /* reset and enable FIFOs, set triggers to the maximum */
        writel(0x0, 0xE2900C08);
@@ -168,30 +126,18 @@ static int aquila_infineon_modem_on(void)
        /* 3. Modem reset */
        while (1) {
                /* PHONE_ON -> low */
-               pin = S5PC110_GPIO_BASE(S5PC110_GPIO_J1_OFFSET);
-               dat = readl(pin + S5PC1XX_GPIO_DAT_OFFSET);
-               dat &= ~(0x1 << 0);
-               writel(dat, pin + S5PC1XX_GPIO_DAT_OFFSET);
+               gpio_set_value(&gpio->gpio_j1, 0, 0);
 
                /* CP_RESET -> low */
-               pin = S5PC110_GPIO_BASE(S5PC110_GPIO_H3_OFFSET);
-               dat = readl(pin + S5PC1XX_GPIO_DAT_OFFSET);
-               dat &= ~(0x1 << 7);
-               writel(dat, pin + S5PC1XX_GPIO_DAT_OFFSET);
+               gpio_set_value(&gpio->gpio_h3, 7, 0);
 
                udelay(200*1000);       /* 200ms */
 
                /* CP_RESET -> high */
-               pin = S5PC110_GPIO_BASE(S5PC110_GPIO_H3_OFFSET);
-               dat = readl(pin + S5PC1XX_GPIO_DAT_OFFSET);
-               dat |= (0x1 << 7);
-               writel(dat, pin + S5PC1XX_GPIO_DAT_OFFSET);
+               gpio_set_value(&gpio->gpio_h3, 7, 1);
 
                /* PHONE_ON -> high */
-               pin = S5PC110_GPIO_BASE(S5PC110_GPIO_J1_OFFSET);
-               dat = readl(pin + S5PC1XX_GPIO_DAT_OFFSET);
-               dat |= (0x1 << 0);
-               writel(dat, pin + S5PC1XX_GPIO_DAT_OFFSET);
+               gpio_set_value(&gpio->gpio_j1, 0, 1);
 
                udelay(27*1000);        /* > 26.6ms */
 
@@ -273,11 +219,8 @@ static int aquila_infineon_modem_on(void)
                }
 
                /* check Modem reaction */
-               pin = S5PC110_GPIO_BASE(S5PC110_GPIO_H1_OFFSET);
-               do {
-                       dat = readl(pin + S5PC1XX_GPIO_DAT_OFFSET);
-                       dat &= (0x1 << 3);
-               } while (dat);
+               while (gpio_get_value(&gpio->gpio_h1, 3))
+                       ;
 
                if (rOneDRAM_MAILBOX_AB != IPC_CP_READY_FOR_LOADING) {
                        printf("OneDRAM is NOT initialized for Modem\n");
@@ -323,11 +266,8 @@ static int aquila_infineon_modem_on(void)
                rOneDRAM_MAILBOX_BA = IPC_CP_IMG_LOADED;
 
                /* check Modem reaction */
-               pin = S5PC110_GPIO_BASE(S5PC110_GPIO_H1_OFFSET);
-               do {
-                       dat = readl(pin + S5PC1XX_GPIO_CON_OFFSET);
-                       dat &= (0x1 << 3);
-               } while (dat);
+               while (gpio_get_value(&gpio->gpio_h1, 3))
+                       ;
 
                if (rOneDRAM_MAILBOX_AB != IPC_CP_READY) {
                        printf("Modem is NOT ready to boot\n");
@@ -370,10 +310,8 @@ static int aquila_infineon_modem_on(void)
                printf("\n");
                printf("Waiting for 5 secs for modem to respond\n");
 
-               pin = S5PC110_GPIO_BASE(S5PC110_GPIO_H1_OFFSET);
                for (i = 0; i < 50000; i++) {
-                       dat = readl(pin + S5PC1XX_GPIO_CON_OFFSET);
-                       dat &= (0x1 << 3);
+                       dat = gpio_get_value(&gpio->gpio_h1, 3);
                        if (dat == 0)
                                break;
                        udelay(100);
@@ -388,31 +326,6 @@ static int aquila_infineon_modem_on(void)
        return 0;
 }
 
-static void gpio_direction_output(int base, int offset, int value)
-{
-       int tmp;
-
-       tmp = readl(base + S5PC1XX_GPIO_CON_OFFSET);
-       tmp &= ~(GPIO_CON_MASK << (offset << 2));
-       tmp |= (1 << (offset << 2));
-       writel(tmp, base + S5PC1XX_GPIO_CON_OFFSET);
-
-       tmp = readl(base + S5PC1XX_GPIO_DAT_OFFSET);
-       tmp &= ~(GPIO_DAT_MASK << (offset << 0));
-       tmp |= (value << (offset << 0));
-       writel(tmp, base + S5PC1XX_GPIO_DAT_OFFSET);
-}
-
-static void gpio_set_value(int base, int offset, int value)
-{
-       int tmp;
-
-       tmp = readl(base + S5PC1XX_GPIO_DAT_OFFSET);
-       tmp &= ~(GPIO_DAT_MASK << (offset << 0));
-       tmp |= (value << (offset << 0));
-       writel(tmp, base + S5PC1XX_GPIO_DAT_OFFSET);
-}
-
 static void mdelay(int msec)
 {
        int i;
@@ -422,25 +335,22 @@ static void mdelay(int msec)
 
 static void tickertape_modem_on(void)
 {
-       int gpio_phone_on_base, gpio_phone_on;
-       int gpio_cp_rst_base, gpio_cp_rst;
+       int gpio_phone_on, gpio_cp_rst;
 
        printf("Tickertape phone on\n");
 
-       gpio_phone_on_base = S5PC110_GPIO_BASE(S5PC110_GPIO_J1_OFFSET);
        gpio_phone_on = 0;
-       gpio_cp_rst_base = S5PC110_GPIO_BASE(S5PC110_GPIO_H3_OFFSET);
        gpio_cp_rst = 7;
 
-       gpio_direction_output(gpio_phone_on_base, gpio_phone_on, 0);
-       gpio_direction_output(gpio_cp_rst_base, gpio_cp_rst, 0);
+       gpio_direction_output(&gpio->gpio_j1, gpio_phone_on, 0);
+       gpio_direction_output(&gpio->gpio_h3, gpio_cp_rst, 0);
 
-       gpio_set_value(gpio_cp_rst_base, gpio_cp_rst, 0);
-       gpio_set_value(gpio_phone_on_base, gpio_phone_on, 1);
+       gpio_set_value(&gpio->gpio_h3, gpio_cp_rst, 0);
+       gpio_set_value(&gpio->gpio_j1, gpio_phone_on, 1);
        mdelay(100);
-       gpio_set_value(gpio_cp_rst_base, gpio_cp_rst, 1);
+       gpio_set_value(&gpio->gpio_h3, gpio_cp_rst, 1);
        mdelay(900);
-       gpio_set_value(gpio_phone_on_base, gpio_phone_on, 0);
+       gpio_set_value(&gpio->gpio_j1, gpio_phone_on, 0);
 }
 
 int do_modem(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
index 549538f..6a64b60 100644 (file)
@@ -42,27 +42,6 @@ DECLARE_GLOBAL_DATA_PTR;
 #define I2C_PMIC       1
 #define I2C_GPIO5      2
 
-/* GPIOs */
-#define CON_MASK(x)            (0xf << ((x) << 2))
-#define CON_INPUT(x)           (0x0 << ((x) << 2))
-#define CON_OUTPUT(x)          (0x1 << ((x) << 2))
-#define CON_SFR(x, v)          ((v) << ((x) << 2))
-#define CON_IRQ(x)             (0xf << ((x) << 2))
-
-#define DAT_MASK(x)            (0x1 << (x))
-#define DAT_SET(x)             (0x1 << (x))
-
-#define PULL_MASK(x)           (0x3 << ((x) << 1))
-#define PULL_DIS(x)            (0x0 << ((x) << 1))
-#define PULL_DOWN(x)           (0x1 << ((x) << 1))
-#define PULL_UP(x)             (0x2 << ((x) << 1))
-
-#define PDN_MASK(x)            (0x3 << ((x) << 1))
-#define OUTPUT0(x)             (0x0 << ((x) << 1))
-#define OUTPUT1(x)             (0x1 << ((x) << 1))
-#define INPUT(x)               (0x2 << ((x) << 1))
-#define PREVIOUS(x)            (0x3 << ((x) << 1))
-
 static unsigned int board_rev;
 
 int board_init(void)
@@ -201,26 +180,27 @@ static void set_board_meminfo(void)
        setenv("meminfo", "mem=80M mem=128M@0x40000000");
 }
 
-static void check_hw_revision(void)
+static unsigned int get_hw_revision(struct s5pc1xx_gpio_bank* bank)
 {
-       unsigned int board = MACH_UNIVERSAL;    /* Default is Universal */
-       unsigned long pin;
-
-       if (cpu_is_s5pc110())
-               pin = S5PC110_GPIO_BASE(S5PC110_GPIO_J0_OFFSET);
-       else
-               pin = S5PC100_GPIO_BASE(S5PC100_GPIO_J0_OFFSET);
+       unsigned int rev;
 
-       pin += S5PC1XX_GPIO_DAT_OFFSET;
+       rev = gpio_get_value(bank, 2);
+       rev |= (gpio_get_value(bank, 3) << 1);
+       rev |= (gpio_get_value(bank, 4) << 2);
 
-       /* check H/W revision */
-       board_rev  = readl(pin);
+       return rev;
+}
 
-       /* GPJ0[4:2] */
-       board_rev >>= 2;
-       board_rev &= 0x7;
+static void check_hw_revision(void)
+{
+       unsigned int board = MACH_UNIVERSAL;    /* Default is Universal */
 
        if (cpu_is_s5pc100()) {
+               struct s5pc100_gpio *gpio =
+                       (struct s5pc100_gpio *)S5PC100_GPIO_BASE;
+
+               board_rev = get_hw_revision(&gpio->gpio_j0);
+
                if (board_rev == 3) {
                        /* C100 TickerTape */
                        board = MACH_TICKERTAPE;
@@ -228,6 +208,11 @@ static void check_hw_revision(void)
                        setenv("meminfo", "mem=128M");
                }
        } else {
+               struct s5pc110_gpio *gpio =
+                       (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
+
+               board_rev = get_hw_revision(&gpio->gpio_j0);
+
                /*
                 * Note Check 'Aquila' board first
                 *
@@ -248,41 +233,30 @@ static void check_hw_revision(void)
                 */
 
                /* C110 Aquila */
-               pin = S5PC110_GPIO_BASE(S5PC110_GPIO_J1_OFFSET);
-               pin += S5PC1XX_GPIO_DAT_OFFSET;
-               if ((readl(pin) & 0xf0) == 0) {
+               if (gpio_get_value(&gpio->gpio_j1, 4) == 0) {
                        board = MACH_AQUILA;
                        board_rev |= J1_B2_BOARD_FEATURE;
 
                        /* Check board */
-                       pin = S5PC110_GPIO_BASE(S5PC110_GPIO_H1_OFFSET);
-                       pin += S5PC1XX_GPIO_DAT_OFFSET;
-                       if ((readl(pin) & (1 << 2)) == 0)
+                       if (gpio_get_value(&gpio->gpio_h1, 2) == 0);
                                board_rev |= LIMO_UNIVERSAL_BOARD;
 
-                       pin = S5PC110_GPIO_BASE(S5PC110_GPIO_H3_OFFSET);
-                       pin += S5PC1XX_GPIO_DAT_OFFSET;
-                       if ((readl(pin) & (1 << 2)) == 0)
+                       if (gpio_get_value(&gpio->gpio_h3, 2) == 0);
                                board_rev |= LIMO_REAL_BOARD;
 #if 0
                        /* C110 Aquila ScreenSplit */
-                       pin = S5PC110_GPIO_BASE(S5PC110_GPIO_MP0_3_OFFSET);
-                       pin += S5PC1XX_GPIO_DAT_OFFSET;
-                       if ((readl(pin) & (1 << 5)))
+                       if (gpio_get_value(&gpio->gpio_mp0_3, 5))
                                board_rev |= SCREEN_SPLIT_FEATURE;
                        else {
-                               pin = S5PC110_GPIO_BASE(S5PC110_GPIO_I_OFFSET);
-                               pin += S5PC1XX_GPIO_DAT_OFFSET;
-                               if ((readl(pin) & (1 << 3)))
+                               if (gpio_get_value(&gpio->gpio_i, 3)
                                        board_rev |= SCREEN_SPLIT_FEATURE;
                        }
 #endif
                }
 
                /* C110 TickerTape */
-               pin = S5PC110_GPIO_BASE(S5PC110_GPIO_D1_OFFSET);
-               pin += S5PC1XX_GPIO_DAT_OFFSET;
-               if ((readl(pin) & 0x03) == 0)
+               if (gpio_get_value(&gpio->gpio_d1, 0) == 0 &&
+                       gpio_get_value(&gpio->gpio_d1, 1) == 0)
                        board = MACH_TICKERTAPE;
        }
 
@@ -337,81 +311,10 @@ static void check_auto_burn(void)
        writel(0xa5a55a5a, magic_base + 0x4);
 }
 
-static void gpio_direction_output(int reg, int offset, int enable)
-{
-       unsigned int value;
-
-       value = readl(reg + S5PC1XX_GPIO_CON_OFFSET);
-       value &= ~CON_MASK(offset);
-       value |= CON_OUTPUT(offset);
-       writel(value, reg + S5PC1XX_GPIO_CON_OFFSET);
-
-       value = readl(reg + S5PC1XX_GPIO_DAT_OFFSET);
-       value &= ~DAT_MASK(offset);
-       if (enable)
-               value |= DAT_SET(offset);
-       writel(value, reg + S5PC1XX_GPIO_DAT_OFFSET);
-}
-
-static void gpio_direction_input(int reg, int offset)
-{
-       unsigned int value;
-
-       value = readl(reg + S5PC1XX_GPIO_CON_OFFSET);
-       value &= ~CON_MASK(offset);
-       value |= CON_INPUT(offset);
-       writel(value, reg + S5PC1XX_GPIO_CON_OFFSET);
-}
-
-static void gpio_irq_mode(int reg, int offset)
-{
-       unsigned int value;
-
-       value = readl(reg + S5PC1XX_GPIO_CON_OFFSET);
-       value &= ~CON_MASK(offset);
-       value |= CON_IRQ(offset);
-       writel(value, reg + S5PC1XX_GPIO_CON_OFFSET);
-}
-
-static void gpio_set_value(int reg, int offset, int enable)
-{
-       unsigned int value;
-
-       value = readl(reg + S5PC1XX_GPIO_DAT_OFFSET);
-       value &= ~DAT_MASK(offset);
-       if (enable)
-               value |= DAT_SET(offset);
-       writel(value, reg + S5PC1XX_GPIO_DAT_OFFSET);
-}
-
-enum pull_mode {
-       PULL_NONE_MODE,
-       PULL_DOWN_MODE,
-       PULL_UP_MODE,
-};
-
-static void gpio_pull_cfg(int reg, int offset, enum pull_mode mode)
-{
-       unsigned int value;
-
-       value = readl(reg + S5PC1XX_GPIO_PULL_OFFSET);
-       value &= ~PULL_MASK(offset);
-       switch (mode) {
-       case PULL_DOWN_MODE:
-               value |= PULL_DOWN(offset);
-               break;
-       case PULL_UP_MODE:
-               value |= PULL_UP(offset);
-               break;
-       default:
-               break;
-       }
-       writel(value, reg + S5PC1XX_GPIO_PULL_OFFSET);
-}
-
 static void pmic_pin_init(void)
 {
        unsigned int reg, value;
+       struct s5pc110_gpio *gpio = (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
 
        if (cpu_is_s5pc100())
                return;
@@ -427,38 +330,35 @@ static void pmic_pin_init(void)
        writel(value, reg);
 
        /* nPOWER: XEINT_22: GPH2[6] interrupt mode */
-       reg = S5PC110_GPIO_BASE(S5PC110_GPIO_H2_OFFSET);
-       gpio_irq_mode(reg, 6);
-       gpio_pull_cfg(reg, 6, PULL_UP_MODE);
+       gpio_cfg_pin(&gpio->gpio_h2, 6, GPIO_IRQ);
+       gpio_set_pull(&gpio->gpio_h2, 6, GPIO_PULL_UP);
 }
 
 static void enable_ldos(void)
 {
-       unsigned int reg;
+       struct s5pc110_gpio *gpio = (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
 
        if (cpu_is_s5pc100())
                return;
 
        /* TOUCH_EN: XMMC3DATA_3: GPG3[6] output high */
-       reg = S5PC110_GPIO_BASE(S5PC110_GPIO_G3_OFFSET);
-       gpio_direction_output(reg, 6, 1);
+       gpio_direction_output(&gpio->gpio_g3, 6, 1);
 }
 
 static void enable_t_flash(void)
 {
-       unsigned int reg;
+       struct s5pc110_gpio *gpio = (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
 
        if (!(board_is_limo_universal() || board_is_limo_real()))
                return;
 
        /* T_FLASH_EN : XM0ADDR_13: MP0_5[4] output high */
-       reg = S5PC110_GPIO_BASE(S5PC110_GPIO_MP0_5_OFFSET);
-       gpio_direction_output(reg, 4, 1);
+       gpio_direction_output(&gpio->gpio_mp0_5, 4, 1);
 }
 
 static void setup_limo_real_gpios(void)
 {
-       unsigned int reg, value;
+       struct s5pc110_gpio *gpio = (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
 
        if (!board_is_limo_real())
                return;
@@ -467,17 +367,14 @@ static void setup_limo_real_gpios(void)
         * Note: Please write GPIO alphabet order
         */
        /* CODEC_LDO_EN: XVVSYNC_LDI: GPF3[4] output high */
-       reg = S5PC110_GPIO_BASE(S5PC110_GPIO_F3_OFFSET);
-       gpio_direction_output(reg, 4, 1);
+       gpio_direction_output(&gpio->gpio_f3, 4, 1);
 
        /* RESET_REQ_N: XM0BEN_1: MP0_2[1] output high */
-       reg = S5PC110_GPIO_BASE(S5PC110_GPIO_MP0_2_OFFSET);
-       gpio_direction_output(reg, 2, 1);
+       gpio_direction_output(&gpio->gpio_mp0_2, 2, 1);
 
        /* T_FLASH_DETECT: EINT28: GPH3[4] interrupt mode */
-       reg = S5PC110_GPIO_BASE(S5PC110_GPIO_H3_OFFSET);
-       gpio_irq_mode(reg, 4);
-       gpio_pull_cfg(reg, 4, PULL_UP_MODE);
+       gpio_cfg_pin(&gpio->gpio_h3, 4, GPIO_IRQ);
+       gpio_set_pull(&gpio->gpio_h3, 4, GPIO_PULL_UP);
 }
 
 #define KBR3           (1 << 3)
@@ -488,63 +385,48 @@ static void setup_limo_real_gpios(void)
 static void check_keypad(void)
 {
        unsigned int reg, value;
-       unsigned int col_mask, col_mode, row_mask, row_mode;
+       unsigned int col_mask, row_mask;
        unsigned int auto_download = 0;
        unsigned int row_value[4], i;
 
        if (cpu_is_s5pc100()) {
+               struct s5pc100_gpio *gpio =
+                       (struct s5pc100_gpio *)S5PC100_GPIO_BASE;
+
                /* Set GPH2[2:0] to KP_COL[2:0] */
-               reg = S5PC100_GPIO_BASE(S5PC100_GPIO_H2_OFFSET);
-               reg += S5PC1XX_GPIO_CON_OFFSET;
-               value = readl(reg);
-               value &= ~(0xFFF);
-               value |= (0x333);
-               writel(value, reg);
+               gpio_cfg_pin(&gpio->gpio_h2, 0, 0x3);
+               gpio_cfg_pin(&gpio->gpio_h2, 1, 0x3);
+               gpio_cfg_pin(&gpio->gpio_h2, 2, 0x3);
 
                /* Set GPH3[2:0] to KP_ROW[2:0] */
-               reg = S5PC100_GPIO_BASE(S5PC100_GPIO_H3_OFFSET);
-               reg += S5PC1XX_GPIO_CON_OFFSET;
-               value = readl(reg);
-               value &= ~(0xFFF);
-               value |= (0x333);
-               writel(value, reg);
+               gpio_cfg_pin(&gpio->gpio_h3, 0, 0x3);
+               gpio_cfg_pin(&gpio->gpio_h3, 1, 0x3);
+               gpio_cfg_pin(&gpio->gpio_h3, 2, 0x3);
 
                reg = S5PC100_KEYPAD_BASE;
        } else {
+               struct s5pc110_gpio *gpio =
+                       (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
+
                if (board_is_limo_real() || board_is_limo_universal()) {
                        row_mask = 0x00FF;
-                       row_mode = 0x0033;
                        col_mask = 0x0FFF;
-                       col_mode = 0x0333;
                } else {
-                       row_mask = col_mask = 0xFFFF;
-                       row_mode = col_mode = 0x3333;
+                       row_mask = 0xFFFF;
+                       col_mask = 0xFFFF;
                }
 
-               /* Set GPH2[3:0] to KP_COL[3:0] */
-               reg = S5PC110_GPIO_BASE(S5PC110_GPIO_H2_OFFSET);
-               value = readl(reg + S5PC1XX_GPIO_CON_OFFSET);
-               value &= ~col_mask;
-               value |= col_mode;
-               writel(value, reg + S5PC1XX_GPIO_CON_OFFSET);
-
-               value = readl(reg + S5PC1XX_GPIO_PULL_OFFSET);
-
-               /* Set GPH3[3:0] to KP_ROW[3:0] */
-               reg = S5PC110_GPIO_BASE(S5PC110_GPIO_H3_OFFSET);
-
-               value = readl(reg + S5PC1XX_GPIO_CON_OFFSET);
-               value &= ~row_mask;
-               value |= row_mode;
-               writel(value, reg + S5PC1XX_GPIO_CON_OFFSET);
-               value = readl(reg + S5PC1XX_GPIO_PULL_OFFSET);
-               value &= ~(0xFF);
-               /* Pull-up enabled */
-               for (i = 0; row_mask; row_mask >>= 4) {
-                       if (row_mask & 0xF)
-                               value |= PULL_UP(i++);
+               for (i = 0; i < 4; i++) {
+                       /* Set GPH3[3:0] to KP_ROW[3:0] */
+                       if (row_mask & (0xF << (i << 2))) {
+                               gpio_cfg_pin(&gpio->gpio_h2, i, 0x3);
+                               gpio_set_pull(&gpio->gpio_h2, i, GPIO_PULL_UP);
+                       }
+
+                       /* Set GPH2[3:0] to KP_COL[3:0] */
+                       if (col_mask & (0xF << (i << 2)))
+                               gpio_cfg_pin(&gpio->gpio_h3, i, 0x3);
                }
-               writel(value, reg + S5PC1XX_GPIO_PULL_OFFSET);
 
                reg = S5PC110_KEYPAD_BASE;
        }
@@ -609,23 +491,20 @@ static void check_mhl(void)
 {
        unsigned char val[2];
        unsigned char addr = 0x39;      /* SIL9230 */
-       unsigned int reg;
+       struct s5pc110_gpio *gpio = (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
 
        /* MHL Power enable */
        /* HDMI_EN : GPJ2[2] output mode */
-       reg = S5PC110_GPIO_BASE(S5PC110_GPIO_J2_OFFSET);
-       gpio_direction_output(reg, 2, 1);
-
+       gpio_direction_output(&gpio->gpio_j2, 2, 1);
 
        /* MHL_RST : MP0_4[7] output mode */
-       reg = S5PC110_GPIO_BASE(S5PC110_GPIO_MP0_4_OFFSET);
-       gpio_direction_output(reg, 7, 0);
+       gpio_direction_output(&gpio->gpio_mp0_4, 7, 0);
 
        /* 10ms required after reset */
        udelay(10000);
 
        /* output enable */
-       gpio_set_value(reg, 7, 1);
+       gpio_set_value(&gpio->gpio_mp0_4, 7, 1);
 
        i2c_gpio_set_bus(I2C_GPIO5);
 
@@ -803,6 +682,18 @@ static void check_micro_usb(void)
        }
 }
 
+#define PDN_MASK(x)            (0x3 << ((x) << 1))
+
+#define OUTPUT0(x)             (0x0 << ((x) << 1))
+#define OUTPUT1(x)             (0x1 << ((x) << 1))
+#define INPUT(x)               (0x2 << ((x) << 1))
+
+#define PULL_DIS(x)            (0x0 << ((x) << 1))
+#define PULL_DOWN(x)           (0x1 << ((x) << 1))
+#define PULL_UP(x)             (0x2 << ((x) << 1))
+
+#define PREVIOUS(x)            (0x3 << ((x) << 1))
+
 struct gpio_powermode {
        unsigned int    conpdn;
        unsigned int    pudpdn;
@@ -920,11 +811,7 @@ static struct gpio_powermode powerdown_modes[] = {
                INPUT(4),
                PULL_DIS(0) | PULL_DOWN(1) | PULL_DOWN(2) | PULL_DIS(3) |
                PULL_DOWN(4),
-       },
-};
-
-static struct gpio_powermode powerdown_mp0_modes[] = {
-       {       /* S5PC110_GPIO_MP0_1_OFFSET */
+       }, {    /* S5PC110_GPIO_MP0_1_OFFSET */
                OUTPUT0(0) | OUTPUT0(1) | OUTPUT1(2) | OUTPUT0(3) |
                OUTPUT0(4) | OUTPUT0(5) | OUTPUT0(6) | OUTPUT1(7),
                PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
@@ -935,13 +822,13 @@ static struct gpio_powermode powerdown_mp0_modes[] = {
                PULL_DIS(0) | PULL_DIS(1) | PULL_DIS(2) | PULL_DIS(3) |
                PULL_DIS(4) | PULL_DIS(5) | PULL_DIS(6) | PULL_DIS(7),
        },
-
 };
 
 static void setup_power_down_mode_registers(void)
 {
+       struct s5pc110_gpio *gpio = (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
+       struct s5pc1xx_gpio_bank *bank;
        struct gpio_powermode *p;
-       unsigned int reg;
        int i;
 
        if (cpu_is_s5pc100())
@@ -950,20 +837,12 @@ static void setup_power_down_mode_registers(void)
        if (!(machine_is_aquila() && board_is_limo_real()))
                return;
 
-       reg = S5PC110_GPIO_BASE(S5PC110_GPIO_A0_OFFSET);
+       bank = &gpio->gpio_a0;
        p = powerdown_modes;
-       for (i = 0; i < ARRAY_SIZE(powerdown_modes); i++, p++) {
-               writel(p->conpdn, reg + S5PC1XX_GPIO_PDNCON_OFFSET);
-               writel(p->pudpdn, reg + S5PC1XX_GPIO_PDNPULL_OFFSET);
-               reg += 0x20;
-       }
 
-       reg = S5PC110_GPIO_BASE(S5PC110_GPIO_MP0_1_OFFSET);
-       p = powerdown_mp0_modes;
-       for (i = 0; i < ARRAY_SIZE(powerdown_mp0_modes); i++, p++) {
-               writel(p->conpdn, reg + S5PC1XX_GPIO_PDNCON_OFFSET);
-               writel(p->pudpdn, reg + S5PC1XX_GPIO_PDNPULL_OFFSET);
-               reg += 0x20;
+       for (i = 0; i < ARRAY_SIZE(powerdown_modes); i++, p++, bank++) {
+               writel(p->conpdn, &bank->pdn_con);
+               writel(p->pudpdn, &bank->pdn_pull);
        }
 }
 
@@ -1091,12 +970,12 @@ int usb_board_init(void)
 #endif
 
 #ifdef CONFIG_GENERIC_MMC
-
 int board_mmc_init(bd_t *bis)
 {
-       unsigned int pin, reg;
+       unsigned int reg;
        unsigned int clock;
        struct s5pc110_clock *clk = (struct s5pc110_clock *)S5PC1XX_CLOCK_BASE;
+       struct s5pc110_gpio *gpio = (struct s5pc110_gpio *)S5PC110_GPIO_BASE;
        int i;
 
        /* MMC0 Clock source = SCLKMPLL */
@@ -1126,14 +1005,12 @@ int board_mmc_init(bd_t *bis)
         * GPG0[2]      SD_0_CDn
         * GPG0[3:6]    SD_0_DATA[0:3]
         */
-       pin = S5PC110_GPIO_BASE(S5PC110_GPIO_G0_OFFSET);
-
-       /* GPG0[0:6] special function 2 */
-       writel(0x02222222, pin + S5PC1XX_GPIO_CON_OFFSET);
-
-       /* GPG0[0:6] pull up */
-       writel(0x00002aaa, pin + S5PC1XX_GPIO_PULL_OFFSET);
-       writel(0x00003fff, pin + S5PC1XX_GPIO_DRV_OFFSET);
+       for (i = 0; i < 7; i++) {
+               /* GPG0[0:6] special function 2 */
+               gpio_cfg_pin(&gpio->gpio_g0, i, 0x2);
+               /* GPG0[0:6] pull up */
+               gpio_set_pull(&gpio->gpio_g0, i, GPIO_PULL_UP);
+       }
 
        return s5pc1xx_mmc_init(0);
 }
index f8eb152..bfbc01a 100644 (file)
@@ -33,6 +33,7 @@ SOBJS = reset.o
 COBJS-y        += cache.o
 COBJS-y        += clock.o
 COBJS-y        += cpu_info.o
+COBJS-y        += gpio.o
 COBJS-y        += timer.o
 COBJS-$(CONFIG_S5PC110)        += sleep.o
 COBJS-$(CONFIG_CMD_USBDOWN) += usb-hs-otg.o usb_downloader.o
diff --git a/cpu/arm_cortexa8/s5pc1xx/gpio.c b/cpu/arm_cortexa8/s5pc1xx/gpio.c
new file mode 100644 (file)
index 0000000..befcf8d
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * (C) Copyright 2009 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+
+#define CON_MASK(x)            (0xf << ((x) << 2))
+#define CON_SFR(x, v)          ((v) << ((x) << 2))
+
+#define DAT_MASK(x)            (0x1 << (x))
+#define DAT_SET(x)             (0x1 << (x))
+
+#define PULL_MASK(x)           (0x3 << ((x) << 1))
+#define PULL_MODE(x, v)                ((v) << ((x) << 1))
+
+void gpio_cfg_pin(struct s5pc1xx_gpio_bank *bank, int gpio, int cfg)
+{
+       unsigned int value;
+
+       value = readl(&bank->con);
+       value &= ~CON_MASK(gpio);
+       value |= CON_SFR(gpio, cfg);
+       writel(value, &bank->con);
+}
+
+void gpio_direction_output(struct s5pc1xx_gpio_bank *bank, int gpio, int enable)
+{
+       unsigned int value;
+
+       gpio_cfg_pin(bank, gpio, GPIO_OUTPUT);
+
+       value = readl(&bank->dat);
+       value &= ~DAT_MASK(gpio);
+       if (enable)
+               value |= DAT_SET(gpio);
+       writel(value, &bank->dat);
+}
+
+void gpio_direction_input(struct s5pc1xx_gpio_bank *bank, int gpio)
+{
+       gpio_cfg_pin(bank, gpio, GPIO_INPUT);
+}
+
+void gpio_set_value(struct s5pc1xx_gpio_bank *bank, int gpio, int enable)
+{
+       unsigned int value;
+
+       value = readl(&bank->dat);
+       value &= ~DAT_MASK(gpio);
+       if (enable)
+               value |= DAT_SET(gpio);
+       writel(value, &bank->dat);
+}
+
+unsigned int gpio_get_value(struct s5pc1xx_gpio_bank *bank, int gpio)
+{
+       unsigned int value;
+
+       value = readl(&bank->dat);
+       return !!(value & DAT_MASK(gpio));
+}
+
+void gpio_set_pull(struct s5pc1xx_gpio_bank *bank, int gpio, int mode)
+{
+       unsigned int value;
+
+       value = readl(&bank->pull);
+       value &= ~PULL_MASK(gpio);
+       switch (mode) {
+       case GPIO_PULL_DOWN:
+       case GPIO_PULL_UP:
+               value |= PULL_MODE(gpio, mode);
+               break;
+       default:
+               break;
+       }
+       writel(value, &bank->pull);
+}
index e201a50..90485aa 100644 (file)
@@ -28,6 +28,7 @@
 #define S5PC1XX_CLOCK_BASE     0xE0100000
 
 /* S5PC100 */
+#define S5PC100_GPIO_BASE      0xE0300000
 #define S5PC100_VIC0_BASE      0xE4000000
 #define S5PC100_VIC1_BASE      0xE4100000
 #define S5PC100_VIC2_BASE      0xE4200000
@@ -39,6 +40,7 @@
 #define S5PC100_UART_BASE      0xEC000000
 
 /* S5PC110 */
+#define S5PC110_GPIO_BASE      0xE0200000
 #define S5PC110_PWMTIMER_BASE  0xE2500000
 #define S5PC110_WATCHDOG_BASE  0xE2700000
 #define S5PC110_UART_BASE      0xE2900000
index d370c79..761d51c 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * (C) Copyright 2009 Samsung Electronics
- * Heungjun Kim <riverful.kim@samsung.com>
  * Minkyu Kang <mk7.kang@samsung.com>
  *
  * This program is free software; you can redistribute it and/or
  * MA 02111-1307 USA
  */
 
-#ifndef __S5PC1XX_GPIO_H
-#define __S5PC1XX_GPIO_H
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
 
-/* GPIO Bank Base */
-#define S5PC100_GPIO_BASE(x)           (0xE0300000 + (x))
-#define S5PC110_GPIO_BASE(x)           (0xE0200000 + (x))
+#ifndef __ASSEMBLY__
+struct s5pc1xx_gpio_bank {
+       unsigned long   con;
+       unsigned long   dat;
+       unsigned long   pull;
+       unsigned long   drv;
+       unsigned long   pdn_con;
+       unsigned long   pdn_pull;
+       unsigned char   res1[8];
+};
 
-/* S5PC100 bank offset */
-#define S5PC100_GPIO_A0_OFFSET         0x000
-#define S5PC100_GPIO_A1_OFFSET         0x020
-#define S5PC100_GPIO_B_OFFSET          0x040
-#define S5PC100_GPIO_C_OFFSET          0x060
-#define S5PC100_GPIO_D_OFFSET          0x080
-#define S5PC100_GPIO_E0_OFFSET         0x0A0
-#define S5PC100_GPIO_E1_OFFSET         0x0C0
-#define S5PC100_GPIO_F0_OFFSET         0x0E0
-#define S5PC100_GPIO_F1_OFFSET         0x100
-#define S5PC100_GPIO_F2_OFFSET         0x120
-#define S5PC100_GPIO_F3_OFFSET         0x140
-#define S5PC100_GPIO_G0_OFFSET         0x160
-#define S5PC100_GPIO_G1_OFFSET         0x180
-#define S5PC100_GPIO_G2_OFFSET         0x1A0
-#define S5PC100_GPIO_G3_OFFSET         0x1C0
-#define S5PC100_GPIO_I_OFFSET          0x1E0
-#define S5PC100_GPIO_J0_OFFSET         0x200
-#define S5PC100_GPIO_J1_OFFSET         0x220
-#define S5PC100_GPIO_J2_OFFSET         0x240
-#define S5PC100_GPIO_J3_OFFSET         0x260
-#define S5PC100_GPIO_J4_OFFSET         0x280
-#define S5PC100_GPIO_K0_OFFSET         0x2A0
-#define S5PC100_GPIO_K1_OFFSET         0x2C0
-#define S5PC100_GPIO_K2_OFFSET         0x2E0
-#define S5PC100_GPIO_K3_OFFSET         0x300
-#define S5PC100_GPIO_L0_OFFSET         0x320
-#define S5PC100_GPIO_L1_OFFSET         0x340
-#define S5PC100_GPIO_L2_OFFSET         0x360
-#define S5PC100_GPIO_L3_OFFSET         0x380
-#define S5PC100_GPIO_L4_OFFSET         0x3A0
-#define S5PC100_GPIO_H0_OFFSET         0xC00
-#define S5PC100_GPIO_H1_OFFSET         0xC20
-#define S5PC100_GPIO_H2_OFFSET         0xC40
-#define S5PC100_GPIO_H3_OFFSET         0xC60
+struct s5pc100_gpio {
+       struct s5pc1xx_gpio_bank gpio_a0;
+       struct s5pc1xx_gpio_bank gpio_a1;
+       struct s5pc1xx_gpio_bank gpio_b;
+       struct s5pc1xx_gpio_bank gpio_c;
+       struct s5pc1xx_gpio_bank gpio_d;
+       struct s5pc1xx_gpio_bank gpio_e0;
+       struct s5pc1xx_gpio_bank gpio_e1;
+       struct s5pc1xx_gpio_bank gpio_f0;
+       struct s5pc1xx_gpio_bank gpio_f1;
+       struct s5pc1xx_gpio_bank gpio_f2;
+       struct s5pc1xx_gpio_bank gpio_f3;
+       struct s5pc1xx_gpio_bank gpio_g0;
+       struct s5pc1xx_gpio_bank gpio_g1;
+       struct s5pc1xx_gpio_bank gpio_g2;
+       struct s5pc1xx_gpio_bank gpio_g3;
+       struct s5pc1xx_gpio_bank gpio_i;
+       struct s5pc1xx_gpio_bank gpio_j0;
+       struct s5pc1xx_gpio_bank gpio_j1;
+       struct s5pc1xx_gpio_bank gpio_j2;
+       struct s5pc1xx_gpio_bank gpio_j3;
+       struct s5pc1xx_gpio_bank gpio_j4;
+       struct s5pc1xx_gpio_bank gpio_k0;
+       struct s5pc1xx_gpio_bank gpio_k1;
+       struct s5pc1xx_gpio_bank gpio_k2;
+       struct s5pc1xx_gpio_bank gpio_k3;
+       struct s5pc1xx_gpio_bank gpio_l0;
+       struct s5pc1xx_gpio_bank gpio_l1;
+       struct s5pc1xx_gpio_bank gpio_l2;
+       struct s5pc1xx_gpio_bank gpio_l3;
+       struct s5pc1xx_gpio_bank gpio_l4;
+       struct s5pc1xx_gpio_bank gpio_h0;
+       struct s5pc1xx_gpio_bank gpio_h1;
+       struct s5pc1xx_gpio_bank gpio_h2;
+       struct s5pc1xx_gpio_bank gpio_h3;
+};
 
-/* S5PC110 bank offset */
-#define S5PC110_GPIO_A0_OFFSET         0x000
-#define S5PC110_GPIO_A1_OFFSET         0x020
-#define S5PC110_GPIO_B_OFFSET          0x040
-#define S5PC110_GPIO_C0_OFFSET         0x060
-#define S5PC110_GPIO_C1_OFFSET         0x080
-#define S5PC110_GPIO_D0_OFFSET         0x0A0
-#define S5PC110_GPIO_D1_OFFSET         0x0C0
-#define S5PC110_GPIO_E0_OFFSET         0x0E0
-#define S5PC110_GPIO_E1_OFFSET         0x100
-#define S5PC110_GPIO_F0_OFFSET         0x120
-#define S5PC110_GPIO_F1_OFFSET         0x140
-#define S5PC110_GPIO_F2_OFFSET         0x160
-#define S5PC110_GPIO_F3_OFFSET         0x180
-#define S5PC110_GPIO_G0_OFFSET         0x1A0
-#define S5PC110_GPIO_G1_OFFSET         0x1C0
-#define S5PC110_GPIO_G2_OFFSET         0x1E0
-#define S5PC110_GPIO_G3_OFFSET         0x200
-#define S5PC110_GPIO_I_OFFSET          0x220
-#define S5PC110_GPIO_J0_OFFSET         0x240
-#define S5PC110_GPIO_J1_OFFSET         0x260
-#define S5PC110_GPIO_J2_OFFSET         0x280
-#define S5PC110_GPIO_J3_OFFSET         0x2A0
-#define S5PC110_GPIO_J4_OFFSET         0x2C0
-#define S5PC110_GPIO_MP0_1_OFFSET      0x2E0
-#define S5PC110_GPIO_MP0_2_OFFSET      0x300
-#define S5PC110_GPIO_MP0_3_OFFSET      0x320
-#define S5PC110_GPIO_MP0_4_OFFSET      0x340
-#define S5PC110_GPIO_MP0_5_OFFSET      0x360
-#define S5PC110_GPIO_MP0_6_OFFSET      0x380
-#define S5PC110_GPIO_MP0_7_OFFSET      0x3A0
-#define S5PC110_GPIO_MP1_0_OFFSET      0x3C0
-#define S5PC110_GPIO_MP1_1_OFFSET      0x3E0
-#define S5PC110_GPIO_MP1_2_OFFSET      0x400
-#define S5PC110_GPIO_MP1_3_OFFSET      0x420
-#define S5PC110_GPIO_MP1_4_OFFSET      0x440
-#define S5PC110_GPIO_MP1_5_OFFSET      0x460
-#define S5PC110_GPIO_MP1_6_OFFSET      0x480
-#define S5PC110_GPIO_MP1_7_OFFSET      0x4A0
-#define S5PC110_GPIO_MP1_8_OFFSET      0x4C0
-#define S5PC110_GPIO_MP2_0_OFFSET      0x4E0
-#define S5PC110_GPIO_MP2_1_OFFSET      0x500
-#define S5PC110_GPIO_MP2_2_OFFSET      0x520
-#define S5PC110_GPIO_MP2_3_OFFSET      0x540
-#define S5PC110_GPIO_MP2_4_OFFSET      0x560
-#define S5PC110_GPIO_MP2_5_OFFSET      0x580
-#define S5PC110_GPIO_MP2_6_OFFSET      0x5A0
-#define S5PC110_GPIO_MP2_7_OFFSET      0x5C0
-#define S5PC110_GPIO_MP2_8_OFFSET      0x5E0
-#define S5PC110_GPIO_H0_OFFSET         0xC00
-#define S5PC110_GPIO_H1_OFFSET         0xC20
-#define S5PC110_GPIO_H2_OFFSET         0xC40
-#define S5PC110_GPIO_H3_OFFSET         0xC60
+struct s5pc110_gpio {
+       struct s5pc1xx_gpio_bank gpio_a0;
+       struct s5pc1xx_gpio_bank gpio_a1;
+       struct s5pc1xx_gpio_bank gpio_b;
+       struct s5pc1xx_gpio_bank gpio_c0;
+       struct s5pc1xx_gpio_bank gpio_c1;
+       struct s5pc1xx_gpio_bank gpio_d0;
+       struct s5pc1xx_gpio_bank gpio_d1;
+       struct s5pc1xx_gpio_bank gpio_e0;
+       struct s5pc1xx_gpio_bank gpio_e1;
+       struct s5pc1xx_gpio_bank gpio_f0;
+       struct s5pc1xx_gpio_bank gpio_f1;
+       struct s5pc1xx_gpio_bank gpio_f2;
+       struct s5pc1xx_gpio_bank gpio_f3;
+       struct s5pc1xx_gpio_bank gpio_g0;
+       struct s5pc1xx_gpio_bank gpio_g1;
+       struct s5pc1xx_gpio_bank gpio_g2;
+       struct s5pc1xx_gpio_bank gpio_g3;
+       struct s5pc1xx_gpio_bank gpio_i;
+       struct s5pc1xx_gpio_bank gpio_j0;
+       struct s5pc1xx_gpio_bank gpio_j1;
+       struct s5pc1xx_gpio_bank gpio_j2;
+       struct s5pc1xx_gpio_bank gpio_j3;
+       struct s5pc1xx_gpio_bank gpio_j4;
+       struct s5pc1xx_gpio_bank gpio_mp0_1;
+       struct s5pc1xx_gpio_bank gpio_mp0_2;
+       struct s5pc1xx_gpio_bank gpio_mp0_3;
+       struct s5pc1xx_gpio_bank gpio_mp0_4;
+       struct s5pc1xx_gpio_bank gpio_mp0_5;
+       struct s5pc1xx_gpio_bank gpio_mp0_6;
+       struct s5pc1xx_gpio_bank gpio_mp0_7;
+       struct s5pc1xx_gpio_bank gpio_mp1_0;
+       struct s5pc1xx_gpio_bank gpio_mp1_1;
+       struct s5pc1xx_gpio_bank gpio_mp1_2;
+       struct s5pc1xx_gpio_bank gpio_mp1_3;
+       struct s5pc1xx_gpio_bank gpio_mp1_4;
+       struct s5pc1xx_gpio_bank gpio_mp1_5;
+       struct s5pc1xx_gpio_bank gpio_mp1_6;
+       struct s5pc1xx_gpio_bank gpio_mp1_7;
+       struct s5pc1xx_gpio_bank gpio_mp1_8;
+       struct s5pc1xx_gpio_bank gpio_mp2_0;
+       struct s5pc1xx_gpio_bank gpio_mp2_1;
+       struct s5pc1xx_gpio_bank gpio_mp2_2;
+       struct s5pc1xx_gpio_bank gpio_mp2_3;
+       struct s5pc1xx_gpio_bank gpio_mp2_4;
+       struct s5pc1xx_gpio_bank gpio_mp2_5;
+       struct s5pc1xx_gpio_bank gpio_mp2_6;
+       struct s5pc1xx_gpio_bank gpio_mp2_7;
+       struct s5pc1xx_gpio_bank gpio_mp2_8;
+       struct s5pc1xx_gpio_bank res1[48];
+       struct s5pc1xx_gpio_bank gpio_h0;
+       struct s5pc1xx_gpio_bank gpio_h1;
+       struct s5pc1xx_gpio_bank gpio_h2;
+       struct s5pc1xx_gpio_bank gpio_h3;
+};
 
-/* GPIO bank Offset */
-#define S5PC1XX_GPIO_CON_OFFSET                0x0
-#define S5PC1XX_GPIO_DAT_OFFSET                0x4
-#define S5PC1XX_GPIO_PULL_OFFSET       0x8
-#define S5PC1XX_GPIO_DRV_OFFSET                0xc
-#define S5PC1XX_GPIO_PDNCON_OFFSET     0x10
-#define S5PC1XX_GPIO_PDNPULL_OFFSET    0x14
+/* functions */
+void gpio_cfg_pin(struct s5pc1xx_gpio_bank *bank, int gpio, int cfg);
+void gpio_direction_output(struct s5pc1xx_gpio_bank *bank, int gpio, int enable);
+void gpio_direction_input(struct s5pc1xx_gpio_bank *bank, int gpio);
+void gpio_set_value(struct s5pc1xx_gpio_bank *bank, int gpio, int enable);
+unsigned int gpio_get_value(struct s5pc1xx_gpio_bank *bank, int gpio);
+void gpio_set_pull(struct s5pc1xx_gpio_bank *bank, int gpio, int mode);
+#endif
+
+/* Pin configurations */
+#define GPIO_INPUT     0x0
+#define GPIO_OUTPUT    0x1
+#define GPIO_IRQ       0xf
+
+/* Pull mode */
+#define GPIO_PULL_NONE 0x0
+#define GPIO_PULL_DOWN 0x1
+#define GPIO_PULL_UP   0x2
 
 #endif