기존 이솝 임베디드 포럼의 지식인 서비스가 게시판 형태로 변경되었습니다.
안녕하세요
S5PV210 ( linux kernel 2.6.32.9 ) 에 TL16C554APN 을 적용 하려 하는데 여러가지 문제점이 있어서 경험을 가지고 계신 분들께 문의 드려 봅니다.
우선 S5PV210 에서
[ H/W Address ] [ TL16C554APN ]
MA0 A0
MA1 A1
MA2 A2
[ H/W Address ] [ 74HC138 ]
MA6 A0
MA7 A1
MA8 A2
로 연결이 되어 있고 TL16C554 4채널 CS 를 위해 74HC138 을 사용 하여 CS 분기를 하였습니다.
TL16C554APN UART 사용 등록은 8250 을 사용 하였습니다.
#
# config define
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
#
# mach-smdkv210.c
#
#define EXT_SROM_PA_CS4 ( 0xA0000000 )
#define EXT_74HC138_A0 ( 0x40 )
#define EXT_74HC138_A1 ( 0x80 )
#define EXT_74HC138_A2 ( 0x100 )
#define EXT_74HC138_nCS_Y0(x) ( (x) )
#define EXT_74HC138_nCS_Y1(x) ( (x) + EXT_74HC138_A0 )
#define EXT_74HC138_nCS_Y2(x) ( (x) + EXT_74HC138_A1 )
#define EXT_74HC138_nCS_Y3(x) ( (x) + EXT_74HC138_A0 + EXT_74HC138_A1)
#define EXT_TL16C554APN_FLAGS (UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SKIP_TEST)
#define EXT_TL16C544APN_PORT(_pbase, _irq, _regshift) \
{ \
.mapbase = (_pbase), \
.irq = _irq, \
.irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH, \
.uartclk = 3686400, \
.regshift = (_regshift), \
.iotype = UPIO_MEM, \
.flags = EXT_TL16C554APN_FLAGS, \
}
static struct plat_serial8250_port ext_tl16c554_uart_data[] = {
EXT_TL16C544APN_PORT( EXT_74HC138_nCS_Y0(EXT_SROM_PA_CS4), IRQ_EINT(2), 1 ),
EXT_TL16C544APN_PORT( EXT_74HC138_nCS_Y1(EXT_SROM_PA_CS4), IRQ_EINT(3), 1 ),
EXT_TL16C544APN_PORT( EXT_74HC138_nCS_Y2(EXT_SROM_PA_CS4), IRQ_EINT(5), 1 ),
EXT_TL16C544APN_PORT( EXT_74HC138_nCS_Y3(EXT_SROM_PA_CS4), IRQ_EINT(6), 1 ),
{},
};
static struct platform_device ext_tl16c554_uart_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = ext_tl16c554_uart_data,
},
};
static void EXT_TL16C554APN_Init(void)
{
unsigned int lnSROM_RegValue = 0;
void __iomem *sram_regs;
lnSROM_RegValue = 0x22222222;
__raw_writel(lnSROM_RegValue,(S5PV210_MP04CON));
__raw_writel(lnSROM_RegValue,(S5PV210_MP05CON));
__raw_writel(lnSROM_RegValue,(S5PV210_MP06CON));
__raw_writel(lnSROM_RegValue,(S5PV210_MP07CON));
sram_regs = ioremap(EXT_SROM_BW_ADDR, 0x40);
lnSROM_RegValue &= ~(0xf << 16); // SROM_CS[4]
lnSROM_RegValue |= (0x2 << 16);
writel(lnSROM_RegValue, sram_regs);
lnSROM_RegValue = ((0x0<<28)|(0x4<<24)|(0xd<<16)|(0x1<<12)|(0x4<<8)|(0x6<<4)|(0x0<<0));
__raw_writel(lnSROM_RegValue, (S5P_SROM_BW+0x14)); // SROM_CS[4]
}
위와 같이 적용 후 실행을 하였더니
serial8250.0: ttyS0 at MMIO 0xa0000000 (irq = 162) is a 16450
serial8250.0: ttyS1 at MMIO 0xa0000040 (irq = 163) is a 16450
serial8250.0: ttyS2 at MMIO 0xa0000080 (irq = 165) is a 16450
serial8250.0: ttyS3 at MMIO 0xa00000c0 (irq = 166) is a 16450
부팅 Log 에 위 와 같이 나옵니다.
그리고 위 메세지가 나올 타이밍에 CS4 가 움직입니다.
이후 UART 테스트를 ttyS0 ~ ttyS3 까지 open 하여 진행 하였으나 CS 가 흔들리지 않아서
이렇게 문의를 드려 보게 되었습니다.
V210에는 아니고... 2440에는 이렇게 써서 External UART을 했습니다.
기억으로는 _regshift 부분이... 16/8 bit인지에 따라서 달랐던 것으로 기억 합니다.
원래 Source의 수정 부분은 FAlinux에 Source를 참조 했었던 것으로 기억합니다.
몇 년 지나니 당췌 기억이 안 나네요.. ^ ^;
#ifdef CONFIG_SERIAL_8250
#include <asm/serial.h>
#include <linux/serial_8250.h>
#define UART_SETUP( _addr, _irq, _regshift ) \
{ \
.membase = 0, \
.mapbase = (_addr), \
.irq = (_irq), \
.flags = UPF_SKIP_TEST | UPF_IOREMAP, \
.iotype = UPIO_MEM, \
.regshift = (_regshift), \
.uartclk = 3686400, \
}
static struct plat_serial8250_port serial_platform_data[] = {
UART_SETUP( S3C2410_CS5 + 0x000, IRQ_EINT0, 0 ),
UART_SETUP( S3C2410_CS5 + 0x020, IRQ_EINT1, 0 ),
UART_SETUP( S3C2410_CS5 + 0x040, IRQ_EINT2, 0 ),
UART_SETUP( S3C2410_CS5 + 0x060, IRQ_EINT3, 0 ),
UART_SETUP( S3C2410_CS5 + 0x080, IRQ_EINT4, 0 ),
UART_SETUP( S3C2410_CS5 + 0x0A0, IRQ_EINT5, 0 ),
UART_SETUP( S3C2410_CS5 + 0x0C0, IRQ_EINT6, 0 ),
UART_SETUP( S3C2410_CS5 + 0x0E0, IRQ_EINT7, 0 ),
/*
UART_SETUP( S3C2410_CS3 + 0x100, IRQ_EINT13, 2 ),
UART_SETUP( S3C2410_CS3 + 0x120, IRQ_EINT13, 2 ),
UART_SETUP( S3C2410_CS3 + 0x140, IRQ_EINT13, 2 ),
UART_SETUP( S3C2410_CS3 + 0x160, IRQ_EINT13, 2 ),
UART_SETUP( S3C2410_CS3 + 0x180, IRQ_EINT13, 2 ),
UART_SETUP( S3C2410_CS3 + 0x1A0, IRQ_EINT13, 2 ),
UART_SETUP( S3C2410_CS3 + 0x1C0, IRQ_EINT13, 2 ),
UART_SETUP( S3C2410_CS3 + 0x1E0, IRQ_EINT13, 2 ),
*/
{(struct plat_serial8250_port *)NULL}
};
static struct platform_device serial_device = {
.name = "serial8250",
.id = 0,
.dev = {
.platform_data = serial_platform_data,
},
};
#endif
----
----
static struct platform_device *aesop2440_devices[] __initdata = {
&s3c_device_usb,
//&s3c_device_lcd,
//&s3c_device_bl, // ghcstop: back light°ü·Ã(brightness Á¶ÀýÀΰ¨?) ÄÚµåµéÀº ´Ù Ʋ·ÁÀÖ´Ù.
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
&s3c_device_sdi,
&s3c_device_usbgadget,
&s3c_device_ts,
&s3c_device_nand,
&s3c_device_sound,
&s3c_device_buttons, // ghcstop add for button driver
&s3c_device_rtc, // ghcstop add
&aesop_device_nor, // ghcstop: 060213
#if 0
&aesop_device_hpi, // ghcstop: 060213
#endif
&smc91x_device, // ghcstop
#if 0
&cs89x_device, // ghcstop
#endif
#ifdef CONFIG_SERIAL_8250
&serial_device,
#endif
};
open() 함수 호출시 처리를 함 보시기 바랍니다.
그 때 어떤 코드가 동작하는지 그리고, 외부 핀이 움직이는지를 함 봐야할 듯 하네요.
위의 정보로는 그다지 쉽게 알 수 있는 내용은 아닐겁니다.
이렇게 쓰는 경우가 많으면 답이 쉽게 나올텐데, 저도 중간에 cs관련 chip을 쓰는 경우는 처음봐서
참....답이 애매하네요.
제가 가지고 있는 자료에는 관련 부분이 틀리네요.....