From 1ba7940d18530f8751b9b1e547f603aefd71cc43 Mon Sep 17 00:00:00 2001 From: Minkyu Kang Date: Tue, 13 Oct 2009 14:05:16 +0900 Subject: [PATCH] s5pc1xx: gpio: use C structure and GPIO API functions Signed-off-by: Minkyu Kang --- board/samsung/universal/i2c-gpio.c | 59 +++--- board/samsung/universal/lowlevel_init.S | 69 ++++--- board/samsung/universal/modem_boot.c | 146 +++------------ board/samsung/universal/universal.c | 313 ++++++++++---------------------- cpu/arm_cortexa8/s5pc1xx/Makefile | 1 + cpu/arm_cortexa8/s5pc1xx/gpio.c | 96 ++++++++++ include/asm-arm/arch-s5pc1xx/cpu.h | 2 + include/asm-arm/arch-s5pc1xx/gpio.h | 222 +++++++++++----------- 8 files changed, 404 insertions(+), 504 deletions(-) create mode 100644 cpu/arm_cortexa8/s5pc1xx/gpio.c diff --git a/board/samsung/universal/i2c-gpio.c b/board/samsung/universal/i2c-gpio.c index 06bb737..3f02293 100644 --- a/board/samsung/universal/i2c-gpio.c +++ b/board/samsung/universal/i2c-gpio.c @@ -27,6 +27,7 @@ #include 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); + } } diff --git a/board/samsung/universal/lowlevel_init.S b/board/samsung/universal/lowlevel_init.S index 7d5ab74..daaf383 100644 --- a/board/samsung/universal/lowlevel_init.S +++ b/board/samsung/universal/lowlevel_init.S @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -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 diff --git a/board/samsung/universal/modem_boot.c b/board/samsung/universal/modem_boot.c index 30dba4a..3ee35c1 100644 --- a/board/samsung/universal/modem_boot.c +++ b/board/samsung/universal/modem_boot.c @@ -42,11 +42,8 @@ #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[]) diff --git a/board/samsung/universal/universal.c b/board/samsung/universal/universal.c index 549538f..6a64b60 100644 --- a/board/samsung/universal/universal.c +++ b/board/samsung/universal/universal.c @@ -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); } diff --git a/cpu/arm_cortexa8/s5pc1xx/Makefile b/cpu/arm_cortexa8/s5pc1xx/Makefile index f8eb152..bfbc01a 100644 --- a/cpu/arm_cortexa8/s5pc1xx/Makefile +++ b/cpu/arm_cortexa8/s5pc1xx/Makefile @@ -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 index 0000000..befcf8d --- /dev/null +++ b/cpu/arm_cortexa8/s5pc1xx/gpio.c @@ -0,0 +1,96 @@ +/* + * (C) Copyright 2009 Samsung Electronics + * Minkyu Kang + * + * 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 +#include +#include + +#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); +} diff --git a/include/asm-arm/arch-s5pc1xx/cpu.h b/include/asm-arm/arch-s5pc1xx/cpu.h index e201a50..90485aa 100644 --- a/include/asm-arm/arch-s5pc1xx/cpu.h +++ b/include/asm-arm/arch-s5pc1xx/cpu.h @@ -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 diff --git a/include/asm-arm/arch-s5pc1xx/gpio.h b/include/asm-arm/arch-s5pc1xx/gpio.h index d370c79..761d51c 100644 --- a/include/asm-arm/arch-s5pc1xx/gpio.h +++ b/include/asm-arm/arch-s5pc1xx/gpio.h @@ -1,6 +1,5 @@ /* * (C) Copyright 2009 Samsung Electronics - * Heungjun Kim * Minkyu Kang * * This program is free software; you can redistribute it and/or @@ -19,109 +18,130 @@ * 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 -- 2.7.4