5d0434315c
There are 8 pins for SD card in Exynos, but the MUX was configured only for 7, since the one was used for card detection. This caused the pin's pull wrong configuration. This commit fixes this and the card detect can work properly, after call this function. Tested-on: Odroid U3 and Odroid X2. Signed-off-by: Przemyslaw Marczak <p.marczak@samsung.com> Cc: Guillaume GARDET <guillaume.gardet@free.fr> Cc: Lukasz Majewski <l.majewski@samsung.com> Cc: Jaehoon Chung <jh80.chung@samsung.com> Cc: Minkyu Kang <mk7.kang@samsung.com> Cc: Simon Glass <sjg@chromium.org> Acked-by: Jaehoon Chung <jh80.chung@samsung.com> Tested-by: Lukasz Majewski <l.majewski@samsung.com> Signed-off-by: Minkyu Kang <mk7.kang@samsung.com>
916 lines
22 KiB
C
916 lines
22 KiB
C
/*
|
|
* Copyright (c) 2012 Samsung Electronics.
|
|
* Abhilash Kesavan <a.kesavan@samsung.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <fdtdec.h>
|
|
#include <asm/gpio.h>
|
|
#include <asm/arch/pinmux.h>
|
|
#include <asm/arch/sromc.h>
|
|
|
|
static void exynos5_uart_config(int peripheral)
|
|
{
|
|
int i, start, count;
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_UART0:
|
|
start = EXYNOS5_GPIO_A00;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART1:
|
|
start = EXYNOS5_GPIO_D00;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART2:
|
|
start = EXYNOS5_GPIO_A10;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART3:
|
|
start = EXYNOS5_GPIO_A14;
|
|
count = 2;
|
|
break;
|
|
default:
|
|
debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
return;
|
|
}
|
|
for (i = start; i < start + count; i++) {
|
|
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
|
gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2));
|
|
}
|
|
}
|
|
|
|
static void exynos5420_uart_config(int peripheral)
|
|
{
|
|
int i, start, count;
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_UART0:
|
|
start = EXYNOS5420_GPIO_A00;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART1:
|
|
start = EXYNOS5420_GPIO_A04;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART2:
|
|
start = EXYNOS5420_GPIO_A10;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART3:
|
|
start = EXYNOS5420_GPIO_A14;
|
|
count = 2;
|
|
break;
|
|
default:
|
|
debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
return;
|
|
}
|
|
|
|
for (i = start; i < start + count; i++) {
|
|
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
|
gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2));
|
|
}
|
|
}
|
|
|
|
static int exynos5_mmc_config(int peripheral, int flags)
|
|
{
|
|
int i, start, start_ext, gpio_func = 0;
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_SDMMC0:
|
|
start = EXYNOS5_GPIO_C00;
|
|
start_ext = EXYNOS5_GPIO_C10;
|
|
gpio_func = S5P_GPIO_FUNC(0x2);
|
|
break;
|
|
case PERIPH_ID_SDMMC1:
|
|
start = EXYNOS5_GPIO_C20;
|
|
start_ext = 0;
|
|
break;
|
|
case PERIPH_ID_SDMMC2:
|
|
start = EXYNOS5_GPIO_C30;
|
|
start_ext = EXYNOS5_GPIO_C43;
|
|
gpio_func = S5P_GPIO_FUNC(0x3);
|
|
break;
|
|
case PERIPH_ID_SDMMC3:
|
|
start = EXYNOS5_GPIO_C40;
|
|
start_ext = 0;
|
|
break;
|
|
default:
|
|
debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
return -1;
|
|
}
|
|
if ((flags & PINMUX_FLAG_8BIT_MODE) && !start_ext) {
|
|
debug("SDMMC device %d does not support 8bit mode",
|
|
peripheral);
|
|
return -1;
|
|
}
|
|
if (flags & PINMUX_FLAG_8BIT_MODE) {
|
|
for (i = start_ext; i <= (start_ext + 3); i++) {
|
|
gpio_cfg_pin(i, gpio_func);
|
|
gpio_set_pull(i, S5P_GPIO_PULL_UP);
|
|
gpio_set_drv(i, S5P_GPIO_DRV_4X);
|
|
}
|
|
}
|
|
for (i = start; i < (start + 2); i++) {
|
|
gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2));
|
|
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
|
gpio_set_drv(i, S5P_GPIO_DRV_4X);
|
|
}
|
|
for (i = (start + 3); i <= (start + 6); i++) {
|
|
gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2));
|
|
gpio_set_pull(i, S5P_GPIO_PULL_UP);
|
|
gpio_set_drv(i, S5P_GPIO_DRV_4X);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int exynos5420_mmc_config(int peripheral, int flags)
|
|
{
|
|
int i, start = 0, start_ext = 0;
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_SDMMC0:
|
|
start = EXYNOS5420_GPIO_C00;
|
|
start_ext = EXYNOS5420_GPIO_C30;
|
|
break;
|
|
case PERIPH_ID_SDMMC1:
|
|
start = EXYNOS5420_GPIO_C10;
|
|
start_ext = EXYNOS5420_GPIO_D14;
|
|
break;
|
|
case PERIPH_ID_SDMMC2:
|
|
start = EXYNOS5420_GPIO_C20;
|
|
start_ext = 0;
|
|
break;
|
|
default:
|
|
start = 0;
|
|
debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
return -1;
|
|
}
|
|
|
|
if ((flags & PINMUX_FLAG_8BIT_MODE) && !start_ext) {
|
|
debug("SDMMC device %d does not support 8bit mode",
|
|
peripheral);
|
|
return -1;
|
|
}
|
|
|
|
if (flags & PINMUX_FLAG_8BIT_MODE) {
|
|
for (i = start_ext; i <= (start_ext + 3); i++) {
|
|
gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2));
|
|
gpio_set_pull(i, S5P_GPIO_PULL_UP);
|
|
gpio_set_drv(i, S5P_GPIO_DRV_4X);
|
|
}
|
|
}
|
|
|
|
for (i = start; i < (start + 3); i++) {
|
|
/*
|
|
* MMC0 is intended to be used for eMMC. The
|
|
* card detect pin is used as a VDDEN signal to
|
|
* power on the eMMC. The 5420 iROM makes
|
|
* this same assumption.
|
|
*/
|
|
if ((peripheral == PERIPH_ID_SDMMC0) && (i == (start + 2))) {
|
|
#ifndef CONFIG_SPL_BUILD
|
|
gpio_request(i, "sdmmc0_vdden");
|
|
#endif
|
|
gpio_set_value(i, 1);
|
|
gpio_cfg_pin(i, S5P_GPIO_OUTPUT);
|
|
} else {
|
|
gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2));
|
|
}
|
|
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
|
gpio_set_drv(i, S5P_GPIO_DRV_4X);
|
|
}
|
|
|
|
for (i = (start + 3); i <= (start + 6); i++) {
|
|
gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2));
|
|
gpio_set_pull(i, S5P_GPIO_PULL_UP);
|
|
gpio_set_drv(i, S5P_GPIO_DRV_4X);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void exynos5_sromc_config(int flags)
|
|
{
|
|
int i;
|
|
|
|
/*
|
|
* SROM:CS1 and EBI
|
|
*
|
|
* GPY0[0] SROM_CSn[0]
|
|
* GPY0[1] SROM_CSn[1](2)
|
|
* GPY0[2] SROM_CSn[2]
|
|
* GPY0[3] SROM_CSn[3]
|
|
* GPY0[4] EBI_OEn(2)
|
|
* GPY0[5] EBI_EEn(2)
|
|
*
|
|
* GPY1[0] EBI_BEn[0](2)
|
|
* GPY1[1] EBI_BEn[1](2)
|
|
* GPY1[2] SROM_WAIT(2)
|
|
* GPY1[3] EBI_DATA_RDn(2)
|
|
*/
|
|
gpio_cfg_pin(EXYNOS5_GPIO_Y00 + (flags & PINMUX_FLAG_BANK),
|
|
S5P_GPIO_FUNC(2));
|
|
gpio_cfg_pin(EXYNOS5_GPIO_Y04, S5P_GPIO_FUNC(2));
|
|
gpio_cfg_pin(EXYNOS5_GPIO_Y05, S5P_GPIO_FUNC(2));
|
|
|
|
for (i = 0; i < 4; i++)
|
|
gpio_cfg_pin(EXYNOS5_GPIO_Y10 + i, S5P_GPIO_FUNC(2));
|
|
|
|
/*
|
|
* EBI: 8 Addrss Lines
|
|
*
|
|
* GPY3[0] EBI_ADDR[0](2)
|
|
* GPY3[1] EBI_ADDR[1](2)
|
|
* GPY3[2] EBI_ADDR[2](2)
|
|
* GPY3[3] EBI_ADDR[3](2)
|
|
* GPY3[4] EBI_ADDR[4](2)
|
|
* GPY3[5] EBI_ADDR[5](2)
|
|
* GPY3[6] EBI_ADDR[6](2)
|
|
* GPY3[7] EBI_ADDR[7](2)
|
|
*
|
|
* EBI: 16 Data Lines
|
|
*
|
|
* GPY5[0] EBI_DATA[0](2)
|
|
* GPY5[1] EBI_DATA[1](2)
|
|
* GPY5[2] EBI_DATA[2](2)
|
|
* GPY5[3] EBI_DATA[3](2)
|
|
* GPY5[4] EBI_DATA[4](2)
|
|
* GPY5[5] EBI_DATA[5](2)
|
|
* GPY5[6] EBI_DATA[6](2)
|
|
* GPY5[7] EBI_DATA[7](2)
|
|
*
|
|
* GPY6[0] EBI_DATA[8](2)
|
|
* GPY6[1] EBI_DATA[9](2)
|
|
* GPY6[2] EBI_DATA[10](2)
|
|
* GPY6[3] EBI_DATA[11](2)
|
|
* GPY6[4] EBI_DATA[12](2)
|
|
* GPY6[5] EBI_DATA[13](2)
|
|
* GPY6[6] EBI_DATA[14](2)
|
|
* GPY6[7] EBI_DATA[15](2)
|
|
*/
|
|
for (i = 0; i < 8; i++) {
|
|
gpio_cfg_pin(EXYNOS5_GPIO_Y30 + i, S5P_GPIO_FUNC(2));
|
|
gpio_set_pull(EXYNOS5_GPIO_Y30 + i, S5P_GPIO_PULL_UP);
|
|
|
|
gpio_cfg_pin(EXYNOS5_GPIO_Y50 + i, S5P_GPIO_FUNC(2));
|
|
gpio_set_pull(EXYNOS5_GPIO_Y50 + i, S5P_GPIO_PULL_UP);
|
|
|
|
gpio_cfg_pin(EXYNOS5_GPIO_Y60 + i, S5P_GPIO_FUNC(2));
|
|
gpio_set_pull(EXYNOS5_GPIO_Y60 + i, S5P_GPIO_PULL_UP);
|
|
}
|
|
}
|
|
|
|
static void exynos5_i2c_config(int peripheral, int flags)
|
|
{
|
|
int func01, func23;
|
|
|
|
/* High-Speed I2C */
|
|
if (flags & PINMUX_FLAG_HS_MODE) {
|
|
func01 = 4;
|
|
func23 = 4;
|
|
} else {
|
|
func01 = 2;
|
|
func23 = 3;
|
|
}
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_I2C0:
|
|
gpio_cfg_pin(EXYNOS5_GPIO_B30, S5P_GPIO_FUNC(func01));
|
|
gpio_cfg_pin(EXYNOS5_GPIO_B31, S5P_GPIO_FUNC(func01));
|
|
break;
|
|
case PERIPH_ID_I2C1:
|
|
gpio_cfg_pin(EXYNOS5_GPIO_B32, S5P_GPIO_FUNC(func01));
|
|
gpio_cfg_pin(EXYNOS5_GPIO_B33, S5P_GPIO_FUNC(func01));
|
|
break;
|
|
case PERIPH_ID_I2C2:
|
|
gpio_cfg_pin(EXYNOS5_GPIO_A06, S5P_GPIO_FUNC(func23));
|
|
gpio_cfg_pin(EXYNOS5_GPIO_A07, S5P_GPIO_FUNC(func23));
|
|
break;
|
|
case PERIPH_ID_I2C3:
|
|
gpio_cfg_pin(EXYNOS5_GPIO_A12, S5P_GPIO_FUNC(func23));
|
|
gpio_cfg_pin(EXYNOS5_GPIO_A13, S5P_GPIO_FUNC(func23));
|
|
break;
|
|
case PERIPH_ID_I2C4:
|
|
gpio_cfg_pin(EXYNOS5_GPIO_A20, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS5_GPIO_A21, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C5:
|
|
gpio_cfg_pin(EXYNOS5_GPIO_A22, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS5_GPIO_A23, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C6:
|
|
gpio_cfg_pin(EXYNOS5_GPIO_B13, S5P_GPIO_FUNC(0x4));
|
|
gpio_cfg_pin(EXYNOS5_GPIO_B14, S5P_GPIO_FUNC(0x4));
|
|
break;
|
|
case PERIPH_ID_I2C7:
|
|
gpio_cfg_pin(EXYNOS5_GPIO_B22, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS5_GPIO_B23, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void exynos5420_i2c_config(int peripheral)
|
|
{
|
|
switch (peripheral) {
|
|
case PERIPH_ID_I2C0:
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B30, S5P_GPIO_FUNC(0x2));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B31, S5P_GPIO_FUNC(0x2));
|
|
break;
|
|
case PERIPH_ID_I2C1:
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B32, S5P_GPIO_FUNC(0x2));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B33, S5P_GPIO_FUNC(0x2));
|
|
break;
|
|
case PERIPH_ID_I2C2:
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_A06, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_A07, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C3:
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_A12, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_A13, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C4:
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_A20, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_A21, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C5:
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_A22, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_A23, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C6:
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B13, S5P_GPIO_FUNC(0x4));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B14, S5P_GPIO_FUNC(0x4));
|
|
break;
|
|
case PERIPH_ID_I2C7:
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B22, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B23, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C8:
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B34, S5P_GPIO_FUNC(0x2));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B35, S5P_GPIO_FUNC(0x2));
|
|
break;
|
|
case PERIPH_ID_I2C9:
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B36, S5P_GPIO_FUNC(0x2));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B37, S5P_GPIO_FUNC(0x2));
|
|
break;
|
|
case PERIPH_ID_I2C10:
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B40, S5P_GPIO_FUNC(0x2));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_B41, S5P_GPIO_FUNC(0x2));
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void exynos5_i2s_config(int peripheral)
|
|
{
|
|
int i;
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_I2S0:
|
|
for (i = 0; i < 5; i++)
|
|
gpio_cfg_pin(EXYNOS5_GPIO_Z0 + i, S5P_GPIO_FUNC(0x02));
|
|
break;
|
|
case PERIPH_ID_I2S1:
|
|
for (i = 0; i < 5; i++)
|
|
gpio_cfg_pin(EXYNOS5_GPIO_B00 + i, S5P_GPIO_FUNC(0x02));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void exynos5_spi_config(int peripheral)
|
|
{
|
|
int cfg = 0, pin = 0, i;
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_SPI0:
|
|
cfg = S5P_GPIO_FUNC(0x2);
|
|
pin = EXYNOS5_GPIO_A20;
|
|
break;
|
|
case PERIPH_ID_SPI1:
|
|
cfg = S5P_GPIO_FUNC(0x2);
|
|
pin = EXYNOS5_GPIO_A24;
|
|
break;
|
|
case PERIPH_ID_SPI2:
|
|
cfg = S5P_GPIO_FUNC(0x5);
|
|
pin = EXYNOS5_GPIO_B11;
|
|
break;
|
|
case PERIPH_ID_SPI3:
|
|
cfg = S5P_GPIO_FUNC(0x2);
|
|
pin = EXYNOS5_GPIO_F10;
|
|
break;
|
|
case PERIPH_ID_SPI4:
|
|
for (i = 0; i < 2; i++) {
|
|
gpio_cfg_pin(EXYNOS5_GPIO_F02 + i, S5P_GPIO_FUNC(0x4));
|
|
gpio_cfg_pin(EXYNOS5_GPIO_E04 + i, S5P_GPIO_FUNC(0x4));
|
|
}
|
|
break;
|
|
}
|
|
if (peripheral != PERIPH_ID_SPI4) {
|
|
for (i = pin; i < pin + 4; i++)
|
|
gpio_cfg_pin(i, cfg);
|
|
}
|
|
}
|
|
|
|
void exynos5420_spi_config(int peripheral)
|
|
{
|
|
int cfg, pin, i;
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_SPI0:
|
|
pin = EXYNOS5420_GPIO_A20;
|
|
cfg = S5P_GPIO_FUNC(0x2);
|
|
break;
|
|
case PERIPH_ID_SPI1:
|
|
pin = EXYNOS5420_GPIO_A24;
|
|
cfg = S5P_GPIO_FUNC(0x2);
|
|
break;
|
|
case PERIPH_ID_SPI2:
|
|
pin = EXYNOS5420_GPIO_B11;
|
|
cfg = S5P_GPIO_FUNC(0x5);
|
|
break;
|
|
case PERIPH_ID_SPI3:
|
|
pin = EXYNOS5420_GPIO_F10;
|
|
cfg = S5P_GPIO_FUNC(0x2);
|
|
break;
|
|
case PERIPH_ID_SPI4:
|
|
cfg = 0;
|
|
pin = 0;
|
|
break;
|
|
default:
|
|
cfg = 0;
|
|
pin = 0;
|
|
debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
return;
|
|
}
|
|
|
|
if (peripheral != PERIPH_ID_SPI4) {
|
|
for (i = pin; i < pin + 4; i++)
|
|
gpio_cfg_pin(i, cfg);
|
|
} else {
|
|
for (i = 0; i < 2; i++) {
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_F02 + i,
|
|
S5P_GPIO_FUNC(0x4));
|
|
gpio_cfg_pin(EXYNOS5420_GPIO_E04 + i,
|
|
S5P_GPIO_FUNC(0x4));
|
|
}
|
|
}
|
|
}
|
|
|
|
static int exynos5_pinmux_config(int peripheral, int flags)
|
|
{
|
|
switch (peripheral) {
|
|
case PERIPH_ID_UART0:
|
|
case PERIPH_ID_UART1:
|
|
case PERIPH_ID_UART2:
|
|
case PERIPH_ID_UART3:
|
|
exynos5_uart_config(peripheral);
|
|
break;
|
|
case PERIPH_ID_SDMMC0:
|
|
case PERIPH_ID_SDMMC1:
|
|
case PERIPH_ID_SDMMC2:
|
|
case PERIPH_ID_SDMMC3:
|
|
return exynos5_mmc_config(peripheral, flags);
|
|
case PERIPH_ID_SROMC:
|
|
exynos5_sromc_config(flags);
|
|
break;
|
|
case PERIPH_ID_I2C0:
|
|
case PERIPH_ID_I2C1:
|
|
case PERIPH_ID_I2C2:
|
|
case PERIPH_ID_I2C3:
|
|
case PERIPH_ID_I2C4:
|
|
case PERIPH_ID_I2C5:
|
|
case PERIPH_ID_I2C6:
|
|
case PERIPH_ID_I2C7:
|
|
exynos5_i2c_config(peripheral, flags);
|
|
break;
|
|
case PERIPH_ID_I2S0:
|
|
case PERIPH_ID_I2S1:
|
|
exynos5_i2s_config(peripheral);
|
|
break;
|
|
case PERIPH_ID_SPI0:
|
|
case PERIPH_ID_SPI1:
|
|
case PERIPH_ID_SPI2:
|
|
case PERIPH_ID_SPI3:
|
|
case PERIPH_ID_SPI4:
|
|
exynos5_spi_config(peripheral);
|
|
break;
|
|
case PERIPH_ID_DPHPD:
|
|
/* Set Hotplug detect for DP */
|
|
gpio_cfg_pin(EXYNOS5_GPIO_X07, S5P_GPIO_FUNC(0x3));
|
|
|
|
/*
|
|
* Hotplug detect should have an external pullup; disable the
|
|
* internal pulldown so they don't fight.
|
|
*/
|
|
gpio_set_pull(EXYNOS5_GPIO_X07, S5P_GPIO_PULL_NONE);
|
|
break;
|
|
default:
|
|
debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int exynos5420_pinmux_config(int peripheral, int flags)
|
|
{
|
|
switch (peripheral) {
|
|
case PERIPH_ID_UART0:
|
|
case PERIPH_ID_UART1:
|
|
case PERIPH_ID_UART2:
|
|
case PERIPH_ID_UART3:
|
|
exynos5420_uart_config(peripheral);
|
|
break;
|
|
case PERIPH_ID_SDMMC0:
|
|
case PERIPH_ID_SDMMC1:
|
|
case PERIPH_ID_SDMMC2:
|
|
case PERIPH_ID_SDMMC3:
|
|
return exynos5420_mmc_config(peripheral, flags);
|
|
case PERIPH_ID_SPI0:
|
|
case PERIPH_ID_SPI1:
|
|
case PERIPH_ID_SPI2:
|
|
case PERIPH_ID_SPI3:
|
|
case PERIPH_ID_SPI4:
|
|
exynos5420_spi_config(peripheral);
|
|
break;
|
|
case PERIPH_ID_I2C0:
|
|
case PERIPH_ID_I2C1:
|
|
case PERIPH_ID_I2C2:
|
|
case PERIPH_ID_I2C3:
|
|
case PERIPH_ID_I2C4:
|
|
case PERIPH_ID_I2C5:
|
|
case PERIPH_ID_I2C6:
|
|
case PERIPH_ID_I2C7:
|
|
case PERIPH_ID_I2C8:
|
|
case PERIPH_ID_I2C9:
|
|
case PERIPH_ID_I2C10:
|
|
exynos5420_i2c_config(peripheral);
|
|
break;
|
|
default:
|
|
debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void exynos4_i2c_config(int peripheral, int flags)
|
|
{
|
|
switch (peripheral) {
|
|
case PERIPH_ID_I2C0:
|
|
gpio_cfg_pin(EXYNOS4_GPIO_D10, S5P_GPIO_FUNC(0x2));
|
|
gpio_cfg_pin(EXYNOS4_GPIO_D11, S5P_GPIO_FUNC(0x2));
|
|
break;
|
|
case PERIPH_ID_I2C1:
|
|
gpio_cfg_pin(EXYNOS4_GPIO_D12, S5P_GPIO_FUNC(0x2));
|
|
gpio_cfg_pin(EXYNOS4_GPIO_D13, S5P_GPIO_FUNC(0x2));
|
|
break;
|
|
case PERIPH_ID_I2C2:
|
|
gpio_cfg_pin(EXYNOS4_GPIO_A06, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS4_GPIO_A07, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C3:
|
|
gpio_cfg_pin(EXYNOS4_GPIO_A12, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS4_GPIO_A13, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C4:
|
|
gpio_cfg_pin(EXYNOS4_GPIO_B2, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS4_GPIO_B3, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C5:
|
|
gpio_cfg_pin(EXYNOS4_GPIO_B6, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS4_GPIO_B7, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C6:
|
|
gpio_cfg_pin(EXYNOS4_GPIO_C13, S5P_GPIO_FUNC(0x4));
|
|
gpio_cfg_pin(EXYNOS4_GPIO_C14, S5P_GPIO_FUNC(0x4));
|
|
break;
|
|
case PERIPH_ID_I2C7:
|
|
gpio_cfg_pin(EXYNOS4_GPIO_D02, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS4_GPIO_D03, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int exynos4_mmc_config(int peripheral, int flags)
|
|
{
|
|
int i, start = 0, start_ext = 0;
|
|
unsigned int func, ext_func;
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_SDMMC0:
|
|
start = EXYNOS4_GPIO_K00;
|
|
start_ext = EXYNOS4_GPIO_K13;
|
|
func = S5P_GPIO_FUNC(0x2);
|
|
ext_func = S5P_GPIO_FUNC(0x3);
|
|
break;
|
|
case PERIPH_ID_SDMMC2:
|
|
start = EXYNOS4_GPIO_K20;
|
|
start_ext = EXYNOS4_GPIO_K33;
|
|
func = S5P_GPIO_FUNC(0x2);
|
|
ext_func = S5P_GPIO_FUNC(0x3);
|
|
break;
|
|
case PERIPH_ID_SDMMC4:
|
|
start = EXYNOS4_GPIO_K00;
|
|
start_ext = EXYNOS4_GPIO_K13;
|
|
func = S5P_GPIO_FUNC(0x3);
|
|
ext_func = S5P_GPIO_FUNC(0x4);
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
for (i = start; i < (start + 7); i++) {
|
|
if (i == (start + 2))
|
|
continue;
|
|
gpio_cfg_pin(i, func);
|
|
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
|
gpio_set_drv(i, S5P_GPIO_DRV_4X);
|
|
}
|
|
/* SDMMC2 do not use 8bit mode at exynos4 */
|
|
if (flags & PINMUX_FLAG_8BIT_MODE) {
|
|
for (i = start_ext; i < (start_ext + 4); i++) {
|
|
gpio_cfg_pin(i, ext_func);
|
|
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
|
gpio_set_drv(i, S5P_GPIO_DRV_4X);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void exynos4_uart_config(int peripheral)
|
|
{
|
|
int i, start, count;
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_UART0:
|
|
start = EXYNOS4_GPIO_A00;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART1:
|
|
start = EXYNOS4_GPIO_A04;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART2:
|
|
start = EXYNOS4_GPIO_A10;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART3:
|
|
start = EXYNOS4_GPIO_A14;
|
|
count = 2;
|
|
break;
|
|
default:
|
|
debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
return;
|
|
}
|
|
for (i = start; i < (start + count); i++) {
|
|
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
|
gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2));
|
|
}
|
|
}
|
|
|
|
static void exynos4x12_i2c_config(int peripheral, int flags)
|
|
{
|
|
switch (peripheral) {
|
|
case PERIPH_ID_I2C0:
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_D10, S5P_GPIO_FUNC(0x2));
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_D11, S5P_GPIO_FUNC(0x2));
|
|
break;
|
|
case PERIPH_ID_I2C1:
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_D12, S5P_GPIO_FUNC(0x2));
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_D13, S5P_GPIO_FUNC(0x2));
|
|
break;
|
|
case PERIPH_ID_I2C2:
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_A06, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_A07, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C3:
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_A12, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_A13, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C4:
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_B2, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_B3, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C5:
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_B6, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_B7, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
case PERIPH_ID_I2C6:
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_C13, S5P_GPIO_FUNC(0x4));
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_C14, S5P_GPIO_FUNC(0x4));
|
|
break;
|
|
case PERIPH_ID_I2C7:
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_D02, S5P_GPIO_FUNC(0x3));
|
|
gpio_cfg_pin(EXYNOS4X12_GPIO_D03, S5P_GPIO_FUNC(0x3));
|
|
break;
|
|
}
|
|
}
|
|
|
|
static int exynos4x12_mmc_config(int peripheral, int flags)
|
|
{
|
|
int i, start = 0, start_ext = 0;
|
|
unsigned int func, ext_func;
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_SDMMC0:
|
|
start = EXYNOS4X12_GPIO_K00;
|
|
start_ext = EXYNOS4X12_GPIO_K13;
|
|
func = S5P_GPIO_FUNC(0x2);
|
|
ext_func = S5P_GPIO_FUNC(0x3);
|
|
break;
|
|
case PERIPH_ID_SDMMC2:
|
|
start = EXYNOS4X12_GPIO_K20;
|
|
start_ext = EXYNOS4X12_GPIO_K33;
|
|
func = S5P_GPIO_FUNC(0x2);
|
|
ext_func = S5P_GPIO_FUNC(0x3);
|
|
break;
|
|
case PERIPH_ID_SDMMC4:
|
|
start = EXYNOS4X12_GPIO_K00;
|
|
start_ext = EXYNOS4X12_GPIO_K13;
|
|
func = S5P_GPIO_FUNC(0x3);
|
|
ext_func = S5P_GPIO_FUNC(0x4);
|
|
break;
|
|
default:
|
|
return -1;
|
|
}
|
|
for (i = start; i < (start + 7); i++) {
|
|
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
|
if (i == (start + 2))
|
|
continue;
|
|
gpio_cfg_pin(i, func);
|
|
gpio_set_drv(i, S5P_GPIO_DRV_4X);
|
|
}
|
|
if (flags & PINMUX_FLAG_8BIT_MODE) {
|
|
for (i = start_ext; i < (start_ext + 4); i++) {
|
|
gpio_cfg_pin(i, ext_func);
|
|
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
|
gpio_set_drv(i, S5P_GPIO_DRV_4X);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void exynos4x12_uart_config(int peripheral)
|
|
{
|
|
int i, start, count;
|
|
|
|
switch (peripheral) {
|
|
case PERIPH_ID_UART0:
|
|
start = EXYNOS4X12_GPIO_A00;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART1:
|
|
start = EXYNOS4X12_GPIO_A04;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART2:
|
|
start = EXYNOS4X12_GPIO_A10;
|
|
count = 4;
|
|
break;
|
|
case PERIPH_ID_UART3:
|
|
start = EXYNOS4X12_GPIO_A14;
|
|
count = 2;
|
|
break;
|
|
default:
|
|
debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
return;
|
|
}
|
|
for (i = start; i < (start + count); i++) {
|
|
gpio_set_pull(i, S5P_GPIO_PULL_NONE);
|
|
gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2));
|
|
}
|
|
}
|
|
|
|
static int exynos4_pinmux_config(int peripheral, int flags)
|
|
{
|
|
switch (peripheral) {
|
|
case PERIPH_ID_UART0:
|
|
case PERIPH_ID_UART1:
|
|
case PERIPH_ID_UART2:
|
|
case PERIPH_ID_UART3:
|
|
exynos4_uart_config(peripheral);
|
|
break;
|
|
case PERIPH_ID_I2C0:
|
|
case PERIPH_ID_I2C1:
|
|
case PERIPH_ID_I2C2:
|
|
case PERIPH_ID_I2C3:
|
|
case PERIPH_ID_I2C4:
|
|
case PERIPH_ID_I2C5:
|
|
case PERIPH_ID_I2C6:
|
|
case PERIPH_ID_I2C7:
|
|
exynos4_i2c_config(peripheral, flags);
|
|
break;
|
|
case PERIPH_ID_SDMMC0:
|
|
case PERIPH_ID_SDMMC2:
|
|
case PERIPH_ID_SDMMC4:
|
|
return exynos4_mmc_config(peripheral, flags);
|
|
case PERIPH_ID_SDMMC1:
|
|
case PERIPH_ID_SDMMC3:
|
|
debug("SDMMC device %d not implemented\n", peripheral);
|
|
return -1;
|
|
default:
|
|
debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int exynos4x12_pinmux_config(int peripheral, int flags)
|
|
{
|
|
switch (peripheral) {
|
|
case PERIPH_ID_UART0:
|
|
case PERIPH_ID_UART1:
|
|
case PERIPH_ID_UART2:
|
|
case PERIPH_ID_UART3:
|
|
exynos4x12_uart_config(peripheral);
|
|
break;
|
|
case PERIPH_ID_I2C0:
|
|
case PERIPH_ID_I2C1:
|
|
case PERIPH_ID_I2C2:
|
|
case PERIPH_ID_I2C3:
|
|
case PERIPH_ID_I2C4:
|
|
case PERIPH_ID_I2C5:
|
|
case PERIPH_ID_I2C6:
|
|
case PERIPH_ID_I2C7:
|
|
exynos4x12_i2c_config(peripheral, flags);
|
|
break;
|
|
case PERIPH_ID_SDMMC0:
|
|
case PERIPH_ID_SDMMC2:
|
|
case PERIPH_ID_SDMMC4:
|
|
return exynos4x12_mmc_config(peripheral, flags);
|
|
case PERIPH_ID_SDMMC1:
|
|
case PERIPH_ID_SDMMC3:
|
|
debug("SDMMC device %d not implemented\n", peripheral);
|
|
return -1;
|
|
default:
|
|
debug("%s: invalid peripheral %d", __func__, peripheral);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int exynos_pinmux_config(int peripheral, int flags)
|
|
{
|
|
if (cpu_is_exynos5()) {
|
|
if (proid_is_exynos5420() || proid_is_exynos5422())
|
|
return exynos5420_pinmux_config(peripheral, flags);
|
|
else if (proid_is_exynos5250())
|
|
return exynos5_pinmux_config(peripheral, flags);
|
|
} else if (cpu_is_exynos4()) {
|
|
if (proid_is_exynos4412())
|
|
return exynos4x12_pinmux_config(peripheral, flags);
|
|
else
|
|
return exynos4_pinmux_config(peripheral, flags);
|
|
}
|
|
|
|
debug("pinmux functionality not supported\n");
|
|
|
|
return -1;
|
|
}
|
|
|
|
#if CONFIG_IS_ENABLED(OF_CONTROL)
|
|
static int exynos4_pinmux_decode_periph_id(const void *blob, int node)
|
|
{
|
|
int err;
|
|
u32 cell[3];
|
|
|
|
err = fdtdec_get_int_array(blob, node, "interrupts", cell,
|
|
ARRAY_SIZE(cell));
|
|
if (err) {
|
|
debug(" invalid peripheral id\n");
|
|
return PERIPH_ID_NONE;
|
|
}
|
|
|
|
return cell[1];
|
|
}
|
|
|
|
static int exynos5_pinmux_decode_periph_id(const void *blob, int node)
|
|
{
|
|
int err;
|
|
u32 cell[3];
|
|
|
|
err = fdtdec_get_int_array(blob, node, "interrupts", cell,
|
|
ARRAY_SIZE(cell));
|
|
if (err)
|
|
return PERIPH_ID_NONE;
|
|
|
|
return cell[1];
|
|
}
|
|
|
|
int pinmux_decode_periph_id(const void *blob, int node)
|
|
{
|
|
if (cpu_is_exynos5())
|
|
return exynos5_pinmux_decode_periph_id(blob, node);
|
|
else if (cpu_is_exynos4())
|
|
return exynos4_pinmux_decode_periph_id(blob, node);
|
|
|
|
return PERIPH_ID_NONE;
|
|
}
|
|
#endif
|